From 22236380c033a1d441d9b35b4bc1529218d4e39d Mon Sep 17 00:00:00 2001 From: George Marques Date: Thu, 2 May 2024 15:06:07 -0300 Subject: [PATCH] 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. --- modules/gdscript/gdscript.cpp | 24 ++++++++++++++++++++++++ modules/gdscript/gdscript.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index f238958f259a..3092f22eed01 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -678,6 +678,27 @@ Error GDScript::_static_init() { #ifdef TOOLS_ENABLED +void GDScript::_static_default_init() { + for (const KeyValue &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 diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 7bd68ac0b170..88e7a27ce7e6 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -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 instances;