GDScript: Initialize static variables with defaults in-editor
When the script is not marked as `@tool` the static constructor is not called and thus the variables contain `null` by default. But since some validated operations requires a valid value, this would cause a crash. This commit solves this by initializing the static variables with a default value based on their types in the editor, when they are not marked as `@tool`, so if some `@tool` script access them, they will have a valid typed value, avoiding the crash.
This commit is contained in:
parent
06d105e268
commit
22236380c0
2 changed files with 27 additions and 0 deletions
|
@ -678,6 +678,27 @@ Error GDScript::_static_init() {
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
void GDScript::_static_default_init() {
|
||||
for (const KeyValue<StringName, MemberInfo> &E : static_variables_indices) {
|
||||
const GDScriptDataType &type = E.value.data_type;
|
||||
// Only initialize builtin types, which are not expected to be `null`.
|
||||
if (!type.has_type || type.kind != GDScriptDataType::BUILTIN) {
|
||||
continue;
|
||||
}
|
||||
if (type.builtin_type == Variant::ARRAY && type.has_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 {
|
||||
Variant default_value;
|
||||
Callable::CallError err;
|
||||
Variant::construct(type.builtin_type, default_value, nullptr, 0, err);
|
||||
static_variables.write[E.value.index] = default_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GDScript::_save_old_static_data() {
|
||||
old_static_variables_indices = static_variables_indices;
|
||||
old_static_variables = static_variables;
|
||||
|
@ -841,6 +862,9 @@ 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();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -169,6 +169,9 @@ private:
|
|||
GDScriptFunction *static_initializer = nullptr;
|
||||
|
||||
Error _static_init();
|
||||
#ifdef TOOLS_ENABLED
|
||||
void _static_default_init(); // Initialize static variables with default values based on their types.
|
||||
#endif
|
||||
|
||||
int subclass_count = 0;
|
||||
RBSet<Object *> instances;
|
||||
|
|
Loading…
Reference in a new issue