diff options
Diffstat (limited to 'core/object/script_language.cpp')
-rw-r--r-- | core/object/script_language.cpp | 105 |
1 files changed, 91 insertions, 14 deletions
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 0b2d5e41cf..bd3199ca0a 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -34,6 +34,7 @@ #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" +#include "core/io/resource_loader.h" #include <stdint.h> @@ -50,7 +51,7 @@ void Script::_notification(int p_what) { switch (p_what) { case NOTIFICATION_POSTINITIALIZE: { if (EngineDebugger::is_active()) { - EngineDebugger::get_script_debugger()->set_break_language(get_language()); + callable_mp(this, &Script::_set_debugger_break_language).call_deferred(); } } break; } @@ -102,6 +103,28 @@ Dictionary Script::_get_script_constant_map() { return ret; } +void Script::_set_debugger_break_language() { + if (EngineDebugger::is_active()) { + EngineDebugger::get_script_debugger()->set_break_language(get_language()); + } +} + +int Script::get_script_method_argument_count(const StringName &p_method, bool *r_is_valid) const { + MethodInfo mi = get_method_info(p_method); + + if (mi == MethodInfo()) { + if (r_is_valid) { + *r_is_valid = false; + } + return 0; + } + + if (r_is_valid) { + *r_is_valid = true; + } + return mi.arguments.size(); +} + #ifdef TOOLS_ENABLED PropertyInfo Script::get_class_category() const { @@ -154,6 +177,24 @@ void Script::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_source_code", "get_source_code"); } +void Script::reload_from_file() { +#ifdef TOOLS_ENABLED + // Replicates how the ScriptEditor reloads script resources, which generally handles it. + // However, when scripts are to be reloaded but aren't open in the internal editor, we go through here instead. + const Ref<Script> rel = ResourceLoader::load(ResourceLoader::path_remap(get_path()), get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE); + if (rel.is_null()) { + return; + } + + set_source_code(rel->get_source_code()); + set_last_modified_time(rel->get_last_modified_time()); + + reload(); +#else + Resource::reload_from_file(); +#endif +} + void ScriptServer::set_scripting_enabled(bool p_enabled) { scripting_enabled = p_enabled; } @@ -168,6 +209,18 @@ ScriptLanguage *ScriptServer::get_language(int p_idx) { return _languages[p_idx]; } +ScriptLanguage *ScriptServer::get_language_for_extension(const String &p_extension) { + MutexLock lock(languages_mutex); + + for (int i = 0; i < _language_count; i++) { + if (_languages[i] && _languages[i]->get_extension() == p_extension) { + return _languages[i]; + } + } + + return nullptr; +} + Error ScriptServer::register_language(ScriptLanguage *p_language) { MutexLock lock(languages_mutex); ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER); @@ -204,8 +257,8 @@ void ScriptServer::init_languages() { if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { Array script_classes = GLOBAL_GET("_global_script_classes"); - for (int i = 0; i < script_classes.size(); i++) { - Dictionary c = script_classes[i]; + for (const Variant &script_class : script_classes) { + Dictionary c = script_class; if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { continue; } @@ -216,8 +269,8 @@ void ScriptServer::init_languages() { #endif Array script_classes = ProjectSettings::get_singleton()->get_global_class_list(); - for (int i = 0; i < script_classes.size(); i++) { - Dictionary c = script_classes[i]; + for (const Variant &script_class : script_classes) { + Dictionary c = script_class; if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { continue; } @@ -313,12 +366,24 @@ void ScriptServer::global_classes_clear() { void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) { ERR_FAIL_COND_MSG(p_class == p_base || (global_classes.has(p_base) && get_global_class_native_base(p_base) == p_class), "Cyclic inheritance in script class."); - GlobalScriptClass g; - g.language = p_language; - g.path = p_path; - g.base = p_base; - global_classes[p_class] = g; - inheriters_cache_dirty = true; + GlobalScriptClass *existing = global_classes.getptr(p_class); + if (existing) { + // Update an existing class (only set dirty if something changed). + if (existing->base != p_base || existing->path != p_path || existing->language != p_language) { + existing->base = p_base; + existing->path = p_path; + existing->language = p_language; + inheriters_cache_dirty = true; + } + } else { + // Add new class. + GlobalScriptClass g; + g.language = p_language; + g.path = p_path; + g.base = p_base; + global_classes[p_class] = g; + inheriters_cache_dirty = true; + } } void ScriptServer::remove_global_class(const StringName &p_class) { @@ -404,8 +469,8 @@ void ScriptServer::save_global_classes() { Dictionary class_icons; Array script_classes = ProjectSettings::get_singleton()->get_global_class_list(); - for (int i = 0; i < script_classes.size(); i++) { - Dictionary d = script_classes[i]; + for (const Variant &script_class : script_classes) { + Dictionary d = script_class; if (!d.has("name") || !d.has("icon")) { continue; } @@ -523,6 +588,13 @@ TypedArray<int> ScriptLanguage::CodeCompletionOption::get_option_cached_characte return charac; } +void ScriptLanguage::_bind_methods() { + BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_AUTO); + BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_PASCAL_CASE); + BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_SNAKE_CASE); + BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_KEBAB_CASE); +} + bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) { if (script->is_placeholder_fallback_enabled()) { return false; @@ -696,7 +768,12 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, } } if (!found) { - properties.push_back(PropertyInfo(p_value.get_type(), p_name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE)); + PropertyHint hint = PROPERTY_HINT_NONE; + const Object *obj = p_value.get_validated_object(); + if (obj && obj->is_class("Node")) { + hint = PROPERTY_HINT_NODE_TYPE; + } + properties.push_back(PropertyInfo(p_value.get_type(), p_name, hint, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_SCRIPT_VARIABLE)); } } |