-
-
Notifications
You must be signed in to change notification settings - Fork 21.9k
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
Improve handling of generic C# types #87890
Conversation
88878bc
to
2dbeb49
Compare
if (GetPathOtherwiseGetOrCreateScript(scriptType, outScript, out string? scriptPath)) | ||
{ | ||
// This path is slower, but it's only executed for the first instantiation of the type | ||
|
||
if (scriptType.IsConstructedGenericType) |
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.
At that point, if this condition is true
, it is possible that scriptPath
already contains a csharp://
path, right? If that's the case, GetVirtualConstructedGenericTypeScriptPath
will throw.
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.
That's a really good point, but I don't think it actually ever happens in practice. We only reach this code when GetPathOtherwiseGetOrCreateScript
returns true
, and that only happens when there is no existing script registered in _scriptTypeBiMap
.
The first time this code executes, when the script hasn't been created yet and thus it's not in _scriptTypeBiMap
, the virtual path (csharp://
) will also not have been added to _pathTypeBiMap
. At this time, the script is created and added with the virtual path to both bimaps, so this code should not be reachable again after that.
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.
I've seen it raised a few times when I was testing earlier. But can't reproduce reliably. I'm wondering if that might have been a compounding error from the one @zaevi reported above (that I witnessed too).
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.
I was wrong, if the script is freed then it can happen because the path will still be in _pathTypeBiMap
but the script will have been removed from _scriptTypeBiMap
. I guess I will also check here if the path starts with csharp://
and avoid entering the if.
2dbeb49
to
2895754
Compare
@zaevi Interesting, it doesn't throw in Linux so I didn't notice. Should be fixed now. |
I'm having weird behaviours with export updates + the error I'm talking about above. See video attached. godot.windows.editor.dev.x86_64.mono_6ur3hBmru1.mp4 |
Could be caused by the cache. It's ok after I delete the |
@paulloz Thanks, I can reproduce following the steps in the video. I'm having the same behavior in 4.2.1-stable. The inspector plugin does not seem to be called at all when modifying generic scripts, but it doesn't seem to be introduced by this PR. Oh I see, for generic scripts like godot/modules/mono/csharp_script.cpp Line 2223 in d335281
We would not be able to update the exports anyway, since it's a generic type definition and we can't call C# methods on an unbound generic. Not sure how we could fix this so I guess I'll leave it for the future since it's a pre-existing issue. I'm also able to reproduce the other error you mentioned, I don't know why I didn't encounter it before. |
2895754
to
e7b6ec9
Compare
You are right about the inspector plugin, but the exports themselves should appear after a build. They currently do on godot.windows.editor.dev.x86_64.mono_9zcHO52g8q.mp4
But at that point the generic type is fully bound, since it's the once in the class hierarchy of a valid node. |
Oh, you are right. I feel like I tested this and it wasn't working. Thank you for testing.
I mean the empty CSharpScript with the path I have checked and it seems |
Back to the reloading order again... Is it possible to somehow refractor the reloading logic to ensure this editor reserialization call comes after a complete iteration of |
e7b6ec9
to
f896c8d
Compare
That sounds like it require drastic changes to the reload logic which risk introducing bugs, I'm not sure it's worth doing such a big change since we'll be moving away from scripts in the future.
I was curious why it was working in So I made scripts with Edit: Also rebased to fix the conflict with InspectorPlugin. |
- Create CSharpScript for generic C# types. - `ScriptPathAttributeGenerator` registers the path for the generic type definition. - `ScriptManagerBridge` lookup uses the generic type definition that was registered by the generator. - Constructed generic types use a virtual `csharp://` path so they can be registered in the map and loaded as if there was a different file for each constructed type, even though they all share the same real path. - This allows getting the base type for a C# type that derives from a generic type. - Shows base scripts in the _Add Node_ and _Create Resource_ dialogs even when they are generic types. - `get_global_class_name` implementation was moved to C# and now always returns the base type even if the script is not a global class (this behavior matches GDScript). - Create `CSharpScript::TypeInfo` struct to hold all the type information about the C# type that corresponds to the `CSharpScript`, and use it as the parameter in `UpdateScriptClassInfo` to avoid adding more parameters.
f896c8d
to
5815d1c
Compare
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.
Seems to work fine from my tests. It's still possible we'll have some weird behaviours since it's a large-ish change, but I'm fairly confident 👌
Thanks! |
Could you, please, elaborate a bit on "we'll be moving away from scripts in the future" ? :) Also if there's any roadmap for C# features in the future, could you or anyone point me the link(s) ? Thank you. |
Improve handling of generic C# types
ScriptPathAttributeGenerator
registers the path for the generic type definition.ScriptManagerBridge
lookup uses the generic type definition that was registered by the generator.csharp://
path so they can be registered in the map and loaded as if there was a different file for each constructed type, even though they all share the same real path.get_global_class_name
implementation was moved to C# and now always returns the base type even if the script is not a global class (this behavior matches GDScript).CSharpScript::TypeInfo
struct to hold all the type information about the C# type that corresponds to theCSharpScript
, and use it as the parameter inUpdateScriptClassInfo
to avoid adding more parameters.There's also a little bit of background on these previously merged PRs:
Godot.SourceGenerators
for generic classes #55597.