summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript.cpp')
-rw-r--r--modules/gdscript/gdscript.cpp365
1 files changed, 216 insertions, 149 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 20d424894a..64287cce99 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -53,9 +53,11 @@
#include "core/io/file_access_encrypted.h"
#include "core/os/os.h"
+#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
#ifdef TOOLS_ENABLED
+#include "core/extension/gdextension_manager.h"
#include "editor/editor_paths.h"
#endif
@@ -74,9 +76,16 @@ bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
if (ok) {
r_ret = v;
return true;
- } else {
- return false;
}
+
+ MethodBind *method = ClassDB::get_method(name, p_name);
+ if (method && method->is_static()) {
+ // Native static method.
+ r_ret = Callable(this, p_name);
+ return true;
+ }
+
+ return false;
}
void GDScriptNativeClass::_bind_methods() {
@@ -115,7 +124,7 @@ Variant GDScriptNativeClass::callp(const StringName &p_method, const Variant **p
}
GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) {
- if (p_script->initializer) {
+ if (likely(p_script->valid) && p_script->initializer) {
return p_script->initializer;
} else {
GDScript *base_src = p_script->_base;
@@ -136,7 +145,11 @@ void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance
}
}
ERR_FAIL_NULL(p_script->implicit_initializer);
- p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error);
+ if (likely(p_script->valid)) {
+ p_script->implicit_initializer->call(p_instance, nullptr, 0, r_error);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ }
}
GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
@@ -662,7 +675,7 @@ String GDScript::_get_debug_path() const {
}
Error GDScript::_static_init() {
- if (static_initializer) {
+ if (likely(valid) && static_initializer) {
Callable::CallError call_err;
static_initializer->call(nullptr, nullptr, 0, call_err);
if (call_err.error != Callable::CallError::CALL_OK) {
@@ -679,8 +692,6 @@ Error GDScript::_static_init() {
return err;
}
-#ifdef TOOLS_ENABLED
-
void GDScript::_static_default_init() {
for (const KeyValue<StringName, MemberInfo> &E : static_variables_indices) {
const GDScriptDataType &type = E.value.data_type;
@@ -689,10 +700,16 @@ void GDScript::_static_default_init() {
continue;
}
if (type.builtin_type == Variant::ARRAY && type.has_container_element_type(0)) {
+ const GDScriptDataType element_type = type.get_container_element_type(0);
Array default_value;
- const GDScriptDataType &element_type = type.get_container_element_type(0);
default_value.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
static_variables.write[E.value.index] = default_value;
+ } else if (type.builtin_type == Variant::DICTIONARY && type.has_container_element_types()) {
+ const GDScriptDataType key_type = type.get_container_element_type_or_variant(0);
+ const GDScriptDataType value_type = type.get_container_element_type_or_variant(1);
+ Dictionary default_value;
+ default_value.set_typed(key_type.builtin_type, key_type.native_type, key_type.script_type, value_type.builtin_type, value_type.native_type, value_type.script_type);
+ static_variables.write[E.value.index] = default_value;
} else {
Variant default_value;
Callable::CallError err;
@@ -702,6 +719,8 @@ void GDScript::_static_default_init() {
}
}
+#ifdef TOOLS_ENABLED
+
void GDScript::_save_old_static_data() {
old_static_variables_indices = static_variables_indices;
old_static_variables = static_variables;
@@ -873,9 +892,11 @@ Error GDScript::reload(bool p_keep_state) {
#ifdef TOOLS_ENABLED
if (can_run && p_keep_state) {
_restore_old_static_data();
- } else if (!can_run) {
- // Initialize static variables with sane default values even if the constructor isn't called.
- _static_default_init();
+ }
+
+ if (p_keep_state) {
+ // Update the properties in the inspector.
+ update_exports();
}
#endif
@@ -903,7 +924,7 @@ void GDScript::get_members(HashSet<StringName> *p_members) {
}
}
-const Variant GDScript::get_rpc_config() const {
+Variant GDScript::get_rpc_config() const {
return rpc_config;
}
@@ -912,18 +933,15 @@ void GDScript::unload_static() const {
}
Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (unlikely(!valid)) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
-
GDScript *top = this;
while (top) {
- HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method);
- if (E) {
- ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script.");
+ if (likely(top->valid)) {
+ HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method);
+ if (E) {
+ ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script.");
- return E->value->call(nullptr, p_args, p_argcount, r_error);
+ return E->value->call(nullptr, p_args, p_argcount, r_error);
+ }
}
top = top->_base;
}
@@ -939,10 +957,6 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
- if (unlikely(!valid)) {
- return false;
- }
-
const GDScript *top = this;
while (top) {
{
@@ -956,9 +970,10 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
{
HashMap<StringName, MemberInfo>::ConstIterator E = top->static_variables_indices.find(p_name);
if (E) {
- if (E->value.getter) {
+ if (likely(top->valid) && E->value.getter) {
Callable::CallError ce;
- r_ret = const_cast<GDScript *>(this)->callp(E->value.getter, nullptr, 0, ce);
+ const Variant ret = const_cast<GDScript *>(this)->callp(E->value.getter, nullptr, 0, ce);
+ r_ret = (ce.error == Callable::CallError::CALL_OK) ? ret : Variant();
return true;
}
r_ret = top->static_variables[E->value.index];
@@ -966,7 +981,7 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
}
}
- {
+ if (likely(top->valid)) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = top->member_functions.find(p_name);
if (E && E->value->is_static()) {
if (top->rpc_config.has(p_name)) {
@@ -999,10 +1014,6 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
- if (unlikely(!valid)) {
- return false;
- }
-
GDScript *top = this;
while (top) {
HashMap<StringName, MemberInfo>::ConstIterator E = top->static_variables_indices.find(p_name);
@@ -1017,7 +1028,7 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) {
return false;
}
}
- if (member->setter) {
+ if (likely(top->valid) && member->setter) {
const Variant *args = &value;
Callable::CallError err;
callp(member->setter, &args, 1, err);
@@ -1037,10 +1048,6 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) {
void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
- if (unlikely(!valid)) {
- return;
- }
-
List<const GDScript *> classes;
const GDScript *top = this;
while (top) {
@@ -1551,10 +1558,14 @@ void GDScript::clear(ClearData *p_clear_data) {
}
}
- RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies();
- for (GDScript *E : must_clear_dependencies) {
- clear_data->scripts.insert(E);
- E->clear(clear_data);
+ // If we're in the process of shutting things down then every single script will be cleared
+ // anyway, so we can safely skip this very costly operation.
+ if (!GDScriptLanguage::singleton->finishing) {
+ RBSet<GDScript *> must_clear_dependencies = get_must_clear_dependencies();
+ for (GDScript *E : must_clear_dependencies) {
+ clear_data->scripts.insert(E);
+ E->clear(clear_data);
+ }
}
for (const KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
@@ -1657,10 +1668,6 @@ GDScript::~GDScript() {
//////////////////////////////
bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
- if (unlikely(!script->valid)) {
- return false;
- }
-
{
HashMap<StringName, GDScript::MemberInfo>::Iterator E = script->member_indices.find(p_name);
if (E) {
@@ -1674,7 +1681,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
return false;
}
}
- if (member->setter) {
+ if (likely(script->valid) && member->setter) {
const Variant *args = &value;
Callable::CallError err;
callp(member->setter, &args, 1, err);
@@ -1701,7 +1708,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
return false;
}
}
- if (member->setter) {
+ if (likely(sptr->valid) && member->setter) {
const Variant *args = &value;
Callable::CallError err;
callp(member->setter, &args, 1, err);
@@ -1713,7 +1720,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
}
}
- {
+ if (likely(sptr->valid)) {
HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
if (E) {
Variant name = p_name;
@@ -1734,19 +1741,14 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
}
bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
- if (unlikely(!script->valid)) {
- return false;
- }
-
{
HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = script->member_indices.find(p_name);
if (E) {
- if (E->value.getter) {
+ if (likely(script->valid) && E->value.getter) {
Callable::CallError err;
- r_ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err);
- if (err.error == Callable::CallError::CALL_OK) {
- return true;
- }
+ const Variant ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err);
+ r_ret = (err.error == Callable::CallError::CALL_OK) ? ret : Variant();
+ return true;
}
r_ret = members[E->value.index];
return true;
@@ -1766,9 +1768,10 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
{
HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = sptr->static_variables_indices.find(p_name);
if (E) {
- if (E->value.getter) {
+ if (likely(sptr->valid) && E->value.getter) {
Callable::CallError ce;
- r_ret = const_cast<GDScript *>(sptr)->callp(E->value.getter, nullptr, 0, ce);
+ const Variant ret = const_cast<GDScript *>(sptr)->callp(E->value.getter, nullptr, 0, ce);
+ r_ret = (ce.error == Callable::CallError::CALL_OK) ? ret : Variant();
return true;
}
r_ret = sptr->static_variables[E->value.index];
@@ -1784,7 +1787,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
}
}
- {
+ if (likely(sptr->valid)) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_name);
if (E) {
if (sptr->rpc_config.has(p_name)) {
@@ -1804,7 +1807,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
}
}
- {
+ if (likely(sptr->valid)) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
if (E) {
Variant name = p_name;
@@ -1844,13 +1847,15 @@ void GDScriptInstance::validate_property(PropertyInfo &p_property) const {
const GDScript *sptr = script.ptr();
while (sptr) {
- HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property);
- if (E) {
- Callable::CallError err;
- Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
- if (err.error == Callable::CallError::CALL_OK) {
- p_property = PropertyInfo::from_dict(property);
- return;
+ if (likely(sptr->valid)) {
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property);
+ if (E) {
+ Callable::CallError err;
+ Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
+ if (err.error == Callable::CallError::CALL_OK) {
+ p_property = PropertyInfo::from_dict(property);
+ return;
+ }
}
}
sptr = sptr->_base;
@@ -1858,49 +1863,47 @@ void GDScriptInstance::validate_property(PropertyInfo &p_property) const {
}
void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- if (unlikely(!script->valid)) {
- return;
- }
-
// exported members, not done yet!
const GDScript *sptr = script.ptr();
List<PropertyInfo> props;
while (sptr) {
- HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
- if (E) {
- Callable::CallError err;
- Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err);
- if (err.error == Callable::CallError::CALL_OK) {
- ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries.");
-
- Array arr = ret;
- for (int i = 0; i < arr.size(); i++) {
- Dictionary d = arr[i];
- ERR_CONTINUE(!d.has("name"));
- ERR_CONTINUE(!d.has("type"));
-
- PropertyInfo pinfo;
- pinfo.name = d["name"];
- pinfo.type = Variant::Type(d["type"].operator int());
- if (d.has("hint")) {
- pinfo.hint = PropertyHint(d["hint"].operator int());
- }
- if (d.has("hint_string")) {
- pinfo.hint_string = d["hint_string"];
- }
- if (d.has("usage")) {
- pinfo.usage = d["usage"];
- }
- if (d.has("class_name")) {
- pinfo.class_name = d["class_name"];
- }
+ if (likely(sptr->valid)) {
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
+ if (E) {
+ Callable::CallError err;
+ Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err);
+ if (err.error == Callable::CallError::CALL_OK) {
+ ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries.");
+
+ Array arr = ret;
+ for (int i = 0; i < arr.size(); i++) {
+ Dictionary d = arr[i];
+ ERR_CONTINUE(!d.has("name"));
+ ERR_CONTINUE(!d.has("type"));
+
+ PropertyInfo pinfo;
+ pinfo.name = d["name"];
+ pinfo.type = Variant::Type(d["type"].operator int());
+ if (d.has("hint")) {
+ pinfo.hint = PropertyHint(d["hint"].operator int());
+ }
+ if (d.has("hint_string")) {
+ pinfo.hint_string = d["hint_string"];
+ }
+ if (d.has("usage")) {
+ pinfo.usage = d["usage"];
+ }
+ if (d.has("class_name")) {
+ pinfo.class_name = d["class_name"];
+ }
- ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE));
- ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX);
+ ERR_CONTINUE(pinfo.name.is_empty() && (pinfo.usage & PROPERTY_USAGE_STORAGE));
+ ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX);
- props.push_back(pinfo);
+ props.push_back(pinfo);
+ }
}
}
}
@@ -1940,21 +1943,19 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
}
bool GDScriptInstance::property_can_revert(const StringName &p_name) const {
- if (unlikely(!script->valid)) {
- return false;
- }
-
Variant name = p_name;
const Variant *args[1] = { &name };
const GDScript *sptr = script.ptr();
while (sptr) {
- HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert);
- if (E) {
- Callable::CallError err;
- Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
- if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
- return true;
+ if (likely(sptr->valid)) {
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert);
+ if (E) {
+ Callable::CallError err;
+ Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
+ if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
+ return true;
+ }
}
}
sptr = sptr->_base;
@@ -1964,22 +1965,20 @@ bool GDScriptInstance::property_can_revert(const StringName &p_name) const {
}
bool GDScriptInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const {
- if (unlikely(!script->valid)) {
- return false;
- }
-
Variant name = p_name;
const Variant *args[1] = { &name };
const GDScript *sptr = script.ptr();
while (sptr) {
- HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert);
- if (E) {
- Callable::CallError err;
- Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
- if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
- r_ret = ret;
- return true;
+ if (likely(sptr->valid)) {
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert);
+ if (E) {
+ Callable::CallError err;
+ Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
+ if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
+ r_ret = ret;
+ return true;
+ }
}
}
sptr = sptr->_base;
@@ -2035,30 +2034,28 @@ void GDScriptInstance::_call_implicit_ready_recursively(GDScript *p_script) {
if (p_script->_base) {
_call_implicit_ready_recursively(p_script->_base);
}
- if (p_script->implicit_ready) {
+ if (likely(p_script->valid) && p_script->implicit_ready) {
Callable::CallError err;
p_script->implicit_ready->call(this, nullptr, 0, err);
}
}
Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- if (unlikely(!script->valid)) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
-
GDScript *sptr = script.ptr();
if (unlikely(p_method == SceneStringName(_ready))) {
// Call implicit ready first, including for the super classes recursively.
_call_implicit_ready_recursively(sptr);
}
while (sptr) {
- HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method);
- if (E) {
- return E->value->call(this, p_args, p_argcount, r_error);
+ if (likely(sptr->valid)) {
+ HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method);
+ if (E) {
+ return E->value->call(this, p_args, p_argcount, r_error);
+ }
}
sptr = sptr->_base;
}
+
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
@@ -2083,12 +2080,14 @@ void GDScriptInstance::notification(int p_notification, bool p_reversed) {
sptr = sptr->_base;
}
for (GDScript *sc : pl) {
- HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
- if (E) {
- Callable::CallError err;
- E->value->call(this, args, 1, err);
- if (err.error != Callable::CallError::CALL_OK) {
- //print error about notification call
+ if (likely(sc->valid)) {
+ HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
+ if (E) {
+ Callable::CallError err;
+ E->value->call(this, args, 1, err);
+ if (err.error != Callable::CallError::CALL_OK) {
+ //print error about notification call
+ }
}
}
}
@@ -2198,9 +2197,26 @@ void GDScriptLanguage::_add_global(const StringName &p_name, const Variant &p_va
global_array.write[globals[p_name]] = p_value;
return;
}
- globals[p_name] = global_array.size();
- global_array.push_back(p_value);
- _global_array = global_array.ptrw();
+
+ if (global_array_empty_indexes.size()) {
+ int index = global_array_empty_indexes[global_array_empty_indexes.size() - 1];
+ globals[p_name] = index;
+ global_array.write[index] = p_value;
+ global_array_empty_indexes.resize(global_array_empty_indexes.size() - 1);
+ } else {
+ globals[p_name] = global_array.size();
+ global_array.push_back(p_value);
+ _global_array = global_array.ptrw();
+ }
+}
+
+void GDScriptLanguage::_remove_global(const StringName &p_name) {
+ if (!globals.has(p_name)) {
+ return;
+ }
+ global_array_empty_indexes.push_back(globals[p_name]);
+ global_array.write[globals[p_name]] = Variant::NIL;
+ globals.erase(p_name);
}
void GDScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
@@ -2258,11 +2274,40 @@ void GDScriptLanguage::init() {
_add_global(E.name, E.ptr);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ GDExtensionManager::get_singleton()->connect("extension_loaded", callable_mp(this, &GDScriptLanguage::_extension_loaded));
+ GDExtensionManager::get_singleton()->connect("extension_unloading", callable_mp(this, &GDScriptLanguage::_extension_unloading));
+ }
+#endif
+
#ifdef TESTS_ENABLED
GDScriptTests::GDScriptTestRunner::handle_cmdline();
#endif
}
+#ifdef TOOLS_ENABLED
+void GDScriptLanguage::_extension_loaded(const Ref<GDExtension> &p_extension) {
+ List<StringName> class_list;
+ ClassDB::get_extension_class_list(p_extension, &class_list);
+ for (const StringName &n : class_list) {
+ if (globals.has(n)) {
+ continue;
+ }
+ Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(n));
+ _add_global(n, nc);
+ }
+}
+
+void GDScriptLanguage::_extension_unloading(const Ref<GDExtension> &p_extension) {
+ List<StringName> class_list;
+ ClassDB::get_extension_class_list(p_extension, &class_list);
+ for (const StringName &n : class_list) {
+ _remove_global(n);
+ }
+}
+#endif
+
String GDScriptLanguage::get_type() const {
return "GDScript";
}
@@ -2272,6 +2317,11 @@ String GDScriptLanguage::get_extension() const {
}
void GDScriptLanguage::finish() {
+ if (finishing) {
+ return;
+ }
+ finishing = true;
+
_call_stack.free();
// Clear the cache before parsing the script_list
@@ -2307,6 +2357,8 @@ void GDScriptLanguage::finish() {
}
script_list.clear();
function_list.clear();
+
+ finishing = false;
}
void GDScriptLanguage::profiling_start() {
@@ -2501,11 +2553,11 @@ void GDScriptLanguage::reload_all_scripts() {
}
}
}
-#endif
+#endif // TOOLS_ENABLED
}
reload_scripts(scripts, true);
-#endif
+#endif // DEBUG_ENABLED
}
void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload) {
@@ -2518,7 +2570,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload
SelfList<GDScript> *elem = script_list.first();
while (elem) {
// Scripts will reload all subclasses, so only reload root scripts.
- if (elem->self()->is_root_script() && elem->self()->get_path().is_resource_file()) {
+ if (elem->self()->is_root_script() && !elem->self()->get_path().is_empty()) {
scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
}
elem = elem->next();
@@ -2575,7 +2627,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload
}
}
-#endif
+#endif // TOOLS_ENABLED
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
@@ -2586,7 +2638,19 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload
for (KeyValue<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) {
Ref<GDScript> scr = E.key;
print_verbose("GDScript: Reloading: " + scr->get_path());
- scr->load_source_code(scr->get_path());
+ if (scr->is_built_in()) {
+ // TODO: It would be nice to do it more efficiently than loading the whole scene again.
+ Ref<PackedScene> scene = ResourceLoader::load(scr->get_path().get_slice("::", 0), "", ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP);
+ ERR_CONTINUE(scene.is_null());
+
+ Ref<SceneState> state = scene->get_state();
+ Ref<GDScript> fresh = state->get_sub_resource(scr->get_path());
+ ERR_CONTINUE(fresh.is_null());
+
+ scr->set_source_code(fresh->get_source_code());
+ } else {
+ scr->load_source_code(scr->get_path());
+ }
scr->reload(p_soft_reload);
//restore state if saved
@@ -2631,7 +2695,7 @@ void GDScriptLanguage::reload_scripts(const Array &p_scripts, bool p_soft_reload
//if instance states were saved, set them!
}
-#endif
+#endif // DEBUG_ENABLED
}
void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
@@ -2759,7 +2823,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
String source = f->get_as_utf8_string();
GDScriptParser parser;
- err = parser.parse(source, p_path, false);
+ err = parser.parse(source, p_path, false, false);
const GDScriptParser::ClassNode *c = parser.get_tree();
if (!c) {
@@ -2872,8 +2936,11 @@ GDScriptLanguage::GDScriptLanguage() {
_debug_parse_err_line = -1;
_debug_parse_err_file = "";
+#ifdef DEBUG_ENABLED
profiling = false;
+ profile_native_calls = false;
script_frame_time = 0;
+#endif
int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "512," + itos(GDScriptFunction::MAX_CALL_DEPTH - 1) + ",1"), 1024);