Open jtnicholl opened 1 year ago
Agh, I just realized #4234 exists, I don't know why I didn't see it the first time I searched.
This is very similar, but a bit wider in scope, since that only includes ifdef
s. I'm guessing it still counts as a duplicate though? Apologies if so.
Edit: Actually, now that I've read it again, they aren't so similar. That one is suggesting evaluating existing OS.get_feature
calls at export seamlessly, while this is suggesting a full-on preprocessor system with a new syntax.
We already have duplicates suggesting the same feature done in different ways (such as 7329 and 5130, which suggest adding structs as reference-types and as value-types respectively).
Still, my bad for somehow missing it while searching.
Currently in 4.x GDScript does not support exporting compiled bytecode (*.gdc
) unlike in 3.x. The source code is exported as is. First we need to resolve this issue, without this conditional compilation is not possible.
If the preprocessor is run in an editor, then GDScript will not be able to analyze the stripped code and show errors and warnings. If the preprocessor will not run in the editor, then the following code will cause a parser error:
#%ifdef debug
var a = 1
#%else
var a = 2
#%endif
Since the define
directive is not mentioned in this proposal, you are only talking about conditional compilation, not about macros, as far as I understand.
I think there is no need for directives, regular if
s can also be analyzed and stripped by the compiler if they only contain constant expressions and/or calls like OS.has_feature()
with constant arguments. Also we could add static if
(or if constexpr
or when
) so you can be sure that the if
will be resolved at compile time. The only problem is that the class body cannot contain if
s. godotengine/godot#26649 proposes version
keyword.
Also I made an export plugin for 4.x: dalexeev/gdscript-preprocessor.
I really like static if
syntax for the directive, if it would work even at top-level code. It's quite intuitive.
As for "nameof" feature, I would suggest a more generic @"some.code"
+ some.@"code"
that:
@
as a compile-time String or StringName constant.@
(if any) is not evaluated at runtime at all. It's only used for context.@
. It can be partial code.You use it like this:
my_obj.emit(MyClass.@"my_method", arg1, arg2)
prints(@"ThisClass.this_method", @"some_value=", some_value)
which (if all identifiers are valid) compiles to:
my_obj.emit("my_method", arg1, arg2)
prints("ThisClass.this_method", "some_value=", some_value)
Another use case not mentioned in this ticket yet is when using platform-specific GDExtension-registered Classes/Nodes.
Another use case not mentioned in this ticket yet is when using platform-specific GDExtension-registered Classes/Nodes.
I second this, I'm writing a gdextension in rust and some functions are only available for iOS, currently it's impossible to use those functions in GDScript, always report cannot find specified functions.
Really need the conditional compilation directives.
Describe the project you are working on
A multiplayer game with a separate dedicated client and cloud-hosted server.
Describe the problem or limitation you are having in your project
In my game, there are lines of code which are only used on the server but not the client, or vice versa. Since I do not plan to distribute the server for self-hosting before the game reaches end-of-life, I would rather not have server-only code present in the client for script-kiddies to datamine. Doing runtime checks to see whether it's the client or server also has a performance impact, though it's likely not significant (especially if it's not checking every frame).
A similar situation I can imagine is multiplatform games. Code related to Steam achievements etc only needs to be in the Steam version, and code related to consoles only in the console versions.
Another one I can think of is game demos. Code that is only used in the full version of a game would best be omitted entirely from the demo version.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
A solution would be support for
ifdef
-style preprocessor statements, allowing code to be excluded entirely from certain exports.This could be expanded further into additional preprocessing features. Some ideas:
nameof
, which would help avoid typos when using methods such asObject.emit
instead ofSignal.emit
.Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
There would be a new syntax added for preprocessor statements. Script-wide operations such as minification would be configured in the export options. Preprocessor addons such as obfuscators would work like other editor addons.
C's syntax using
#
would not work because GDScript uses#
for comments, so it'd have to use something else. Perhaps just replace the#
with a symbol that isn't used, such as?
.If this enhancement will not be used often, can it be worked around with a few lines of script?
For
ifdef
statements, you can use something likeOS.has_feature
, but the code is still there for dataminers to see. You could instead have multiple versions of the script and only include them in certain exports, but this is not simple to do. You could also use C++ or C# which support this already, but that's not a few lines of script, it's rewriting your entire project.Is there a reason why this should be core and not an add-on in the asset library?
I'm not sure if this could be done with an addon, but if so I assume it would be very difficult. Perhaps you could run a script at export, but it would also have to work when running the project from the editor. And depending on how it works, the code editor might complain of syntax errors because of the preprocessor statements.