-
-
Notifications
You must be signed in to change notification settings - Fork 84
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
WIP: Add CSharp wrapper #351
base: main
Are you sure you want to change the base?
Conversation
- Begin effort on PCam3D and some basic Godot extensions and PCam types
This looks very promising! Thanks for putting this up so quickly and starting the work on it. To note am not overly familar with C# implementation in Godot and am still reading up on the general guidelines and approaches for it, so take the thought below with a grain of salt. Wonder if we should be using the non-abbreviated name for the class names? So instead of public class PhantomCamera3D : PhantomCamera Related to the above, wonder if we can use the Also related, wonder if this should act like just a class you assign to a given |
@ramokz thanks for the feedback, and no worries, I'm totally new to Godot and C# is not my main language by any means, so I don't have any strong opinions 😅
I had considered this as well and I think I originally used the shorthand to avoid collisions before realizing that wasn't actually an issue. In hindsight, I agree with you here, let's use the full names.
In C#, as long as each file is defined under the same namespace, it treats them all as a package. So in my project, I only had to import the single namespace That being said, I hadn't looked much at the 2D implementation yet, but with a good amount of overlap, I also agree that having a base interface to reduce redundancy is the way to go.
These are really good examples. One thing I had really hoped to do is make it so a user could cast a Node3D into a PhantomCamera like with any C#-based nodes: var pCam3D = GetNode<PhantomCamera3D>("path/to/pcam3d"); I wanted this so there wasn't a clear disconnect between a PhantomCamera object and the underlying node that drives it (for example, not being able to call normal Node3D properties or methods on it) but I ran into a number of issues trying this. However, DialogueManager seems to derive from Node so I'm gonna study what they did and have another go at it. I'd like for users to use this like any other c# Node and not have to do any gymnastics around it. A few other questions I had:
|
1b73f50
to
b6493f0
Compare
Second pass is up. Changes:
|
var pCam3D = GetNode<PhantomCamera3D>("path/to/pcam3d");
100% agree. That would be the ideal approach to have DX alignment between working in GDScript and C#. Reading up on this a bit further, I don't believe it's possible when doing a non-GDExtension addon, like this one, to have both C# and GDScript recognize custom classes written in either language. I.e. C# doesn't see a Related, I wasn't sure at first what the code here was doing: public static class GodotExtension
{
public static PhantomCamera3D AsPhantomCamera3D(this Node3D node3D)
{ return new PhantomCamera3D(node3D);
}
public static PhantomCamera2D AsPhantomCamera2D(this Node2D node2D)
{ return new PhantomCamera2D(node2D);
}} But digging a bit further about how Godot does GDScript -> C# cross-language class referencing, or rather the lack thereof, I can see how it makes sense and works with these two lines: var pCamNode = GetNode<Node3D>("Player/PlayerCam");
var pCam = pCamNode.AsPhantomCamera3D(); In the grand scheme of things, i.e. one extra line per
Do you mean the
What imports do you keep seeing? Don't seem to get anything usual aside from typical
Think that would be very useful for testing / debugging. Adding a test scene file in the The only comment I have for the scene you've made already is that it would be ideal to reuse as much of the existing GDScript files that doesn't directly involve the addon's logic. So rather than making a C# version of the player movement script, it can just be the same GDScript ( |
A small thought about the location of the main wrapper file, would it cayse any issues by having the |
Yea it's definitely not possible lol. I'm not really sure why DialogueManager derives from Node since they don't get anything from it, but yea, the C# type extension was the most ergonomic choice.
Yep. I noticed other projects have them commit to the project root, which seems fine (and it's standard to commit those files in c# projects), as long as we're not polluting the
These two files popup every time and I just roll them back before committing:
Awesome, will do. I also plan to create a unit-test-like scene that should allow for running the scene to execute a series of tests to check for regressions when making future updates to the gdscript/api
That shouldn't be an issue. I also hadn't consider the Manager, I'll set that up as well. The only opinion I have on that is it should live in the same directory (or even the same file) as PhantomCamera.cs unless you want it to be in a different namespace. It's not a requirement, but it is standard to have one directory per namespace (and vice versa). |
Ok, new update: I think I have finished the whole API (at least from what I could find). For now everything is in the PhantomCamera.cs file. It's a little beefy, but not too unwieldly. I still need to write tests to cover everything, so I'll be working on those this evening. I also updated the original PR comment to encompass all the changes. Let me know what you think! |
Thanks for updating the original comment with an easy-to-read overview. Think it covers everything very succinctly.
Ah apologies, for some reason thought it was for the
This is a problem that I've seen some other folks have had before. But some also don't encounter this — myself included.
That would amazing to have! Honestly, I am not overly familiar with setting up unit-tests, so any support with that would be greatly appreciated. It's something I have considered as the project has been growing over time, just never found a good time to explore it.
Personally, I think it's fine for it to sit in the same file and namespace. So leaving it inside the I also verified an export built with template flag One small error I'm encountering in 2D scenes is in relation to the signal Another thing I noticed is that accessing NativeCalls.cs:3666 @ Godot.GodotObject Godot.NativeCalls.godot_icall_1_427(nint, nint, Godot.NativeInterop.godot_string_name): Failed to retrieve non-existent singleton 'PhantomCameraManager'. When I reference I did see that |
This is actually turning out to be a bit more difficult that I thought 😅 I started writing my own little test runner suite and then decided to try GdUnit. GdUnit is really cool, but does add a number of dev dependencies and I've not had much luck getting the SceneRunner to function correctly. I may revert back to my own version, as that at least worked without issues.
I will look into this!
I actually ran into this same issue once I started writing tests. I believe the reason # Make the dialogue manager available as a singleton
if Engine.has_singleton("DialogueManager"):
Engine.unregister_singleton("DialogueManager")
Engine.register_singleton("DialogueManager", self) I meant to ask about doing this for the PCamManager, but I got caught up trying to get GdUnit working so it's been sitting in my Todo list lol |
- added Engine singleton registration to PhantomCameraManager - fixed incorrect LookAtMode signal (not available in 2d) - added c# project files - created basic test runner and added some tests (wip)
I've reverted back to my hand-made test suite since it just works ™️ . I also fixed the look at target change signal and added the Engine singleton registration, which I have confirmed does fix the |
There is an argument to be made that unit-testing could be its own PR, as it doesn't directly affect this feature addition.
Good spot! Think it should be fine to add that in. Runs well from my tests as well. The signal error has also been resolved. Thanks for the quick fix! |
if Engine.has_singleton(PHANTOM_CAMERA_CONSTS.PCAM_MANAGER_NODE_NAME): | ||
Engine.unregister_singleton(PHANTOM_CAMERA_CONSTS.PCAM_MANAGER_NODE_NAME) |
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.
Does this need to be unregistered first?
Wonder if it could just be a case of adding the singleton if it doesn't exist — basically, inverting the conditional checker and adding the Engine.register_singleton
inside of it.
Normally I would advocate for new tests being added as part of a PR with new features, but since in this case we're also introducing a testing framework and setting the stage for future testing, there's definitely some discussion around that. I'll pop an issue with some prelim info later today and split this PR up. The testing can be a fast-follow PR if you're ok with that.
To be totally honest, I don't know the answer. I just mimicked what |
Think a fast-follow PR sounds like a sensible approach, so am happy to go with that.
Looking briefly at Godot's docs about it, it appears not to do anything special beyond the obvious. In fact, it specifically mentions, “The singleton object is not freed.”. So can't see what purpose it has in |
- fix several bugs from invalid getter/setters, properties, and types - added more tests - added LimitTarget query result type for working with TileMaps and CollisionShape2Ds - reorganized scripts since main script file had become quite large
Added a new update. I've continued adding tests for the sole purpose of making sure things work and I've fixed numerous bugs along the way 😅 I also split the files how you suggested previously, the single file had reached a point of becoming quite a burden. I also inverted the singleton registration like we discussed. Also changed how Get/SetLimitTarget in PhantomCamera2D.cs worked so users could work with TileMaps and CollisonShape2Ds more directly. I originally coded it as a NodePath, which was opaque and error prone. I also realized I've missed quite a bit of the API related to specific modes, so I gathered that list and TODO'ed them for myself to pick up tomorrow. One question on this: If the user interacts with a property incompatible with the current settings, should we throw an exception in C#? example- changing Once I get things all squared away I will pick the testing changes out into a separate PR and clean this one up before taking it out of draft status. All in all, I'm really happy with how well the C# API is shaping up! Looking forward to getting it all done soon. |
That is a good shout. I did want to do the same in the GDScript file, but it doesn't allow for specifying two nodes types as an
It would help with user comprehension if the code threw a warning / exception if they were making a property change that had no effect on the |
- added missing shared camera properties - added missing phantom camera 2d properties - added missing phantom camera 3d properties
Hi @ramokz just checking in since it's been a while. I need to take a break for a bit as I was burning myself out, but I'm looking to get back to it this week. Hope all's well! |
Hey, no problem at all! Experienced burnout myself in the past and wouldn't wish it upon my worst enemy. |
Hi, this work looks really nice! I see you only need to make a "unit test like scene". I ask, because I use C#, and the wrapper would be very useful right now as I am attempting to port my game to use the Phantom Camera library to fix jittering issues on my end (hopefully). Absolutely no pressure if you don't feel comfortable doing it, I am simply requesting as it would be very nice. |
Hi @SimoneRizzuto I can take responsibility on this one 😅 I wouldn't feel comfortable merging this as is because I would not consider it stable. As I have been writing tests, I've found numerous problems in how I was connecting gdscript objects to C# and finding that things did not work as I had assumed (yay tests lol). I have also found things that I missed, which adds more tests, and while we have decided to introduce testing as a separate PR, it has been very valuable in stabilizing this work. All that being said, I am setting aside time this weekend to try and get this wrapped up as it has been languishing for quite some time now. |
@sircodemane Maybe I'll truck along on another feature of my game in the meantime. |
@sircodemane as an aside, don't feel pressured to have it wrapped up at any specific point in time. Ultimately, this is an entirely voluntary effort, and so will always favor people taking the time they feel they need if life demands time/energy elsewhere. |
Yeah, agreed. |
Heyo, I didn't quite have the time I'd hoped to work on this, but I was able to dive back in and start getting my bearings again. I've started looking at changes in upstream to see what updates I need to make to be compatible. I expect to have more updates throughout this week. Thanks yall! ❤️ |
- Begin effort on PCam3D and some basic Godot extensions and PCam types
Context
Using C# with GD Scripts is hard, having a CSharp wrapper will make things much easier for users. Addresses #286
Changes
All underlying object types can be reference by calling the node type field:
Each class also follows the Godot convention of having a
MethodName
field with all the string constants for the gdscript getters and setters. PhantomCamera contains the shared strings, PhantomCamera2D and PhantomCamera3D contain their own unique strings.TODO: