godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.11k stars 69 forks source link

Add macros to register GDNative/GDExtension methods/properties #4797

Open SeleDreams opened 2 years ago

SeleDreams commented 2 years ago

Describe the project you are working on

I am working on games using C++ in Godot rather than GDScript and C# due to the fact C++ has a wide amount of libraries available, and is easily portable while still working on most platforms out of the box without having to port a runtime like Mono.

Describe the problem or limitation you are having in your project

The current system in Godot, whether it is in Godot 3 or Godot 4 (so GDNative and GDExtension) require to create a method in each class that manually defines their members, they also require to have a single central function that will register every type manually (requiring to include absolutely all headers in the same source file and register them).

This is a time consuming process that also makes it easy to make mistakes breaking the entire build process due to how centralised it is

Describe the feature / enhancement and how it helps to overcome the problem or limitation

If we look at C++ game engines that are considered industry standard such as Unreal Engine, they made the process way easier by simply requiring to use a macro such as UPROPERTY to define the properties and UFUNCTION for methods to the engine just before their definition here is an example of Unreal Engine C++ script found on google image to show how this looks for functions and properties image

Unreal also has several macros that are used to define the classes themselves not requiring the programmer to create a separate file to manually enable each of them by including all the headers

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I can imagine macros such as

GODOT_PROPERTY

GODOT_METHOD

GODOT_CLASS

etc that would be used to define classes, methods and properties those would use a class factory to automatically get included without a need for a manual inclusion by the programmer

If this enhancement will not be used often, can it be worked around with a few lines of script?

It currently can be done without, but it makes the process pretty convoluted when it comes to making full games in C++

Is there a reason why this should be core and not an add-on in the asset library?

This improvement actively would make it easier and faster to get actual games done in C++ rather than only addons

Calinou commented 2 years ago

If such a macro is added, it should also be used in core for binding properties along with their setter/getter methods.

However, there are a few caveats:

We can add separate macros for registering properties and methods, but it won't reduce the amount of code nearly as much as having a single macro that binds everything needed at once.

SeleDreams commented 2 years ago

If such a macro is added, it should also be used in core for binding properties along with their setter/getter methods.

However, there are a few caveats:

  • Properties can have different hints and usages associated to them.
  • Properties may not be part of any group.
  • Setter/getter methods may have names that don't fit any kind of automated generation. For instance, not only we use an is_ prefix for boolean getters instead of get_, but we also sometimes add a suffix so the getter's name makes more sense (the same goes for the setter).

We can add separate macros for registering properties and methods, but it won't reduce the amount of code nearly as much as having a single macro that binds everything needed at once.

What do you mean by different hints and usages, do you mean the hints of typings ?

for not being part of a group, yeah, from what i remember in unreal this is an optional argument we're not forced to fill

I think a way to fix the getter and setter method issue would be to have two optional arguments prefix and suffix to define custom prefixes and suffixes, else it would use the default ones

Duroxxigar commented 2 years ago

@Calinou All of those caveats are already handled by UE's system. What I'm reading from this proposal is that we should strive to have that same kind of system, and I agree personally. However, the UHT (Unreal Header Tool), is quite complex. We can get a super simple system set up, sure; but it would require a lot of work to get it to be comparable. To handle the auto-generated name, you would simply just need to define that in the Godot equivalent UHT.

All-in-all, this is no small task. You need a tool to read your .h file, look for any of the macros, read if there is anything inside of the macros (additional specifiers, like in UE's case BlueprintReadWrite), and then generate the _bind_methods() method.

Imo - this is definitely the right route to take; it's more of a matter of manpower though. There are also more important things to be working on than removing some boilerplate that lower-level people would be encountering more frequently than the vast majority of users. (I've been off n' on workin' on my own equivalent system over the years to be honest, but it hasn't gone much of anywhere due to other more pressing projects)

YuriSizov commented 2 years ago

You say this is a lot of work and the resulting system is quite complex, and the main benefit is having the associated instructions next to each exposed property or method instead of having them all together in _bind_methods?

GDCLASS is already quite a heavy macro for hiding a lot of complexity. I'm not sure with an arguably superficial benefit it would be desired to add even more complex macro magic.

Diddykonga commented 2 years ago

As pointed out for this to work one would need a tool like UHT which parses and generates C++ code. Which is no easy feat to create, and an even harder one to maintain, I would advise against going down this route.

I'm a fan of having more macros/attributes/etc. but personally I think it would be better if we were to wait for later versions of C++(23 or 26), which will most likely contain the Reflection TS, which will allow the compiler to handle all of what, UHT or Godot's equivalent, would of have done but faster and better.

SeleDreams commented 2 years ago

I wasn't even aware C++23/26 would have this kind of features, how would that work ?

Le mer. 6 juil. 2022 à 03:48, Diddykonga @.***> a écrit :

As pointed out for this to work one would need a tool like UHT which parses and generates C++ code. Which is no easy feat to create, and even harder one to maintain, I would advise against going down this route.

I'm a fan of having more macros/attributes/etc. but personally I think it would be better if we were to wait for later versions of C++(23 or 26), which will most likely contain the Reflection TS, which will allow the compiler to handle all of what, UHT or Godot's equivalent, would of have done but faster and better.

— Reply to this email directly, view it on GitHub https://github.com/godotengine/godot-proposals/issues/4797#issuecomment-1175685590, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD4UF4IV6YJZIZO77XNX7ITVSTQXJANCNFSM52PFA2ZA . You are receiving this because you authored the thread.Message ID: @.***>

Diddykonga commented 2 years ago

I wasn't even aware C++23/26 would have this kind of features, how would that work ?

Let me clarify, its not a guarantee whether the Reflection TS is accepted into C++ at any version regardless of 23 or 26, although the person who created it and is pushing it, is also someone who has a history in C++ and thinks that they may be able to get it in around that time.

Here is the last video I watched on the matter, they have done multiple talks about it at different events, and of course it is slowly but surely evolving syntactically and semantically. It should be a very powerful system for C++ if supported, and would be as big of an improvement as adding templates was if not more so.
https://www.youtube.com/watch?v=ARxj3dfF_h0&t=3316s

Calinou commented 2 years ago

Remember that new C++ standards aren't immediately usable in production as they're finalized, as you need to wait for various compilers to be shipped in Linux distributions (especially LTS distributions like Ubuntu, Debian and RHEL/CentOS). Some people will also stick to older Visual Studio versions for a while out of habit.

My personal guideline is that you need to wait 5 years for a C++ standard to be truly usable in production. This also gives compiler developers some time to fix bugs within the implementation itself :slightly_smiling_face: By that guideline, C++20 will be usable in production in 2025, C++23 in 2028, and C++26 in 2031.