utopia-rise / godot-kotlin-jvm

Godot Kotlin JVM Module
MIT License
637 stars 46 forks source link

Clojure support #242

Closed arunvickram closed 1 year ago

arunvickram commented 3 years ago

Hi everyone,

I was wondering what would be necessary to help get Clojure working on Godot? I'd love to get started on trying to get it working!

raniejade commented 3 years ago

Not to derail the issue, but I think clojure (or any other JVM language) support does not belong in this repo as this focuses more on Kotlin/JVM side of things. The glue code (C++) in this repo can be extracted so that it can be re-usable by other JVM languages - but it will incur an additional maintenance burden.

CedNaru commented 3 years ago

So first I have to explain a bit how our repo works so you can understand what to do. The source code is divided into 2 great parts ( to simplify), the Kotlin and the C++ one. Don't forget what I'm explaining is a very simplified way to see things.

The C++ part of the code is the actual module we compile Godot with. What it does conceptually is simple. It implements the Godot Script API so it can communicate with a JVM. It defines a protocol so both C++ and JVM can exchange Godot-related Data.

Then the Kotlin code comes. It contains several tools to generate Kotlin code and plugins to help the compilation but the biggest part is the Godot Library. We reimplemented the Godot core types (Vector2, AABB, Array, etc..) and generated wrappers around all the different objects in the Godot API. https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/kt/godot-runtime/src/main/kotlin/godot/core https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/kt/godot-library/src/main/kotlin/godot/gen/godot

That library is what you import when you want to create a Kotlin Script for Godot, you just inherit one of the wrappers and override/add properties and method to it.

Now how does this work in action? When you write and build a Kotlin Script, a Kotlin entry file is generated. This is a special file that the C++ module will execute at the start of the engine using its ability to communicate with the JVM. The files contain the list of all the scripts/methods/properties/signals in your project. It could be manually written but it's a pain to do so we automated the process using annotations you have to use in your scripts. This is basically the registering phase. The C++ module will use that to know every single method it can call from the JVM. Only a few JVM methods are "hardcoded" in the module, the rest is dynamically determined using that entry file. Then during execution, you can add a script file ending with .kt and assign them to your Godot object. The module will map the .kt path to the actual method/properties it received from the entry file and ask the JVM to execute them when needed (either because called from another language like GDScript, or because of some of the "notification" method like "draw" or "process" or etc).

Now how to implement a new language on top of that? I'm confident that most part of the code can be reused as it is (like 80/90%). The Godot Library can be reused simply because you can use the Kotlin library from other JVM languages (How boilerplate this depends on the language itself so it's outside our control). And the ability for the C++ code to communicate is almost agnostic to the JVM language used.

On the C++ side, the main work would be to create an additional file so it can map .clj (I think it's that one ?) files to properties/method just like it already does from Kotlin. It would probably require creating a Clojure version (or whatever other JVM language you want) of those files:

and maybe make https://github.com/utopia-rise/godot-kotlin-jvm/blob/master/src/gd_kotlin.h a bit more generic?

On the JVM side, like I said the library can be reused if you interop with Kotlin code from Clojure. Creating your own Clojure wrappers is also possible but it's way more works as you would need to rewrite yourself all the Kotlin code in Clojure which I don't recommend. No, the biggest challenge would be to create the EntryFile I told you about. So far our entry files have some dependency on the Kotlin Standard Lib so I am not sure if you can just make a generator create one in Clojure easily but as long as the entry file got the same qualified name, the C++ code will be able to call it as the C++ doesn't care about the source code used, only the final bytecode generated. So you will need to either manually write the entry file by hand each time. or have your own generator that can analyze your Clojure scripts when building (I don't know how Clojure works in that regard so hard to know if such introspection is actually easy or not).

This time it's not a few files you have to adapt like C++ but this whole directory. https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/kt/entry-generation

It contains the code to generate the entry file + extra plugin for the Kotlin compilator so the code source can be analyzed during a build using annotations.

This basically sums up the explanation. Of course, some other parts of the repo won't work anymore like the IDEA plugin for the Godot Kotlin Script because they are obviously made to work with Kotlin itself. I won't talk about those things as I really don't get how they work (Far from the part I'm responsible for) and they are not necessary for the projects to run anyway, it's just QOL tools.

When it comes to the stand of our 4 maintainers. We won't help with such an extension to the repo, at least for a while because we want to make Kotlin the priority and first debug/optimize what can be the base for other languages. But we are always willing to explain stuff to potential contributors so they can understand how the repo works. Unlike Ranie, I don't think it has to necessarily go into another repo. Probably the extra Clojure/other JVM language tools and entry generator will have their own repo yes. But for example, the actual C++ of the module can be made more generic inside our repo so that part can work with other languages out of the box. This is exactly what Godot intends to do in the near future for C# for example so people can freely use other Microsoft-related languages (Most likely F#) with the same engine final binary.

piiertho commented 3 years ago

On my side I do agree with @CedNaru Kotlin first, but I don't think we should close this repo to other JVM languages. Or maybe I'm missing something ?

CedNaru commented 3 years ago

Additional statement:

Given the major rework going on with Godot extension system currently: https://github.com/godotengine/godot/pull/49744

A good chunk of the C++ code will probably have to be reworked when we switch to 4.0. Most likely the whole Scripting API will be abandoned in favor of that new extension system. So be careful to not start working on something that could not make it to 4.0.

CedNaru commented 1 year ago

Closing as we now support Java and designed the entry generator to be easily have third party language support. But we have no intention of supporting officially other JVM languages for maintainability reasons. We leave the door open for contributors that would wish to do it themselves. On top of the explanations in that issue are outdated and don't represent the state of Godot Kotlin today.