diff options
Diffstat (limited to 'modules/mono')
104 files changed, 1463 insertions, 797 deletions
diff --git a/modules/mono/SCsub b/modules/mono/SCsub index db35e804aa..d10ebc7b47 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -55,7 +55,7 @@ env_mono.add_source_files(env.modules_sources, "utils/*.cpp") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp") -if env["platform"] in ["osx", "iphone"]: +if env["platform"] in ["macos", "ios"]: env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m") elif env["platform"] == "android": @@ -63,5 +63,4 @@ elif env["platform"] == "android": if env["tools"]: env_mono.add_source_files(env.modules_sources, "editor/*.cpp") - -SConscript("editor_templates/SCsub") + SConscript("editor/script_templates/SCsub") diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py index 1920ef1c1a..3459244bc2 100644 --- a/modules/mono/build_scripts/make_android_mono_config.py +++ b/modules/mono/build_scripts/make_android_mono_config.py @@ -43,7 +43,7 @@ String get_godot_android_mono_config() { Compression::decompress(w, config_uncompressed_size, config_compressed_data, config_compressed_size, Compression::MODE_DEFLATE); String s; - if (s.parse_utf8((const char *)w, data.size())) { + if (s.parse_utf8((const char *)w, data.size()) != OK) { ERR_FAIL_V(String()); } return s; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 8e441e7e07..e69904c54b 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -63,15 +63,15 @@ def copy_file(src_dir, dst_dir, src_name, dst_name=""): def is_desktop(platform): - return platform in ["windows", "osx", "linuxbsd", "server", "uwp", "haiku"] + return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"] def is_unix_like(platform): - return platform in ["osx", "linuxbsd", "server", "android", "haiku", "iphone"] + return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"] def module_supports_tools_on(platform): - return platform not in ["android", "javascript", "iphone"] + return platform not in ["android", "javascript", "ios"] def find_wasm_src_dir(mono_root): @@ -89,7 +89,7 @@ def configure(env, env_mono): bits = env["bits"] is_android = env["platform"] == "android" is_javascript = env["platform"] == "javascript" - is_ios = env["platform"] == "iphone" + is_ios = env["platform"] == "ios" is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"] tools_enabled = env["tools"] @@ -206,7 +206,7 @@ def configure(env, env_mono): copy_file(mono_bin_path, "#bin", mono_dll_file) else: - is_apple = env["platform"] in ["osx", "iphone"] + is_apple = env["platform"] in ["macos", "ios"] is_macos = is_apple and not is_ios sharedlib_ext = ".dylib" if is_apple else ".so" @@ -221,7 +221,7 @@ def configure(env, env_mono): ) if not mono_root and is_macos: - # Try with some known directories under OSX + # Try with some known directories under macOS hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"] for hint_dir in hint_dirs: if os.path.isdir(hint_dir): @@ -270,7 +270,7 @@ def configure(env, env_mono): def copy_mono_lib(libname_wo_ext): copy_file( - mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch) + mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.ios.%s.a" % (libname_wo_ext, arch) ) # Copy Mono libraries to the output folder. These are meant to be bundled with @@ -539,7 +539,7 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): os.makedirs(target_mono_lib_dir) lib_file_names = [] - if platform == "osx": + if platform == "macos": lib_file_names = [ lib_name + ".dylib" for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"] diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index 5884a24454..c4547b4323 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -40,17 +40,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Dictionary classes_dict; - List<StringName> names; + List<StringName> class_list; + ClassDB::get_class_list(&class_list); + // Must be alphabetically sorted for hash to compute. + class_list.sort_custom<StringName::AlphCompare>(); - const StringName *k = nullptr; - - while ((k = ClassDB::classes.next(k))) { - names.push_back(*k); - } - //must be alphabetically sorted for hash to compute - names.sort_custom<StringName::AlphCompare>(); - - for (const StringName &E : names) { + for (const StringName &E : class_list) { ClassDB::ClassInfo *t = ClassDB::classes.getptr(E); ERR_FAIL_COND(!t); if (t->api != p_api || !t->exposed) { @@ -66,10 +61,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->method_map.next(k))) { - String name = k->operator String(); + for (const KeyValue<StringName, MethodBind *> &F : t->method_map) { + String name = F.key.operator String(); ERR_CONTINUE(name.is_empty()); @@ -77,7 +70,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { continue; // Ignore non-virtual methods that start with an underscore } - snames.push_back(*k); + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -131,10 +124,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->constant_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, int64_t> &F : t->constant_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -158,10 +149,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->signal_map.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -193,10 +182,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = nullptr; - - while ((k = t->property_setget.next(k))) { - snames.push_back(*k); + for (const KeyValue<StringName, ClassDB::PropertySetGet> &F : t->property_setget) { + snames.push_back(F.key); } snames.sort_custom<StringName::AlphCompare>(); @@ -238,11 +225,10 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { } } - FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE); - ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_output_file + "'."); + Ref<FileAccess> f = FileAccess::open(p_output_file, FileAccess::WRITE); + ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_output_file + "'."); JSON json; f->store_string(json.stringify(classes_dict, "\t")); - f->close(); print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file)); } diff --git a/modules/mono/config.py b/modules/mono/config.py index df02d9a309..3e6584590c 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -1,4 +1,4 @@ -supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"] +supported_platforms = ["windows", "macos", "linuxbsd", "server", "android", "haiku", "javascript", "ios"] def can_build(env, platform): @@ -15,7 +15,7 @@ def configure(env): from SCons.Script import BoolVariable, PathVariable, Variables, Help - default_mono_static = platform in ["iphone", "javascript"] + default_mono_static = platform in ["ios", "javascript"] default_mono_bundles_zlib = platform in ["javascript"] envvars = Variables() diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 085ab9a467..1e4d82ca30 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -45,17 +45,17 @@ #ifdef TOOLS_ENABLED #include "core/os/keyboard.h" #include "editor/bindings_generator.h" +#include "editor/editor_internal_calls.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/node_dock.h" +#include "editor/script_templates/templates.gen.h" #endif #ifdef DEBUG_METHODS_ENABLED #include "class_db_api_json.h" #endif -#include "editor/editor_internal_calls.h" -#include "editor_templates/templates.gen.h" #include "godotsharp_dirs.h" #include "mono_gd/gd_mono_cache.h" #include "mono_gd/gd_mono_class.h" @@ -373,11 +373,13 @@ Ref<Script> CSharpLanguage::make_template(const String &p_template, const String Vector<ScriptLanguage::ScriptTemplate> CSharpLanguage::get_built_in_templates(StringName p_object) { Vector<ScriptLanguage::ScriptTemplate> templates; +#ifdef TOOLS_ENABLED for (int i = 0; i < TEMPLATES_ARRAY_SIZE; i++) { if (TEMPLATES[i].inherit == p_object) { templates.append(TEMPLATES[i]); } } +#endif return templates; } @@ -386,7 +388,7 @@ String CSharpLanguage::validate_path(const String &p_path) const { List<String> keywords; get_reserved_words(&keywords); if (keywords.find(class_name)) { - return TTR("Class name can't be a reserved keyword"); + return RTR("Class name can't be a reserved keyword"); } return ""; } @@ -479,11 +481,14 @@ static String variant_type_to_managed_name(const String &p_var_type_name) { Variant::VECTOR3, Variant::VECTOR3I, Variant::TRANSFORM2D, + Variant::VECTOR4, + Variant::VECTOR4I, Variant::PLANE, Variant::QUATERNION, Variant::AABB, Variant::BASIS, Variant::TRANSFORM3D, + Variant::PROJECTION, Variant::COLOR, Variant::STRING_NAME, Variant::NODE_PATH, @@ -527,10 +532,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe String CSharpLanguage::_get_indentation() const { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0); + bool use_space_indentation = EDITOR_GET("text_editor/behavior/indent/type"); if (use_space_indentation) { - int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4); + int indent_size = EDITOR_GET("text_editor/behavior/indent/size"); String space_indent = ""; for (int i = 0; i < indent_size; i++) { @@ -684,10 +689,10 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) { #ifdef DEBUG_ENABLED MutexLock lock(unsafe_object_references_lock); ObjectID id = p_obj->get_instance_id(); - Map<ObjectID, int>::Element *elem = unsafe_object_references.find(id); + HashMap<ObjectID, int>::Iterator elem = unsafe_object_references.find(id); ERR_FAIL_NULL(elem); - if (--elem->value() == 0) { - unsafe_object_references.erase(elem); + if (--elem->value == 0) { + unsafe_object_references.remove(elem); } #endif } @@ -873,7 +878,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 (Object *&obj : script->instances) { + for (Object *obj : script->instances) { script->pending_reload_instances.insert(obj->get_instance_id()); RefCounted *rc = Object::cast_to<RefCounted>(obj); @@ -883,7 +888,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } #ifdef TOOLS_ENABLED - for (PlaceHolderScriptInstance *&script_instance : script->placeholders) { + for (PlaceHolderScriptInstance *script_instance : script->placeholders) { Object *obj = script_instance->get_owner(); script->pending_reload_instances.insert(obj->get_instance_id()); @@ -895,9 +900,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif // Save state and remove script from instances - Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; + RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; - for (Object *&obj : script->instances) { + for (Object *obj : script->instances) { ERR_CONTINUE(!obj->get_script_instance()); CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance()); @@ -920,9 +925,9 @@ 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) { - 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) + while (script->instances.begin()) { + Object *obj = *script->instances.begin(); + obj->set_script(Ref<RefCounted>()); // Remove script and existing script instances (placeholder are not removed before domain reload) } script->_clear(); @@ -1097,14 +1102,14 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { const StringName &name = G.first; const Array &serialized_data = G.second; - Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name); + HashMap<StringName, CSharpScript::EventSignal>::Iterator match = script->event_signals.find(name); if (!match) { // The event or its signal attribute were removed continue; } - const CSharpScript::EventSignal &event_signal = match->value(); + const CSharpScript::EventSignal &event_signal = match->value; MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); MonoDelegate *delegate = nullptr; @@ -1426,7 +1431,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b return true; } -Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { +RBMap<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { return script_bindings.insert(p_object, p_script_binding); } @@ -1435,7 +1440,7 @@ void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance MutexLock lock(csharp_lang->language_bind_mutex); - Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance); + RBMap<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance); if (match) { return (void *)match; } @@ -1465,7 +1470,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin { MutexLock lock(csharp_lang->language_bind_mutex); - Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding; + RBMap<Object *, CSharpScriptBinding>::Element *data = (RBMap<Object *, CSharpScriptBinding>::Element *)p_binding; CSharpScriptBinding &script_binding = data->value(); @@ -1486,7 +1491,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) { CRASH_COND(!p_binding); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner); @@ -1556,7 +1561,7 @@ void *CSharpLanguage::get_instance_binding(Object *p_object) { // `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that. if (binding) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)binding)->value(); if (!script_binding.inited) { MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex()); @@ -1796,8 +1801,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { List<PropertyInfo> props; - for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = script->member_info.front(); E; E = E.next()) { - props.push_front(E.value()); + for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) { + props.push_front(E.value); } // Call _get_property_list @@ -1893,7 +1898,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const { return false; } -Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Variant CSharpInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { ERR_FAIL_COND_V(!script.is_valid(), Variant()); GD_MONO_SCOPE_THREAD_ATTACH; @@ -2299,7 +2304,7 @@ CSharpInstance::~CSharpInstance() { void *data = CSharpLanguage::get_instance_binding(owner); CRASH_COND(data == nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); CRASH_COND(!script_binding.inited); #ifdef DEBUG_ENABLED @@ -2313,9 +2318,9 @@ CSharpInstance::~CSharpInstance() { #ifdef DEBUG_ENABLED // CSharpInstance must not be created unless it's going to be added to the list for sure - Set<Object *>::Element *match = script->instances.find(owner); + HashSet<Object *>::Iterator match = script->instances.find(owner); CRASH_COND(!match); - script->instances.erase(match); + script->instances.remove(match); #else script->instances.erase(owner); #endif @@ -2329,7 +2334,7 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) #endif #ifdef TOOLS_ENABLED -void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { +void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) { if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -2565,12 +2570,12 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda if ((changed || p_instance_to_update) && placeholders.size()) { // Update placeholders if any - Map<StringName, Variant> values; + HashMap<StringName, Variant> values; List<PropertyInfo> propnames; _update_exports_values(values, propnames); if (changed) { - for (PlaceHolderScriptInstance *&script_instance : placeholders) { + for (PlaceHolderScriptInstance *script_instance : placeholders) { script_instance->update(propnames, values); } } else { @@ -2805,7 +2810,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage GD_MONO_ASSERT_THREAD_ATTACHED; if (p_variant_type == Variant::INT && p_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(p_type.type_class->get_mono_ptr())) { - r_hint = PROPERTY_HINT_ENUM; + MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type()); + r_hint = GDMonoUtils::Marshal::type_has_flags_attribute(reftype) ? PROPERTY_HINT_FLAGS : PROPERTY_HINT_ENUM; Vector<MonoClassField *> fields = p_type.type_class->get_enum_fields(); @@ -2842,7 +2848,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage uint64_t val = GDMonoUtils::unbox_enum_value(val_obj, enum_basetype, r_error); ERR_FAIL_COND_V_MSG(r_error, -1, "Failed to unbox '" + enum_field_name + "' constant enum value."); - if (val != (unsigned int)i) { + unsigned int expected_val = r_hint == PROPERTY_HINT_FLAGS ? 1 << i : i; + if (val != expected_val) { uses_default_values = false; } @@ -2862,6 +2869,12 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage r_hint = PROPERTY_HINT_RESOURCE_TYPE; r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); + } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(Node)->is_assignable_from(p_type.type_class)) { + GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class); + CRASH_COND(field_native_class == nullptr); + + r_hint = PROPERTY_HINT_NODE_TYPE; + r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); } else if (p_allow_generics && p_variant_type == Variant::ARRAY) { // Nested arrays are not supported in the inspector @@ -2908,7 +2921,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage } #endif -Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Variant CSharpScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (unlikely(GDMono::get_singleton() == nullptr)) { // Probably not the best error but eh. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; @@ -2936,7 +2949,7 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i } // No static method found. Try regular instance calls - return Script::call(p_method, p_args, p_argcount, r_error); + return Script::callp(p_method, p_args, p_argcount, r_error); } void CSharpScript::_resource_path_changed() { @@ -3059,16 +3072,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { Vector<GDMonoMethod *> methods = top->get_all_methods(); for (int i = 0; i < methods.size(); i++) { if (!methods[i]->is_static()) { - Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]); - if (Multiplayer::RPC_MODE_DISABLED != mode) { - Multiplayer::RPCConfig nd; - nd.name = methods[i]->get_name(); - nd.rpc_mode = mode; - // TODO Transfer mode, channel - nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; - nd.channel = 0; - if (-1 == p_script->rpc_functions.find(nd)) { - p_script->rpc_functions.push_back(nd); + Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]); + if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { + // RPC annotations can only be used once per method + if (p_script->rpc_functions.find(rpc_config) == -1) { + p_script->rpc_functions.push_back(rpc_config); } } } @@ -3142,7 +3150,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg void *data = CSharpLanguage::get_existing_instance_binding(p_owner); CRASH_COND(data == nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited && !script_binding.gchandle.is_released()) { MonoObject *mono_object = script_binding.gchandle.get_target(); if (mono_object) { @@ -3219,10 +3227,10 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal Object *owner = ClassDB::instantiate(NATIVE_GDMONOCLASS_NAME(native)); - REF ref; + Ref<RefCounted> ref; RefCounted *r = Object::cast_to<RefCounted>(owner); if (r) { - ref = REF(r); + ref = Ref<RefCounted>(r); } CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error); @@ -3399,9 +3407,9 @@ ScriptLanguage *CSharpScript::get_language() const { bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { #ifdef TOOLS_ENABLED - const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property); + HashMap<StringName, Variant>::ConstIterator E = exported_members_defval_cache.find(p_property); if (E) { - r_value = E->get(); + r_value = E->value; return true; } @@ -3489,8 +3497,8 @@ Ref<Script> CSharpScript::get_base_script() const { void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const { List<PropertyInfo> props; - for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = member_info.front(); E; E = E.next()) { - props.push_front(E.value()); + for (const KeyValue<StringName, PropertyInfo> &E : member_info) { + props.push_front(E.value); } for (const PropertyInfo &prop : props) { @@ -3503,15 +3511,19 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } -Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { - if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) { - return Multiplayer::RPC_MODE_ANY_PEER; - } - if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) { - return Multiplayer::RPC_MODE_AUTHORITY; +Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const { + Multiplayer::RPCConfig rpc_config; + + MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute)); + if (rpc_attribute != nullptr) { + rpc_config.name = p_member->get_name(); + rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute); + rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute); + rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute); + rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute); } - return Multiplayer::RPC_MODE_DISABLED; + return rpc_config; } const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const { @@ -3572,7 +3584,7 @@ CSharpScript::~CSharpScript() { #endif } -void CSharpScript::get_members(Set<StringName> *p_members) { +void CSharpScript::get_members(HashSet<StringName> *p_members) { #if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) if (p_members) { for (const StringName &member_name : exported_members_names) { @@ -3584,7 +3596,7 @@ void CSharpScript::get_members(Set<StringName> *p_members) { /*************** RESOURCE ***************/ -RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { +Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { if (r_error) { *r_error = ERR_FILE_CANT_OPEN; } @@ -3597,7 +3609,7 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p #if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED) Error err = script->load_source_code(p_path); - ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load C# script file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot load C# script file '" + p_path + "'."); #endif script->set_path(p_original_path); @@ -3623,7 +3635,7 @@ String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : ""; } -Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { +Error ResourceFormatSaverCSharpScript::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { Ref<CSharpScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); @@ -3639,20 +3651,18 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r } #endif - Error err; - FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); + { + Error err; + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); - file->store_string(source); + file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - memdelete(file); - return ERR_CANT_CREATE; + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } } - file->close(); - memdelete(file); - #ifdef TOOLS_ENABLED if (ScriptServer::is_reload_scripts_on_save_enabled()) { CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false); @@ -3662,13 +3672,13 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r return OK; } -void ResourceFormatSaverCSharpScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { +void ResourceFormatSaverCSharpScript::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const { if (Object::cast_to<CSharpScript>(p_resource.ptr())) { p_extensions->push_back("cs"); } } -bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const { +bool ResourceFormatSaverCSharpScript::recognize(const Ref<Resource> &p_resource) const { return Object::cast_to<CSharpScript>(p_resource.ptr()) != nullptr; } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index d6cd9e6e57..b17473470f 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -110,7 +110,7 @@ private: Ref<CSharpScript> base_cache; // TODO what's this for? - Set<Object *> instances; + HashSet<Object *> instances; #ifdef GD_MONO_HOT_RELOAD struct StateBackup { @@ -121,8 +121,8 @@ private: List<Pair<StringName, Array>> event_signals; }; - Set<ObjectID> pending_reload_instances; - Map<ObjectID, StateBackup> pending_reload_state; + HashSet<ObjectID> pending_reload_instances; + RBMap<ObjectID, StateBackup> pending_reload_state; StringName tied_class_name_for_reload; StringName tied_class_namespace_for_reload; #endif @@ -132,29 +132,29 @@ private: SelfList<CSharpScript> script_list = this; - Map<StringName, Vector<SignalParameter>> _signals; - Map<StringName, EventSignal> event_signals; + HashMap<StringName, Vector<SignalParameter>> _signals; + HashMap<StringName, EventSignal> event_signals; bool signals_invalidated = true; Vector<Multiplayer::RPCConfig> rpc_functions; #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache - Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache - Set<PlaceHolderScriptInstance *> placeholders; + HashMap<StringName, Variant> exported_members_defval_cache; // member_default_values_cache + HashSet<PlaceHolderScriptInstance *> placeholders; bool source_changed_cache = false; bool placeholder_fallback_enabled = false; bool exports_invalidated = true; - void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); + void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames); void _update_member_info_no_exports(); void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override; #endif #if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) - Set<StringName> exported_members_names; + HashSet<StringName> exported_members_names; #endif - OrderedHashMap<StringName, PropertyInfo> member_info; + HashMap<StringName, PropertyInfo> member_info; void _clear(); @@ -179,12 +179,12 @@ private: static void update_script_class_info(Ref<CSharpScript> p_script); static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native); - Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const; + Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const; protected: static void _bind_methods(); - Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override; + Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override; void _resource_path_changed() override; bool _get(const StringName &p_name, Variant &r_ret) const; bool _set(const StringName &p_name, const Variant &p_value); @@ -202,9 +202,9 @@ public: void set_source_code(const String &p_code) override; #ifdef TOOLS_ENABLED - virtual const Vector<DocData::ClassDoc> &get_documentation() const override { + virtual Vector<DocData::ClassDoc> get_documentation() const override { // TODO - static Vector<DocData::ClassDoc> docs; + Vector<DocData::ClassDoc> docs; return docs; } #endif // TOOLS_ENABLED @@ -218,7 +218,7 @@ public: void get_script_property_list(List<PropertyInfo> *r_list) const override; void update_exports() override; - void get_members(Set<StringName> *p_members) override; + void get_members(HashSet<StringName> *p_members) override; bool is_tool() const override { return tool; } bool is_valid() const override { return valid; } @@ -295,7 +295,7 @@ public: void get_method_list(List<MethodInfo> *p_list) const override; bool has_method(const StringName &p_method) const override; - Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override; + Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override; void mono_object_disposed(MonoObject *p_obj); @@ -356,11 +356,11 @@ class CSharpLanguage : public ScriptLanguage { Mutex script_gchandle_release_mutex; Mutex language_bind_mutex; - Map<Object *, CSharpScriptBinding> script_bindings; + RBMap<Object *, CSharpScriptBinding> script_bindings; #ifdef DEBUG_ENABLED // List of unsafe object references - Map<ObjectID, int> unsafe_object_references; + HashMap<ObjectID, int> unsafe_object_references; Mutex unsafe_object_references_lock; #endif @@ -467,7 +467,7 @@ public: virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override; virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override; /* TODO */ bool validate(const String &p_script, const String &p_path, List<String> *r_functions, - List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override { + List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override { return true; } String validate_path(const String &p_path) const override; @@ -502,6 +502,7 @@ public: /* TODO? */ void get_public_functions(List<MethodInfo> *p_functions) const override {} /* TODO? */ void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {} + /* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {} void reload_all_scripts() override; void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override; @@ -518,7 +519,7 @@ public: void thread_enter() override; void thread_exit() override; - Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); + RBMap<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object); #ifdef DEBUG_ENABLED @@ -534,7 +535,7 @@ public: class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader { public: - RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; void get_recognized_extensions(List<String> *p_extensions) const override; bool handles_type(const String &p_type) const override; String get_resource_type(const String &p_path) const override; @@ -542,9 +543,9 @@ public: class ResourceFormatSaverCSharpScript : public ResourceFormatSaver { public: - Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override; - void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const override; - bool recognize(const RES &p_resource) const override; + Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0) override; + void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override; + bool recognize(const Ref<Resource> &p_resource) const override; }; #endif // CSHARP_SCRIPT_H diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index 0128f5c706..5a499742e9 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -57,7 +57,7 @@ <PropertyGroup Condition=" '$(GodotTargetPlatform)' == '' "> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Linux))' ">linuxbsd</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(FreeBSD))' ">linuxbsd</GodotTargetPlatform> - <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">osx</GodotTargetPlatform> + <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">macos</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Windows))' ">windows</GodotTargetPlatform> </PropertyGroup> @@ -76,12 +76,12 @@ --> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'windows' ">GODOT_WINDOWS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'linuxbsd' ">GODOT_LINUXBSD;GODOT_PC</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'osx' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'macos' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'server' ">GODOT_SERVER;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'uwp' ">GODOT_UWP;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'haiku' ">GODOT_HAIKU;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'android' ">GODOT_ANDROID;GODOT_MOBILE</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'iphone' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'ios' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'javascript' ">GODOT_JAVASCRIPT;GODOT_HTML5;GODOT_WASM;GODOT_WEB</GodotPlatformConstants> <GodotDefineConstants>$(GodotDefineConstants);$(GodotPlatformConstants)</GodotDefineConstants> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj index ae78da27bc..303ca3a293 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj @@ -12,6 +12,6 @@ <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> </ItemGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj index dad6b9ae7a..02f1764f32 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -19,6 +19,6 @@ A client using this library is only compatible with servers of the same major ve </Description> </PropertyGroup> <ItemGroup> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs index 56fca6b5cb..ebdaca0ce8 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs @@ -334,8 +334,13 @@ namespace GodotTools.Build } } - private void IssuesListRmbSelected(int index, Vector2 atPosition) + private void IssuesListClicked(int index, Vector2 atPosition, int mouseButtonIndex) { + if (mouseButtonIndex != (int)MouseButton.Right) + { + return; + } + _ = index; // Unused _issuesListContextMenu.Clear(); @@ -350,7 +355,7 @@ namespace GodotTools.Build if (_issuesListContextMenu.ItemCount > 0) { - _issuesListContextMenu.Position = (Vector2i)(_issuesList.RectGlobalPosition + atPosition); + _issuesListContextMenu.Position = (Vector2i)(_issuesList.GlobalPosition + atPosition); _issuesListContextMenu.Popup(); } } @@ -375,7 +380,7 @@ namespace GodotTools.Build }; _issuesList.ItemActivated += IssueActivated; _issuesList.AllowRmbSelect = true; - _issuesList.ItemRmbSelected += IssuesListRmbSelected; + _issuesList.ItemClicked += IssuesListClicked; hsc.AddChild(_issuesList); _issuesListContextMenu = new PopupMenu(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index bac7a2e6db..02e9d98647 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -63,6 +63,7 @@ namespace GodotTools.Build startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = true; if (UsingMonoMsBuildOnWindows) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index 2dbc78ab77..3c020a2589 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -126,7 +126,7 @@ namespace GodotTools.Build { base._Ready(); - RectMinSize = new Vector2(0, 228) * EditorScale; + CustomMinimumSize = new Vector2(0, 228) * EditorScale; SizeFlagsVertical = (int)SizeFlags.ExpandFill; var toolBarHBox = new HBoxContainer { SizeFlagsHorizontal = (int)SizeFlags.ExpandFill }; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs index 16dd1c8c6b..63b97e981e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs @@ -99,7 +99,7 @@ namespace GodotTools.Build if (Utils.OS.IsWindows) { // %APPDATA% for both - return new[] {Path.Combine(applicationData, "NuGet", "NuGet.Config")}; + return new[] { Path.Combine(applicationData, "NuGet", "NuGet.Config") }; } var paths = new string[2]; @@ -156,6 +156,7 @@ namespace GodotTools.Build </packageSources> </configuration> "; + System.IO.Directory.CreateDirectory(Path.GetDirectoryName(nuGetConfigPath)); System.IO.File.WriteAllText(nuGetConfigPath, defaultConfig, Encoding.UTF8); // UTF-8 with BOM } diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index ed758cc137..e9718cc82c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -107,7 +107,7 @@ namespace GodotTools.Export ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); // The Godot exporter expects us to pass the abi in the tags parameter - exporter.AddSharedObject(soFilePath, tags: new[] { abi }); + exporter.AddSharedObject(soFilePath, tags: new[] { abi }, ""); } } } @@ -134,7 +134,7 @@ namespace GodotTools.Export if (platform == OS.Platforms.MacOS) { - exporter.AddSharedObject(tempOutputFilePath, tags: null); + exporter.AddSharedObject(tempOutputFilePath, tags: null, ""); } else { @@ -336,10 +336,10 @@ MONO_AOT_MODE_LAST = 1000, // Add the required Mono libraries to the Xcode project - string MonoLibFile(string libFileName) => libFileName + ".iphone.fat.a"; + string MonoLibFile(string libFileName) => libFileName + ".ios.fat.a"; string MonoLibFromTemplate(string libFileName) => - Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName)); + Path.Combine(Internal.FullExportTemplatesDir, "ios-mono-libs", MonoLibFile(libFileName)); exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0")); diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 3e46a89b7c..cca18a2a1f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -337,7 +337,7 @@ namespace GodotTools.Export string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}"; - string templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + string templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); bool validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -347,7 +347,7 @@ namespace GodotTools.Export if (isDebug) { target = "debug"; // Support both 'release_debug' and 'debug' for the template data directory name - templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -380,7 +380,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. + // macOS 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); } @@ -398,13 +398,13 @@ namespace GodotTools.Export private static string GetBclProfileDir(string profile) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; return Path.Combine(templatesDir, "bcl", profile); } private static string DeterminePlatformBclDir(string platform) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; string platformBclDir = Path.Combine(templatesDir, "bcl", platform); if (!File.Exists(Path.Combine(platformBclDir, "mscorlib.dll"))) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 69960bdbeb..b39c3d1c0d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -263,16 +263,16 @@ namespace GodotTools var args = new List<string>(); - bool osxAppBundleInstalled = false; + bool macOSAppBundleInstalled = false; if (OS.IsMacOS) { // The package path is '/Applications/Visual Studio Code.app' const string vscodeBundleId = "com.microsoft.VSCode"; - osxAppBundleInstalled = Internal.IsOsxAppBundleInstalled(vscodeBundleId); + macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(vscodeBundleId); - if (osxAppBundleInstalled) + if (macOSAppBundleInstalled) { args.Add("-b"); args.Add(vscodeBundleId); @@ -307,13 +307,13 @@ namespace GodotTools if (OS.IsMacOS) { - if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) + if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; } - command = osxAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; + command = macOSAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; } else { diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index b9aa760f4d..f1d45463c5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -19,7 +19,7 @@ <ItemGroup> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <Reference Include="GodotSharp"> <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath> <Private>False</Private> diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 3f1d5ac3ca..7a0983a8cb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -30,7 +30,7 @@ namespace GodotTools.Ides.MonoDevelop { string bundleId = BundleIds[_editorId]; - if (Internal.IsOsxAppBundleInstalled(bundleId)) + if (Internal.IsMacOSAppBundleInstalled(bundleId)) { command = "open"; diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs index 77370090ec..12c90178c9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs @@ -12,12 +12,12 @@ namespace GodotTools.Internals public static string UpdateApiAssembliesFromPrebuilt(string config) => internal_UpdateApiAssembliesFromPrebuilt(config); - public static string FullTemplatesDir => - internal_FullTemplatesDir(); + public static string FullExportTemplatesDir => + internal_FullExportTemplatesDir(); public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path); - public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId); + public static bool IsMacOSAppBundleInstalled(string bundleId) => internal_IsMacOSAppBundleInstalled(bundleId); public static bool GodotIs32Bits() => internal_GodotIs32Bits(); @@ -57,13 +57,13 @@ namespace GodotTools.Internals private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string internal_FullTemplatesDir(); + private static extern string internal_FullExportTemplatesDir(); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string internal_SimplifyGodotPath(this string path); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool internal_IsOsxAppBundleInstalled(string bundleId); + private static extern bool internal_IsMacOSAppBundleInstalled(string bundleId); [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool internal_GodotIs32Bits(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 93a1360cb6..5cef6e5c3c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -37,13 +37,13 @@ namespace GodotTools.Utils public static class Platforms { public const string Windows = "windows"; - public const string MacOS = "osx"; + public const string MacOS = "macos"; public const string LinuxBSD = "linuxbsd"; public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; public const string Android = "android"; - public const string iOS = "iphone"; + public const string iOS = "ios"; public const string HTML5 = "javascript"; } @@ -184,7 +184,8 @@ namespace GodotTools.Utils { RedirectStandardOutput = true, RedirectStandardError = true, - UseShellExecute = false + UseShellExecute = false, + CreateNoWindow = true }; using (Process process = Process.Start(startInfo)) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 07128770b7..2e628cb576 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -100,6 +100,9 @@ #define BINDINGS_GENERATOR_VERSION UINT32_C(13) +// Types that will be ignored by the generator and won't be available in C#. +const Vector<String> ignored_types = { "PhysicsServer3DExtension" }; + const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n"); static String fix_doc_description(const String &p_bbcode) { @@ -278,12 +281,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 +314,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 +490,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); + + HashMap<StringName, TypeInterface>::ConstIterator 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()); @@ -748,10 +802,13 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type); - String im_sig = "IntPtr " CS_PARAM_METHODBIND ", "; - String im_unique_sig = imethod.return_type.cname.operator String() + ",IntPtr,IntPtr"; + String im_sig = "IntPtr " CS_PARAM_METHODBIND; + String im_unique_sig = imethod.return_type.cname.operator String() + ",IntPtr"; - im_sig += "IntPtr " CS_PARAM_INSTANCE; + if (!imethod.is_static) { + im_sig += ", IntPtr " CS_PARAM_INSTANCE; + im_unique_sig += ",IntPtr"; + } // Get arguments information int i = 0; @@ -860,6 +917,8 @@ void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) { ARRAY_ALL(Vector2i); ARRAY_ALL(Vector3); ARRAY_ALL(Vector3i); + ARRAY_ALL(Vector4); + ARRAY_ALL(Vector4i); #undef ARRAY_ALL #undef ARRAY_IS_EMPTY @@ -897,7 +956,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { } } - p_output.append(MEMBER_BEGIN "public const int "); + p_output.append(MEMBER_BEGIN "public const long "); p_output.append(iconstant.proxy_name); p_output.append(" = "); p_output.append(itos(iconstant.value)); @@ -933,8 +992,13 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append("\n" INDENT1 OPEN_BLOCK); } + if (ienum.is_flags) { + p_output.append("\n" INDENT1 "[System.Flags]"); + } + p_output.append("\n" INDENT1 "public enum "); p_output.append(enum_proxy_name); + p_output.append(" : long"); p_output.append("\n" INDENT1 OPEN_BLOCK); const ConstantInterface &last = ienum.constants.back()->get(); @@ -978,8 +1042,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE); if (!DirAccess::exists(p_proj_dir)) { Error err = da->make_dir_recursive(p_proj_dir); @@ -1021,8 +1085,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { compile_items.push_back(output_file); } - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - const TypeInterface &itype = E.get(); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + const TypeInterface &itype = E.value; if (itype.api_type == ClassDB::API_EDITOR) { continue; @@ -1113,8 +1177,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE); if (!DirAccess::exists(p_proj_dir)) { Error err = da->make_dir_recursive(p_proj_dir); @@ -1130,8 +1194,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { Vector<String> compile_items; - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - const TypeInterface &itype = E.get(); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + const TypeInterface &itype = E.value; if (itype.api_type != ClassDB::API_EDITOR) { continue; @@ -1223,8 +1287,8 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { String output_dir = path::abspath(path::realpath(p_output_dir)); - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE); if (!DirAccess::exists(output_dir)) { Error err = da->make_dir_recursive(output_dir); @@ -1360,7 +1424,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } } - output.append(MEMBER_BEGIN "public const int "); + output.append(MEMBER_BEGIN "public const long "); output.append(iconstant.proxy_name); output.append(" = "); output.append(itos(iconstant.value)); @@ -1376,8 +1440,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str for (const EnumInterface &ienum : itype.enums) { ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG); + if (ienum.is_flags) { + output.append(MEMBER_BEGIN "[System.Flags]"); + } + output.append(MEMBER_BEGIN "public enum "); output.append(ienum.cname.operator String()); + output.append(" : long"); output.append(MEMBER_BEGIN OPEN_BLOCK); const ConstantInterface &last = ienum.constants.back()->get(); @@ -1516,9 +1585,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too const TypeInterface *current_type = &p_itype; while (!setter && current_type->base_name != StringName()) { - OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name); ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); - current_type = &base_match.get(); + current_type = &base_match->value; setter = current_type->find_method_by_name(p_iprop.setter); } @@ -1527,9 +1596,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too current_type = &p_itype; while (!getter && current_type->base_name != StringName()) { - OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name); ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); - current_type = &base_match.get(); + current_type = &base_match->value; getter = current_type->find_method_by_name(p_iprop.getter); } @@ -1595,7 +1664,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.append("static "); } - p_output.append(prop_itype->cs_type); + String prop_cs_type = prop_itype->cs_type + _get_generic_type_parameters(*prop_itype, proptype_name.generic_type_parameters); + + p_output.append(prop_cs_type); p_output.append(" "); p_output.append(p_iprop.proxy_name); p_output.append("\n" INDENT2 OPEN_BLOCK); @@ -1679,8 +1750,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String arguments_sig; String cs_in_statements; - String icall_params = method_bind_field + ", "; - icall_params += sformat(p_itype.cs_in, "this"); + String icall_params = method_bind_field; + if (!p_imethod.is_static) { + icall_params += ", " + sformat(p_itype.cs_in, "this"); + } StringBuilder default_args_doc; @@ -1703,6 +1776,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf "Invalid default value for parameter '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'."); } + String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); + // Add the current arguments to the signature // If the argument has a default value which is not a constant, we will make it Nullable { @@ -1714,7 +1789,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf arguments_sig += "Nullable<"; } - arguments_sig += arg_type->cs_type; + arguments_sig += arg_cs_type; if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { arguments_sig += "> "; @@ -1741,7 +1816,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String arg_in = iarg.name; arg_in += "_in"; - cs_in_statements += arg_type->cs_type; + cs_in_statements += arg_cs_type; cs_in_statements += " "; cs_in_statements += arg_in; cs_in_statements += " = "; @@ -1761,7 +1836,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf cs_in_statements += " : "; } - String cs_type = arg_type->cs_type; + String cs_type = arg_cs_type; if (cs_type.ends_with("[]")) { cs_type = cs_type.substr(0, cs_type.length() - 2); } @@ -1778,7 +1853,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // 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 " + param_def_arg + "</param>"); + default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is <c>" + param_def_arg + "</c>.</param>"); } else { icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name); } @@ -1838,13 +1913,15 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output.append(MEMBER_BEGIN); p_output.append(p_imethod.is_internal ? "internal " : "public "); - if (p_itype.is_singleton) { + if (p_itype.is_singleton || p_imethod.is_static) { p_output.append("static "); } else if (p_imethod.is_virtual) { p_output.append("virtual "); } - p_output.append(return_type->cs_type + " "); + String return_cs_type = return_type->cs_type + _get_generic_type_parameters(*return_type, p_imethod.return_type.generic_type_parameters); + + p_output.append(return_cs_type + " "); p_output.append(p_imethod.proxy_name + "("); p_output.append(arguments_sig + ")\n" OPEN_BLOCK_L2); @@ -1855,7 +1932,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output.append("return;\n" CLOSE_BLOCK_L2); } else { p_output.append("return default("); - p_output.append(return_type->cs_type); + p_output.append(return_cs_type); p_output.append(");\n" CLOSE_BLOCK_L2); } @@ -1879,10 +1956,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf return OK; // Won't increment method bind count } - const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod); + HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); - const InternalCall *im_icall = match->value(); + const InternalCall *im_icall = match->value; String im_call = im_icall->editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS; im_call += "."; @@ -1897,7 +1974,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf } else if (return_type->cs_out.is_empty()) { p_output.append("return " + im_call + "(" + icall_params + ");\n"); } else { - p_output.append(sformat(return_type->cs_out, im_call, icall_params, return_type->cs_type, return_type->im_type_out)); + p_output.append(sformat(return_type->cs_out, im_call, icall_params, return_cs_type, return_type->im_type_out)); p_output.append("\n"); } @@ -2037,8 +2114,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { generated_icall_funcs.clear(); - for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) { - const TypeInterface &itype = type_elem.get(); + for (const KeyValue<StringName, TypeInterface> &type_elem : obj_types) { + const TypeInterface &itype = type_elem.value; bool is_derived_type = itype.base_name != StringName(); @@ -2196,12 +2273,10 @@ uint32_t BindingsGenerator::get_version() { } Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p_content) { - FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); - - ERR_FAIL_COND_V_MSG(!file, ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'."); + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(file.is_null(), ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'."); file->store_string(p_content.as_string()); - file->close(); return OK; } @@ -2217,7 +2292,10 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte String argc_str = itos(p_imethod.arguments.size()); - String c_func_sig = "MethodBind* " CS_PARAM_METHODBIND ", " + p_itype.c_type_in + " " CS_PARAM_INSTANCE; + String c_func_sig = "MethodBind* " CS_PARAM_METHODBIND; + if (!p_imethod.is_static) { + c_func_sig += ", " + p_itype.c_type_in + " " CS_PARAM_INSTANCE; + } String c_in_statements; String c_args_var_content; @@ -2262,10 +2340,10 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte i++; } - const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod); + HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); - const InternalCall *im_icall = match->value(); + const InternalCall *im_icall = match->value; String icall_method = im_icall->name; if (!generated_icall_funcs.find(im_icall)) { @@ -2309,17 +2387,21 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte String fail_ret = return_type->c_type_out.ends_with("*") && !return_type->ret_as_byref_arg ? "nullptr" : return_type->c_type_out + "()"; - if (return_type->ret_as_byref_arg) { - p_output.append("\tif (" CS_PARAM_INSTANCE " == nullptr) { *arg_ret = "); - p_output.append(fail_ret); - p_output.append("; ERR_FAIL_MSG(\"Parameter ' " CS_PARAM_INSTANCE " ' is null.\"); }\n"); - } else { - p_output.append("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE ", "); - p_output.append(fail_ret); - p_output.append(");\n"); + if (!p_imethod.is_static) { + if (return_type->ret_as_byref_arg) { + p_output.append("\tif (" CS_PARAM_INSTANCE " == nullptr) { *arg_ret = "); + p_output.append(fail_ret); + p_output.append("; ERR_FAIL_MSG(\"Parameter ' " CS_PARAM_INSTANCE " ' is null.\"); }\n"); + } else { + p_output.append("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE ", "); + p_output.append(fail_ret); + p_output.append(");\n"); + } } } else { - p_output.append("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n"); + if (!p_imethod.is_static) { + p_output.append("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n"); + } } if (p_imethod.arguments.size()) { @@ -2363,7 +2445,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } } - p_output.append(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", "); + p_output.append(CS_PARAM_METHODBIND "->call("); + p_output.append(p_imethod.is_static ? "nullptr" : CS_PARAM_INSTANCE); + p_output.append(", "); p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "nullptr"); p_output.append(", total_length, vcall_error);\n"); @@ -2374,7 +2458,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } } } else { - p_output.append("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", "); + p_output.append("\t" CS_PARAM_METHODBIND "->ptrcall("); + p_output.append(p_imethod.is_static ? "nullptr" : CS_PARAM_INSTANCE); + p_output.append(", "); p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "nullptr, "); p_output.append(!ret_void ? "&" C_LOCAL_RET ");\n" : "nullptr);\n"); } @@ -2400,29 +2486,29 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(const TypeReference &p_typeref) { - const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator builtin_type_match = builtin_types.find(p_typeref.cname); if (builtin_type_match) { - return &builtin_type_match->get(); + return &builtin_type_match->value; } - const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator obj_type_match = obj_types.find(p_typeref.cname); if (obj_type_match) { - return &obj_type_match.get(); + return &obj_type_match->value; } if (p_typeref.is_enum) { - const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator enum_match = enum_types.find(p_typeref.cname); if (enum_match) { - return &enum_match->get(); + return &enum_match->value; } // Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead. - const Map<StringName, TypeInterface>::Element *int_match = builtin_types.find(name_cache.type_int); + HashMap<StringName, TypeInterface>::ConstIterator int_match = builtin_types.find(name_cache.type_int); ERR_FAIL_NULL_V(int_match, nullptr); - return &int_match->get(); + return &int_match->value; } return nullptr; @@ -2437,16 +2523,52 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol ERR_PRINT(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'."); - const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname); + HashMap<StringName, TypeInterface>::ConstIterator match = placeholder_types.find(p_typeref.cname); if (match) { - return &match->get(); + return &match->value; } TypeInterface placeholder; TypeInterface::create_placeholder_type(placeholder, p_typeref.cname); - return &placeholder_types.insert(placeholder.cname, placeholder)->get(); + return &placeholder_types.insert(placeholder.cname, placeholder)->value; +} + +const String BindingsGenerator::_get_generic_type_parameters(const TypeInterface &p_itype, const List<TypeReference> &p_generic_type_parameters) { + if (p_generic_type_parameters.is_empty()) { + return ""; + } + + ERR_FAIL_COND_V_MSG(p_itype.type_parameter_count != p_generic_type_parameters.size(), "", + "Generic type parameter count mismatch for type '" + p_itype.name + "'." + + " Found " + itos(p_generic_type_parameters.size()) + ", but requires " + + itos(p_itype.type_parameter_count) + "."); + + int i = 0; + String params = "<"; + for (const TypeReference ¶m_type : p_generic_type_parameters) { + const TypeInterface *param_itype = _get_type_or_placeholder(param_type); + + ERR_FAIL_COND_V_MSG(param_itype->is_singleton, "", + "Generic type parameter is a singleton: '" + param_itype->name + "'."); + + if (p_itype.api_type == ClassDB::API_CORE) { + ERR_FAIL_COND_V_MSG(param_itype->api_type == ClassDB::API_EDITOR, "", + "Generic type parameter '" + param_itype->name + "' has type from the editor API." + + " Core API cannot have dependencies on the editor API."); + } + + params += param_itype->cs_type; + if (i < p_generic_type_parameters.size() - 1) { + params += ", "; + } + + i++; + } + params += ">"; + + return params; } StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta) { @@ -2594,6 +2716,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() { continue; } + if (ignored_types.has(type_cname)) { + _log("Ignoring type '%s' because it's in the list of ignored types\n", String(type_cname).utf8().get_data()); + class_list.pop_front(); + continue; + } + if (!ClassDB::is_class_exposed(type_cname)) { _log("Ignoring type '%s' because it's not exposed\n", String(type_cname).utf8().get_data()); class_list.pop_front(); @@ -2634,7 +2762,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List<PropertyInfo> property_list; ClassDB::get_property_list(type_cname, &property_list, true); - Map<StringName, StringName> accessor_methods; + HashMap<StringName, StringName> accessor_methods; for (const PropertyInfo &property : property_list) { if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY || (property.type == Variant::NIL && property.usage & PROPERTY_USAGE_ARRAY)) { @@ -2712,6 +2840,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() { imethod.name = method_info.name; imethod.cname = cname; + if (method_info.flags & METHOD_FLAG_STATIC) { + imethod.is_static = true; + } + if (method_info.flags & METHOD_FLAG_VIRTUAL) { imethod.is_virtual = true; } @@ -2743,7 +2875,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { " We only expected Object.free, but found '" + itype.name + "." + imethod.name + "'."); } - } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + } else if (return_info.type == Variant::INT && return_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { imethod.return_type.cname = return_info.class_name; imethod.return_type.is_enum = true; } else if (return_info.class_name != StringName()) { @@ -2754,6 +2886,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ERR_FAIL_COND_V_MSG(bad_reference_hint, false, String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." + " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'."); + } else if (return_info.type == Variant::ARRAY && return_info.hint == PROPERTY_HINT_ARRAY_TYPE) { + imethod.return_type.cname = Variant::get_type_name(return_info.type); + imethod.return_type.generic_type_parameters.push_back(TypeReference(return_info.hint_string)); } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { imethod.return_type.cname = return_info.hint_string; } else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { @@ -2778,11 +2913,14 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { iarg.type.cname = arginfo.class_name; + } else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + iarg.type.cname = Variant::get_type_name(arginfo.type); + iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string)); } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { iarg.type.cname = arginfo.hint_string; } else if (arginfo.type == Variant::NIL) { @@ -2825,9 +2963,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { imethod.proxy_name += "_"; } - Map<StringName, StringName>::Element *accessor = accessor_methods.find(imethod.cname); + HashMap<StringName, StringName>::Iterator accessor = accessor_methods.find(imethod.cname); if (accessor) { - const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value()); + const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value); // We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also // we don't know if an accessor method in a different class could have other purposes, so better leave those untouched. @@ -2864,12 +3002,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // Populate signals const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map; - const StringName *k = nullptr; - while ((k = signal_map.next(k))) { + for (const KeyValue<StringName, MethodInfo> &E : signal_map) { SignalInterface isignal; - const MethodInfo &method_info = signal_map.get(*k); + const MethodInfo &method_info = E.value; isignal.name = method_info.name; isignal.cname = method_info.name; @@ -2884,11 +3021,14 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { iarg.type.cname = arginfo.class_name; + } else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + iarg.type.cname = Variant::get_type_name(arginfo.type); + iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string)); } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { iarg.type.cname = arginfo.hint_string; } else if (arginfo.type == Variant::NIL) { @@ -2945,11 +3085,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List<String> constants; ClassDB::get_integer_constant_list(type_cname, &constants, true); - const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; - k = nullptr; + const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map; - while ((k = enum_map.next(k))) { - StringName enum_proxy_cname = *k; + for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) { + StringName enum_proxy_cname = E.key; String enum_proxy_name = enum_proxy_cname.operator String(); if (itype.find_property_by_proxy_name(enum_proxy_cname)) { // We have several conflicts between enums and PascalCase properties, @@ -2958,10 +3097,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() { enum_proxy_cname = StringName(enum_proxy_name); } EnumInterface ienum(enum_proxy_cname); - const List<StringName> &enum_constants = enum_map.get(*k); + ienum.is_flags = E.value.is_bitfield; + const List<StringName> &enum_constants = E.value.constants; for (const StringName &constant_cname : enum_constants) { String constant_name = constant_cname.operator String(); - int *value = class_info->constant_map.getptr(constant_cname); + int64_t *value = class_info->constant_map.getptr(constant_cname); ERR_FAIL_NULL_V(value, false); constants.erase(constant_name); @@ -2988,7 +3128,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { TypeInterface enum_itype; enum_itype.is_enum = true; - enum_itype.name = itype.name + "." + String(*k); + enum_itype.name = itype.name + "." + String(E.key); enum_itype.cname = StringName(enum_itype.name); enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name; TypeInterface::postsetup_enum_type(enum_itype); @@ -2996,7 +3136,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } for (const String &constant_name : constants) { - int *value = class_info->constant_map.getptr(StringName(constant_name)); + int64_t *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); @@ -3084,6 +3224,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "new %s" + r_iarg.default_argument; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; + case Variant::VECTOR4: + case Variant::VECTOR4I: + r_iarg.default_argument = "new %s" + r_iarg.default_argument; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::OBJECT: ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false, "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value."); @@ -3124,7 +3269,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar if (transform == Transform2D()) { r_iarg.default_argument = "Transform2D.Identity"; } else { - r_iarg.default_argument = "new Transform2D(new Vector2" + transform.elements[0].operator String() + ", new Vector2" + transform.elements[1].operator String() + ", new Vector2" + transform.elements[2].operator String() + ")"; + r_iarg.default_argument = "new Transform2D(new Vector2" + transform.columns[0].operator String() + ", new Vector2" + transform.columns[1].operator String() + ", new Vector2" + transform.columns[2].operator String() + ")"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; @@ -3138,6 +3283,15 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; + case Variant::PROJECTION: { + Projection transform = p_val.operator Projection(); + if (transform == Projection()) { + r_iarg.default_argument = "Projection.Identity"; + } else { + r_iarg.default_argument = "new Projection(new Vector4" + transform.matrix[0].operator String() + ", new Vector4" + transform.matrix[1].operator String() + ", new Vector4" + transform.matrix[2].operator String() + ", new Vector4" + transform.matrix[3].operator String() + ")"; + } + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + } break; case Variant::BASIS: { Basis basis = p_val.operator Basis(); if (basis == Basis()) { @@ -3473,13 +3627,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.name = "Array"; itype.cname = itype.name; itype.proxy_name = itype.name; + itype.type_parameter_count = 1; itype.c_out = "\treturn memnew(Array(%1));\n"; itype.c_type = itype.name; itype.c_type_in = itype.c_type + "*"; itype.c_type_out = itype.c_type + "*"; itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()"; - itype.cs_out = "return new " + itype.cs_type + "(%0(%1));"; + itype.cs_out = "return new %2(%0(%1));"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; builtin_types.insert(itype.cname, itype); @@ -3489,13 +3644,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.name = "Dictionary"; itype.cname = itype.name; itype.proxy_name = itype.name; + itype.type_parameter_count = 2; itype.c_out = "\treturn memnew(Dictionary(%1));\n"; itype.c_type = itype.name; itype.c_type_in = itype.c_type + "*"; itype.c_type_out = itype.c_type + "*"; itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()"; - itype.cs_out = "return new " + itype.cs_type + "(%0(%1));"; + itype.cs_out = "return new %2(%0(%1));"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; builtin_types.insert(itype.cname, itype); @@ -3518,11 +3674,11 @@ void BindingsGenerator::_populate_global_constants() { int global_constants_count = CoreConstants::get_global_constant_count(); if (global_constants_count > 0) { - Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); + HashMap<String, DocData::ClassDoc>::Iterator match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope"); CRASH_COND_MSG(!match, "Could not find '@GlobalScope' in DocData."); - const DocData::ClassDoc &global_scope_doc = match->value(); + const DocData::ClassDoc &global_scope_doc = match->value; for (int i = 0; i < global_constants_count; i++) { String constant_name = CoreConstants::get_global_constant_name(i); @@ -3537,7 +3693,7 @@ void BindingsGenerator::_populate_global_constants() { } } - int constant_value = CoreConstants::get_global_constant_value(i); + int64_t constant_value = CoreConstants::get_global_constant_value(i); StringName enum_name = CoreConstants::get_global_constant_enum(i); ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), constant_value); @@ -3545,6 +3701,7 @@ void BindingsGenerator::_populate_global_constants() { if (enum_name != StringName()) { EnumInterface ienum(enum_name); + // TODO: ienum.is_flags is always false for core constants since they don't seem to support bitfield enums List<EnumInterface>::Element *enum_match = global_enums.find(ienum); if (enum_match) { enum_match->get().constants.push_back(iconstant); @@ -3637,8 +3794,8 @@ void BindingsGenerator::_initialize() { core_custom_icalls.clear(); editor_custom_icalls.clear(); - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { - _generate_method_icalls(E.get()); + for (const KeyValue<StringName, TypeInterface> &E : obj_types) { + _generate_method_icalls(E.value); } initialized = true; diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 5460f018f0..ee170e4558 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -45,12 +45,12 @@ class BindingsGenerator { struct ConstantInterface { String name; String proxy_name; - int value = 0; + int64_t value = 0; const DocData::ConstantDoc *const_doc; ConstantInterface() {} - ConstantInterface(const String &p_name, const String &p_proxy_name, int p_value) { + ConstantInterface(const String &p_name, const String &p_proxy_name, int64_t p_value) { name = p_name; proxy_name = p_proxy_name; value = p_value; @@ -60,6 +60,7 @@ class BindingsGenerator { struct EnumInterface { StringName cname; List<ConstantInterface> constants; + bool is_flags = false; _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const { return p_ienum.cname == cname; @@ -87,6 +88,8 @@ class BindingsGenerator { StringName cname; bool is_enum = false; + List<TypeReference> generic_type_parameters; + TypeReference() {} TypeReference(const StringName &p_cname) : @@ -137,6 +140,11 @@ class BindingsGenerator { bool is_vararg = false; /** + * Determines if the method is static. + */ + bool is_static = false; + + /** * Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing, * but can be overridden by the user to add custom functionality. * e.g.: _ready, _process, etc. @@ -201,6 +209,8 @@ class BindingsGenerator { String name; StringName cname; + int type_parameter_count; + /** * Identifier name of the base class. */ @@ -528,24 +538,24 @@ class BindingsGenerator { bool log_print_enabled = true; bool initialized = false; - OrderedHashMap<StringName, TypeInterface> obj_types; + HashMap<StringName, TypeInterface> obj_types; - Map<StringName, TypeInterface> placeholder_types; - Map<StringName, TypeInterface> builtin_types; - Map<StringName, TypeInterface> enum_types; + HashMap<StringName, TypeInterface> placeholder_types; + HashMap<StringName, TypeInterface> builtin_types; + HashMap<StringName, TypeInterface> enum_types; List<EnumInterface> global_enums; List<ConstantInterface> global_constants; List<InternalCall> method_icalls; - Map<const MethodInterface *, const InternalCall *> method_icalls_map; + HashMap<const MethodInterface *, const InternalCall *> method_icalls_map; List<const InternalCall *> generated_icall_funcs; List<InternalCall> core_custom_icalls; List<InternalCall> editor_custom_icalls; - Map<StringName, List<StringName>> blacklisted_methods; + HashMap<StringName, List<StringName>> blacklisted_methods; void _initialize_blacklisted_methods(); @@ -580,6 +590,9 @@ class BindingsGenerator { StringName type_Vector2 = StaticCString::create("Vector2"); StringName type_Rect2 = StaticCString::create("Rect2"); StringName type_Vector3 = StaticCString::create("Vector3"); + StringName type_Vector3i = StaticCString::create("Vector3i"); + StringName type_Vector4 = StaticCString::create("Vector4"); + StringName type_Vector4i = StaticCString::create("Vector4i"); // Object not included as it must be checked for all derived classes static constexpr int nullable_types_count = 17; @@ -658,6 +671,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); @@ -666,6 +687,8 @@ class BindingsGenerator { const TypeInterface *_get_type_or_null(const TypeReference &p_typeref); const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref); + const String _get_generic_type_parameters(const TypeInterface &p_itype, const List<TypeReference> &p_generic_type_parameters); + StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta); StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta); diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index 095fd831a3..a1789412f4 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -120,11 +120,11 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr } break; case CompletionKind::NODE_PATHS: { { - // AutoLoads - OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + // Autoloads. + HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (OrderedHashMap<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))); } } @@ -144,7 +144,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr } } break; case CompletionKind::SCENE_PATHS: { - DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); List<String> directories; directories.push_back(dir_access->get_current_dir()); diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index f7f710f3f1..5e4fe90553 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -47,7 +47,7 @@ #include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../mono_gd/gd_mono_marshal.h" -#include "../utils/osx_utils.h" +#include "../utils/macos_utils.h" #include "code_completion.h" #include "godotsharp_export.h" @@ -188,8 +188,8 @@ MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_c return GDMonoMarshal::mono_string_from_godot(error_str); } -MonoString *godot_icall_Internal_FullTemplatesDir() { - String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); +MonoString *godot_icall_Internal_FullExportTemplatesDir() { + String full_templates_dir = EditorSettings::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG); return GDMonoMarshal::mono_string_from_godot(full_templates_dir); } @@ -198,10 +198,10 @@ MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) { return GDMonoMarshal::mono_string_from_godot(path.simplify_path()); } -MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) { -#ifdef OSX_ENABLED +MonoBoolean godot_icall_Internal_IsMacOSAppBundleInstalled(MonoString *p_bundle_id) { +#ifdef MACOS_ENABLED String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id); - return (MonoBoolean)osx_is_app_bundle_installed(bundle_id); + return (MonoBoolean)macos_is_app_bundle_installed(bundle_id); #else (void)p_bundle_id; // UNUSED return (MonoBoolean) false; @@ -364,9 +364,9 @@ void register_editor_internal_calls() { // Internals GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullExportTemplatesDir", godot_icall_Internal_FullExportTemplatesDir); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsMacOSAppBundleInstalled", godot_icall_Internal_IsMacOSAppBundleInstalled); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration); diff --git a/modules/mono/editor/editor_internal_calls.h b/modules/mono/editor/editor_internal_calls.h index a899634d57..8262ac211a 100644 --- a/modules/mono/editor/editor_internal_calls.h +++ b/modules/mono/editor/editor_internal_calls.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_INTERNAL_CALL_H -#define EDITOR_INTERNAL_CALL_H +#ifndef EDITOR_INTERNAL_CALLS_H +#define EDITOR_INTERNAL_CALLS_H void register_editor_internal_calls(); -#endif // EDITOR_INTERNAL_CALL_H +#endif // EDITOR_INTERNAL_CALLS_H diff --git a/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs index b0ded3133f..2ca81ab7cd 100644 --- a/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs +++ b/modules/mono/editor/script_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/script_templates/CharacterBody3D/basic_movement.cs index d8c2f67ac8..a6935fe497 100644 --- a/modules/mono/editor_templates/CharacterBody3D/basic_movement.cs +++ b/modules/mono/editor/script_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/editor_templates/EditorPlugin/plugin.cs b/modules/mono/editor/script_templates/EditorPlugin/plugin.cs index 6e6a799be6..eba5fd12a4 100644 --- a/modules/mono/editor_templates/EditorPlugin/plugin.cs +++ b/modules/mono/editor/script_templates/EditorPlugin/plugin.cs @@ -1,4 +1,5 @@ // meta-description: Basic plugin template + #if TOOLS using _BINDINGS_NAMESPACE_; using System; diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs new file mode 100644 index 0000000000..9e1b7ef580 --- /dev/null +++ b/modules/mono/editor/script_templates/EditorScenePostImport/basic_import_script.cs @@ -0,0 +1,16 @@ +// meta-description: Basic import script template + +#if TOOLS +using _BINDINGS_NAMESPACE_; +using System; + +[Tool] +public partial class _CLASS_ : _BASE_ +{ + public override Godot.Object _PostImport(Node scene) + { + // Modify the contents of the scene upon import. + return scene; // Return the modified root node when you're done. + } +} +#endif diff --git a/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs new file mode 100644 index 0000000000..bf2c9434e4 --- /dev/null +++ b/modules/mono/editor/script_templates/EditorScenePostImport/no_comments.cs @@ -0,0 +1,15 @@ +// meta-description: Basic import script template (no comments) + +#if TOOLS +using _BINDINGS_NAMESPACE_; +using System; + +[Tool] +public partial class _CLASS_ : _BASE_ +{ + public override Godot.Object _PostImport(Node scene) + { + return scene; + } +} +#endif diff --git a/modules/mono/editor_templates/EditorScript/basic_editor_script.cs b/modules/mono/editor/script_templates/EditorScript/basic_editor_script.cs index 2088822890..1b347edc1c 100644 --- a/modules/mono/editor_templates/EditorScript/basic_editor_script.cs +++ b/modules/mono/editor/script_templates/EditorScript/basic_editor_script.cs @@ -1,4 +1,5 @@ // meta-description: Basic editor script template + #if TOOLS using _BINDINGS_NAMESPACE_; using System; @@ -6,9 +7,9 @@ using System; [Tool] public partial class _CLASS_ : _BASE_ { + // Called when the script is executed (using File -> Run in Script Editor). public override void _Run() { - // Called when the script is executed (using File -> Run in Script Editor). } } #endif diff --git a/modules/mono/editor_templates/Node/default.cs b/modules/mono/editor/script_templates/Node/default.cs index 73d69dd993..4c86d1666f 100644 --- a/modules/mono/editor_templates/Node/default.cs +++ b/modules/mono/editor/script_templates/Node/default.cs @@ -8,12 +8,10 @@ public partial class _CLASS_ : _BASE_ // Called when the node enters the scene tree for the first time. public override void _Ready() { - } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(float delta) { - } } diff --git a/modules/mono/editor_templates/Object/empty.cs b/modules/mono/editor/script_templates/Object/empty.cs index e5bee64fe1..34526d514f 100644 --- a/modules/mono/editor_templates/Object/empty.cs +++ b/modules/mono/editor/script_templates/Object/empty.cs @@ -5,5 +5,4 @@ using System; public partial class _CLASS_ : _BASE_ { - } diff --git a/modules/mono/editor_templates/SCsub b/modules/mono/editor/script_templates/SCsub index 39f6cb5c01..39f6cb5c01 100644 --- a/modules/mono/editor_templates/SCsub +++ b/modules/mono/editor/script_templates/SCsub diff --git a/modules/mono/editor_templates/VisualShaderNodeCustom/basic.cs b/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs index a1b93e7daa..a1b93e7daa 100644 --- a/modules/mono/editor_templates/VisualShaderNodeCustom/basic.cs +++ b/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs index ef135da51a..2febf37f05 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs @@ -2,17 +2,27 @@ using System; namespace Godot { + /// <summary> + /// An attribute that determines if an assembly has scripts. If so, what types of scripts the assembly has. + /// </summary> [AttributeUsage(AttributeTargets.Assembly)] public class AssemblyHasScriptsAttribute : Attribute { private readonly bool requiresLookup; private readonly System.Type[] scriptTypes; + /// <summary> + /// Constructs a new AssemblyHasScriptsAttribute instance. + /// </summary> public AssemblyHasScriptsAttribute() { requiresLookup = true; } + /// <summary> + /// Constructs a new AssemblyHasScriptsAttribute instance. + /// </summary> + /// <param name="scriptTypes">The specified type(s) of scripts.</param> public AssemblyHasScriptsAttribute(System.Type[] scriptTypes) { requiresLookup = false; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs index e93bc89811..0b00878e8c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/DisableGodotGeneratorsAttribute.cs @@ -2,6 +2,9 @@ using System; namespace Godot { + /// <summary> + /// An attribute that disables Godot Generators. + /// </summary> [AttributeUsage(AttributeTargets.Class)] public class DisableGodotGeneratorsAttribute : Attribute { } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs index 6adf044886..46eb128d37 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs @@ -2,12 +2,20 @@ using System; namespace Godot { + /// <summary> + /// An attribute used to export objects. + /// </summary> [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public class ExportAttribute : Attribute { private PropertyHint hint; private string hintString; + /// <summary> + /// Constructs a new ExportAttribute Instance. + /// </summary> + /// <param name="hint">A hint to the exported object.</param> + /// <param name="hintString">A string representing the exported object.</param> public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "") { this.hint = hint; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs index 55848769d5..8d4ff0fdb7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/GodotMethodAttribute.cs @@ -2,6 +2,9 @@ using System; namespace Godot { + /// <summary> + /// An attribute for a method. + /// </summary> [AttributeUsage(AttributeTargets.Method)] internal class GodotMethodAttribute : Attribute { @@ -9,6 +12,10 @@ namespace Godot public string MethodName { get { return methodName; } } + /// <summary> + /// Constructs a new GodotMethodAttribute instance. + /// </summary> + /// <param name="methodName">The name of the method.</param> public GodotMethodAttribute(string methodName) { this.methodName = methodName; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs new file mode 100644 index 0000000000..0a1c8322d7 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs @@ -0,0 +1,43 @@ +using System; + +namespace Godot +{ + /// <summary> + /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>, + /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers). + /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking + /// (and RPCs). + /// </summary> + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class RPCAttribute : Attribute + { + /// <summary> + /// RPC mode for the annotated method. + /// </summary> + public RPCMode Mode { get; } = RPCMode.Disabled; + + /// <summary> + /// If the method will also be called locally; otherwise, it is only called remotely. + /// </summary> + public bool CallLocal { get; set; } = false; + + /// <summary> + /// Transfer mode for the annotated method. + /// </summary> + public TransferMode TransferMode { get; set; } = TransferMode.Reliable; + + /// <summary> + /// Transfer channel for the annotated mode. + /// </summary> + public int TransferChannel { get; set; } = 0; + + /// <summary> + /// Constructs a <see cref="RPCAttribute"/> instance. + /// </summary> + /// <param name="mode">The RPC mode to use.</param> + public RPCAttribute(RPCMode mode = RPCMode.Authority) + { + Mode = mode; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs deleted file mode 100644 index b8b9bc660c..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Godot -{ - [AttributeUsage(AttributeTargets.Method)] - public class AnyPeerAttribute : Attribute { } - - [AttributeUsage(AttributeTargets.Method)] - public class AuthorityAttribute : Attribute { } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs index 12eb1035c3..3ebb6612de 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs @@ -2,11 +2,18 @@ using System; namespace Godot { + /// <summary> + /// An attribute that contains the path to the object's script. + /// </summary> [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class ScriptPathAttribute : Attribute { private string path; + /// <summary> + /// Constructs a new ScriptPathAttribute instance. + /// </summary> + /// <param name="path">The file path to the script</param> public ScriptPathAttribute(string path) { this.path = path; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 656796c5c7..37bdc42c2d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -526,10 +526,10 @@ namespace Godot /// <summary> /// Introduce an additional rotation around the given <paramref name="axis"/> - /// by <paramref name="phi"/> (in radians). The axis must be a normalized vector. + /// by <paramref name="angle"/> (in radians). The axis must be a normalized vector. /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> - /// <param name="phi">The angle to rotate, in radians.</param> + /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated basis matrix.</returns> public Basis Rotated(Vector3 axis, real_t phi) { @@ -770,10 +770,10 @@ namespace Godot /// <summary> /// Constructs a pure rotation basis matrix, rotated around the given <paramref name="axis"/> - /// by <paramref name="phi"/> (in radians). The axis must be a normalized vector. + /// by <paramref name="angle"/> (in radians). The axis must be a normalized vector. /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> - /// <param name="phi">The angle to rotate, in radians.</param> + /// <param name="angle">The angle to rotate, in radians.</param> public Basis(Vector3 axis, real_t phi) { Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs index 072e0f20ff..6475237002 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs @@ -4,9 +4,16 @@ namespace Godot { public static class Dispatcher { + /// <summary> + /// Implements an external instance of GodotTaskScheduler. + /// </summary> + /// <returns>A GodotTaskScheduler instance.</returns> [MethodImpl(MethodImplOptions.InternalCall)] private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler(); + /// <summary> + /// Initializes the synchronization context as the context of the GodotTaskScheduler. + /// </summary> public static GodotSynchronizationContext SynchronizationContext => godot_icall_DefaultGodotTaskScheduler().Context; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 74aa38386f..bb076a9633 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -239,6 +239,27 @@ namespace Godot } /// <summary> + /// Converts one or more arguments of any type to string in the best way possible and prints them to the console. The following BBCode tags are supported: b, i, u, s, indent, code, url, center, right, color, bgcolor, fgcolor. Color tags only support named colors such as [code]red[/code], [i]not[/i] hexadecimal color codes. Unsupported tags will be left as-is in standard output. + /// When printing to standard output, the supported subset of BBCode is converted to ANSI escape codes for the terminal emulator to display. Displaying ANSI escape codes is currently only supported on Linux and macOS. Support for ANSI escape codes may vary across terminal emulators, especially for italic and strikethrough. + /// + /// Note: Consider using <see cref="PushError(string)"/> and <see cref="PushWarning(string)"/> + /// to print error and warning messages instead of <see cref="Print(object[])"/> or <see cref="PrintRich(object[])"/>. + /// This distinguishes them from print messages used for debugging purposes, + /// while also displaying a stack trace when an error or warning is printed. + /// </summary> + /// <example> + /// <code> + /// GD.PrintRich("[b]Hello world![/b]"); // Prints out "Hello world!" in bold. + /// </code> + /// </example> + /// <param name="what">Arguments that will be printed.</param> + /// </summary> + public static void PrintRich(params object[] what) + { + godot_icall_GD_print_rich(GetPrintParams(what)); + } + + /// <summary> /// Prints the current stack trace information to the console. /// </summary> public static void PrintStack() @@ -562,6 +583,9 @@ namespace Godot internal static extern void godot_icall_GD_print(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void godot_icall_GD_print_rich(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void godot_icall_GD_printerr(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs index c01c926e82..1b599beab5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotSynchronizationContext.cs @@ -14,6 +14,9 @@ namespace Godot _queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state)); } + /// <summary> + /// Calls the Key method on each workItem object in the _queue to activate their callbacks. + /// </summary> public void ExecutePendingContinuations() { while (_queue.TryTake(out var workItem)) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs index 8eaeea50dc..408bed71b2 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTaskScheduler.cs @@ -6,11 +6,25 @@ using System.Threading.Tasks; namespace Godot { + /// <summary> + /// GodotTaskScheduler contains a linked list of tasks to perform as a queue. Methods + /// within the class are used to control the queue and perform the contained tasks. + /// </summary> public class GodotTaskScheduler : TaskScheduler { + /// <summary> + /// The current synchronization context. + /// </summary> internal GodotSynchronizationContext Context { get; } + + /// <summary> + /// The queue of tasks for the task scheduler. + /// </summary> private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); + /// <summary> + /// Constructs a new GodotTaskScheduler instance. + /// </summary> public GodotTaskScheduler() { Context = new GodotSynchronizationContext(); @@ -53,12 +67,19 @@ namespace Godot } } + /// <summary> + /// Executes all queued tasks and pending tasks from the current context. + /// </summary> public void Activate() { ExecuteQueuedTasks(); Context.ExecutePendingContinuations(); } + /// <summary> + /// Loops through and attempts to execute each task in _tasks. + /// </summary> + /// <exception cref="InvalidOperationException"></exception> private void ExecuteQueuedTasks() { while (true) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs index 0397957d00..e747e03c1e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaitable.cs @@ -1,10 +1,17 @@ namespace Godot { + /// <summary> + /// An interface that requires a GetAwaiter() method to get a reference to the Awaiter. + /// </summary> public interface IAwaitable { IAwaiter GetAwaiter(); } + /// <summary> + /// A templated interface that requires a GetAwaiter() method to get a reference to the Awaiter. + /// </summary> + /// <typeparam name="TResult">A reference to the result to be passed out.</typeparam> public interface IAwaitable<out TResult> { IAwaiter<TResult> GetAwaiter(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs index d3be9d781c..dec225eb29 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/IAwaiter.cs @@ -2,6 +2,9 @@ using System.Runtime.CompilerServices; namespace Godot { + /// <summary> + /// An interface that requires a boolean for completion status and a method that gets the result of completion. + /// </summary> public interface IAwaiter : INotifyCompletion { bool IsCompleted { get; } @@ -9,6 +12,10 @@ namespace Godot void GetResult(); } + /// <summary> + /// A templated interface that requires a boolean for completion status and a method that gets the result of completion and returns it. + /// </summary> + /// <typeparam name="TResult">A reference to the result to be passed out.</typeparam> public interface IAwaiter<out TResult> : INotifyCompletion { bool IsCompleted { get; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs index c3fa2f3e82..90b4d1b8d3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs @@ -1,5 +1,8 @@ namespace Godot { + /// <summary> + /// An interface that requires methods for before and after serialization. + /// </summary> public interface ISerializationListener { void OnBeforeSerialize(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs index ee4d0eed08..50ae2eb112 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs @@ -80,6 +80,11 @@ namespace Godot private static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>); /// <summary> + /// Returns <see langword="true"/> if the <see cref="FlagsAttribute"/> is applied to the given type. + /// </summary> + private static bool TypeHasFlagsAttribute(Type type) => type.IsDefined(typeof(FlagsAttribute), false); + + /// <summary> /// Returns the generic type definition of <paramref name="type"/>. /// </summary> /// <exception cref="InvalidOperationException"> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index ce213da6a7..36b7d0f80f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -198,6 +198,28 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by + /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="start">The start value for the interpolation.</param> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination value for the interpolation.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Converts an angle expressed in degrees to radians. /// </summary> /// <param name="deg">An angle expressed in degrees.</param> @@ -276,10 +298,14 @@ namespace Godot /// Returns a normalized value considering the given range. /// This is the opposite of <see cref="Lerp(real_t, real_t, real_t)"/>. /// </summary> - /// <param name="from">The interpolated value.</param> + /// <param name="from">The start value for interpolation.</param> /// <param name="to">The destination value for interpolation.</param> - /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> - /// <returns>The resulting value of the inverse interpolation.</returns> + /// <param name="weight">The interpolated value.</param> + /// <returns> + /// The resulting value of the inverse interpolation. + /// The returned value will be between 0.0 and 1.0 if <paramref name="weight"/> is + /// between <paramref name="from"/> and <paramref name="to"/> (inclusive). + /// </returns> public static real_t InverseLerp(real_t from, real_t to, real_t weight) { return (weight - from) / (to - from); @@ -516,6 +542,21 @@ namespace Godot } /// <summary> + /// Maps a <paramref name="value"/> from [<paramref name="inFrom"/>, <paramref name="inTo"/>] + /// to [<paramref name="outFrom"/>, <paramref name="outTo"/>]. + /// </summary> + /// <param name="value">The value to map.</param> + /// <param name="inFrom">The start value for the input interpolation.</param> + /// <param name="inTo">The destination value for the input interpolation.</param> + /// <param name="outFrom">The start value for the output interpolation.</param> + /// <param name="outTo">The destination value for the output interpolation.</param> + /// <returns>The resulting mapped value mapped.</returns> + public static real_t RangeLerp(real_t value, real_t inFrom, real_t inTo, real_t outFrom, real_t outTo) + { + return Lerp(outFrom, outTo, InverseLerp(inFrom, inTo, value)); + } + + /// <summary> /// Rounds <paramref name="s"/> to the nearest whole number, /// with halfway cases rounded towards the nearest multiple of two. /// </summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index 40fb5f8788..9ae01016cb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -170,6 +170,21 @@ namespace Godot } /// <summary> + /// Returns all names concatenated with a slash character (<c>/</c>). + /// </summary> + /// <example> + /// <code> + /// var nodepath = new NodePath("Path2D/PathFollow2D/Sprite2D:texture:load_path"); + /// GD.Print(nodepath.GetConcatenatedNames()); // Path2D/PathFollow2D/Sprite2D + /// </code> + /// </example> + /// <returns>The names concatenated with <c>/</c>.</returns> + public string GetConcatenatedNames() + { + return godot_icall_NodePath_get_concatenated_names(GetPtr(this)); + } + + /// <summary> /// Returns all subnames concatenated with a colon character (<c>:</c>) /// as separator, i.e. the right side of the first colon in a node path. /// </summary> @@ -269,6 +284,9 @@ namespace Godot private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string godot_icall_NodePath_get_concatenated_names(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 63af1c5892..fd97a71e47 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -118,15 +118,15 @@ namespace Godot /// <summary> /// Returns <see langword="true"/> if point is inside the plane. - /// Comparison uses a custom minimum epsilon threshold. + /// Comparison uses a custom minimum tolerance threshold. /// </summary> /// <param name="point">The point to check.</param> - /// <param name="epsilon">The tolerance threshold.</param> + /// <param name="tolerance">The tolerance threshold.</param> /// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns> - public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon) + public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon) { real_t dist = _normal.Dot(point) - D; - return Mathf.Abs(dist) <= epsilon; + return Mathf.Abs(dist) <= tolerance; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index 8e253388bf..89947899cb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -297,9 +297,9 @@ namespace Godot } /// <summary> - /// Rotates the transform by <paramref name="phi"/> (in radians), using matrix multiplication. + /// Rotates the transform by <paramref name="angle"/> (in radians), using matrix multiplication. /// </summary> - /// <param name="phi">The angle to rotate, in radians.</param> + /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> public Transform2D Rotated(real_t phi) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 5d9aabdd2f..7b211b6577 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -186,11 +186,11 @@ namespace Godot } /// <summary> - /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="phi"/> (in radians), + /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians), /// using matrix multiplication. The axis must be a normalized vector. /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> - /// <param name="phi">The angle to rotate, in radians.</param> + /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> public Transform3D Rotated(Vector3 axis, real_t phi) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 8679f28132..7bdbe1c28b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -81,6 +81,15 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y) + { + x = this.x; + y = this.y; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); @@ -212,6 +221,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -461,9 +491,9 @@ namespace Godot } /// <summary> - /// Rotates this vector by <paramref name="phi"/> radians. + /// Rotates this vector by <paramref name="angle"/> radians. /// </summary> - /// <param name="phi">The angle to rotate by, in radians.</param> + /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> public Vector2 Rotated(real_t phi) { @@ -502,8 +532,9 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. /// - /// This method also handles interpolating the lengths if the input vectors have different lengths. - /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. + /// This method also handles interpolating the lengths if the input vectors + /// have different lengths. For the special case of one or both input vectors + /// having zero length, this method behaves like <see cref="Lerp"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> @@ -512,9 +543,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 9b51de5c8c..b61954a84c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -82,6 +82,15 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y) + { + x = this.x; + y = this.y; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> @@ -452,7 +461,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector2i"/> + /// Divides each component of the <see cref="Vector2i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 1e60fb9523..480165d44a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -96,6 +96,16 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y, out real_t z) + { + x = this.x; + y = this.y; + z = this.z; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); @@ -204,6 +214,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -478,11 +509,11 @@ namespace Godot } /// <summary> - /// Rotates this vector around a given <paramref name="axis"/> vector by <paramref name="phi"/> radians. + /// Rotates this vector around a given <paramref name="axis"/> vector by <paramref name="angle"/> (in radians). /// The <paramref name="axis"/> vector must be a normalized vector. /// </summary> /// <param name="axis">The vector to rotate around. Must be normalized.</param> - /// <param name="phi">The angle to rotate by, in radians.</param> + /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> public Vector3 Rotated(Vector3 axis, real_t phi) { @@ -541,8 +572,9 @@ namespace Godot /// Returns the result of the spherical linear interpolation between /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. /// - /// This method also handles interpolating the lengths if the input vectors have different lengths. - /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp]. + /// This method also handles interpolating the lengths if the input vectors + /// have different lengths. For the special case of one or both input vectors + /// having zero length, this method behaves like <see cref="Lerp"/>. /// </summary> /// <param name="to">The destination vector for interpolation.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> @@ -551,9 +583,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index eb06d2b87e..0d4894f206 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -97,6 +97,16 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y, out int z) + { + x = this.x; + y = this.y; + z = this.z; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> @@ -439,7 +449,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector3i"/> + /// Divides each component of the <see cref="Vector3i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 1fcfe74c86..e59f45bbf6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -18,7 +18,7 @@ <Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" /> <Compile Include="Core\Attributes\ExportAttribute.cs" /> <Compile Include="Core\Attributes\GodotMethodAttribute.cs" /> - <Compile Include="Core\Attributes\RPCAttributes.cs" /> + <Compile Include="Core\Attributes\RPCAttribute.cs" /> <Compile Include="Core\Attributes\ScriptPathAttribute.cs" /> <Compile Include="Core\Attributes\SignalAttribute.cs" /> <Compile Include="Core\Attributes\ToolAttribute.cs" /> diff --git a/modules/mono/glue/arguments_vector.h b/modules/mono/glue/arguments_vector.h index 7c991d87a4..4405809887 100644 --- a/modules/mono/glue/arguments_vector.h +++ b/modules/mono/glue/arguments_vector.h @@ -37,7 +37,7 @@ template <typename T, int POOL_SIZE = 5> struct ArgumentsVector { private: T pool[POOL_SIZE]; - T *_ptr; + T *_ptr = nullptr; int size; ArgumentsVector() = delete; diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index 8e7b125ed5..7b9dbc87cf 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -68,7 +68,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { void *data = CSharpLanguage::get_existing_instance_binding(p_ptr); if (data) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited) { MonoGCHandleData &gchandle = script_binding.gchandle; if (!gchandle.is_released()) { @@ -115,7 +115,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole void *data = CSharpLanguage::get_existing_instance_binding(rc); if (data) { - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited) { MonoGCHandleData &gchandle = script_binding.gchandle; if (!gchandle.is_released()) { @@ -148,7 +148,7 @@ MonoObject *godot_icall_Object_weakref(Object *p_ptr) { RefCounted *rc = Object::cast_to<RefCounted>(p_ptr); if (rc) { - REF r = rc; + Ref<RefCounted> r = rc; if (!r.is_valid()) { return nullptr; } @@ -199,7 +199,7 @@ MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoStrin } Callable::CallError error; - Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error); + Variant result = p_ptr->callp(StringName(name), args.ptr(), argc, error); *r_result = GDMonoMarshal::variant_to_mono_object(result); diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index 8aead217cf..8b1c2b729e 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -90,6 +90,27 @@ void godot_icall_GD_print(MonoArray *p_what) { print_line(str); } +void godot_icall_GD_print_rich(MonoArray *p_what) { + String str; + int length = mono_array_length(p_what); + + for (int i = 0; i < length; i++) { + MonoObject *elem = mono_array_get(p_what, MonoObject *, i); + + MonoException *exc = nullptr; + String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); + + if (exc) { + GDMonoUtils::set_pending_exception(exc); + return; + } + + str += elem_str; + } + + print_line_rich(str); +} + void godot_icall_GD_printerr(MonoArray *p_what) { String str; int length = mono_array_length(p_what); @@ -300,6 +321,7 @@ void godot_register_gd_icalls() { GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pusherror", godot_icall_GD_pusherror); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pushwarning", godot_icall_GD_pushwarning); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print", godot_icall_GD_print); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print_rich", godot_icall_GD_print_rich); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printerr", godot_icall_GD_printerr); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints); diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 9638b23410..f9ad1a9893 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GLUE_HEADER_H +#define GLUE_HEADER_H + #ifdef MONO_GLUE_ENABLED #include "../mono_gd/gd_mono_marshal.h" @@ -84,3 +87,5 @@ void godot_register_glue_header_icalls() { #include "arguments_vector.h" #endif // MONO_GLUE_ENABLED + +#endif // GLUE_HEADER_H diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp index 0ea9814b1a..16e1509eb0 100644 --- a/modules/mono/glue/nodepath_glue.cpp +++ b/modules/mono/glue/nodepath_glue.cpp @@ -68,6 +68,10 @@ MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx)); } +MonoString *godot_icall_NodePath_get_concatenated_names(NodePath *p_ptr) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_names()); +} + MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames()); } @@ -85,6 +89,7 @@ void godot_register_nodepath_icalls() { GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path); + GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count); diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 7c2cb2e260..f17b24e399 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -76,7 +76,7 @@ String _get_mono_user_dir() { exe_dir = exe_dir.plus_file("../../..").simplify_path(); } - DirAccessRef d = DirAccess::create_for_path(exe_dir); + Ref<DirAccess> d = DirAccess::create_for_path(exe_dir); if (d->file_exists("._sc_") || d->file_exists("_sc_")) { // contain yourself @@ -184,7 +184,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_editor_tools_dir)) { data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools"); } @@ -222,7 +222,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_mono_root_dir)) { data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib"); diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp index 8ed21c323f..c159bb9eea 100644 --- a/modules/mono/managed_callable.cpp +++ b/modules/mono/managed_callable.cpp @@ -36,7 +36,7 @@ #ifdef GD_MONO_HOT_RELOAD SelfList<ManagedCallable>::List ManagedCallable::instances; -Map<ManagedCallable *, Array> ManagedCallable::instances_pending_reload; +RBMap<ManagedCallable *, Array> ManagedCallable::instances_pending_reload; Mutex ManagedCallable::instances_mutex; #endif @@ -66,9 +66,8 @@ bool ManagedCallable::compare_less(const CallableCustom *p_a, const CallableCust } uint32_t ManagedCallable::hash() const { - // hmm uint32_t hash = delegate_invoke->get_name().hash(); - return hash_djb2_one_64(delegate_handle.handle, hash); + return hash_murmur3_one_64(delegate_handle.handle, hash); } String ManagedCallable::get_as_text() const { diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h index ea7231f43b..11bee6cf60 100644 --- a/modules/mono/managed_callable.h +++ b/modules/mono/managed_callable.h @@ -43,12 +43,12 @@ class ManagedCallable : public CallableCustom { friend class CSharpLanguage; MonoGCHandleData delegate_handle; - GDMonoMethod *delegate_invoke; + GDMonoMethod *delegate_invoke = nullptr; #ifdef GD_MONO_HOT_RELOAD SelfList<ManagedCallable> self_instance = this; static SelfList<ManagedCallable>::List instances; - static Map<ManagedCallable *, Array> instances_pending_reload; + static RBMap<ManagedCallable *, Array> instances_pending_reload; static Mutex instances_mutex; #endif diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index ab9e508c99..e2aff1d19d 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CSHARP_GC_HANDLE_H -#define CSHARP_GC_HANDLE_H +#ifndef MONO_GC_HANDLE_H +#define MONO_GC_HANDLE_H #include <mono/jit/jit.h> @@ -104,4 +104,4 @@ public: ~MonoGCHandleRef() { release(); } }; -#endif // CSHARP_GC_HANDLE_H +#endif // MONO_GC_HANDLE_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 4cd4772d2c..d3d3bb2bef 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -55,7 +55,7 @@ #ifdef ANDROID_ENABLED #include "android_mono_config.h" #include "support/android_support.h" -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) #include "support/ios_support.h" #endif @@ -188,7 +188,7 @@ MonoDomain *gd_initialize_mono_runtime() { MonoDomain *gd_initialize_mono_runtime() { gd_mono_debug_init(); -#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED) +#if defined(IOS_ENABLED) || defined(ANDROID_ENABLED) // I don't know whether this actually matters or not const char *runtime_version = "mobile"; #else @@ -263,7 +263,7 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { r_config_dir = mono_reg_info.config_dir; } -#elif defined(OSX_ENABLED) +#elif defined(MACOS_ENABLED) const char *c_assembly_rootdir = mono_assembly_getrootdir(); const char *c_config_dir = mono_get_config_dir(); @@ -343,7 +343,7 @@ void GDMono::initialize() { #if defined(ANDROID_ENABLED) gdmono::android::support::initialize(); -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) gdmono::ios::support::initialize(); #endif @@ -643,9 +643,8 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const // Create destination directory if needed if (!DirAccess::exists(dst_dir)) { - DirAccess *da = DirAccess::create_for_path(dst_dir); + Ref<DirAccess> da = DirAccess::create_for_path(dst_dir); Error err = da->make_dir_recursive(dst_dir); - memdelete(da); if (err != OK) { ERR_PRINT("Failed to create destination directory for the API assemblies. Error: " + itos(err) + "."); @@ -653,7 +652,7 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const } } - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String xml_file = assembly_name + ".xml"; if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK) { @@ -1168,9 +1167,8 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - GDMonoAssembly *assembly = domain_assemblies.get(*k); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + GDMonoAssembly *assembly = E.value; if (assembly->get_image() == image) { GDMonoClass *klass = assembly->get_class(p_raw_class); if (klass) { @@ -1191,9 +1189,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName & int32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - GDMonoAssembly *assembly = domain_assemblies.get(*k); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + GDMonoAssembly *assembly = E.value; klass = assembly->get_class(p_namespace, p_name); if (klass) { return klass; @@ -1206,9 +1203,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName & void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id]; - const String *k = nullptr; - while ((k = domain_assemblies.next(k))) { - memdelete(domain_assemblies.get(*k)); + for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) { + memdelete(E.value); } assemblies.erase(p_domain_id); @@ -1299,13 +1295,11 @@ GDMono::~GDMono() { // Leave the rest to 'mono_jit_cleanup' #endif - const int32_t *k = nullptr; - while ((k = assemblies.next(k))) { - HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k); + for (const KeyValue<int32_t, HashMap<String, GDMonoAssembly *>> &E : assemblies) { + const HashMap<String, GDMonoAssembly *> &domain_assemblies = E.value; - const String *kk = nullptr; - while ((kk = domain_assemblies.next(kk))) { - memdelete(domain_assemblies.get(*kk)); + for (const KeyValue<String, GDMonoAssembly *> &F : domain_assemblies) { + memdelete(F.value); } } assemblies.clear(); diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index aab0b31c37..51fd0f8483 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -94,16 +94,16 @@ private: UnhandledExceptionPolicy unhandled_exception_policy; - MonoDomain *root_domain; - MonoDomain *scripts_domain; + MonoDomain *root_domain = nullptr; + MonoDomain *scripts_domain = nullptr; HashMap<int32_t, HashMap<String, GDMonoAssembly *>> assemblies; - GDMonoAssembly *corlib_assembly; - GDMonoAssembly *project_assembly; + GDMonoAssembly *corlib_assembly = nullptr; + GDMonoAssembly *project_assembly = nullptr; #ifdef TOOLS_ENABLED - GDMonoAssembly *tools_assembly; - GDMonoAssembly *tools_project_editor_assembly; + GDMonoAssembly *tools_assembly = nullptr; + GDMonoAssembly *tools_project_editor_assembly = nullptr; #endif LoadedApiAssembly core_api_assembly; @@ -150,7 +150,7 @@ private: void _init_godot_api_hashes(); void _init_exception_policy(); - GDMonoLog *gdmono_log; + GDMonoLog *gdmono_log = nullptr; #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) MonoRegInfo mono_reg_info; @@ -250,7 +250,7 @@ public: namespace gdmono { class ScopeDomain { - MonoDomain *prev_domain; + MonoDomain *prev_domain = nullptr; public: ScopeDomain(MonoDomain *p_domain) { @@ -270,7 +270,7 @@ public: }; class ScopeExitDomainUnload { - MonoDomain *domain; + MonoDomain *domain = nullptr; public: ScopeExitDomainUnload(MonoDomain *p_domain) : diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 3991b14612..42c6b6305f 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -412,10 +412,10 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { ERR_FAIL_NULL_V(image, nullptr); - Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class); + HashMap<MonoClass *, GDMonoClass *>::Iterator match = cached_raw.find(p_mono_class); if (match) { - return match->value(); + return match->value; } StringName namespace_name = String::utf8(mono_class_get_namespace(p_mono_class)); diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index b25d773be7..0a3ae6c4fe 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -36,7 +36,7 @@ #include "core/string/ustring.h" #include "core/templates/hash_map.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "gd_mono_utils.h" class GDMonoAssembly { @@ -68,8 +68,8 @@ class GDMonoAssembly { }; String name; - MonoImage *image; - MonoAssembly *assembly; + MonoImage *image = nullptr; + MonoAssembly *assembly = nullptr; bool attrs_fetched = false; MonoCustomAttrInfo *attributes = nullptr; @@ -79,7 +79,7 @@ class GDMonoAssembly { #endif HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes; - Map<MonoClass *, GDMonoClass *> cached_raw; + HashMap<MonoClass *, GDMonoClass *> cached_raw; static Vector<String> search_dirs; diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index d8fd244067..69d8c7edc9 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -108,9 +108,12 @@ void CachedData::clear_godot_api_cache() { class_Transform2D = nullptr; class_Vector3 = nullptr; class_Vector3i = nullptr; + class_Vector4 = nullptr; + class_Vector4i = nullptr; class_Basis = nullptr; class_Quaternion = nullptr; class_Transform3D = nullptr; + class_Projection = nullptr; class_AABB = nullptr; class_Color = nullptr; class_Plane = nullptr; @@ -140,8 +143,11 @@ void CachedData::clear_godot_api_cache() { field_ExportAttribute_hintString = nullptr; class_SignalAttribute = nullptr; class_ToolAttribute = nullptr; - class_AnyPeerAttribute = nullptr; - class_AuthorityAttribute = nullptr; + class_RPCAttribute = nullptr; + property_RPCAttribute_Mode = nullptr; + property_RPCAttribute_CallLocal = nullptr; + property_RPCAttribute_TransferMode = nullptr; + property_RPCAttribute_TransferChannel = nullptr; class_GodotMethodAttribute = nullptr; field_GodotMethodAttribute_methodName = nullptr; class_ScriptPathAttribute = nullptr; @@ -176,6 +182,7 @@ void CachedData::clear_godot_api_cache() { methodthunk_MarshalUtils_TypeIsGenericIEnumerable.nullify(); methodthunk_MarshalUtils_TypeIsGenericICollection.nullify(); methodthunk_MarshalUtils_TypeIsGenericIDictionary.nullify(); + methodthunk_MarshalUtils_TypeHasFlagsAttribute.nullify(); methodthunk_MarshalUtils_GetGenericTypeDefinition.nullify(); @@ -235,9 +242,12 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i)); + CACHE_CLASS_AND_CHECK(Vector4, GODOT_API_CLASS(Vector4)); + CACHE_CLASS_AND_CHECK(Vector4i, GODOT_API_CLASS(Vector4i)); CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion)); CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D)); + CACHE_CLASS_AND_CHECK(Projection, GODOT_API_CLASS(Projection)); CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); @@ -267,8 +277,11 @@ void update_godot_api_cache() { CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute)); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); - CACHE_CLASS_AND_CHECK(AnyPeerAttribute, GODOT_API_CLASS(AnyPeerAttribute)); - CACHE_CLASS_AND_CHECK(AuthorityAttribute, GODOT_API_CLASS(AuthorityAttribute)); + CACHE_CLASS_AND_CHECK(RPCAttribute, GODOT_API_CLASS(RPCAttribute)); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, Mode, CACHED_CLASS(RPCAttribute)->get_property("Mode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, CallLocal, CACHED_CLASS(RPCAttribute)->get_property("CallLocal")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferMode, CACHED_CLASS(RPCAttribute)->get_property("TransferMode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferChannel, CACHED_CLASS(RPCAttribute)->get_property("TransferChannel")); CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute)); CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName")); CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute)); @@ -300,6 +313,7 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIEnumerable, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIEnumerable", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericICollection, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericICollection", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIDictionary", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeHasFlagsAttribute, GODOT_API_CLASS(MarshalUtils)->get_method("TypeHasFlagsAttribute", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GetGenericTypeDefinition, GODOT_API_CLASS(MarshalUtils)->get_method("GetGenericTypeDefinition", 2)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 49f47b0a15..e9cc26899e 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -41,91 +41,97 @@ struct CachedData { // corlib classes // Let's use the no-namespace format for these too - GDMonoClass *class_MonoObject; // object - GDMonoClass *class_bool; // bool - GDMonoClass *class_int8_t; // sbyte - GDMonoClass *class_int16_t; // short - GDMonoClass *class_int32_t; // int - GDMonoClass *class_int64_t; // long - GDMonoClass *class_uint8_t; // byte - GDMonoClass *class_uint16_t; // ushort - GDMonoClass *class_uint32_t; // uint - GDMonoClass *class_uint64_t; // ulong - GDMonoClass *class_float; // float - GDMonoClass *class_double; // double - GDMonoClass *class_String; // string - GDMonoClass *class_IntPtr; // System.IntPtr - - GDMonoClass *class_System_Collections_IEnumerable; - GDMonoClass *class_System_Collections_ICollection; - GDMonoClass *class_System_Collections_IDictionary; + GDMonoClass *class_MonoObject = nullptr; // object + GDMonoClass *class_bool = nullptr; // bool + GDMonoClass *class_int8_t = nullptr; // sbyte + GDMonoClass *class_int16_t = nullptr; // short + GDMonoClass *class_int32_t = nullptr; // int + GDMonoClass *class_int64_t = nullptr; // long + GDMonoClass *class_uint8_t = nullptr; // byte + GDMonoClass *class_uint16_t = nullptr; // ushort + GDMonoClass *class_uint32_t = nullptr; // uint + GDMonoClass *class_uint64_t = nullptr; // ulong + GDMonoClass *class_float = nullptr; // float + GDMonoClass *class_double = nullptr; // double + GDMonoClass *class_String = nullptr; // string + GDMonoClass *class_IntPtr = nullptr; // System.IntPtr + + GDMonoClass *class_System_Collections_IEnumerable = nullptr; + GDMonoClass *class_System_Collections_ICollection = nullptr; + GDMonoClass *class_System_Collections_IDictionary = nullptr; #ifdef DEBUG_ENABLED - GDMonoClass *class_System_Diagnostics_StackTrace; + GDMonoClass *class_System_Diagnostics_StackTrace = nullptr; GDMonoMethodThunkR<MonoArray *, MonoObject *> methodthunk_System_Diagnostics_StackTrace_GetFrames; - GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool; - GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool = nullptr; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool = nullptr; #endif - GDMonoClass *class_KeyNotFoundException; + GDMonoClass *class_KeyNotFoundException = nullptr; - MonoClass *rawclass_Dictionary; + MonoClass *rawclass_Dictionary = nullptr; // ----------------------------------------------- - GDMonoClass *class_Vector2; - GDMonoClass *class_Vector2i; - GDMonoClass *class_Rect2; - GDMonoClass *class_Rect2i; - GDMonoClass *class_Transform2D; - GDMonoClass *class_Vector3; - GDMonoClass *class_Vector3i; - GDMonoClass *class_Basis; - GDMonoClass *class_Quaternion; - GDMonoClass *class_Transform3D; - GDMonoClass *class_AABB; - GDMonoClass *class_Color; - GDMonoClass *class_Plane; - GDMonoClass *class_StringName; - GDMonoClass *class_NodePath; - GDMonoClass *class_RID; - GDMonoClass *class_GodotObject; - GDMonoClass *class_GodotResource; - GDMonoClass *class_Node; - GDMonoClass *class_Control; - GDMonoClass *class_Node3D; - GDMonoClass *class_WeakRef; - GDMonoClass *class_Callable; - GDMonoClass *class_SignalInfo; - GDMonoClass *class_Array; - GDMonoClass *class_Dictionary; - GDMonoClass *class_MarshalUtils; - GDMonoClass *class_ISerializationListener; + GDMonoClass *class_Vector2 = nullptr; + GDMonoClass *class_Vector2i = nullptr; + GDMonoClass *class_Rect2 = nullptr; + GDMonoClass *class_Rect2i = nullptr; + GDMonoClass *class_Transform2D = nullptr; + GDMonoClass *class_Vector3 = nullptr; + GDMonoClass *class_Vector3i = nullptr; + GDMonoClass *class_Vector4 = nullptr; + GDMonoClass *class_Vector4i = nullptr; + GDMonoClass *class_Basis = nullptr; + GDMonoClass *class_Quaternion = nullptr; + GDMonoClass *class_Transform3D = nullptr; + GDMonoClass *class_Projection = nullptr; + GDMonoClass *class_AABB = nullptr; + GDMonoClass *class_Color = nullptr; + GDMonoClass *class_Plane = nullptr; + GDMonoClass *class_StringName = nullptr; + GDMonoClass *class_NodePath = nullptr; + GDMonoClass *class_RID = nullptr; + GDMonoClass *class_GodotObject = nullptr; + GDMonoClass *class_GodotResource = nullptr; + GDMonoClass *class_Node = nullptr; + GDMonoClass *class_Control = nullptr; + GDMonoClass *class_Node3D = nullptr; + GDMonoClass *class_WeakRef = nullptr; + GDMonoClass *class_Callable = nullptr; + GDMonoClass *class_SignalInfo = nullptr; + GDMonoClass *class_Array = nullptr; + GDMonoClass *class_Dictionary = nullptr; + GDMonoClass *class_MarshalUtils = nullptr; + GDMonoClass *class_ISerializationListener = nullptr; #ifdef DEBUG_ENABLED - GDMonoClass *class_DebuggingUtils; + GDMonoClass *class_DebuggingUtils = nullptr; GDMonoMethodThunk<MonoObject *, MonoString **, int *, MonoString **> methodthunk_DebuggingUtils_GetStackFrameInfo; #endif - GDMonoClass *class_ExportAttribute; - GDMonoField *field_ExportAttribute_hint; - GDMonoField *field_ExportAttribute_hintString; - GDMonoClass *class_SignalAttribute; - GDMonoClass *class_ToolAttribute; - GDMonoClass *class_AnyPeerAttribute; - GDMonoClass *class_AuthorityAttribute; - GDMonoClass *class_GodotMethodAttribute; - GDMonoField *field_GodotMethodAttribute_methodName; - GDMonoClass *class_ScriptPathAttribute; - GDMonoField *field_ScriptPathAttribute_path; - GDMonoClass *class_AssemblyHasScriptsAttribute; - GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup; - GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes; - - GDMonoField *field_GodotObject_ptr; - GDMonoField *field_StringName_ptr; - GDMonoField *field_NodePath_ptr; - GDMonoField *field_Image_ptr; - GDMonoField *field_RID_ptr; + GDMonoClass *class_ExportAttribute = nullptr; + GDMonoField *field_ExportAttribute_hint = nullptr; + GDMonoField *field_ExportAttribute_hintString = nullptr; + GDMonoClass *class_SignalAttribute = nullptr; + GDMonoClass *class_ToolAttribute = nullptr; + GDMonoClass *class_RPCAttribute = nullptr; + GDMonoProperty *property_RPCAttribute_Mode = nullptr; + GDMonoProperty *property_RPCAttribute_CallLocal = nullptr; + GDMonoProperty *property_RPCAttribute_TransferMode = nullptr; + GDMonoProperty *property_RPCAttribute_TransferChannel = nullptr; + GDMonoClass *class_GodotMethodAttribute = nullptr; + GDMonoField *field_GodotMethodAttribute_methodName = nullptr; + GDMonoClass *class_ScriptPathAttribute = nullptr; + GDMonoField *field_ScriptPathAttribute_path = nullptr; + GDMonoClass *class_AssemblyHasScriptsAttribute = nullptr; + GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup = nullptr; + GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes = nullptr; + + GDMonoField *field_GodotObject_ptr = nullptr; + GDMonoField *field_StringName_ptr = nullptr; + GDMonoField *field_NodePath_ptr = nullptr; + GDMonoField *field_Image_ptr = nullptr; + GDMonoField *field_RID_ptr = nullptr; GDMonoMethodThunk<MonoObject *> methodthunk_GodotObject_Dispose; GDMonoMethodThunkR<Array *, MonoObject *> methodthunk_Array_GetPtr; @@ -147,6 +153,7 @@ struct CachedData { GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIEnumerable; GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericICollection; GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIDictionary; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeHasFlagsAttribute; GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_GetGenericTypeDefinition; diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 89c37e087b..51c5aa3542 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -194,7 +194,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base #ifdef DEBUG_ENABLED // For debug builds, we also fetched from native base classes as well before if this is not a native base class. - // This allows us to warn the user here if he is using snake_case by mistake. + // This allows us to warn the user here if they are using snake_case by mistake. if (p_native_base != this) { GDMonoClass *native_top = p_native_base; @@ -247,7 +247,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base if (existing_method) { memdelete(*existing_method); // Must delete old one } - methods.set(key, method); + methods.insert(key, method); break; } @@ -266,11 +266,9 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { ERR_FAIL_COND_V(!methods_fetched, nullptr); - const MethodKey *k = nullptr; - - while ((k = methods.next(k))) { - if (k->name == p_name) { - return methods.get(*k); + for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) { + if (E.key.name == p_name) { + return E.value; } } @@ -307,7 +305,7 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, uint16_t p_param if (raw_method) { GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method)); - methods.set(key, method); + methods.insert(key, method); return method; } @@ -342,7 +340,7 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName } GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method)); - methods.set(key, method); + methods.insert(key, method); return method; } @@ -362,10 +360,10 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo } GDMonoField *GDMonoClass::get_field(const StringName &p_name) { - Map<StringName, GDMonoField *>::Element *result = fields.find(p_name); + HashMap<StringName, GDMonoField *>::Iterator result = fields.find(p_name); if (result) { - return result->value(); + return result->value; } if (fields_fetched) { @@ -394,10 +392,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { while ((raw_field = mono_class_get_fields(mono_class, &iter)) != nullptr) { StringName name = String::utf8(mono_field_get_name(raw_field)); - Map<StringName, GDMonoField *>::Element *match = fields.find(name); + HashMap<StringName, GDMonoField *>::Iterator match = fields.find(name); if (match) { - fields_list.push_back(match->get()); + fields_list.push_back(match->value); } else { GDMonoField *field = memnew(GDMonoField(raw_field, this)); fields.insert(name, field); @@ -411,10 +409,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { } GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { - Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name); + HashMap<StringName, GDMonoProperty *>::Iterator result = properties.find(p_name); if (result) { - return result->value(); + return result->value; } if (properties_fetched) { @@ -443,10 +441,10 @@ const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { while ((raw_property = mono_class_get_properties(mono_class, &iter)) != nullptr) { StringName name = String::utf8(mono_property_get_name(raw_property)); - Map<StringName, GDMonoProperty *>::Element *match = properties.find(name); + HashMap<StringName, GDMonoProperty *>::Iterator match = properties.find(name); if (match) { - properties_list.push_back(match->get()); + properties_list.push_back(match->value); } else { GDMonoProperty *property = memnew(GDMonoProperty(raw_property, this)); properties.insert(name, property); @@ -479,10 +477,10 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { if (mono_class_is_delegate(raw_class)) { StringName name = String::utf8(mono_class_get_name(raw_class)); - Map<StringName, GDMonoClass *>::Element *match = delegates.find(name); + HashMap<StringName, GDMonoClass *>::Iterator match = delegates.find(name); if (match) { - delegates_list.push_back(match->get()); + delegates_list.push_back(match->value); } else { GDMonoClass *delegate = memnew(GDMonoClass(String::utf8(mono_class_get_namespace(raw_class)), String::utf8(mono_class_get_name(raw_class)), raw_class, assembly)); delegates.insert(name, delegate); @@ -549,9 +547,8 @@ GDMonoClass::~GDMonoClass() { Vector<GDMonoMethod *> deleted_methods; deleted_methods.resize(methods.size()); - const MethodKey *k = nullptr; - while ((k = methods.next(k))) { - GDMonoMethod *method = methods.get(*k); + for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) { + GDMonoMethod *method = E.value; if (method) { for (int i = 0; i < offset; i++) { diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index bfb5797d4b..6b35da30f9 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -32,7 +32,7 @@ #define GD_MONO_CLASS_H #include "core/string/ustring.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "gd_mono_field.h" #include "gd_mono_header.h" @@ -70,11 +70,11 @@ class GDMonoClass { StringName namespace_name; StringName class_name; - MonoClass *mono_class; - GDMonoAssembly *assembly; + MonoClass *mono_class = nullptr; + GDMonoAssembly *assembly = nullptr; bool attrs_fetched; - MonoCustomAttrInfo *attributes; + MonoCustomAttrInfo *attributes = nullptr; // This contains both the original method names and remapped method names from the native Godot identifiers to the C# functions. // Most method-related functions refer to this and it's possible this is unintuitive for outside users; this may be a prime location for refactoring or renaming. @@ -85,15 +85,15 @@ class GDMonoClass { Vector<GDMonoMethod *> method_list; bool fields_fetched; - Map<StringName, GDMonoField *> fields; + HashMap<StringName, GDMonoField *> fields; Vector<GDMonoField *> fields_list; bool properties_fetched; - Map<StringName, GDMonoProperty *> properties; + HashMap<StringName, GDMonoProperty *> properties; Vector<GDMonoProperty *> properties_list; bool delegates_fetched; - Map<StringName, GDMonoClass *> delegates; + HashMap<StringName, GDMonoClass *> delegates; Vector<GDMonoClass *> delegates_list; friend class GDMonoAssembly; diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 333a06c94a..cb025fc67a 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -140,6 +140,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Vector4)) { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + + if (tclass == CACHED_CLASS(Vector4i)) { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(Basis)) { GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis()); mono_field_set_value(p_object, mono_field, &from); @@ -158,6 +170,12 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Projection)) { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(AABB)) { GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB()); mono_field_set_value(p_object, mono_field, &from); @@ -328,6 +346,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + } break; + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::TRANSFORM2D: { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D()); mono_field_set_value(p_object, mono_field, &from); @@ -352,6 +378,10 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color()); mono_field_set_value(p_object, mono_field, &from); diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index abcdef378c..1d30f7a369 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -28,22 +28,22 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOFIELD_H -#define GDMONOFIELD_H +#ifndef GD_MONO_FIELD_H +#define GD_MONO_FIELD_H #include "gd_mono.h" #include "gd_mono_header.h" #include "i_mono_class_member.h" class GDMonoField : public IMonoClassMember { - GDMonoClass *owner; - MonoClassField *mono_field; + GDMonoClass *owner = nullptr; + MonoClassField *mono_field = nullptr; StringName name; ManagedType type; bool attrs_fetched; - MonoCustomAttrInfo *attributes; + MonoCustomAttrInfo *attributes = nullptr; public: virtual GDMonoClass *get_enclosing_class() const final { return owner; } @@ -75,4 +75,4 @@ public: ~GDMonoField(); }; -#endif // GDMONOFIELD_H +#endif // GD_MONO_FIELD_H diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index 01a6521876..6ea3c5539e 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -77,23 +77,20 @@ static String make_text(const char *log_domain, const char *log_level, const cha } void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) { - FileAccess *f = GDMonoLog::get_singleton()->log_file; - if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) { String text = make_text(log_domain, log_level, message); text += "\n"; - f->seek_end(); - f->store_string(text); + GDMonoLog::get_singleton()->log_file->seek_end(); + GDMonoLog::get_singleton()->log_file->store_string(text); } if (fatal) { String text = make_text(log_domain, log_level, message); ERR_PRINT("Mono: FATAL ERROR '" + text + "', ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'."); // Make sure to flush before aborting - f->flush(); - f->close(); - memdelete(f); + GDMonoLog::get_singleton()->log_file->flush(); + GDMonoLog::get_singleton()->log_file.unref(); abort(); } @@ -101,8 +98,8 @@ void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { if (!DirAccess::exists(p_logs_dir)) { - DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND_V(!diraccess, false); + Ref<DirAccess> diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V(diraccess.is_null(), false); Error logs_mkdir_err = diraccess->make_dir_recursive(p_logs_dir); ERR_FAIL_COND_V_MSG(logs_mkdir_err != OK, false, "Failed to create mono logs directory."); } @@ -113,8 +110,8 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { static const uint64_t MAX_SECS = 5 * 86400; // 5 days - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - ERR_FAIL_COND(!da); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND(da.is_null()); Error err = da->change_dir(p_logs_dir); ERR_FAIL_COND_MSG(err != OK, "Cannot change directory to '" + p_logs_dir + "'."); @@ -170,7 +167,7 @@ void GDMonoLog::initialize() { log_file_path = logs_dir.plus_file(log_file_name); log_file = FileAccess::open(log_file_path, FileAccess::WRITE); - if (!log_file) { + if (log_file.is_null()) { ERR_PRINT("Mono: Cannot create log file at: " + log_file_path); } } @@ -178,7 +175,7 @@ void GDMonoLog::initialize() { mono_trace_set_level_string(log_level.get_data()); log_level_id = get_log_level_id(log_level.get_data()); - if (log_file) { + if (log_file.is_valid()) { OS::get_singleton()->print("Mono: Log file is: '%s'\n", log_file_path.utf8().get_data()); mono_trace_set_log_handler(mono_log_callback, this); } else { @@ -192,11 +189,6 @@ GDMonoLog::GDMonoLog() { GDMonoLog::~GDMonoLog() { singleton = nullptr; - - if (log_file) { - log_file->close(); - memdelete(log_file); - } } #else diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index 9aa67a09e2..93ba6a410e 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -35,7 +35,7 @@ #include "core/typedefs.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) // We have custom mono log callbacks for WASM and iOS #define GD_MONO_LOG_ENABLED #endif @@ -48,7 +48,7 @@ class GDMonoLog { #ifdef GD_MONO_LOG_ENABLED int log_level_id = -1; - FileAccess *log_file = nullptr; + Ref<FileAccess> log_file; String log_file_path; bool _try_create_logs_dir(const String &p_logs_dir); diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 957abca37b..a860442764 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -99,6 +99,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Vector3i)) { return Variant::VECTOR3I; } + if (vtclass == CACHED_CLASS(Vector4)) { + return Variant::VECTOR4; + } + + if (vtclass == CACHED_CLASS(Vector4i)) { + return Variant::VECTOR4I; + } if (vtclass == CACHED_CLASS(Basis)) { return Variant::BASIS; @@ -111,7 +118,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Transform3D)) { return Variant::TRANSFORM3D; } - + if (vtclass == CACHED_CLASS(Projection)) { + return Variant::PROJECTION; + } if (vtclass == CACHED_CLASS(AABB)) { return Variant::AABB; } @@ -539,6 +548,14 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var.operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); } + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_var.operator ::Vector4()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4), &from); + } + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_var.operator ::Vector4i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4i), &from); + } case Variant::PLANE: { GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from); @@ -559,6 +576,10 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from); } + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_var.operator ::Projection()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Projection), &from); + } case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from); diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 20d4743e5c..3b6fd25d71 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOMARSHAL_H -#define GDMONOMARSHAL_H +#ifndef GD_MONO_MARSHAL_H +#define GD_MONO_MARSHAL_H #include "core/variant/variant.h" @@ -196,14 +196,14 @@ PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array); #pragma pack(push, 1) struct M_Callable { - MonoObject *target; - MonoObject *method_string_name; - MonoDelegate *delegate; + MonoObject *target = nullptr; + MonoObject *method_string_name = nullptr; + MonoDelegate *delegate = nullptr; }; struct M_SignalInfo { - MonoObject *owner; - MonoObject *name_string_name; + MonoObject *owner = nullptr; + MonoObject *name_string_name = nullptr; }; #pragma pack(pop) @@ -256,6 +256,18 @@ enum { offsetof(Vector3, y) == (sizeof(real_t) * 1) && offsetof(Vector3, z) == (sizeof(real_t) * 2)), + MATCHES_Vector4 = (MATCHES_real_t && (sizeof(Vector4) == (sizeof(real_t) * 4)) && + offsetof(Vector4, x) == (sizeof(real_t) * 0) && + offsetof(Vector4, y) == (sizeof(real_t) * 1) && + offsetof(Vector4, z) == (sizeof(real_t) * 2) && + offsetof(Vector4, w) == (sizeof(real_t) * 3)), + + MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4i)) && + offsetof(Vector4i, x) == (sizeof(int32_t) * 0) && + offsetof(Vector4i, y) == (sizeof(int32_t) * 1) && + offsetof(Vector4i, z) == (sizeof(int32_t) * 2) && + offsetof(Vector4i, w) == (sizeof(int32_t) * 3)), + MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) && offsetof(Vector3i, x) == (sizeof(int32_t) * 0) && offsetof(Vector3i, y) == (sizeof(int32_t) * 1) && @@ -273,6 +285,8 @@ enum { offsetof(Transform3D, basis) == 0 && offsetof(Transform3D, origin) == sizeof(Basis)), + MATCHES_Projection = (MATCHES_Vector4 && (sizeof(Projection) == (sizeof(Vector4) * 4))), + MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) && offsetof(AABB, position) == (sizeof(Vector3) * 0) && offsetof(AABB, size) == (sizeof(Vector3) * 1)), @@ -291,9 +305,9 @@ enum { // In the future we may force this if we want to ref return these structs #ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY /* clang-format off */ -static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && - MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color && - MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i); +static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && MATCHES_Vector4 && + MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_Projection && MATCHES_AABB && MATCHES_Color && + MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i && MATCHES_Vector4i); /* clang-format on */ #endif } // namespace InteropLayout @@ -367,9 +381,9 @@ struct M_Transform2D { static _FORCE_INLINE_ M_Transform2D convert_from(const Transform2D &p_from) { M_Transform2D ret = { - M_Vector2::convert_from(p_from.elements[0]), - M_Vector2::convert_from(p_from.elements[1]), - M_Vector2::convert_from(p_from.elements[2]) + M_Vector2::convert_from(p_from.columns[0]), + M_Vector2::convert_from(p_from.columns[1]), + M_Vector2::convert_from(p_from.columns[2]) }; return ret; } @@ -401,6 +415,32 @@ struct M_Vector3i { } }; +struct M_Vector4 { + real_t x, y, z, w; + + static _FORCE_INLINE_ Vector4 convert_to(const M_Vector4 &p_from) { + return Vector4(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4 convert_from(const Vector4 &p_from) { + M_Vector4 ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + +struct M_Vector4i { + int32_t x, y, z, w; + + static _FORCE_INLINE_ Vector4i convert_to(const M_Vector4i &p_from) { + return Vector4i(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4i convert_from(const Vector4i &p_from) { + M_Vector4i ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + struct M_Basis { M_Vector3 elements[3]; @@ -412,9 +452,9 @@ struct M_Basis { static _FORCE_INLINE_ M_Basis convert_from(const Basis &p_from) { M_Basis ret = { - M_Vector3::convert_from(p_from.elements[0]), - M_Vector3::convert_from(p_from.elements[1]), - M_Vector3::convert_from(p_from.elements[2]) + M_Vector3::convert_from(p_from.rows[0]), + M_Vector3::convert_from(p_from.rows[1]), + M_Vector3::convert_from(p_from.rows[2]) }; return ret; } @@ -447,6 +487,22 @@ struct M_Transform3D { } }; +struct M_Projection { + M_Vector4 vec1; + M_Vector4 vec2; + M_Vector4 vec3; + M_Vector4 vec4; + + static _FORCE_INLINE_ Projection convert_to(const M_Projection &p_from) { + return Projection(M_Vector4::convert_to(p_from.vec1), M_Vector4::convert_to(p_from.vec2), M_Vector4::convert_to(p_from.vec3), M_Vector4::convert_to(p_from.vec4)); + } + + static _FORCE_INLINE_ M_Projection convert_from(const Projection &p_from) { + M_Projection ret = { M_Vector4::convert_from(p_from.matrix[0]), M_Vector4::convert_from(p_from.matrix[1]), M_Vector4::convert_from(p_from.matrix[2]), M_Vector4::convert_from(p_from.matrix[3]) }; + return ret; + } +}; + struct M_AABB { M_Vector3 position; M_Vector3 size; @@ -533,8 +589,11 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D) DECL_TYPE_MARSHAL_TEMPLATES(Vector3) DECL_TYPE_MARSHAL_TEMPLATES(Vector3i) DECL_TYPE_MARSHAL_TEMPLATES(Basis) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4i) DECL_TYPE_MARSHAL_TEMPLATES(Quaternion) DECL_TYPE_MARSHAL_TEMPLATES(Transform3D) +DECL_TYPE_MARSHAL_TEMPLATES(Projection) DECL_TYPE_MARSHAL_TEMPLATES(AABB) DECL_TYPE_MARSHAL_TEMPLATES(Color) DECL_TYPE_MARSHAL_TEMPLATES(Plane) @@ -543,4 +602,4 @@ DECL_TYPE_MARSHAL_TEMPLATES(Plane) #define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from)) } // namespace GDMonoMarshal -#endif // GDMONOMARSHAL_H +#endif // GD_MONO_MARSHAL_H diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index 6e87a60ee2..be11ef5bfe 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -54,7 +54,7 @@ class GDMonoMethod : public IMonoClassMember { friend class GDMonoClass; - MonoMethod *mono_method; + MonoMethod *mono_method = nullptr; public: virtual GDMonoClass *get_enclosing_class() const final; diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index bb163b89bc..0180dee3ea 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -39,7 +39,7 @@ #include "gd_mono_method.h" #include "gd_mono_utils.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) #define HAVE_METHOD_THUNKS #endif diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index 003bcf05e1..6fc681aeb5 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -36,14 +36,14 @@ #include "i_mono_class_member.h" class GDMonoProperty : public IMonoClassMember { - GDMonoClass *owner; - MonoProperty *mono_property; + GDMonoClass *owner = nullptr; + MonoProperty *mono_property = nullptr; StringName name; ManagedType type; bool attrs_fetched; - MonoCustomAttrInfo *attributes; + MonoCustomAttrInfo *attributes = nullptr; unsigned int param_buffer_size; diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index a884bf4da0..1983d6ebe2 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -70,7 +70,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { void *data = CSharpLanguage::get_instance_binding(unmanaged); ERR_FAIL_NULL_V(data, nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); + CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->value(); ERR_FAIL_COND_V(!script_binding.inited, nullptr); MonoGCHandleData &gchandle = script_binding.gchandle; @@ -614,6 +614,14 @@ bool type_is_generic_idictionary(MonoReflectionType *p_reftype) { return (bool)res; } +bool type_has_flags_attribute(MonoReflectionType *p_reftype) { + NO_GLUE_RET(false); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeHasFlagsAttribute).invoke(p_reftype, &exc); + UNHANDLED_EXCEPTION(exc); + return (bool)res; +} + void get_generic_type_definition(MonoReflectionType *p_reftype, MonoReflectionType **r_generic_reftype) { MonoException *exc = nullptr; CACHED_METHOD_THUNK(MarshalUtils, GetGenericTypeDefinition).invoke(p_reftype, r_generic_reftype, &exc); diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 4c2c2c93c2..300cacfa4b 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GD_MONOUTILS_H -#define GD_MONOUTILS_H +#ifndef GD_MONO_UTILS_H +#define GD_MONO_UTILS_H #include <mono/metadata/threads.h> @@ -61,6 +61,7 @@ bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype); bool type_is_generic_ienumerable(MonoReflectionType *p_reftype); bool type_is_generic_icollection(MonoReflectionType *p_reftype); bool type_is_generic_idictionary(MonoReflectionType *p_reftype); +bool type_has_flags_attribute(MonoReflectionType *p_reftype); void get_generic_type_definition(MonoReflectionType *p_reftype, MonoReflectionType **r_generic_reftype); @@ -201,4 +202,4 @@ void add_internal_call(const char *p_name, R (*p_func)(P...)) { #define GD_MONO_ASSERT_THREAD_ATTACHED ((void)0) #endif -#endif // GD_MONOUTILS_H +#endif // GD_MONO_UTILS_H diff --git a/modules/mono/mono_gd/gd_mono_wasm_m2n.h b/modules/mono/mono_gd/gd_mono_wasm_m2n.h index 68299aa984..83e2750e5a 100644 --- a/modules/mono/mono_gd/gd_mono_wasm_m2n.h +++ b/modules/mono/mono_gd/gd_mono_wasm_m2n.h @@ -47,11 +47,11 @@ struct Mono_InterpMethodArguments { size_t ilen; void **iargs; size_t flen; - double *fargs; + double *fargs = nullptr; void **retval; size_t is_float_ret; //#ifdef TARGET_WASM - void *sig; + void *sig = nullptr; //#endif }; } // extern "C" diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h index 2f444d5089..03e86df698 100644 --- a/modules/mono/mono_gd/support/ios_support.h +++ b/modules/mono/mono_gd/support/ios_support.h @@ -31,7 +31,7 @@ #ifndef IOS_SUPPORT_H #define IOS_SUPPORT_H -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #include "core/string/ustring.h" @@ -45,6 +45,6 @@ void cleanup(); } // namespace ios } // namespace gdmono -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED #endif // IOS_SUPPORT_H diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm index df97dfba49..7c941b9d1e 100644 --- a/modules/mono/mono_gd/support/ios_support.mm +++ b/modules/mono/mono_gd/support/ios_support.mm @@ -30,7 +30,7 @@ #include "ios_support.h" -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #import <Foundation/Foundation.h> #include <os/log.h> @@ -147,4 +147,4 @@ GD_PINVOKE_EXPORT void xamarin_start_wwan(const char *p_uri) { os_log_error(OS_LOG_DEFAULT, "Not implemented: 'xamarin_start_wwan'"); } -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index 531a4bb11f..755e1f7a30 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -40,7 +40,11 @@ Ref<ResourceFormatSaverCSharpScript> resource_saver_cs; mono_bind::GodotSharp *_godotsharp = nullptr; -void register_mono_types() { +void initialize_mono_module(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } + GDREGISTER_CLASS(CSharpScript); _godotsharp = memnew(mono_bind::GodotSharp); @@ -59,7 +63,11 @@ void register_mono_types() { ResourceSaver::add_resource_format_saver(resource_saver_cs); } -void unregister_mono_types() { +void uninitialize_mono_module(ModuleInitializationLevel p_level) { + if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } + ScriptServer::unregister_language(script_language_cs); if (script_language_cs) { diff --git a/modules/mono/register_types.h b/modules/mono/register_types.h index 12f7e36f02..bc2690c277 100644 --- a/modules/mono/register_types.h +++ b/modules/mono/register_types.h @@ -31,7 +31,9 @@ #ifndef MONO_REGISTER_TYPES_H #define MONO_REGISTER_TYPES_H -void register_mono_types(); -void unregister_mono_types(); +#include "modules/register_module_types.h" + +void initialize_mono_module(ModuleInitializationLevel p_level); +void uninitialize_mono_module(ModuleInitializationLevel p_level); #endif // MONO_REGISTER_TYPES_H diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 315a9c29f6..618e1b58e0 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -63,7 +63,7 @@ bool SignalAwaiterCallable::compare_less(const CallableCustom *p_a, const Callab uint32_t SignalAwaiterCallable::hash() const { uint32_t hash = signal.hash(); - return hash_djb2_one_64(target_id, hash); + return hash_murmur3_one_64(target_id, hash); } String SignalAwaiterCallable::get_as_text() const { @@ -164,7 +164,7 @@ bool EventSignalCallable::compare_less(const CallableCustom *p_a, const Callable uint32_t EventSignalCallable::hash() const { uint32_t hash = event_signal->field->get_name().hash(); - return hash_djb2_one_64(owner->get_instance_id(), hash); + return hash_murmur3_one_64(owner->get_instance_id(), hash); } String EventSignalCallable::get_as_text() const { diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h index 1a62f36625..532aa3e327 100644 --- a/modules/mono/signal_awaiter_utils.h +++ b/modules/mono/signal_awaiter_utils.h @@ -68,7 +68,7 @@ public: }; class EventSignalCallable : public CallableCustom { - Object *owner; + Object *owner = nullptr; const CSharpScript::EventSignal *event_signal; public: diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/macos_utils.cpp index 835c611709..cd4f7a827e 100644 --- a/modules/mono/utils/osx_utils.cpp +++ b/modules/mono/utils/macos_utils.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.cpp */ +/* macos_utils.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "osx_utils.h" +#include "macos_utils.h" -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #include "core/string/print_string.h" -#include <CoreFoundation/CoreFoundation.h> -#include <CoreServices/CoreServices.h> +#import <CoreFoundation/CoreFoundation.h> +#import <CoreServices/CoreServices.h> -bool osx_is_app_bundle_installed(const String &p_bundle_id) { +bool macos_is_app_bundle_installed(const String &p_bundle_id) { CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8); CFArrayRef result = LSCopyApplicationURLsForBundleIdentifier(bundle_id, nullptr); CFRelease(bundle_id); diff --git a/modules/mono/utils/osx_utils.h b/modules/mono/utils/macos_utils.h index 2f6c6dad51..ca4957f5a7 100644 --- a/modules/mono/utils/osx_utils.h +++ b/modules/mono/utils/macos_utils.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.h */ +/* macos_utils.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,13 +30,13 @@ #include "core/string/ustring.h" -#ifndef OSX_UTILS_H -#define OSX_UTILS_H +#ifndef MONO_MACOS_UTILS_H +#define MONO_MACOS_UTILS_H -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED -bool osx_is_app_bundle_installed(const String &p_bundle_id); +bool macos_is_app_bundle_installed(const String &p_bundle_id); #endif -#endif // OSX_UTILS_H +#endif // MONO_MACOS_UTILS_H diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h index 2ca1a4cbf1..b7bd9a2495 100644 --- a/modules/mono/utils/macros.h +++ b/modules/mono/utils/macros.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef UTIL_MACROS_H -#define UTIL_MACROS_H +#ifndef MONO_MACROS_H +#define MONO_MACROS_H #define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name #define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c) @@ -69,4 +69,4 @@ public: #define SCOPE_EXIT \ auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() -> void -#endif // UTIL_MACROS_H +#endif // MONO_MACROS_H diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 15a0b28181..a1905dfcfe 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -62,7 +62,8 @@ String cwd() { } String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return "."; } return result.simplify_path(); @@ -73,7 +74,7 @@ String cwd() { } String result; - if (result.parse_utf8(buffer)) { + if (result.parse_utf8(buffer) != OK) { return "."; } @@ -114,7 +115,8 @@ String realpath(const String &p_path) { ::CloseHandle(hFile); String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return p_path; } @@ -127,10 +129,10 @@ String realpath(const String &p_path) { } String result; - bool parse_ok = result.parse_utf8(resolved_path); + Error parse_ok = result.parse_utf8(resolved_path); ::free(resolved_path); - if (parse_ok) { + if (parse_ok != OK) { return p_path; } diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index a8cd8daf04..9a2c757361 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PATH_UTILS_H -#define PATH_UTILS_H +#ifndef MONO_PATH_UTILS_H +#define MONO_PATH_UTILS_H #include "core/string/string_builder.h" #include "core/string/ustring.h" @@ -58,4 +58,4 @@ String realpath(const String &p_path); String relative_to(const String &p_path, const String &p_relative_to); } // namespace path -#endif // PATH_UTILS_H +#endif // MONO_PATH_UTILS_H diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index dd29299330..975f2d8332 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -145,7 +145,7 @@ bool is_csharp_keyword(const String &p_name) { p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" || p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" || p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" || - p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" || + p_name == "foreach" || p_name == "goto" || p_name == "if" || p_name == "implicit" || p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" || p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" || p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" || @@ -167,20 +167,18 @@ String escape_csharp_keyword(const String &p_name) { Error read_all_file_utf8(const String &p_path, String &r_content) { Vector<uint8_t> sourcef; Error err; - FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); uint64_t len = f->get_length(); sourcef.resize(len + 1); uint8_t *w = sourcef.ptrw(); uint64_t r = f->get_buffer(w, len); - f->close(); - memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); w[len] = 0; String source; - if (source.parse_utf8((const char *)w)) { + if (source.parse_utf8((const char *)w) != OK) { ERR_FAIL_V(ERR_INVALID_DATA); } diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index d79888716a..fa4c5e89f4 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STRING_FORMAT_H -#define STRING_FORMAT_H +#ifndef MONO_STRING_UTILS_H +#define MONO_STRING_UTILS_H #include "core/string/ustring.h" #include "core/variant/variant.h" @@ -59,4 +59,4 @@ String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE char *str_format_new(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2; char *str_format_new(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0; -#endif // STRING_FORMAT_H +#endif // MONO_STRING_UTILS_H |
