-
-
Notifications
You must be signed in to change notification settings - Fork 21.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix incorrect handling of exported typed dictionaries containing nodes in .NET #97948
Fix incorrect handling of exported typed dictionaries containing nodes in .NET #97948
Conversation
…ch led to incorrect scene serialization
…en their default value is null
|
||
_parse_dictionary_hint_string(dnp_base_prop.hint_string, key_subtype, key_subtype_hint, &key_class_name, value_subtype, value_subtype_hint, &value_class_name); | ||
|
||
dict.set_typed(key_subtype, StringName(key_class_name), Variant(), value_subtype, StringName(value_class_name), Variant()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not entirely correct if the type arguments for the dictionary are script types. However, the hint string does not include any information about scripts, so I'm not sure what the best way to address it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution. You are totally right about the Dictionary hint being wrong, but I don't really understand the part about set_typed
. We're not calling set_typed
for typed Arrays and that works fine with arrays of nodes (e.g.: Godot.Collections.Array<Label>
). So I feel like there may be a way to fix the bug without set_typed
.
Calling set_typed
is probably something that we should do anyway, and not just on Dictionary but on Array as well. However, I don't really like the current PR's implementation, it relays heavily on reflection which may be incompatible with trimming/NativeAOT, and may add substantial cost to typed Dictionaries which may be unacceptable to some users.
I have not looked at the changes to packed_scene.cpp
at all, that's an area of Godot I'm not very familiar with so I don't think I can comment on it.
@@ -791,7 +795,7 @@ static bool GetStringArrayEnumHint(VariantType elementVariantType, | |||
} | |||
} | |||
|
|||
hint = PropertyHint.DictionaryType; | |||
hint = containsNodeType ? PropertyHint.TypeString : PropertyHint.DictionaryType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should always be PropertyHint.TypeString
, no need for the containsNodeType
variable.
hint = containsNodeType ? PropertyHint.TypeString : PropertyHint.DictionaryType; | |
hint = PropertyHint.TypeString; |
The reason why I think You are correct that, to be thorough, arrays should have a |
Well, what I was getting at was that I would separate the property hint changes from the But I think whatever PR includes the |
This should fix #97850. This pull request consists of multiple commits because there are multiple distinct bugs that needed to be fixed.
As observed here, the scene is written with a copy of the node selected in the inspector instead of a path to it. The reason for this is that the property hint that the scene serializer looks for to rewrite node references as paths is PROPERTY_HINT_TYPE_STRING, but the code generation for exposing .NET properties to Godot does not account for this. That's fixed here.
With that first bug fixed, another one reveals itself: the nodes in the exported dictionary are all nulled out on the .NET side of things. Looking further with
Get(nameof(Controls))
, what is happening is that the node paths that are stored in the scene are not being turned back into node references. The scene reader is getting an untyped dictionary, which causes the relevantget_typed_*_builtin
to not returnVariant::OBJECT
. The fix is to callset_typed
on typed dictionaries from .NET so Godot also sees them as typed dictionaries.These two fixes are still not enough because if no default non-null value is provided for the exported dictionary, which is the case in the MRP given, the scene reader still fails to convert node paths to the expected node type. That's fixed here.
Here's an updated MRP with a patched scene, because the first bug makes changes to the scene that are not easily reverted automatically: MRP-97850-patched-scene.zip
Do note that because of #97190, the scene will not load correctly if you open it before building the project, so make sure you do that.