diff options
Diffstat (limited to 'modules/mono/csharp_script.cpp')
-rw-r--r-- | modules/mono/csharp_script.cpp | 224 |
1 files changed, 117 insertions, 107 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index e39127e0a1..a77b1d83ad 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -42,7 +42,6 @@ #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" @@ -58,8 +57,10 @@ #include "godotsharp_dirs.h" #include "managed_callable.h" #include "mono_gd/gd_mono_cache.h" +#include "servers/text_server.h" #include "signal_awaiter_utils.h" #include "utils/macros.h" +#include "utils/naming_utils.h" #include "utils/string_utils.h" #define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->get_string_names().m_var) @@ -91,11 +92,6 @@ String CSharpLanguage::get_extension() const { return "cs"; } -Error CSharpLanguage::execute_file(const String &p_path) { - // ?? - return OK; -} - void CSharpLanguage::init() { #ifdef DEBUG_METHODS_ENABLED if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) { @@ -106,11 +102,9 @@ void CSharpLanguage::init() { } #endif -#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) - // Generate the bindings here, before loading assemblies. The Godot assemblies - // may be missing if the glue wasn't generated yet in order to build them. - List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); - BindingsGenerator::handle_cmdline_args(cmdline_args); + GLOBAL_DEF("dotnet/project/assembly_name", ""); +#ifdef TOOLS_ENABLED + GLOBAL_DEF("dotnet/project/solution_directory", ""); #endif gdmono = memnew(GDMono); @@ -328,7 +322,7 @@ void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { } static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { - String base_class = p_base_class_name; + String base_class = pascal_to_pascal_case(p_base_class_name); if (p_class_name == base_class) { base_class = "Godot." + base_class; } @@ -340,8 +334,8 @@ bool CSharpLanguage::is_using_templates() { } Ref<Script> CSharpLanguage::make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { - Ref<CSharpScript> script; - script.instantiate(); + Ref<CSharpScript> scr; + scr.instantiate(); String class_name_no_spaces = p_class_name.replace(" ", "_"); String base_class_name = get_base_class_name(p_base_class_name, class_name_no_spaces); @@ -350,8 +344,8 @@ Ref<Script> CSharpLanguage::make_template(const String &p_template, const String .replace("_BASE_", base_class_name) .replace("_CLASS_", class_name_no_spaces) .replace("_TS_", _get_indentation()); - script->set_source_code(processed_template); - return script; + scr->set_source_code(processed_template); + return scr; } Vector<ScriptLanguage::ScriptTemplate> CSharpLanguage::get_built_in_templates(StringName p_object) { @@ -373,6 +367,10 @@ String CSharpLanguage::validate_path(const String &p_path) const { if (keywords.find(class_name)) { return RTR("Class name can't be a reserved keyword"); } + if (!TS->is_valid_identifier(class_name)) { + return RTR("Class name must be a valid identifier"); + } + return ""; } @@ -389,17 +387,22 @@ bool CSharpLanguage::supports_builtin_mode() const { } #ifdef TOOLS_ENABLED +struct VariantCsName { + Variant::Type variant_type; + const String cs_type; +}; + static String variant_type_to_managed_name(const String &p_var_type_name) { if (p_var_type_name.is_empty()) { return "Variant"; } if (ClassDB::class_exists(p_var_type_name)) { - return p_var_type_name; + return pascal_to_pascal_case(p_var_type_name); } if (p_var_type_name == Variant::get_type_name(Variant::OBJECT)) { - return "Godot.Object"; + return "GodotObject"; } if (p_var_type_name == Variant::get_type_name(Variant::INT)) { @@ -454,34 +457,34 @@ static String variant_type_to_managed_name(const String &p_var_type_name) { return "Signal"; } - Variant::Type var_types[] = { - Variant::BOOL, - Variant::INT, - Variant::VECTOR2, - Variant::VECTOR2I, - Variant::RECT2, - Variant::RECT2I, - 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, - Variant::RID, - Variant::CALLABLE + const VariantCsName var_types[] = { + { Variant::BOOL, "bool" }, + { Variant::INT, "long" }, + { Variant::VECTOR2, "Vector2" }, + { Variant::VECTOR2I, "Vector2I" }, + { Variant::RECT2, "Rect2" }, + { Variant::RECT2I, "Rect2I" }, + { Variant::VECTOR3, "Vector3" }, + { Variant::VECTOR3I, "Vector3I" }, + { Variant::TRANSFORM2D, "Transform2D" }, + { Variant::VECTOR4, "Vector4" }, + { Variant::VECTOR4I, "Vector4I" }, + { Variant::PLANE, "Plane" }, + { Variant::QUATERNION, "Quaternion" }, + { Variant::AABB, "Aabb" }, + { Variant::BASIS, "Basis" }, + { Variant::TRANSFORM3D, "Transform3D" }, + { Variant::PROJECTION, "Projection" }, + { Variant::COLOR, "Color" }, + { Variant::STRING_NAME, "StringName" }, + { Variant::NODE_PATH, "NodePath" }, + { Variant::RID, "Rid" }, + { Variant::CALLABLE, "Callable" }, }; - for (unsigned int i = 0; i < sizeof(var_types) / sizeof(Variant::Type); i++) { - if (p_var_type_name == Variant::get_type_name(var_types[i])) { - return p_var_type_name; + for (unsigned int i = 0; i < sizeof(var_types) / sizeof(VariantCsName); i++) { + if (p_var_type_name == Variant::get_type_name(var_types[i].variant_type)) { + return var_types[i].cs_type; } } @@ -583,7 +586,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() _recursion_flag_ = false; }; - if (!gdmono->is_runtime_initialized()) { + if (!gdmono || !gdmono->is_runtime_initialized()) { return Vector<StackInfo>(); } @@ -673,6 +676,7 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft #ifdef GD_MONO_HOT_RELOAD bool CSharpLanguage::is_assembly_reloading_needed() { + ERR_FAIL_NULL_V(gdmono, false); if (!gdmono->is_runtime_initialized()) { return false; } @@ -707,6 +711,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() { } void CSharpLanguage::reload_assemblies(bool p_soft_reload) { + ERR_FAIL_NULL(gdmono); if (!gdmono->is_runtime_initialized()) { return; } @@ -775,28 +780,28 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // As scripts are going to be reloaded, must proceed without locking here - for (Ref<CSharpScript> &script : scripts) { + for (Ref<CSharpScript> &scr : scripts) { // If someone removes a script from a node, deletes the script, builds, adds a script to the // same node, then builds again, the script might have no path and also no script_class. In // that case, we can't (and don't need to) reload it. - if (script->get_path().is_empty() && !script->valid) { + if (scr->get_path().is_empty() && !scr->valid) { continue; } - to_reload.push_back(script); + to_reload.push_back(scr); // 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) { - script->pending_reload_instances.insert(obj->get_instance_id()); + for (Object *obj : scr->instances) { + scr->pending_reload_instances.insert(obj->get_instance_id()); // Since this script instance wasn't a placeholder, add it to the list of placeholders // that will have to be eventually replaced with a script instance in case it turns into one. // This list is not cleared after the reload and the collected instances only leave // the list if the script is instantiated or if it was a tool script but becomes a // non-tool script in a rebuild. - script->pending_replace_placeholders.insert(obj->get_instance_id()); + scr->pending_replace_placeholders.insert(obj->get_instance_id()); RefCounted *rc = Object::cast_to<RefCounted>(obj); if (rc) { @@ -805,9 +810,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } #ifdef TOOLS_ENABLED - for (PlaceHolderScriptInstance *script_instance : script->placeholders) { - Object *obj = script_instance->get_owner(); - script->pending_reload_instances.insert(obj->get_instance_id()); + for (PlaceHolderScriptInstance *instance : scr->placeholders) { + Object *obj = instance->get_owner(); + scr->pending_reload_instances.insert(obj->get_instance_id()); RefCounted *rc = Object::cast_to<RefCounted>(obj); if (rc) { @@ -817,9 +822,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif // Save state and remove script from instances - RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; + RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = scr->pending_reload_state; - for (Object *obj : script->instances) { + for (Object *obj : scr->instances) { ERR_CONTINUE(!obj->get_script_instance()); CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance()); @@ -844,14 +849,14 @@ 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.begin()) { - Object *obj = *script->instances.begin(); + for (Ref<CSharpScript> &scr : scripts) { + while (scr->instances.begin()) { + Object *obj = *scr->instances.begin(); obj->set_script(Ref<RefCounted>()); // Remove script and existing script instances (placeholder are not removed before domain reload) } - script->was_tool_before_reload = script->tool; - script->_clear(); + scr->was_tool_before_reload = scr->tool; + scr->_clear(); } // Do domain reload @@ -896,44 +901,44 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { List<Ref<CSharpScript>> to_reload_state; - for (Ref<CSharpScript> &script : to_reload) { + for (Ref<CSharpScript> &scr : to_reload) { #ifdef TOOLS_ENABLED - script->exports_invalidated = true; + scr->exports_invalidated = true; #endif - if (!script->get_path().is_empty()) { - script->reload(p_soft_reload); + if (!scr->get_path().is_empty()) { + scr->reload(p_soft_reload); - if (!script->valid) { - script->pending_reload_instances.clear(); - script->pending_reload_state.clear(); + if (!scr->valid) { + scr->pending_reload_instances.clear(); + scr->pending_reload_state.clear(); continue; } } else { - bool success = GDMonoCache::managed_callbacks.ScriptManagerBridge_TryReloadRegisteredScriptWithClass(script.ptr()); + bool success = GDMonoCache::managed_callbacks.ScriptManagerBridge_TryReloadRegisteredScriptWithClass(scr.ptr()); if (!success) { // Couldn't reload - script->pending_reload_instances.clear(); - script->pending_reload_state.clear(); + scr->pending_reload_instances.clear(); + scr->pending_reload_state.clear(); continue; } } - StringName native_name = script->get_instance_base_type(); + StringName native_name = scr->get_instance_base_type(); { - for (const ObjectID &obj_id : script->pending_reload_instances) { + for (const ObjectID &obj_id : scr->pending_reload_instances) { Object *obj = ObjectDB::get_instance(obj_id); if (!obj) { - script->pending_reload_state.erase(obj_id); + scr->pending_reload_state.erase(obj_id); continue; } if (!ClassDB::is_parent_class(obj->get_class_name(), native_name)) { // No longer inherits the same compatible type, can't reload - script->pending_reload_state.erase(obj_id); + scr->pending_reload_state.erase(obj_id); continue; } @@ -941,11 +946,11 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Check if the script must be instantiated or kept as a placeholder // when the script may not be a tool (see #65266) - bool replace_placeholder = script->pending_replace_placeholders.has(obj->get_instance_id()); - if (!script->is_tool() && script->was_tool_before_reload) { + bool replace_placeholder = scr->pending_replace_placeholders.has(obj->get_instance_id()); + if (!scr->is_tool() && scr->was_tool_before_reload) { // The script was a tool before the rebuild so the removal was intentional. replace_placeholder = false; - script->pending_replace_placeholders.erase(obj->get_instance_id()); + scr->pending_replace_placeholders.erase(obj->get_instance_id()); } #ifdef TOOLS_ENABLED @@ -954,20 +959,20 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Non-placeholder script instances are removed in godot_icall_Object_Disposed. CRASH_COND(!si->is_placeholder()); - if (replace_placeholder || script->is_tool() || ScriptServer::is_scripting_enabled()) { + if (replace_placeholder || scr->is_tool() || ScriptServer::is_scripting_enabled()) { // Replace placeholder with a script instance. - CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id]; + CSharpScript::StateBackup &state_backup = scr->pending_reload_state[obj_id]; // Backup placeholder script instance state before replacing it with a script instance. si->get_property_state(state_backup.properties); - ScriptInstance *script_instance = script->instance_create(obj); + ScriptInstance *instance = scr->instance_create(obj); - if (script_instance) { - script->placeholders.erase(static_cast<PlaceHolderScriptInstance *>(si)); - script->pending_replace_placeholders.erase(obj->get_instance_id()); - obj->set_script_instance(script_instance); + if (instance) { + scr->placeholders.erase(static_cast<PlaceHolderScriptInstance *>(si)); + scr->pending_replace_placeholders.erase(obj->get_instance_id()); + obj->set_script_instance(instance); } } @@ -978,18 +983,18 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif // Re-create the script instance. - if (replace_placeholder || script->is_tool() || ScriptServer::is_scripting_enabled()) { + if (replace_placeholder || scr->is_tool() || ScriptServer::is_scripting_enabled()) { // Create script instance or replace placeholder with a script instance. - ScriptInstance *script_instance = script->instance_create(obj); + ScriptInstance *instance = scr->instance_create(obj); - if (script_instance) { - script->pending_replace_placeholders.erase(obj->get_instance_id()); - obj->set_script_instance(script_instance); + if (instance) { + scr->pending_replace_placeholders.erase(obj->get_instance_id()); + obj->set_script_instance(instance); continue; } } // The script instance could not be instantiated or wasn't in the list of placeholders to replace. - obj->set_script(script); + obj->set_script(scr); #if DEBUG_ENABLED // If we reached here, the instantiated script must be a placeholder. CRASH_COND(!obj->get_script_instance()->is_placeholder()); @@ -997,21 +1002,21 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } } - to_reload_state.push_back(script); + to_reload_state.push_back(scr); } - for (Ref<CSharpScript> &script : to_reload_state) { - for (const ObjectID &obj_id : script->pending_reload_instances) { + for (Ref<CSharpScript> &scr : to_reload_state) { + for (const ObjectID &obj_id : scr->pending_reload_instances) { Object *obj = ObjectDB::get_instance(obj_id); if (!obj) { - script->pending_reload_state.erase(obj_id); + scr->pending_reload_state.erase(obj_id); continue; } ERR_CONTINUE(!obj->get_script_instance()); - CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id]; + CSharpScript::StateBackup &state_backup = scr->pending_reload_state[obj_id]; CSharpInstance *csi = CAST_CSHARP_INSTANCE(obj->get_script_instance()); @@ -1028,8 +1033,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } } - script->pending_reload_instances.clear(); - script->pending_reload_state.clear(); + scr->pending_reload_instances.clear(); + scr->pending_reload_state.clear(); } // Deserialize managed callables @@ -1136,6 +1141,7 @@ void CSharpLanguage::_editor_init_callback() { // Add plugin to EditorNode and enable it EditorNode::add_editor_plugin(godotsharp_editor); ED_SHORTCUT("mono/build_solution", TTR("Build Solution"), KeyModifierMask::ALT | Key::B); + ED_SHORTCUT_OVERRIDE("mono/build_solution", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::B); godotsharp_editor->enable_plugin(); get_singleton()->godotsharp_editor = godotsharp_editor; @@ -2138,8 +2144,8 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda _update_exports_values(values, propnames); if (changed) { - for (PlaceHolderScriptInstance *script_instance : placeholders) { - script_instance->update(propnames, values); + for (PlaceHolderScriptInstance *instance : placeholders) { + instance->update(propnames, values); } } else { p_instance_to_update->update(propnames, values); @@ -2601,6 +2607,10 @@ Ref<Script> CSharpScript::get_base_script() const { return base_script; } +StringName CSharpScript::get_global_name() const { + return StringName(); +} + void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const { #ifdef TOOLS_ENABLED const CSharpScript *top = this; @@ -2701,28 +2711,28 @@ Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const // TODO ignore anything inside bin/ and obj/ in tools builds? - Ref<CSharpScript> script; + Ref<CSharpScript> scr; if (GDMonoCache::godot_api_cache_updated) { - GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &script); + GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &scr); } else { - script = Ref<CSharpScript>(memnew(CSharpScript)); + scr = Ref<CSharpScript>(memnew(CSharpScript)); } #if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED) - Error err = script->load_source_code(p_path); + Error err = scr->load_source_code(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); + scr->set_path(p_original_path); - script->reload(); + scr->reload(); if (r_error) { *r_error = OK; } - return script; + return scr; } void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List<String> *p_extensions) const { |