-
Notifications
You must be signed in to change notification settings - Fork 55
Description
Introduction and motivation
I've been working with the kotlin API quite a lot in the last couple of weeks. While I'm very happy with it in general, one of the papercuts is the @Register family of annotations (@RegisterClass, @RegisterFunction and @RegisterProperty).
Imagine the following scenario:
@RegisterClass
class MyButton : Button(){
override fun _onReady(){
GD.print("hello world!")
}
}This will never print anything. Why? Because _onReady needs to be annotated with @RegisterFunction. I've lost count of how many times I was pulling my hair why some action wouldn't trigger in my game, and in 90% of all cases it was because I was missing an annotation. The information is also redundant: we're overriding a function of the Godot API. Of course we want Godot to "see" it, why wouldn't we?
To reduce this pain, and just get rid of a pitfall, I propose the following set of rules where the Godot gradle plugin should automatically register classes, functions and properties, no matter if they're annotated or not.
Rules for auto-registration
- Every
classwhich directly or indirectly inherits fromgodot.Node(and is notabstract) should be treated as if it was annotated by@RegisterClass.
It prevents anyone from forgetting it, and there is no use case for a subclass of
godot.Nodethat isn't usable in the editor. Conversely, with this rule, I would argue that the explicit@RegisterClassannotation can be deprecated and marked for removal. It is always a mistake to annotate a class with@RegisterClassif it doesn't inherit directly or indirectly fromgodot.Nodeas Godot will not know what to do with it.
- Every function which is an
overrideof a function ofgodot.Nodeor its subclasses in thegodotnamespace should be treated as if it was annotated by@RegisterFunction.
For example,
override fun _onReady(){}should be enough, there's no need for@RegisterFunction. There is no use case for overriding a Godot-defined API that shouldn't be visible to Godot.
- Every property which is annotated as
@Exportshould also be treated as if it was annotated by@RegisterProperty.
There is no use case where we want to export a property to the Godot editor and hide it at the same time. The inverse however is not true: a property which is marked as
@RegisterPropertyshould not necessarily show up in the editor, which justifies the distinction between@Exportand@RegisterProperty.
Implementation considerations
All three rules are detectable with reasonable effort (both on the gradle plugin authors side as well as in terms of runtime overhead) via JVM reflection. No rule requires method bodies to be inspected, therefore all rules can be evaluated via the reflection API alone; no source code scanning is required. The most expensive part will be scanning the user project for classes, but this already needs to happen in the existing gradle plugin to find the annotated classes.
I would also be willing to help out with the implementation of these rules if needed, as long as I can code it in Java or Kotlin. I have a fair amount of experience with JVM reflection from my day job.