diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index fcb7a11a14a5..dcca12ab7d7c 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -598,6 +598,17 @@ [/codeblock] + + + + Export a property with [constant PROPERTY_USAGE_STORAGE] flag. The property is not displayed in the editor, but it is serialized and stored in the scene or resource file. This can be useful for [annotation @tool] scripts. Also the property value is copied when [method Resource.duplicate] or [method Node.duplicate] is called, unlike non-exported variables. + [codeblock] + var a # Not stored in the file, not displayed in the editor. + @export_storage var b # Stored in the file, not displayed in the editor. + @export var c: int # Stored in the file, displayed in the editor. + [/codeblock] + + diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index f3a4f2eaa692..086cdbbbf1a6 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -100,6 +100,7 @@ GDScriptParser::GDScriptParser() { register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation); // Export annotations. register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); + register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations, varray(), true); register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations, varray(""), true); register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations); @@ -3996,11 +3997,11 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node } hint_string += arg_string; } - variable->export_info.hint_string = hint_string; // This is called after the analyzer is done finding the type, so this should be set here. DataType export_type = variable->get_datatype(); + bool use_default_variable_type_check = true; if (p_annotation->name == SNAME("@export_range")) { if (export_type.builtin_type == Variant::INT) { @@ -4032,11 +4033,9 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node return true; } - } + } else if (p_annotation->name == SNAME("@export")) { + use_default_variable_type_check = false; - // WARNING: Do not merge with the previous `else if`! Otherwise `else` (default variable type check) - // will not work for the above annotations. `@export` and `@export_enum` validate the type separately. - if (p_annotation->name == SNAME("@export")) { if (variable->datatype_specifier == nullptr && variable->initializer == nullptr) { push_error(R"(Cannot use simple "@export" annotation with variable without type or initializer, since type can't be inferred.)", p_annotation); return false; @@ -4154,6 +4153,8 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node variable->export_info.type = Variant::ARRAY; } } else if (p_annotation->name == SNAME("@export_enum")) { + use_default_variable_type_check = false; + Variant::Type enum_type = Variant::INT; if (export_type.kind == DataType::BUILTIN && export_type.builtin_type == Variant::STRING) { @@ -4171,7 +4172,15 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node push_error(vformat(R"("@export_enum" annotation requires a variable of type "int" or "String" but type "%s" was given instead.)", export_type.to_string()), variable); return false; } - } else { + } else if (p_annotation->name == SNAME("@export_storage")) { + use_default_variable_type_check = false; // Can be applied to a variable of any type. + + // Save the info because the compiler uses export info for overwriting member info. + variable->export_info = export_type.to_property_info(variable->identifier->name); + variable->export_info.usage |= PROPERTY_USAGE_STORAGE; + } + + if (use_default_variable_type_check) { // Validate variable type with export. if (!export_type.is_variant() && (export_type.kind != DataType::BUILTIN || export_type.builtin_type != t_type)) { // Allow float/int conversion. diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd index dafd2ec0c818..39f490c4b3ea 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd @@ -4,14 +4,13 @@ enum MyEnum {A, B, C} const Utils = preload("../../utils.notest.gd") -@export var x1 = MyEnum -@export var x2 = MyEnum.A -@export var x3 := MyEnum -@export var x4 := MyEnum.A -@export var x5: MyEnum +@export var test_1 = MyEnum +@export var test_2 = MyEnum.A +@export var test_3 := MyEnum +@export var test_4 := MyEnum.A +@export var test_5: MyEnum func test(): for property in get_property_list(): - if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE: - print(Utils.get_property_signature(property)) - print(" ", Utils.get_property_additional_info(property)) + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property) diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out index f1a13f10454e..505af5f1f397 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out +++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out @@ -1,11 +1,11 @@ GDTEST_OK -@export var x1: Dictionary +var test_1: Dictionary hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE -@export var x2: TestExportEnumAsDictionary.MyEnum +var test_2: TestExportEnumAsDictionary.MyEnum hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM -@export var x3: Dictionary +var test_3: Dictionary hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE -@export var x4: TestExportEnumAsDictionary.MyEnum +var test_4: TestExportEnumAsDictionary.MyEnum hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM -@export var x5: TestExportEnumAsDictionary.MyEnum +var test_5: TestExportEnumAsDictionary.MyEnum hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM diff --git a/modules/gdscript/tests/scripts/parser/features/annotations.gd b/modules/gdscript/tests/scripts/parser/features/annotations.gd index 13c89a0a09dd..7a7d6d953e92 100644 --- a/modules/gdscript/tests/scripts/parser/features/annotations.gd +++ b/modules/gdscript/tests/scripts/parser/features/annotations.gd @@ -1,48 +1,49 @@ extends Node -@export_enum("A", "B", "C") var a0 -@export_enum("A", "B", "C",) var a1 +const Utils = preload("../../utils.notest.gd") + +@export_enum("A", "B", "C") var test_1 +@export_enum("A", "B", "C",) var test_2 @export_enum( "A", "B", "C" -) var a2 +) var test_3 @export_enum( "A", "B", "C", -) var a3 +) var test_4 @export -var a4: int +var test_5: int @export() -var a5: int +var test_6: int -@export() var a6: int -@warning_ignore("onready_with_export") @onready @export var a7: int -@warning_ignore("onready_with_export") @onready() @export() var a8: int +@export() var test_7: int = 42 +@warning_ignore("onready_with_export") @onready @export var test_8: int = 42 +@warning_ignore("onready_with_export") @onready() @export() var test_9: int = 42 @warning_ignore("onready_with_export") @onready @export -var a9: int +var test_10: int = 42 @warning_ignore("onready_with_export") @onready() @export() -var a10: int +var test_11: int = 42 @warning_ignore("onready_with_export") @onready() @export() -var a11: int - +var test_12: int = 42 func test(): for property in get_property_list(): - if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE: - print(property) + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property, self) diff --git a/modules/gdscript/tests/scripts/parser/features/annotations.out b/modules/gdscript/tests/scripts/parser/features/annotations.out index 3af0436c533f..2ba9dd7496e0 100644 --- a/modules/gdscript/tests/scripts/parser/features/annotations.out +++ b/modules/gdscript/tests/scripts/parser/features/annotations.out @@ -1,13 +1,25 @@ GDTEST_OK -{ "name": "a0", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 } -{ "name": "a1", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 } -{ "name": "a2", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 } -{ "name": "a3", "class_name": &"", "type": 2, "hint": 2, "hint_string": "A,B,C", "usage": 4102 } -{ "name": "a4", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a5", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a6", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a7", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a8", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a9", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a10", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "a11", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } +var test_1: int = null + hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE +var test_2: int = null + hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE +var test_3: int = null + hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE +var test_4: int = null + hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE +var test_5: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_6: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_7: int = 42 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_8: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_9: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_10: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_11: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_12: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.gd b/modules/gdscript/tests/scripts/parser/features/export_enum.gd index 9b2c22dea13d..4f2a43f4fe51 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_enum.gd +++ b/modules/gdscript/tests/scripts/parser/features/export_enum.gd @@ -1,15 +1,16 @@ -@export_enum("Red", "Green", "Blue") var untyped +const Utils = preload("../../utils.notest.gd") -@export_enum("Red", "Green", "Blue") var weak_int = 0 -@export_enum("Red", "Green", "Blue") var weak_string = "" +@export_enum("Red", "Green", "Blue") var test_untyped -@export_enum("Red", "Green", "Blue") var hard_int: int -@export_enum("Red", "Green", "Blue") var hard_string: String +@export_enum("Red", "Green", "Blue") var test_weak_int = 0 +@export_enum("Red", "Green", "Blue") var test_weak_string = "" -@export_enum("Red:10", "Green:20", "Blue:30") var with_values +@export_enum("Red", "Green", "Blue") var test_hard_int: int +@export_enum("Red", "Green", "Blue") var test_hard_string: String + +@export_enum("Red:10", "Green:20", "Blue:30") var test_with_values func test(): for property in get_property_list(): - if property.name in ["untyped", "weak_int", "weak_string", "hard_int", - "hard_string", "with_values"]: - prints(property.name, property.type, property.hint_string) + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property, self) diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.out b/modules/gdscript/tests/scripts/parser/features/export_enum.out index 330b7eaf01fb..43f5e197ad68 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_enum.out +++ b/modules/gdscript/tests/scripts/parser/features/export_enum.out @@ -1,7 +1,13 @@ GDTEST_OK -untyped 2 Red,Green,Blue -weak_int 2 Red,Green,Blue -weak_string 4 Red,Green,Blue -hard_int 2 Red,Green,Blue -hard_string 4 Red,Green,Blue -with_values 2 Red:10,Green:20,Blue:30 +var test_untyped: int = null + hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE +var test_weak_int: int = 0 + hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE +var test_weak_string: String = "" + hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE +var test_hard_int: int = 0 + hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE +var test_hard_string: String = "" + hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE +var test_with_values: int = null + hint=ENUM hint_string="Red:10,Green:20,Blue:30" usage=DEFAULT|SCRIPT_VARIABLE diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.gd b/modules/gdscript/tests/scripts/parser/features/export_variable.gd index c9d05a7e684d..2a218774de8d 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_variable.gd +++ b/modules/gdscript/tests/scripts/parser/features/export_variable.gd @@ -1,23 +1,22 @@ extends Node -@export var example = 99 -@export_range(0, 100) var example_range = 100 -@export_range(0, 100, 1) var example_range_step = 101 -@export_range(0, 100, 1, "or_greater") var example_range_step_or_greater = 102 +const Utils = preload("../../utils.notest.gd") -@export var color: Color -@export_color_no_alpha var color_no_alpha: Color -@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var nodepath := ^"hello" -@export var node: Node -@export var node_array: Array[Node] +@export var test_weak_int = 1 +@export var test_hard_int: int = 2 +@export_storage var test_storage_untyped +@export_storage var test_storage_weak_int = 3 # Property info still `Variant`, unlike `@export`. +@export_storage var test_storage_hard_int: int = 4 +@export_range(0, 100) var test_range = 100 +@export_range(0, 100, 1) var test_range_step = 101 +@export_range(0, 100, 1, "or_greater") var test_range_step_or_greater = 102 +@export var test_color: Color +@export_color_no_alpha var test_color_no_alpha: Color +@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var test_node_path := ^"hello" +@export var test_node: Node +@export var test_node_array: Array[Node] func test(): - print(example) - print(example_range) - print(example_range_step) - print(example_range_step_or_greater) - print(color) - print(color_no_alpha) - print(nodepath) - print(node) - print(var_to_str(node_array)) + for property in get_property_list(): + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property, self) diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.out b/modules/gdscript/tests/scripts/parser/features/export_variable.out index 5430c975f4de..baadcd4ee82f 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_variable.out +++ b/modules/gdscript/tests/scripts/parser/features/export_variable.out @@ -1,10 +1,27 @@ GDTEST_OK -99 -100 -101 -102 -(0, 0, 0, 1) -(0, 0, 0, 1) -hello - -Array[Node]([]) +var test_weak_int: int = 1 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_hard_int: int = 2 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +var test_storage_untyped: Variant = null + hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT +var test_storage_weak_int: Variant = 3 + hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT +var test_storage_hard_int: int = 4 + hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE +var test_range: int = 100 + hint=RANGE hint_string="0,100" usage=DEFAULT|SCRIPT_VARIABLE +var test_range_step: int = 101 + hint=RANGE hint_string="0,100,1" usage=DEFAULT|SCRIPT_VARIABLE +var test_range_step_or_greater: int = 102 + hint=RANGE hint_string="0,100,1,or_greater" usage=DEFAULT|SCRIPT_VARIABLE +var test_color: Color = Color(0, 0, 0, 1) + hint=NONE hint_string="Color" usage=DEFAULT|SCRIPT_VARIABLE +var test_color_no_alpha: Color = Color(0, 0, 0, 1) + hint=COLOR_NO_ALPHA hint_string="" usage=DEFAULT|SCRIPT_VARIABLE +var test_node_path: NodePath = NodePath("hello") + hint=NODE_PATH_VALID_TYPES hint_string="Sprite2D,Sprite3D,Control,Node" usage=DEFAULT|SCRIPT_VARIABLE +var test_node: Node = null + hint=NODE_TYPE hint_string="Node" usage=DEFAULT|SCRIPT_VARIABLE +var test_node_array: Array = Array[Node]([]) + hint=TYPE_STRING hint_string="24/34:Node" usage=DEFAULT|SCRIPT_VARIABLE diff --git a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd index e46f24cc5f33..0133d7fcfcc5 100644 --- a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd +++ b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.gd @@ -1,17 +1,17 @@ -extends RefCounted # TODO: Fix standalone annotations parsing. +const Utils = preload("../../utils.notest.gd") # GH-73843 @export_group("Resource") # GH-78252 -@export var prop_1: int -@export_category("prop_1") -@export var prop_2: int +@export var test_1: int +@export_category("test_1") +@export var test_2: int func test(): var resource := Resource.new() prints("Not shadowed:", resource.get_class()) for property in get_property_list(): - if property.name in ["prop_1", "prop_2"]: - print(property) + if str(property.name).begins_with("test_"): + Utils.print_property_extended_info(property, self) diff --git a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out index 96ae84e986ff..9387ec50d7c4 100644 --- a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out +++ b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out @@ -1,5 +1,8 @@ GDTEST_OK Not shadowed: Resource -{ "name": "prop_1", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } -{ "name": "prop_1", "class_name": &"", "type": 0, "hint": 0, "hint_string": "", "usage": 128 } -{ "name": "prop_2", "class_name": &"", "type": 2, "hint": 0, "hint_string": "int", "usage": 4102 } +var test_1: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE +@export_category("test_1") + hint=NONE hint_string="" usage=CATEGORY +var test_2: int = 0 + hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.gd b/modules/gdscript/tests/scripts/runtime/features/member_info.gd index 805ea42455c9..6fe9647b4d3b 100644 --- a/modules/gdscript/tests/scripts/runtime/features/member_info.gd +++ b/modules/gdscript/tests/scripts/runtime/features/member_info.gd @@ -60,7 +60,7 @@ func test(): var script: Script = get_script() for property in script.get_property_list(): if str(property.name).begins_with("test_"): - print(Utils.get_property_signature(property, true)) + print(Utils.get_property_signature(property, null, true)) for property in get_property_list(): if str(property.name).begins_with("test_"): print(Utils.get_property_signature(property)) diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.out b/modules/gdscript/tests/scripts/runtime/features/member_info.out index 3a91507da91d..7c826ac05a84 100644 --- a/modules/gdscript/tests/scripts/runtime/features/member_info.out +++ b/modules/gdscript/tests/scripts/runtime/features/member_info.out @@ -6,13 +6,13 @@ static var test_static_var_hard_int: int var test_var_untyped: Variant var test_var_weak_null: Variant var test_var_weak_int: Variant -@export var test_var_weak_int_exported: int +var test_var_weak_int_exported: int var test_var_weak_variant_type: Variant -@export var test_var_weak_variant_type_exported: Variant.Type +var test_var_weak_variant_type_exported: Variant.Type var test_var_hard_variant: Variant var test_var_hard_int: int var test_var_hard_variant_type: Variant.Type -@export var test_var_hard_variant_type_exported: Variant.Type +var test_var_hard_variant_type_exported: Variant.Type var test_var_hard_node_process_mode: Node.ProcessMode var test_var_hard_my_enum: TestMemberInfo.MyEnum var test_var_hard_array: Array diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd index d0cbeeab85b1..563c6ce569cc 100644 --- a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd +++ b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd @@ -30,7 +30,7 @@ func test(): var b := B.new() for property in (B as GDScript).get_property_list(): if str(property.name).begins_with("test_"): - print(Utils.get_property_signature(property, true)) + print(Utils.get_property_signature(property, null, true)) print("---") for property in b.get_property_list(): if str(property.name).begins_with("test_"): diff --git a/modules/gdscript/tests/scripts/utils.notest.gd b/modules/gdscript/tests/scripts/utils.notest.gd index 781843b8e276..31818c9d018f 100644 --- a/modules/gdscript/tests/scripts/utils.notest.gd +++ b/modules/gdscript/tests/scripts/utils.notest.gd @@ -20,24 +20,32 @@ static func get_type(property: Dictionary, is_return: bool = false) -> String: return type_string(property.type) -static func get_property_signature(property: Dictionary, is_static: bool = false) -> String: +static func get_property_signature(property: Dictionary, base: Object = null, is_static: bool = false) -> String: + if property.usage & PROPERTY_USAGE_CATEGORY: + return '@export_category("%s")' % str(property.name).c_escape() + if property.usage & PROPERTY_USAGE_GROUP: + return '@export_group("%s")' % str(property.name).c_escape() + if property.usage & PROPERTY_USAGE_SUBGROUP: + return '@export_subgroup("%s")' % str(property.name).c_escape() + var result: String = "" if not (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE): printerr("Missing `PROPERTY_USAGE_SCRIPT_VARIABLE` flag.") - if property.usage & PROPERTY_USAGE_DEFAULT: - result += "@export " if is_static: result += "static " result += "var " + property.name + ": " + get_type(property) + if is_instance_valid(base): + result += " = " + var_to_str(base.get(property.name)) return result -static func get_property_additional_info(property: Dictionary) -> String: - return 'hint=%s hint_string="%s" usage=%s' % [ +static func print_property_extended_info(property: Dictionary, base: Object = null, is_static: bool = false) -> void: + print(get_property_signature(property, base, is_static)) + print(' hint=%s hint_string="%s" usage=%s' % [ get_property_hint_name(property.hint).trim_prefix("PROPERTY_HINT_"), str(property.hint_string).c_escape(), get_property_usage_string(property.usage).replace("PROPERTY_USAGE_", ""), - ] + ]) static func get_method_signature(method: Dictionary, is_signal: bool = false) -> String: @@ -153,7 +161,6 @@ static func get_property_usage_string(usage: int) -> String: return "PROPERTY_USAGE_NONE" const FLAGS: Array[Array] = [ - [PROPERTY_USAGE_DEFAULT, "PROPERTY_USAGE_DEFAULT"], [PROPERTY_USAGE_STORAGE, "PROPERTY_USAGE_STORAGE"], [PROPERTY_USAGE_EDITOR, "PROPERTY_USAGE_EDITOR"], [PROPERTY_USAGE_INTERNAL, "PROPERTY_USAGE_INTERNAL"], @@ -187,6 +194,10 @@ static func get_property_usage_string(usage: int) -> String: var result: String = "" + if (usage & PROPERTY_USAGE_DEFAULT) == PROPERTY_USAGE_DEFAULT: + result += "PROPERTY_USAGE_DEFAULT|" + usage &= ~PROPERTY_USAGE_DEFAULT + for flag in FLAGS: if usage & flag[0]: result += flag[1] + "|"