-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
C#: Add global class support #72619
C#: Add global class support #72619
Conversation
Haven't had time to actually review it yet, but I will mention now that the reason I had made the mapped Godot name customizable (but defaulting to the C# class name) was because Reduz mentioned having no intention of introducing namespacing into Godot's centralized user types. If people start namespacing their types using underscored prefixes and the like ( |
I haven't thought about that, but assuming the user's class is inside a namespace we could probably combine the class name with its namespace to register it as a global class and that'd be less likely to conflict. We could also add the ability to customize the name in the future without breaking compatibility so I'd prefer not yo add it for the first implementation. |
6de09d0
to
eee1b95
Compare
Some actual testing later:
[GlobalClass]
public partial class ResCS : Resource
{
[Export]
public string Name;
} try
{
OS.Alert(ResourceSaver.Save(new ResCS() { Name = "string" }, "res://rcs.tres").ToString());
OS.Alert(ResourceLoader.Load<ResCS>("res://rcs.tres").Name);
}
catch (Exception ex)
{
OS.Alert(ex.ToString());
}
|
I have been unable to reproduce 2. Can you share the While testing 2, I think I've run into 3 but I'm not sure of the exact steps to reproduce it. |
OutputTest.zip |
OK, I think I understand what you meant now. Your |
Point 3 also boils down to user error / missing While debugging this I found one additional oddity: The global class list (in the debugger and the new method added on master) contains types not marked as |
b354c25
to
c52261d
Compare
I think global classes should be registered regardless of having the Also, in my testing classes were sometimes unregistered even if they had the
That's odd, while testing I have also been able to see some classes without the I also realized I wasn't assigning some out parameters in |
Does this PR also allow us now to export custom node types as classes or is it an unrelated issue? |
This PR should allow you to use any C# class derived from I don't have screenshots from this PR, but these screenshots from the related GDScript PR and the GDScript documentation for named classes should give you an idea of where these C# global classes would show up: By the way, this should allow us to finally get rid of |
I have been testing this build for a short while and noticed this bug:
Godot_CSharp_bug.mp4Project I used: |
c52261d
to
5f73edd
Compare
The @bleuthoot-sven Thanks for testing, I think this issue may be fixed now, can you try the latest version of this PR? It's in commit 5f73edd5d94cdf659fd842410f3b605cab73cbc5, also make sure to clear the GodotNuGetFallbackFolder directory. |
Yup, seems to work fine now. I have one additional question that is very likely not related to this PR, but discovered it while playing around with this PR. When adding a resource to a node Is this intentional or a (known) issue? |
If it also happens in GDScript, then it seems like the issue is in the inspector code. So it's out of scope for this PR. Not sure if it's a known issue though. |
5f73edd
to
4f56e68
Compare
3dd8725
to
fd95a5e
Compare
fd95a5e
to
aa26f6f
Compare
I briefly tested the current state and didn't manage to immediately crash it again (or find any glaring issues), I'll take a deeper look later. |
Can confirm the issue I mentioned above seem to be fixed now. |
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.
Generally LGTM otherwise, is probably in a state where it could be merged and improved in followups when issues crop up.
I tested with custom resources, nodes, resource loader and main loops.
I encountered two minor somewhat related issues:
ERROR: Script does not inherit a CustomResourceLoader: res://res_loader.cs.
at: (core\io\resource_loader.cpp:1104)
Appears a few times when (re-)loading assemblies, but the resource loaded worked just fine anyways.
Loader in question:
using Godot;
using System;
[GlobalClass]
[Tool]
public partial class res_loader : ResourceFormatLoader
{
public override string[] _GetRecognizedExtensions() => new[] { "test_res" };
public override Variant _Load(string path, string originalPath, bool useSubThreads, int cacheMode) => new res3();
}
And one times when exiting the editor I got the error as some scripts apparently survived the language, tho not sure if that is actually related to this PR:
ERROR: FATAL: DEV_ASSERT failed "_first == nullptr" is false.
at: SelfList<class CSharpScript>::List::~List (C:\dir\godot_3\core/templates/self_list.h:114)
================================================================
CrashHandlerException: Program crashed
Engine version: Godot Engine v4.1.dev.mono.custom_build (e46806eb86f3bc0ad65ff303a57456a2185d6c4a)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[0] SelfList<CSharpScript>::List::~List (C:\dir\godot_3\core\templates\self_list.h:114)
[1] CSharpLanguage::~CSharpLanguage (C:\dir\godot_3\modules\mono\csharp_script.cpp:1235)
[2] CSharpLanguage::`scalar deleting destructor'
[3] uninitialize_mono_module (C:\dir\godot_3\modules\mono\register_types.cpp:74)
[4] uninitialize_modules (C:\dir\godot_4.0.1\modules\register_module_types.gen.cpp:279)
[5] Main::cleanup (C:\dir\godot_3\main\main.cpp:3566)
[6] widechar_main (C:\dir\godot_3\platform\windows\godot_windows.cpp:183)
[7] _main (C:\dir\godot_3\platform\windows\godot_windows.cpp:205)
[8] main (C:\dir\godot_3\platform\windows\godot_windows.cpp:217)
[9] __scrt_common_main_seh (D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[10] <couldn't map PC to fn name>
-- END OF BACKTRACE --
================================================================
94e800c
to
37af8d0
Compare
We are trying to create a c# binding to GDExtension Google Mediapipe. |
efs->update_file(*p_script_path); | ||
} | ||
#else | ||
CRASH_NOW_MSG("EditorFileSystem is only available when running in the Godot editor."); |
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.
We could add a DEV_ASSERT
, but for production user templates is it really worth crashing instead of just erroring out? Or is it impossible to recover once we're here?
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.
It is only called behind a IsEditorHint check, so it should be unreachable unless someone messes around with reflection (except that the check would have crashed again, so good that you commented and I double checked)
Thb calling this outside the editor means just that there is a logic error in the caller, so a DEV_ASSERT or just a normal ERR_FAIL would be enough here.
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.
It is as RedworkDE says, this code path should be unreachable so I used a crash because a user should never see it anyway. But it makes sense to me to use a DEV_ASSERT
too so I changed it. Let me know if the check is backwards.
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'm no expert on the C# integration, but the scope of the changes looks sensible to me, and this was well tested and reviewed by @RedworkDE.
Would love to get @neikeq's eyes on it too to give more confidence that this is the right approach, but I think we can benefit a lot from merging this this week to include in 4.1 dev 4 for wider testing, so we can polish in the beta phase.
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs
Outdated
Show resolved
Hide resolved
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
Outdated
Show resolved
Hide resolved
I double checked all the interop methods again and did not find any other issues or discrepancies with them. |
Co-authored-by: willnationsdev <willnationsdev@gmail.com>
37af8d0
to
a1f454f
Compare
Congratulations everyone and big thanks to Raul and Will for the work they've put into giving our C# users a powerful feature and parity with GDScript users! Let's catch all the bugs during the bug-fixing phase and send this to everyone in one month with the stable release 🎉 |
Bit late to the party but is there any chance we can change the name to something like Either way, really really awesome job everyone :D 🎉 🎉 |
Port of #63126 originally implemented by @willnationsdev to the current
master
.Adds support for C# to be able to define global classes using the
[GlobalClass]
attribute and export global script classes using the[Export]
attribute.Differences from the original PR
ExportAttribute
constructor is not included.[Global]
attribute was renamed to[GlobalClass]
.[GlobalClass]
attribute always uses the name of the C# class.[GlobalClass]
attribute does not contain the icon path, a separate[Icon]
attribute is provided.[Icon]
attribute allows specifying the path to the icon of a C# class similar to the@icon
annotation in GDScript.EditorFileSystem::update_file
call was moved fromCSharpLanguage::reload_assemblies
toScriptManagerBridge.LookupScriptsInAssembly
.Related issues and PRs