diff options
Diffstat (limited to 'modules/gdscript/gdscript.cpp')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 259 |
1 files changed, 129 insertions, 130 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 10babad378..bd6cef0b6e 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -111,9 +111,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { if (p_script->initializer) { return p_script->initializer; } else { - GDScript *base = p_script->_base; - if (base != nullptr) { - return _super_constructor(base); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + return _super_constructor(base_src); } else { return nullptr; } @@ -121,9 +121,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { } void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error) { - GDScript *base = p_script->_base; - if (base != nullptr) { - _super_implicit_constructor(base, p_instance, r_error); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + _super_implicit_constructor(base_src, p_instance, r_error); if (r_error.error != Callable::CallError::CALL_OK) { return; } @@ -151,7 +151,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco /* STEP 2, INITIALIZE AND CONSTRUCT */ { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.insert(instance->owner); } @@ -160,7 +160,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -177,7 +177,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -396,9 +396,9 @@ ScriptInstance *GDScript::instance_create(Object *p_this) { if (top->native.is_valid()) { if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'"); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type: '" + p_this->get_class() + "'"); } - ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type '" + p_this->get_class() + "'" + "."); + ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type '" + p_this->get_class() + "'" + "."); } } @@ -418,7 +418,7 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) } bool GDScript::instance_has(const Object *p_this) const { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); return instances.has((Object *)p_this); } @@ -620,19 +620,15 @@ void GDScript::_update_doc() { } if (!is_enum) { DocData::ConstantDoc constant_doc; - String doc_description; + String const_description; if (doc_constants.has(E.key)) { - doc_description = doc_constants[E.key]; + const_description = doc_constants[E.key]; } - DocData::constant_doc_from_variant(constant_doc, E.key, E.value, doc_description); + DocData::constant_doc_from_variant(constant_doc, E.key, E.value, const_description); doc.constants.push_back(constant_doc); } } - for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { - E.value->_update_doc(); - } - _add_doc(doc); } #endif @@ -674,36 +670,14 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc base_cache = Ref<GDScript>(); } - if (c->extends_used) { - String path = ""; - if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) { - path = c->extends_path; - if (path.is_relative_path()) { - String base = get_path(); - if (base.is_empty() || base.is_relative_path()) { - ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data()); - } else { - path = base.get_base_dir().path_join(path); - } - } - } else if (c->extends.size() != 0) { - const StringName &base = c->extends[0]; - - if (ScriptServer::is_global_class(base)) { - path = ScriptServer::get_global_class_path(base); - } - } - - if (!path.is_empty()) { - if (path != get_path()) { - Ref<GDScript> bf = ResourceLoader::load(path); - - if (bf.is_valid()) { - base_cache = bf; - bf->inheriters_cache.insert(get_instance_id()); - } - } else { - ERR_PRINT(("Path extending itself in " + path).utf8().get_data()); + GDScriptParser::DataType base_type = parser.get_tree()->base_type; + if (base_type.kind == GDScriptParser::DataType::CLASS) { + Ref<GDScript> bf = GDScriptCache::get_full_script(base_type.script_path, err, path); + if (err == OK) { + bf = Ref<GDScript>(bf->find_class(base_type.class_type->fqcn)); + if (bf.is_valid()) { + base_cache = bf; + bf->inheriters_cache.insert(get_instance_id()); } } } @@ -825,13 +799,6 @@ void GDScript::update_exports() { #endif } -void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) { - p_sc->path = p_path; - for (KeyValue<StringName, Ref<GDScript>> &E : p_sc->subclasses) { - _set_subclass_path(E.value, p_path); - } -} - String GDScript::_get_debug_path() const { if (is_built_in() && !get_name().is_empty()) { return get_name() + " (" + get_path() + ")"; @@ -843,7 +810,7 @@ String GDScript::_get_debug_path() const { Error GDScript::reload(bool p_keep_state) { bool has_instances; { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); has_instances = instances.size(); } @@ -860,7 +827,7 @@ Error GDScript::reload(bool p_keep_state) { basedir = basedir.get_base_dir(); } -// Loading a template, don't parse. + // Loading a template, don't parse. #ifdef TOOLS_ENABLED if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) { return OK; @@ -913,10 +880,6 @@ Error GDScript::reload(bool p_keep_state) { GDScriptCompiler compiler; err = compiler.compile(&parser, this, p_keep_state); -#ifdef TOOLS_ENABLED - _update_doc(); -#endif - if (err) { if (can_run) { if (EngineDebugger::is_active()) { @@ -937,14 +900,6 @@ Error GDScript::reload(bool p_keep_state) { } #endif - valid = true; - - for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { - _set_subclass_path(E.value, path); - } - - _init_rpc_methods_properties(); - return OK; } @@ -1050,6 +1005,16 @@ Error GDScript::load_byte_code(const String &p_path) { return ERR_COMPILATION_FAILED; } +void GDScript::set_path(const String &p_path, bool p_take_over) { + if (is_root_script()) { + Script::set_path(p_path, p_take_over); + } + this->path = p_path; + for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) { + kv.value->set_path(p_path, p_take_over); + } +} + Error GDScript::load_source_code(const String &p_path) { Vector<uint8_t> sourcef; Error err; @@ -1077,10 +1042,12 @@ Error GDScript::load_source_code(const String &p_path) { } source = s; + path = p_path; #ifdef TOOLS_ENABLED source_changed_cache = true; -#endif - path = p_path; + set_edited(false); + set_last_modified_time(FileAccess::get_modified_time(path)); +#endif // TOOLS_ENABLED return OK; } @@ -1120,6 +1087,52 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const { return false; } +GDScript *GDScript::find_class(const String &p_qualified_name) { + String first = p_qualified_name.get_slice("::", 0); + + GDScript *result = nullptr; + if (first.is_empty() || first == name) { + result = this; + } else if (first == get_root_script()->path) { + result = get_root_script(); + } else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) { + result = E->value.ptr(); + } else if (_owner != nullptr) { + // Check parent scope. + return _owner->find_class(p_qualified_name); + } + + int name_count = p_qualified_name.get_slice_count("::"); + for (int i = 1; result != nullptr && i < name_count; i++) { + String current_name = p_qualified_name.get_slice("::", i); + if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) { + result = E->value.ptr(); + } else { + // Couldn't find inner class. + return nullptr; + } + } + + return result; +} + +bool GDScript::is_subclass(const GDScript *p_script) { + String fqn = p_script->fully_qualified_name; + if (!fqn.is_empty() && fqn != fully_qualified_name && fqn.begins_with(fully_qualified_name)) { + String fqn_rest = fqn.substr(fully_qualified_name.length()); + return find_class(fqn_rest) == p_script; + } + return false; +} + +GDScript *GDScript::get_root_script() { + GDScript *result = this; + while (result->_owner) { + result = result->_owner; + } + return result; +} + bool GDScript::has_script_signal(const StringName &p_signal) const { if (_signals.has(p_signal)) { return true; @@ -1185,7 +1198,7 @@ GDScript::GDScript() : script_list(this) { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.add(&script_list); } @@ -1231,32 +1244,18 @@ void GDScript::_init_rpc_methods_properties() { rpc_config = base->rpc_config.duplicate(); } - GDScript *cscript = this; - HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin(); - while (cscript) { - // RPC Methods - for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) { - Variant config = E.value->get_rpc_config(); - if (config.get_type() != Variant::NIL) { - rpc_config[E.value->get_name()] = config; - } - } - - if (cscript != this) { - ++sub_E; - } - - if (sub_E) { - cscript = sub_E->value.ptr(); - } else { - cscript = nullptr; + // RPC Methods + for (KeyValue<StringName, GDScriptFunction *> &E : member_functions) { + Variant config = E.value->get_rpc_config(); + if (config.get_type() != Variant::NIL) { + rpc_config[E.value->get_name()] = config; } } } GDScript::~GDScript() { { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1293,7 +1292,7 @@ GDScript::~GDScript() { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.remove(&script_list); } @@ -1720,7 +1719,7 @@ GDScriptInstance::GDScriptInstance() { } GDScriptInstance::~GDScriptInstance() { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1823,7 +1822,7 @@ void GDScriptLanguage::finish() { void GDScriptLanguage::profiling_start() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1845,7 +1844,7 @@ void GDScriptLanguage::profiling_start() { void GDScriptLanguage::profiling_stop() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); profiling = false; #endif @@ -1855,7 +1854,7 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1878,7 +1877,7 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_ int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1924,7 +1923,7 @@ void GDScriptLanguage::reload_all_scripts() { print_verbose("GDScript: Reloading all scripts"); List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1940,10 +1939,10 @@ void GDScriptLanguage::reload_all_scripts() { scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - print_verbose("GDScript: Reloading: " + script->get_path()); - script->load_source_code(script->get_path()); - script->reload(true); + for (Ref<GDScript> &scr : scripts) { + print_verbose("GDScript: Reloading: " + scr->get_path()); + scr->load_source_code(scr->get_path()); + scr->reload(true); } #endif } @@ -1953,7 +1952,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1972,21 +1971,21 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - bool reload = script == p_script || to_reload.has(script->get_base()); + for (Ref<GDScript> &scr : scripts) { + bool reload = scr == p_script || to_reload.has(scr->get_base()); if (!reload) { continue; } - to_reload.insert(script, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); + to_reload.insert(scr, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); if (!p_soft_reload) { //save state and remove script from instances - HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script]; + HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[scr]; - while (script->instances.front()) { - Object *obj = script->instances.front()->get(); + while (scr->instances.front()) { + Object *obj = scr->instances.front()->get(); //save instance info List<Pair<StringName, Variant>> state; if (obj->get_script_instance()) { @@ -1999,8 +1998,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //same thing for placeholders #ifdef TOOLS_ENABLED - while (script->placeholders.size()) { - Object *obj = (*script->placeholders.begin())->get_owner(); + while (scr->placeholders.size()) { + Object *obj = (*scr->placeholders.begin())->get_owner(); //save instance info if (obj->get_script_instance()) { @@ -2010,13 +2009,13 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so obj->set_script(Variant()); } else { // no instance found. Let's remove it so we don't loop forever - script->placeholders.erase(*script->placeholders.begin()); + scr->placeholders.erase(*scr->placeholders.begin()); } } #endif - for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : script->pending_reload_state) { + for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : scr->pending_reload_state) { map[F.key] = F.value; //pending to reload, use this one instead } } @@ -2041,9 +2040,9 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } obj->set_script(scr); - ScriptInstance *script_instance = obj->get_script_instance(); + ScriptInstance *script_inst = obj->get_script_instance(); - if (!script_instance) { + if (!script_inst) { //failed, save reload state for next time if not saved if (!scr->pending_reload_state.has(obj->get_instance_id())) { scr->pending_reload_state[obj->get_instance_id()] = saved_state; @@ -2051,14 +2050,14 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so continue; } - if (script_instance->is_placeholder() && scr->is_placeholder_fallback_enabled()) { - PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_instance); + if (script_inst->is_placeholder() && scr->is_placeholder_fallback_enabled()) { + PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_inst); for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { placeholder->property_set_fallback(G->get().first, G->get().second); } } else { for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { - script_instance->set(G->get().first, G->get().second); + script_inst->set(G->get().first, G->get().second); } } @@ -2076,7 +2075,7 @@ void GDScriptLanguage::frame() { #ifdef DEBUG_ENABLED if (profiling) { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -2337,26 +2336,26 @@ GDScriptLanguage::~GDScriptLanguage() { // Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit). SelfList<GDScript> *s = script_list.first(); while (s) { - GDScript *script = s->self(); + GDScript *scr = s->self(); // This ensures the current script is not released before we can check what's the next one // in the list (we can't get the next upfront because we don't know if the reference breaking // will cause it -or any other after it, for that matter- to be released so the next one // is not the same as before). - script->reference(); + scr->reference(); - for (KeyValue<StringName, GDScriptFunction *> &E : script->member_functions) { + for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) { GDScriptFunction *func = E.value; for (int i = 0; i < func->argument_types.size(); i++) { func->argument_types.write[i].script_type_ref = Ref<Script>(); } func->return_type.script_type_ref = Ref<Script>(); } - for (KeyValue<StringName, GDScript::MemberInfo> &E : script->member_indices) { + for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) { E.value.data_type.script_type_ref = Ref<Script>(); } s = s->next(); - script->unreference(); + scr->unreference(); } singleton = nullptr; @@ -2388,20 +2387,20 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str } Error err; - Ref<GDScript> script = GDScriptCache::get_full_script(p_path, err); + Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE); // TODO: Reintroduce binary and encrypted scripts. - if (script.is_null()) { + if (scr.is_null()) { // Don't fail loading because of parsing error. - script.instantiate(); + scr.instantiate(); } if (r_error) { *r_error = OK; } - return script; + return scr; } void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { |