diff --git a/README.md b/README.md index 89b5dd60b3..406d476366 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ -# Godot Kotlin JVM - -# Kotlin/JVM binding for the Godot Game Engine +# Godot Kotlin/JVM +## Kotlin/JVM binding for the Godot Game Engine

@@ -8,26 +7,47 @@ ## Overview -This is a **Kotlin** language binding for the [**Godot**](https://godotengine.org/) game engine. It is built as a module (like the C# binding) to interact with **Godot**'s core internally. The binding provides you Godot API's as Kotlin classes, so you can write your game logic completely in Kotlin. Your code will be compiled into a .jar which is then executed by an embedded JVM, so you don't have to worry that your users have Java installed. It's already embedded in your game executable. -You also don't have to worry about any binding logic. Just write your game scripts like you would for [GDScript](https://docs.godotengine.org/en/3.1/getting_started/scripting/gdscript/gdscript_basics.html) or [C#](https://docs.godotengine.org/en/3.1/getting_started/scripting/c_sharp/) but with all the syntactic sugar of Kotlin. +This is a [**Kotlin**](https://kotlinlang.org) language binding for the [**Godot**](https://godotengine.org/) game engine. +It is built as a module (like the C# binding) to interact with **Godot**'s core internally. + +The binding provides you Godot API's as [Kotlin classes](https://godot-kotl.in/en/stable/getting-started/your-first-class/), +so you can write your game logic completely in Kotlin. + +### Code Distribution + +There are two methods for distributing JVM bytecode produced by the Kotlin compiler: + +1. A classic JAR file: your code will be packed into a `.jar` file, which is then executed by an embedded JVM. + So the developer does not have to worry about their user installing a JRE. The JVM is already embedded in your game executable. +2. Dynamic Library using GraalVM Native Image: please read more about this in our [documentation page](https://godot-kotl.in/en/stable/user-guide/advanced/graal-vm-native-image/). + +Just write your game scripts like you would for [GDScript](https://docs.godotengine.org/en/4.2/getting_started/scripting/gdscript/gdscript_basics.html) +or for [C#](https://docs.godotengine.org/en/3.1/getting_started/scripting/c_sharp/) but with all the syntactic sugar of Kotlin. [![GitHub](https://img.shields.io/github/license/utopia-rise/godot-kotlin-jvm?style=flat-square)](LICENSE) -## Important notes +## Important Notes -This version of the binding is currently **Alpha**! +This version of the binding is currently **Alpha**! This means that the bindings are not +production-ready. However, if you are curious in using Kotlin in Godot, this is a good opportunity +to help us in improving the project! ## Documentation -The documentation can be found [here](https://godot-kotl.in) -## Developer discussion +The documentation can be found [here](https://godot-kotl.in). It's a work in progress, and we would love your input to +make it even better! + +## Developer Discussion & Contribution -Ask questions and collaborate on [Discord](https://discord.gg/zpb5Ru7v9x) +Join us on our [Discord](https://discord.gg/zpb5Ru7v9x) server to ask questions and work together +with a friendly community. -## Contribution -If you want to contribute to the project, please read through the contribution guidlines and getting started sections [here](https://godot-kotl.in/en/stable/contribution/guidelines/) +If you want to contribute to the project, please read through the [contribution guidelines](https://godot-kotl.in/en/stable/contribution/guidelines/) +and the [setup](https://godot-kotl.in/en/stable/contribution/setup/) sections. ## Partners -Jetbrains is helping us to develop this project by providing development tools to maintainers. -Intellij IDEA is our IDE of choice for Kotlin development and we strongly recommend using it. + +JetBrains is helping us to develop this project by providing development tools to maintainers. +Intellij IDEA is our IDE of choice for Kotlin development and we strongly recommend using it. + [![jblogo](.README/jetbrains.svg)](https://www.jetbrains.com/) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 619537161f..35e28cdcd9 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -8,15 +8,26 @@ theme: name: material favicon: assets/img/favicon.ico palette: - - scheme: default + - media: "(prefers-color-scheme)" + primary: deep purple toggle: - icon: material/toggle-switch-off-outline + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep purple + toggle: + icon: material/brightness-7 name: Switch to dark mode - - scheme: slate + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep purple toggle: - icon: material/toggle-switch - name: Switch to light mode + icon: material/brightness-4 + name: Switch to system preference logo: assets/img/logo.png + font: + code: JetBrains Mono features: - navigation.tabs - navigation.expand @@ -35,6 +46,7 @@ markdown_extensions: - pymdownx.highlight - pymdownx.superfences - pymdownx.tabbed + - pymdownx.details - admonition - meta @@ -46,10 +58,10 @@ extra_css: nav: - Home: index.md - - Getting started: + - Getting Started: - Requirements: getting-started/requirements.md - - Setting up: getting-started/setting-up.md - - Your first class: getting-started/your-first-class.md + - Setting-up: getting-started/setting-up.md + - Your first Kotlin class: getting-started/your-first-class.md - User guide: - API differences: user-guide/api-differences.md - Classes: user-guide/classes.md @@ -63,13 +75,13 @@ nav: - Versioning: user-guide/versioning.md - Supported platforms: user-guide/supported-platforms.md - Advanced: - - Abstract Classes: user-guide/advanced/abstract_classes.md - - Custom src dirs: user-guide/advanced/custom-src-dirs.md - - Custom gradle wrapper path: user-guide/advanced/custom_gradle_wrapper_path.md + - Abstract classes: user-guide/advanced/abstract-classes.md + - Custom source directories: user-guide/advanced/custom-src-dirs.md + - Custom gradle wrapper path: user-guide/advanced/custom-gradle-wrapper-path.md - Gradle plugin configuration: user-guide/advanced/gradle-plugin-configuration.md - - Commandline args: user-guide/advanced/commandline-args.md + - Command-line arguments: user-guide/advanced/commandline-args.md - Kotlin singletons: user-guide/advanced/kotlin-singleton.md - - GraalVM native-image: user-guide/advanced/graal-vm-native-image.md + - GraalVM Native Image: user-guide/advanced/graal-vm-native-image.md - Develop libraries: - Introduction: develop-libraries/introduction.md - Setup: develop-libraries/setup.md @@ -79,9 +91,9 @@ nav: - Guidelines: contribution/guidelines.md - Setup: contribution/setup.md - Build with C# support: contribution/build-with-csharp-support.md - - Support for other jvm based languages: contribution/support_for_other_jvm_based_languages.md + - Support for other JVM-based languages: contribution/support-for-other-jvm-based-languages.md - Knowledge base: - Artefact differentiation: contribution/knowledge-base/artefact-differentiation.md - Entry generation: contribution/knowledge-base/entry-generation.md - Shared buffer: contribution/knowledge-base/shared-buffer.md - - Memory Management: contribution/knowledge-base/memory-management.md \ No newline at end of file + - Memory management: contribution/knowledge-base/memory-management.md \ No newline at end of file diff --git a/docs/src/doc/assets/img/idea-plugin/plugin-godot-kotlin.png b/docs/src/doc/assets/img/idea-plugin/plugin-godot-kotlin.png new file mode 100644 index 0000000000..1b21277c6c Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/plugin-godot-kotlin.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/plugins-view.png b/docs/src/doc/assets/img/idea-plugin/plugins-view.png new file mode 100644 index 0000000000..b823d10de7 Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/plugins-view.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/wizard-1.png b/docs/src/doc/assets/img/idea-plugin/wizard-1.png new file mode 100644 index 0000000000..cca4013628 Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/wizard-1.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/wizard-2.png b/docs/src/doc/assets/img/idea-plugin/wizard-2.png new file mode 100644 index 0000000000..4554ee81cf Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/wizard-2.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/wizard-3.png b/docs/src/doc/assets/img/idea-plugin/wizard-3.png new file mode 100644 index 0000000000..538ebea0b8 Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/wizard-3.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/wizard-4.png b/docs/src/doc/assets/img/idea-plugin/wizard-4.png new file mode 100644 index 0000000000..e530e4b659 Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/wizard-4.png differ diff --git a/docs/src/doc/assets/img/idea-plugin/wizard-5.png b/docs/src/doc/assets/img/idea-plugin/wizard-5.png new file mode 100644 index 0000000000..ed9090275d Binary files /dev/null and b/docs/src/doc/assets/img/idea-plugin/wizard-5.png differ diff --git a/docs/src/doc/assets/img/wizard_1.png b/docs/src/doc/assets/img/wizard_1.png deleted file mode 100644 index f44f02470c..0000000000 Binary files a/docs/src/doc/assets/img/wizard_1.png and /dev/null differ diff --git a/docs/src/doc/assets/img/wizard_2.png b/docs/src/doc/assets/img/wizard_2.png deleted file mode 100644 index 932630135b..0000000000 Binary files a/docs/src/doc/assets/img/wizard_2.png and /dev/null differ diff --git a/docs/src/doc/assets/img/wizard_3.png b/docs/src/doc/assets/img/wizard_3.png deleted file mode 100644 index 0b04b21c38..0000000000 Binary files a/docs/src/doc/assets/img/wizard_3.png and /dev/null differ diff --git a/docs/src/doc/contribution/build-with-csharp-support.md b/docs/src/doc/contribution/build-with-csharp-support.md index c1431bc222..6968a7182e 100644 --- a/docs/src/doc/contribution/build-with-csharp-support.md +++ b/docs/src/doc/contribution/build-with-csharp-support.md @@ -1,9 +1,10 @@ ## Build engine for C# and Kotlin/JVM -1. Fulfill requirements mentioned [here](https://docs.godotengine.org/en/stable/development/compiling/compiling_with_mono.html) -2. `scons p= tools=yes module_mono_enabled=yes mono_glue=no` + +1. Fulfill requirements mentioned [here](https://docs.godotengine.org/en/stable/development/compiling/compiling_with_mono.html). +2. `scons p= tools=yes module_mono_enabled=yes mono_glue=no`. 3. ` --generate-mono-glue modules/mono/glue` - - For this step to work you need a jre in the `godot-root` folder - - And a `godot-bootstrap.jar` in `/bin` -4. `export LD_PRELOAD=/jre-{amd64|arm64}/lib/libjsig.so` -5. `scons -j$(nproc) platform= module_mono_enabled=yes` -6. run with `../../../../bin/godot.linuxbsd.editor.x86_64.mono` \ No newline at end of file + - For this step to work you need a JRE in the `godot-root` folder. + - And a `godot-bootstrap.jar` in `/bin`. +4. `export LD_PRELOAD=/jre-{amd64|arm64}/lib/libjsig.so`. +5. `scons -j$(nproc) platform= module_mono_enabled=yes`. +6. Run with `../../../../bin/godot.linuxbsd.editor.x86_64.mono`. \ No newline at end of file diff --git a/docs/src/doc/contribution/general.md b/docs/src/doc/contribution/general.md index a2ed14487c..b9959b9721 100644 --- a/docs/src/doc/contribution/general.md +++ b/docs/src/doc/contribution/general.md @@ -1,12 +1,20 @@ -We encourage you to contribute to the project if you want. Even if you don't have any idea how the module works or if it seems overwhelming at first, we're here to help you getting started. +We encourage you to contribute to the project if you want. Even if you don't have any idea how +the module works or if it seems overwhelming at first, we're here to help you getting started. ## Keywords + The following keywords are used throughout the contribution documentation: - `godot-root`: root dir in which the godot engine is cloned into - `module-dir`: root dir of our module ## Discussions -Most of our discussions are happening on Discord. So if you have Discord or don't mind starting using it, feel free to [join](https://discord.gg/zpb5Ru7v9x) our server. But don't worry if you don't have or want to use Discord. Then the discussions are just in the corresponding issue. If you discuss on Discord though: don't forget to document all relevant outcome in the corresponding issue. -If you have critique or an opinion on a discussed topic, please be kind and give valuable feedback. If you are on the receiving end of the critique: don't take it personally. Many people are no native english speaker and it can happen that something which is not rude at all in the language of the writer, might sound rude in english. \ No newline at end of file +Most of our discussions are happening on Discord. So, if you have Discord or don't mind starting using it, +feel free to [join](https://discord.gg/zpb5Ru7v9x) our server. But don't worry if you don't have or want to use Discord. +Then the discussions are just in the corresponding issue. If you discuss on Discord though: don't forget to document all +relevant outcome in the corresponding issue. + +If you have critique or an opinion on a discussed topic, please be kind and give valuable feedback. If you are on the +receiving end of the critique: don't take it personally. Many people are no native english speaker and it can happen that +something which is not rude at all in the language of the writer, might sound rude in english. \ No newline at end of file diff --git a/docs/src/doc/contribution/guidelines.md b/docs/src/doc/contribution/guidelines.md index 61b7ef5f5d..992c7240f9 100644 --- a/docs/src/doc/contribution/guidelines.md +++ b/docs/src/doc/contribution/guidelines.md @@ -1,8 +1,14 @@ ## General -We are working with the Code Owners feature of GitHub. This means each piece of code in our module has a maintainer who is the "Owner" of said code. This maintainer is usually the one who implemented it or has the most knowledge about that particular part of the module. General code may not have a specific "Owner". In this case the fallback is: all Maintainers. -## Before Contributing -Before you start to invest your precious time in writing code that you want to contribute, consider following these guidelines. They are here to make the lives of all people involved easier. +We are working with the Code Owners feature of GitHub. This means each piece of code in our module has a maintainer who +is the "Owner" of said code. +This maintainer is usually the one who implemented it or has the most knowledge about that particular part of the module. +General code may not have a specific "Owner". In this case the fallback is: all Maintainers. + +## Before contributing + +Before you start to invest your precious time in writing code that you want to contribute, consider following these guidelines. +They are here to make the lives of all people involved easier. - If you have an idea or a bug you want to fix, first look if an issue already exists that describes this Feature/Bug. - If such a issue exists, and a person is already assigned, it means the assigned person is working on it. But don't go away yet! Maybe this person could need your help, or you have some valuable input for the topic. @@ -10,8 +16,12 @@ Before you start to invest your precious time in writing code that you want to c - If the issue does not yet exist, open one and describe as best as you can, what your idea/what the bug is you want to tackle. The provided templates are a good starting point. ## Code + ### Code style -We enforce the code style to match the official Kotlin [coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html). Read there on how to set those up for your IDE. We will enforce this later on through CI and linting. + +We enforce the code style to match the official Kotlin [coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html). +Read there on how to set those up for your IDE. We will enforce this later on through CI and linting. ### Branching + We do branching like described in `git-flow`. \ No newline at end of file diff --git a/docs/src/doc/contribution/knowledge-base/artefact-differentiation.md b/docs/src/doc/contribution/knowledge-base/artefact-differentiation.md index f320a1f332..34a37e5523 100644 --- a/docs/src/doc/contribution/knowledge-base/artefact-differentiation.md +++ b/docs/src/doc/contribution/knowledge-base/artefact-differentiation.md @@ -1,29 +1,52 @@ This document describes what the individual artefacts are for and how they are used. ## godot-library + ### Overview -The `godot-library` contains the godot api as kotlin classes as well as registration code. It is automatically added as a dependency to the users code by the `godot-gradle-plugin`. Hence, it is deployed to mavenCentral. It is also used as a dependency by `godot-bootstrap` and thus present in the `godot-bootstrap.jar` which gets shipped alongside the engine. + +The `godot-library` contains the godot api as Kotlin classes as well as registration code. +It is automatically added as a dependency to the users code by the `godot-gradle-plugin`. +Hence, it is deployed to `mavenCentral`. It is also used as a dependency by `godot-bootstrap` and +thus present in the `godot-bootstrap.jar` which gets shipped alongside the engine. ### Usage -The `godot-library` is mainly used by the end user implicitly. Implicitly because he does not add it by himself. The `godot-gradle-plugin` does that. But it is also used by the `godot-bootstrap.jar` for initial loading and usage in the editor. Important is, that during runtime, only the version that was added as a dependency to the users code through the `godot-gradle-plugin` is used. The version inside `godot-bootstrap` is only used for the editor. + +The `godot-library` is mainly used by the end user implicitly. Implicitly because he/she does not add it by himself. +The `godot-gradle-plugin` does that. But, it is also used by the `godot-bootstrap.jar` for initial loading and usage in the editor. +Important is, that during runtime, only the version that was added as a dependency to the users code through the `godot-gradle-plugin` is used. +The version inside `godot-bootstrap` is only used for the editor. ## godot-bootstrap + ### Overview -The `godot-bootstrap` is a shadowJar (also known as fat jar) which contains the `godot-library` and runtime code to reload usercode in the editor after rebuilds. + +The `godot-bootstrap` is a "shadow JAR" (also known as [fat JAR](https://jenkov.com/tutorials/maven/maven-build-fat-jar.html)) which contains the `godot-library` +and runtime code to reload usercode in the editor after rebuilds. ### Usage -The `godot-bootstrap` is shipped alongside the engine for editor use and is bundled together with the game executable during export. It is never used by the user directly nor added as a dependency anywhere. + +The `godot-bootstrap` is shipped alongside the engine for editor use and is bundled together with the game executable during export. +It is never used by the user directly nor added as a dependency anywhere. ## main + ### Overview -The `main.jar` is built when the user builds his code. It is a shadowJar containing only the users code as well as all the dependencies the user has defined recursively. This is needed so they and all dependencies and the dependencies of the dependencies are present at runtime. + +The `main.jar` is built when the user builds his code. It is a shadow JAR containing only the users code as well as all the dependencies +the user has defined recursively. This is needed so they and all dependencies and the dependencies of the dependencies are present at runtime. ### Usage -This jar is bundled together with the game executable during export and executed through the `godot-bootstrap` during runtime. It is nowhere else used. + +This JAR is bundled together with the game executable during export and executed through the `godot-bootstrap` during runtime. It is nowhere else used. ## usercode + ### Overview + The `usercode` artifact is a shared library which is only used on GraalVM native image builds. It contains all code from the `main.jar` and the `godot-bootstrap.jar`. ### Usage -It replaces the `godot-bootstrap.jar` and the `main.jar` when the game is exported. It is only used when configured either as a commandline arg or through the configuration file (see [GraalVM documentation](../../user-guide/advanced/graal-vm-native-image.md) for more information). While it is used (either in game or editor) no usercode can be reloaded. \ No newline at end of file + +It replaces the `godot-bootstrap.jar` and the `main.jar` when the game is exported. It is only used when configured either as a +command line argument or through the configuration file (see [GraalVM documentation](../../user-guide/advanced/graal-vm-native-image.md) for more information). +While it is used (either in game or editor) no usercode can be reloaded. \ No newline at end of file diff --git a/docs/src/doc/contribution/knowledge-base/entry-generation.md b/docs/src/doc/contribution/knowledge-base/entry-generation.md index ae359b22ce..b72dd608cd 100644 --- a/docs/src/doc/contribution/knowledge-base/entry-generation.md +++ b/docs/src/doc/contribution/knowledge-base/entry-generation.md @@ -1,28 +1,48 @@ # Entry generation ## General -To make it more language agnostic, the entry gen provides a set of model classes which represent the needed information about the source code by the entry gen. It expects this information to be gathered and assembled by the calling tool and to be provided in the entry point of the entry gen. -For kotlin and java, this tool is `godot-kotlin-symbol-processor` which in essence is a compiler plugin, which analyses the source code, and gathers the information needed by the entry gen. It then calls the entry gen which in turn generates the needed entry files. +To make it more language agnostic, the entry generator provides a set of model classes which represent the needed information about the source code by the entry genenerator. +It expects this information to be gathered and assembled by the calling tool and to be provided in the entry point of the entry generator. -## godot-kotlin-symbol-processor -Previously, we implemented our own compiler plugin based on the [mpapt](https://github.com/Foso/MpApt) project. Even though it worked very well, the code was far from easy to understand and as the compiler plugin api is not stable, it also introduced a lot of maintenance work to keep it up to date with the ever evolving kotlin compiler. +For Kotlin and Java, this tool is `godot-kotlin-symbol-processor` (a Kotlin compiler's plugin), which analyses the source code, and gathers the information needed by the entry generator. +It then calls the entry generator which in turn generates the needed entry files. -To mitigate that problem we switched to [KSP (Kotlin Symbol Processing API)](https://github.com/google/ksp) which is basically a kotlin annotation processor (kapt) on steroids. Meaning it in essence is a compiler plugin which lets you inspect the source code being compiled through a abstracted and simplified api. This means for us that we can work against a more stable api and the work of keeping it up to date with kotlin compiler changes is offloaded to a well maintained open source project with far more people with better knowledge about the internal workings of the kotlin compiler. +## The godot-kotlin-symbol-processor -We use our implementation of a kotlin symbol processor to gather all needed information for the entry gen and convert it into the format it understands. With this it should be more easy to implement additional jvm languages as the entry gen itself can stay the same for all languages. Only the symbol processor has to change per language. +Previously, we implemented our own compiler plugin based on the [mpapt](https://github.com/Foso/MpApt) project. +Even though it worked very well, the code was far from easy to understand and as the compiler plugin API is not stable yet. +Furthermore, `MpApt` introduced a lot of maintenance work to keep it up to date with the ever evolving Kotlin compiler. -## Default value extraction -We extract the default values with the help of Jetbrain's [Program Structure Interface (PSI)](https://plugins.jetbrains.com/docs/intellij/psi.html), which is basically a language specific AST (Abstract Syntax Tree). But as the simplified API of KSP does not allow the introspection of the source code representation, we implemented this ourselves in the `godot-kotlin-symbol-processor` as well. +To mitigate that problem we switched to [KSP (Kotlin Symbol Processing API)](https://github.com/google/ksp) which is basically a Kotlin Annotation Processor (KAPT) on steroids. +Meaning it in essence is a compiler plugin which lets you inspect the source code being compiled through a abstracted and simplified API. +This means for us that we can work against a more stable api and the work of keeping it up to date with Kotlin compiler changes is offloaded +to a well maintained open source project with far more people with better knowledge about the internal workings of the Kotlin compiler. + +We use our implementation of a Kotlin Symbol Processing to gather all needed information for the entry generator and convert it into the format it understands. +With this it should be more easy to implement additional JVM languages as the entry generator itself can stay the same for all languages. Only the symbol processor has to change per language. + +## Default Value Extraction + +We extract the default values with the help of JetBrains' [Program Structure Interface (PSI)](https://plugins.jetbrains.com/docs/intellij/psi.html), +that is a language specific AST (Abstract Syntax Tree). But as the simplified API of KSP does not allow the introspection of the source code representation, +we implemented this ourselves in the `godot-kotlin-symbol-processor` as well. ## Debugging -As `godot-kotlin-symbol-processor` is a kotlin compiler plugin and thus the execution context of the entry gen is as well, it cannot be debugged traditionally by just clicking debug on the `build` task in intellij like you would do normally for kapt annotation processors. -To debug it you have to execute the following command in the terminal: `./gradlew build --no-daemon -Dorg.gradle.debug=true -Dkotlin.compiler.execution.strategy="in-process" -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n"` from within a sample project. +As `godot-kotlin-symbol-processor` is a Kotlin compiler plugin and thus the execution context of the entry generator is as well, +it cannot be debugged traditionally by just clicking the Debug button on the `build` task in IntelliJ IDEA like you would do normally for KAPT annotation processors. + +To debug a project, open a terminal, change to project's root directory and type the following command: + +```bash +./gradlew build --no-daemon -Dorg.gradle.debug=true -Dkotlin.compiler.execution.strategy="in-process" -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n" +``` -This will halt the compilation until you attach a remote debugger. You can find a preconfigured run configuration for it in the sample project `tests` called `DebugEntryGenerator`. +This will halt the compilation until you attach a remote debugger. You can find a pre-configured run for it in the sample project `tests` called `DebugEntryGenerator`. !!! note - Compilation with attached debugger will be way slower. Especially for the initial build. So be patient. It takes some time until it hits your breakpoints. + Compilation with attached debugger will be way slower. Especially for the initial build. So, please, be patient. It takes some time until it hits your breakpoints. -Keep in mind: As this spawns a new daemon for each build, no incremental build is supported. Each build builds everything. If you need to debug a incremental build issue, the only way atm is to log relevant debug information to a file. \ No newline at end of file +Keep in mind: as this spawns a new daemon for each build, no incremental build is supported. +Each build builds everything. If you need to debug a incremental build issue, the only way at the moment is logging relevant debug information to a file. \ No newline at end of file diff --git a/docs/src/doc/contribution/knowledge-base/memory-management.md b/docs/src/doc/contribution/knowledge-base/memory-management.md index 817fe8660d..8100f312ec 100644 --- a/docs/src/doc/contribution/knowledge-base/memory-management.md +++ b/docs/src/doc/contribution/knowledge-base/memory-management.md @@ -1,32 +1,79 @@ The purpose of this page is to give some clarification about how Godot and the JVM manage their memory together. ## Regular Godot memory management + ### Object and Refcounted -Godot got two ways to manage memory. Classes belonging to the `Object` category are manually freed. If not done, it will remain in memory until the program terminates and leak. To make memory management easier, another category called `Refcounted` exists. They keep an internal counter of the numbers of how many times they are references by other parts of the program. It's only when reaching 0 that it will automatically be freed from memory. + +Godot manages the memory in two ways. Classes belonging to the `Object` category are manually freed. +If not done, it will remain in memory until the program terminates and leak. To make memory management easier, +another category called `Refcounted` exists. Through an internal counter, these classes keep track of how many +times they are referenced by other parts of the program. When the counter reaches 0 the instances will be freed +automatically from memory. ### Instance binding -Other languages can have different ways to handle memory than Godot. To help with it, Godot objects can hold `instance bindings`. It's a set of callbacks that can be implemented by whoever wish to add a language to Godot. There are callbacks for the different phases of the lifecycle of an object: creation, destruction and counter updates. Using those callbacks, one can then synchronize the state of the Godot object with the memory of the targeted languages. -## JVM +Other languages can have different ways to handle memory than Godot. To help with it, Godot objects can hold `instance bindings`. +It's a set of callbacks that can be implemented by whoever wish to add a new language binding to Godot. +There are callbacks for the different phases of the lifecycle of an object: *creation*, *destruction* and *counter updates*. +Using those callbacks, one can then synchronize the state of the Godot object with the memory of the targeted languages. + +## Java Virtual Machine + ### Garbage Collector -The JVM doesn't allow to manually manage memory. Instead, a subsystem will periodically run over the different objects in memory and check if they should be freed. The idea is similar to reference counting, as an object will be freed when it's not referenced by any other parts of the code. But unlike Reference counting it's not immediate, there is a delay before it happens as the Garbage Collector needs to run and find candidates for deletion before. All in all, it's different from the ways Godot works and require a whole system to bridge the two worlds. -### Wrapper and Script Instance -Each time a Godot object requires some interactions with the JVM (Sent as a parameter from C++ to a Kotlin script methods, created directly by a Kotlin scripts, etc...), it needs to acquire an existence inside it. A Godot objects can be of 2 differents types within the JVM. The first is a `Wrapper`, there is a wrapper class for every Godot base type already existing in C++ (Object, Refcounted, Nodes, etc...). As the name implies, they are simply wrapping a C++ pointer and use it to call all the C++ methods the Godot object holds. The second type are the `Script Instances`, they are the custom scripts users wrote. For this type, the process is the reverse, they expose a set of Kotlin properties and methods to the C++ so they can be used by the engine like you would do with a common GDScript. +The JVM doesn't allow to manually manage memory. Instead, a subsystem, called Garbage Collector, will periodically run over the +different objects in memory and check if they should be freed. The idea is similar to reference counting, as an object will be +freed when it's not referenced by any other parts of the code. But unlike the reference counting technique it's not immediate, +there is a delay before it happens as the Garbage Collector needs to run and find candidates for deletion before. + +All in all, it's different from the ways Godot works and require a whole system to bridge the two worlds. + +### Wrapper and script instance + +Each time a Godot object requires some interactions with the JVM (e.g., sending a parameter from C++ to a Kotlin script methods, +created directly by a Kotlin scripts, etc...), it needs to acquire an existence inside it. A Godot object can be of two differents +types within the JVM. -### Memory Manager -In C++ Godot, an object is 2 things, a base type and an optional script. We mirror this in the JVM with the wrappers and script instances. One major difference is that in C++, the script instance is simply a member of the base script and fake inheritance this way. In Kotlin, for technical reasons, we don't have another choice than doing true inheritance. A script instance always inherits a wrapper type. The consequences are that for a given C++ object, we can have 2 different JVM objects, each with their own lifecycle. The wrapper is bound to the Godot instance and the script instance is bound to its script. A Godot object can freely add, remove and switch script during its lifetime. In order to manage this, we have a singleton named `MemoryManager`. It got several functions: +The first is a `Wrapper`, there is a wrapper class for every Godot base type already existing in C++ (Object, Refcounted, Nodes, etc...). +As the name implies, they simply wrap a C++ pointer and use it to call all the C++ methods the Godot object holds. -- Keeping an up-to-date database of all Kotlin instances, being wrapper or script instance existing in the JVM. -- Matching any C++ pointer with an existing JVM instance (Necessary when a C++ parameter is sent to a Kotlin function) -- Synchronizing the life of JVM and C++ instances. +The second type are the `Script Instances`, they are the custom scripts users wrote. For this type, the process is the reverse, +they expose a set of Kotlin properties and methods to the C++ so they can be used by the engine like you would do with a common GDScript code. + +### Memory manager + +In C++ Godot, an object made out of two components: a *base type* and an *optional script*. We mirror the Godot's object structure in the JVM +with the wrappers and script instances. One major difference is that in C++, the script instance is simply a member of the base script and +emulate inheritance this way. In Kotlin, for technical reasons, we don't have another choice than doing true inheritance. +A script instance always inherits a wrapper type. The consequences are that for a given C++ object, we can have 2 different JVM objects, each with their own lifecycle. +The wrapper is bound to the Godot instance and the script instance is bound to its script. +A Godot object can freely add, remove and switch script during its lifetime. + +To manage this, we created a singleton named `MemoryManager`, providing the following functionalities: + +* Keeping an up-to-date database of all Kotlin instances, being wrapper or script instance existing in the JVM. +* Matching any C++ pointer with an existing JVM instance (necessary when a C++ parameter is sent to a Kotlin function). +* Synchronizing the life of JVM and C++ instances. ![Memory Manager](../../assets/img/memory_manager.png) -It's using a container simply named `GodotBinding`, holding a reference to both wrapper and script instance (when they exist). This is this type of object that is used as an `instance binding` back in C++. This means that as long as the C++ object is alive, the JVM instances will also stay alive. +It's using a container simply named `GodotBinding`, holding a reference to both wrapper and script instance (when they exist). +This is this type of object that is used as an `instance binding` back in C++. +This means that as long as the C++ object is alive, the JVM instances will also stay alive. ### Refcounted management -`Refcounted` objects are a bit harder to manage as they don't rely on manual management but reference counting. Kotlin instances all contribute to increase that counter, so the native object won't die as long as the JVM needs it. It's a vicious cycle because throught the binding C++ is also holding a reference to the Kotlin instance, it means they are both keeping each other alive. If kept that way, both will never be able to be freed even if unused. The solution to this is to transform the instance binding into a weak reference when the C++ side no longer use it. That way, the Godot Binding will be able to be freed by the GC. When this happens, the MemoryManager will then decrement the counter of the C++ RefCounted and free it. + +`Refcounted` objects are a bit harder to manage as they don't rely on manual management but reference counting. +Kotlin instances all contribute to increase that counter, so the native object won't die as long as the JVM needs it. +It's a vicious cycle because throught the binding C++ is also holding a reference to the Kotlin instance, it means they are both keeping each other alive. +If kept that way, both will never be able to be freed even if unused. + +The solution to problem is to transform the instance binding into a *weak reference* when the C++ side no longer use it. +That way, the Godot binding will be able to be freed by the garbage collector. When this happens, the `MemoryManager` will then decrement +the counter of the C++ `RefCounted` and free it. ### Triangular references -`GodotBinding`, `Wrapper` and `Script Instance` all holds references to each other, linking their lives to each other. It's made this way because the binding is the object referenced by the C++ to keep everything alive. Conversely, any usage of the wrapper or script instance have to keep the native C++ object alive as well. + +`GodotBinding`, `Wrapper` and `Script Instance` all holds references to each other, linking their lifetimes to each other. +It's made this way because the binding is the object referenced by the C++ to keep everything alive. +Conversely, any usage of the wrapper or script instance have to keep the native C++ object alive as well. diff --git a/docs/src/doc/contribution/knowledge-base/shared-buffer.md b/docs/src/doc/contribution/knowledge-base/shared-buffer.md index a00fed732c..7b5bd33d0a 100644 --- a/docs/src/doc/contribution/knowledge-base/shared-buffer.md +++ b/docs/src/doc/contribution/knowledge-base/shared-buffer.md @@ -1,41 +1,61 @@ # Shared buffer ## General -The classical way of making the JVM and C++ code interact with each other is to use JNI. JNI works well, but its overhead is too high when you wish to make a lot of small calls, especially when you wish to call a method with a lot of parameters. A way to bypass that is to create a buffer that will be shared between the two languages so we only have to write and read from that buffer to exchange data. + +The classical way of making the JVM and C++ code interact with each other is to use Java Native Interface (JNI). +JNI works well, but its overhead is too high when you wish to make a lot of small calls, especially when you wish +to call a method with a lot of parameters. A way to bypass this is to create a buffer that will be shared between +the two languages so we only have to write and read from that buffer to exchange data. ## Marshalls -The only data written in that buffer are the usual Godot types: primitives, strings, coreTypes, and objects. We don't need a generic way of serializing data like protobuff. We tried that solution at first, but it was too slow for an interprocess job. Writing data to the buffer is quite simple in C++, we just use the Marshalls utility of the Godot Engine. On the Kotlin side, we just reimplement them from scratch. + +The only data written in that buffer are the usual Godot types: primitives, strings, coreTypes, and objects. +We don't need a generic way of serializing data like *protobuff*. We tried that solution at first, but it was +too slow for an interprocess job. Writing data to the buffer is quite simple in C++, we just use the `Marshalls` +utility of the Godot Engine. On the Kotlin side, we just reimplement them from scratch. ## Memory -To avoid unnecessary locks, we create one buffer for each thread that works with both C++ and the JVM. That way, one thread doesn't need to wait for another to finish its job with the buffer. The buffer currently has a size of 8 KB by default. The reason for that is that we allow strings up to 512 bytes in size and up to 16 parameters for a registered Kotlin function. -## String -String is a special case because it has a dynamic size so they can potentially have any size. We have set a maximum size allowed in the buffer. If we go above it, it switches to a regular JNI call. When it is done that way, the string is stored in a queue so we can retrieve the strings from it instead of reading from the buffer. In most cases, you would rarely reach that maximum size in a video game. Other dynamic types like `Array` and `Dictionary` are not an issue as only their pointers is sent to the JVM. +To avoid unnecessary locks, we create one buffer for each thread that works with both C++ and the JVM. +That way, one thread doesn't need to wait for another to finish its job with the buffer. +The buffer currently has a size of 8 KB by default. The reason for that is that we allow strings +up to 512 bytes in size and up to 16 parameters for a registered Kotlin function. + +## Strings + +Strings are a special case because they can change their size dynamically. +We have set a maximum string size allowed in the buffer. If we go above it, it switches to a regular JNI call. +When it is done that way, the string is stored in a queue so we can retrieve the strings from it instead +of reading from the buffer. In most cases, you would rarely reach that maximum size in a video game. +Other dynamic types like `Array` and `Dictionary` are not an issue as only their pointers is sent to the JVM. ## Buffer structure -The first value of the buffer is always an `Int` that indicates the number of variables to read. Each variable starts with another Int that indicates its type then followed by the relevant data of that type. - -| type | ordinal | content | -| --- | --- | ---| -| Nil | 0 | | -| Bool | 1 | Bool: 4 Bytes | -| Int | 2 | Long: 8 Bytes | -| Real | 3 | Double: 8 Bytes | -| String | 4 | Bool: 4Bytes, Dynamic: 512 Bytes at most (if Bool is set to true, empty otherwise) | -| Vector2 | 5 | x: Float: 4 Bytes, y: Float: 4 Bytes | -| Rect2 | 6 | position : Vector2: 8 Bytes, size : Vector2: 8 Bytes | -| Vector3 | 7 | x: Float: 4 Bytes, y: Float: 4 Bytes, z: Float: 4 Bytes | -| Transform2D | 8 | x: Vector2: 8 Bytes, y: Vector2: 8 Bytes, origin: Vector2: 8 Bytes | -| Plane | 9 | normal: Vector3: 12 Bytes, d: Float: 4 Bytes | -| Quat | 10 | x: Float: 4 Bytes, y: Float: 4 Bytes, z: Float: 4 Bytes, w: Float: 4 Bytes | -| AABB | 11 | position : Vector3: 12 Bytes, size : Vector3: 12 Bytes | -| Basis | 12 | x : Vector3: 12 Bytes, y : Vector3: 12 Bytes, z : Vector3: 12 Bytes | -| Transform | 13 | basis: Basis: 36 Bytes, origin: Vector3: 12 Bytes | -| Color | 14 | red: Float: 4 Bytes, green: Float: 4 Bytes, blue: Float: 4 Bytes, alpha: Float: 4 Bytes | -| NodePath | 15 | pointer: ptr: 8 Bytes | -| RID | 16 | pointer: ptr: 8 Bytes | -| Object | 17 | pointer: ptr: 8 Bytes, JVM_constructor_index: Int: 4 Bytes, isReference: Bool: 4 Bytes, object_id: Long: 8 Bytes | -| Dictionnary | 18 | pointer: ptr: 8 Bytes | -| Array | 19 | pointer: ptr: 8 Bytes | -| PoolXArray | 20 to 27 | pointer: ptr: 8 Bytes | +The first value of the buffer is always an `Int` that indicates the number of variables to read. +Each variable starts with another integer (the *ordinal*) indicating its type then followed by the relevant data of that type. + +The table below shows how each type is mapped to its ordinal number, giving a meaning to the passed data: + +| type | ordinal | content | +|-------------|----------|------------------------------------------------------------------------------------------------------------------| +| Nil | 0 | | +| Bool | 1 | Bool: 4 Bytes | +| Int | 2 | Long: 8 Bytes | +| Real | 3 | Double: 8 Bytes | +| String | 4 | Bool: 4Bytes, Dynamic: 512 Bytes at most (if Bool is set to true, empty otherwise) | +| Vector2 | 5 | x: Float: 4 Bytes, y: Float: 4 Bytes | +| Rect2 | 6 | position : Vector2: 8 Bytes, size : Vector2: 8 Bytes | +| Vector3 | 7 | x: Float: 4 Bytes, y: Float: 4 Bytes, z: Float: 4 Bytes | +| Transform2D | 8 | x: Vector2: 8 Bytes, y: Vector2: 8 Bytes, origin: Vector2: 8 Bytes | +| Plane | 9 | normal: Vector3: 12 Bytes, d: Float: 4 Bytes | +| Quat | 10 | x: Float: 4 Bytes, y: Float: 4 Bytes, z: Float: 4 Bytes, w: Float: 4 Bytes | +| AABB | 11 | position : Vector3: 12 Bytes, size : Vector3: 12 Bytes | +| Basis | 12 | x : Vector3: 12 Bytes, y : Vector3: 12 Bytes, z : Vector3: 12 Bytes | +| Transform | 13 | basis: Basis: 36 Bytes, origin: Vector3: 12 Bytes | +| Color | 14 | red: Float: 4 Bytes, green: Float: 4 Bytes, blue: Float: 4 Bytes, alpha: Float: 4 Bytes | +| NodePath | 15 | pointer: ptr: 8 Bytes | +| RID | 16 | pointer: ptr: 8 Bytes | +| Object | 17 | pointer: ptr: 8 Bytes, JVM_constructor_index: Int: 4 Bytes, isReference: Bool: 4 Bytes, object_id: Long: 8 Bytes | +| Dictionnary | 18 | pointer: ptr: 8 Bytes | +| Array | 19 | pointer: ptr: 8 Bytes | +| PoolXArray | 20 to 27 | pointer: ptr: 8 Bytes | diff --git a/docs/src/doc/contribution/setup.md b/docs/src/doc/contribution/setup.md index 8fba496290..00c9b4a619 100644 --- a/docs/src/doc/contribution/setup.md +++ b/docs/src/doc/contribution/setup.md @@ -1,8 +1,8 @@ To build our module, you need to same dependencies as the ones described in the [official Godot documentation](https://docs.godotengine.org/en/stable/development/compiling/index.html). -Make sure that Java is installed and its PATH set in your system as well (at least Java 11 is needed!). +Make sure that Java is installed and its `PATH` set in your system as well (**at least Java 11 is needed**). -1. Clone godot repo with the stable tag you want to develop for: `git clone git@github.com:godotengine/godot.git 4.1.2-stable --recursive` +1. Clone Godot's repository with the stable tag you want to develop for: `git clone git@github.com:godotengine/godot.git 4.1.2-stable --recursive` 2. In the `godot-root` dir, run the following command: `git submodule add git@github.com:utopia-rise/godot-kotlin-jvm.git modules/kotlin_jvm` @@ -27,11 +27,14 @@ stands for the JMX port of you choice. You can then set up remote debug configur ## Publishing locally + In order to publish our artifacts locally, you'll need to run `gradlew :tools-common:publishToMavenLocal publishToMavenLocal` -Check in you maven local repository what the version is you've just published: `ls ~/.m2/repository/com/utopia-rise/godot-gradle-plugin`. The version should look something like this: `0.7.2-4.1.2-c8df371-SNAPSHOT`. +Check in you maven local repository what the version is you've just published: `ls ~/.m2/repository/com/utopia-rise/godot-gradle-plugin`. +The version should look something like this: `0.7.2-4.1.2-c8df371-SNAPSHOT`. Your test project should use `mavenLocal()` in the repositories block in `build.gradle.kts` and the following in `settings.gradle.kts`: + ```kotlin pluginManagement { repositories { @@ -49,8 +52,11 @@ pluginManagement { } ``` -## Important things to note: -When you build a sample, it generates a `godot-bootstrap.jar` in `build/libs`. This jar is needed by the engine to function correctly. You need to copy this jar to `/bin`. If you want to automate that, consider using the following gradle task in the samples `build.gradle.kts`- but don't commit it! +## Important notes + +When you build a sample, it generates a `godot-bootstrap.jar` in `build/libs`. +This JAR is needed by the engine to function correctly. You need to copy this jar to `/bin`. +If you want to automate that, consider using the following gradle task in the samples `build.gradle.kts`- but don't commit it! ```kt afterEvaluate { diff --git a/docs/src/doc/contribution/support-for-other-jvm-based-languages.md b/docs/src/doc/contribution/support-for-other-jvm-based-languages.md new file mode 100644 index 0000000000..e1c1e91a72 --- /dev/null +++ b/docs/src/doc/contribution/support-for-other-jvm-based-languages.md @@ -0,0 +1,8 @@ +If you want to have support for other JVM-based languages than Kotlin or Java, you have to fork this project. +If you do and have questions, feel free to ask us on [Discord](https://discord.gg/zpb5Ru7v9x). +We're happy to help you out with this. + +However, keep in mind that this is not an easy task and it requires that the language, and its tooling, have at least the following capabilities: + +- Compile time annotation processing (otherwise you need to register every class by hand). +- Java/Kotlin interoperability. \ No newline at end of file diff --git a/docs/src/doc/contribution/support_for_other_jvm_based_languages.md b/docs/src/doc/contribution/support_for_other_jvm_based_languages.md deleted file mode 100644 index 826e1266d6..0000000000 --- a/docs/src/doc/contribution/support_for_other_jvm_based_languages.md +++ /dev/null @@ -1,6 +0,0 @@ -If you want to have support for other jvm based languages than Kotlin or Java, you'll have to fork the project. If you do and have questions, feel free to ask us on [Discord](https://discord.gg/zpb5Ru7v9x). We're happy to help you out with this. - -Keep in mind however: this is no easy task and requires that the language, and it's tooling you want to implement has at least the following capabilities: - -- Compile time annotation processing (or you need to register every class by hand) -- Java/Kotlin interop \ No newline at end of file diff --git a/docs/src/doc/develop-libraries/introduction.md b/docs/src/doc/develop-libraries/introduction.md index 3d4ac90faf..3bc39867e0 100644 --- a/docs/src/doc/develop-libraries/introduction.md +++ b/docs/src/doc/develop-libraries/introduction.md @@ -1,7 +1,10 @@ -Godot Kotlin Jvm libraries are basically the equivalent of Godot Addons but specifically for the use in other Godot Kotlin Jvm projects like Games or Applications. +Godot Kotlin/JVM libraries are basically the equivalent of Godot Addons, +but specifically for the use in other Godot Kotlin/JVM projects like Games or Applications. !!!Relevance - If you build a library which does not register any classes to godot, you can just create a regular jvm library, and you will have no need for this documentation. + If you build a library which does not register any classes to Godot, you can just create a regular JVM library, and you will have no need for this documentation. -# Overview -A Godot Kotlin Jvm library is just a regular jvm library with additional metadata annotations for registered classes. For registered classes in a library registration files are generated and provided to the consumer, so they can be used in the consuming project. \ No newline at end of file +## Overview + +A Godot Kotlin/JVM library is just a regular JVM library with additional metadata annotations for registered classes. +For registered classes in a library registration files are generated and provided to the consumer, so they can be used in the consuming project. \ No newline at end of file diff --git a/docs/src/doc/develop-libraries/publishing.md b/docs/src/doc/develop-libraries/publishing.md index 0a119ea3c3..0e549b2cf4 100644 --- a/docs/src/doc/develop-libraries/publishing.md +++ b/docs/src/doc/develop-libraries/publishing.md @@ -1 +1 @@ -The publishing process is the same as it is for regular jvm libraries. \ No newline at end of file +The publishing process is the same as it is for regular JVM libraries. \ No newline at end of file diff --git a/docs/src/doc/develop-libraries/setup.md b/docs/src/doc/develop-libraries/setup.md index 51eca50e18..73949da97a 100644 --- a/docs/src/doc/develop-libraries/setup.md +++ b/docs/src/doc/develop-libraries/setup.md @@ -1,10 +1,12 @@ -The basic project setup is the same as for regular Godot Kotlin Jvm projects. Head over to the corresponding [getting started](../getting-started/requirements.md) guide to set up the basics of the project. +The basic project setup is the same as for regular Godot Kotlin/JVM projects. +Head over to the corresponding [getting started](../getting-started/requirements.md) guide to set up the basics of the project. ## Library specific setup + The following configuration properties for customizing the behaviour of your library are available to you in the `build.gradle.kts` file: -| property | default value | usage | -|-------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| classPrefix | _not set_ | Allows you to define a prefix with which each registered class is prefixed. This helps prevent naming conflicts in the users project. Use this if you register classes which names are pretty generic. | -| projectName | _the gradle project name_ | Defines the name of your project. For the user, this is the directory to which the `gdj` registration files are generated to. For example: `gdj/dependencies//ARegisteredClassFromYourLibrary.gdj` | -| isRegistrationFileGenerationEnabled | true | Defines whether `gdj` files are generated during the build of your library. Safe to turn off if you don't have any sample projects or tests in your library project which depend on these registration files. The registration files for the consumer are not affected. These are generated from special metadata annotaions. | \ No newline at end of file +| Property | default value | usage | +|---------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `classPrefix` | _not set_ | Allows you to define a prefix with which each registered class is prefixed. This helps prevent naming conflicts in the users project. Use this if you register classes which names are pretty generic. | +| `projectName` | _the gradle project name_ | Defines the name of your project. For the user, this is the directory to which the `gdj` registration files are generated to. For example: `gdj/dependencies//ARegisteredClassFromYourLibrary.gdj` | +| `isRegistrationFileGenerationEnabled` | true | Defines whether `gdj` files are generated during the build of your library. Safe to turn off if you don't have any sample projects or tests in your library project which depend on these registration files. The registration files for the consumer are not affected. These are generated from special metadata annotaions. | \ No newline at end of file diff --git a/docs/src/doc/getting-started/requirements.md b/docs/src/doc/getting-started/requirements.md index 9e60bca32d..1083818c85 100644 --- a/docs/src/doc/getting-started/requirements.md +++ b/docs/src/doc/getting-started/requirements.md @@ -5,22 +5,29 @@ Also make sure to regularily test your exports on each platform. It's best to even test the exports on each platform before even writing anything else than the first test class ## Java + To use this module at least JDK 11 is needed, note you will need the JDK not just the JRE, and the environment variable `JAVA_HOME` to be present before being able to run the custom godot editor. ### Mac & Linux + You can install Java via [SDKMAN!](https://sdkman.io/). Once you installed it, you can run `sdk install java 11.0.11.hs-adpt` to install the LTS version of Java from [AdoptOpenJDK](https://adoptopenjdk.net/). If you want to pick a different version, you can run `sdk list java`. ### Windows + You can install Java via [Chocolatey](https://community.chocolatey.org/). For example, to install [AdoptOpenJDK](https://adoptopenjdk.net/) you can run `choco install adoptopenjdk11`. ## IDE + There is currently no plan to support the built-in Godot editor, using [IntelliJ IDEA](https://jetbrains.com/idea) is strongly recommended (the community edition is free). Editors such as VSCode can be used, however, we only provide first class support for IntelliJ IDEA. You can install it via [JetBrains Toolbox](https://www.jetbrains.com/toolbox-app/) app. -### Intellij IDEA plugin +### Intellij IDEA Plugin + We also recommend installing our [IntelliJ IDEA plugin](https://plugins.jetbrains.com/plugin/16505-godot-jvm) as it provides you with a lot of useful checks and helpers to detect errors during development. ## Godot Editor -You need our custom engine build from the latest [GitHub release](https://github.com/utopia-rise/godot-kotlin-jvm/releases) to be able to use this project. If you need other modules you can also [build it yourself](../contribution/setup.md). + +You need our custom engine build from the latest [GitHub releases](https://github.com/utopia-rise/godot-kotlin-jvm/releases) to be able to use this project. If you need other modules you can also [build it yourself](../contribution/setup.md). ## Exporting -You need our custom export templates for your exported games to work with the jvm. Have a look at the [Exporting](../user-guide/exporting.md) documentation. + +You need our custom export templates for your exported games to work with the JVM. Have a look at the [Exporting](../user-guide/exporting.md) documentation. diff --git a/docs/src/doc/getting-started/setting-up.md b/docs/src/doc/getting-started/setting-up.md index 03f53039e0..7bb79d6a3e 100644 --- a/docs/src/doc/getting-started/setting-up.md +++ b/docs/src/doc/getting-started/setting-up.md @@ -1,26 +1,82 @@ -## Setting up using IntelliJ IDEA project wizard -The easiest way to setup a new project is via IntelliJ's project wizard (you need to install our IntelliJ IDEA [plugin](./requirements.md#intellij-idea-plugin)). +# Setting-up -In IntelliJ IDEA click `New Project` and select `Godot Kotlin JVM`. Fill out the fields and click `Next` when you are done. +This page illustrates how to set-up a project with Godot/Kotlin JVM. Currently, there are +two ways to create a new project: [using a custom IntelliJ IDEA plugin](#setting-up-using-intellij-idea-project-wizard) +or [manually](#setting-up-manually). -![Wizard 1](../assets/img/wizard_1.png) +The recommended solution is using the custom IntelliJ IDEA plugin. -Select the directory where your project will be created and click `Finish`. +## Setting-up using IntelliJ IDEA project wizard -![Wizard 2](../assets/img/wizard_2.png) +The easiest way to setup a new project is via IntelliJ's project wizard (the user needs to install our IntelliJ IDEA [plugin](./requirements.md#intellij-idea-plugin)). -IntelliJ IDEA should open up your project and if you wait for a bit you should see a toast notification `Load Gradle Project` in the lower right of the window. Click that and you are ready to go! +### Installing IntelliJ IDEA's plugin -![Wizard 3](../assets/img/wizard_3.png) +To install our plugin to create new projects for Godot/Kotlin JVM, run your local copy of IntelliJ IDEA. When the editor +is running, open the `Settings` and select the `Plugins` entry. From this view, select `Marketplace` on the top-bar. +![Plugins View](../assets/img/idea-plugin/plugins-view.png) + +Type `godot kotlin` into the search bar, and our plugin will be shown as follows. + +![Godot Kotlin Plugin](../assets/img/idea-plugin/plugin-godot-kotlin.png) + +Click the `Install` button and wait for the IDE to download the plugin. Once the downloading +process is complete, press the `OK` button on the bottom-right. The IDE will prompt a new +alert dialog, asking the user to restart the program. To enable the plugin a full restart +is required, so please do so. + +### Creating a new project + +To create a new project, please refer to the following instructions: + +1. Open IntelliJ IDEA +2. Create a new project clicking on `New Project` +3. In the `New Project` window, select `Godot Kotlin JVM`. +4. Fill out the package fields as necessary +5. (Optional) Select the builds that your project is interested in, such as Android or iOS. + + ![Wizard 1](../assets/img/idea-plugin/wizard-1.png) + + !!!note "Default Platforms" + If the user does not select any additional platform, the plugin will not add the + necessary files for that target. By default, the main plugin target + is Desktop. + +6. After filling all the necessary fields, click the `Next` button. +7. In the next window, choose the directory where your project will be set up. +8. Click the `Create` button. The IDE will create several files, including a Gradle build file. + + ![Wizard 2](../assets/img/idea-plugin/wizard-2.png) + +9. IntelliJ IDEA opens up the newly created project and after a while, a toast notification +on the right-bottom will appear. To proceed forward, click on `Load Gradle Project` button. + + ![Wizard 3](../assets/img/idea-plugin/wizard-3.png) + + Pressing the button allows the IDE to create source files, where the user can create new scripts. + + ??? info "'GodotKotlinJvm is setting up' bar?" + Notice that the loading process takes a bit, so, a pop-up bar will appear on top of a file's + content. During this process, the IDE is building file inidices and it is linking the required + dependencies. The bar will disappear automatically when the process is done. + ![Wizard 4](../assets/img/idea-plugin/wizard-4.png) + +10. Once the loading is complete, the user will be able to see Kotlin source code with the package +name the user inserted during the project's creation. Finally, the game development can start! 🚀 + +![Wizard 5](../assets/img/idea-plugin/wizard-5.png) ## Setting up manually -If you do not want to use our IntelliJ IDEA plugin you can follow these steps to setup a project. + +If the user does not want to use our IntelliJ IDEA plugin, then they can follow these steps to setup a project. !!! note - The following steps requires Gradle to be installed, checkout their [website](https://gradle.org) for installation instructions. + The following steps requires Gradle to be installed, checkout their [website](https://gradle.org) + for installation instructions. -Firstly, you need to setup a gradle [wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). The wrapper will ensure that anyone who wants to build your project from source will use the same gradle version. +Firstly, you need to setup a Gradle [wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). +The wrapper will ensure that anyone who wants to build your project from source will use the same Gradle version. === "Windows" ```shell @@ -34,16 +90,19 @@ Firstly, you need to setup a gradle [wrapper](https://docs.gradle.org/current/us touch build.gradle.kts gradle.properties settings.gradle.kts ``` -The above command will create three files, which will be empty for now. +The above command(s) will create three empty files. As next step, type the following +command on the terminal: ```shell -gradle wrapper --gradle-version=6.8 +gradle wrapper --gradle-version=8.1 ``` -You should have the wrapper setup after running the command above. Up next is setting up the gradle build. Open up `build.gradle.kts` and paste the following: +After running the above command, the user should have the wrapper setup ready to be used. +Up next is setting-up the Gradle build. Now, open the `build.gradle.kts` file +and paste the following content: -=== "build.gradle.kts" - ```kt +=== "`build.gradle.kts`" + ```kotlin plugins { kotlin("jvm") version "$kotlinVersion" id("com.utopia-rise.godot-kotlin-jvm") version "$godotKotlinVersion" @@ -55,6 +114,8 @@ You should have the wrapper setup after running the command above. Up next is se ``` !!! note - Replace `$kotlinVersion` and `$godotkotlinVersion` to the appropriate version you want to use. + Please replace `$kotlinVersion` and `$godotkotlinVersion` to the appropriate version you want to use. -The snippet above uses our gradle plugin. Without the plugin, you will have to manually define all needed dependencies, manually register your classes, signals, properties, functions and manually create and copy the needed jar's to the appropriate locations. +The snippet above uses our Gradle plugin. Without the plugin, the user has to manually define all needed +dependencies, manually register the classes, signals, properties, functions and manually create and copy +the needed JAR's to the appropriate locations. diff --git a/docs/src/doc/getting-started/your-first-class.md b/docs/src/doc/getting-started/your-first-class.md index 130c0a70a2..6bff91a440 100644 --- a/docs/src/doc/getting-started/your-first-class.md +++ b/docs/src/doc/getting-started/your-first-class.md @@ -18,7 +18,7 @@ class Simple: Node3D() { } ``` -The [classes](../user-guide/classes.md) section covers in detail what we did here, but for now `@RegisterClass` will register the class to Godot. Now we can trigger a build. +The [classes](../user-guide/classes.md) section covers in details what we did here, but for now `@RegisterClass` will register the class to Godot. Now we can trigger a build. ```shell ./gradlew build @@ -33,6 +33,33 @@ Once the build completes, you will be able to use your class in Godot. Simply at ## Final project structure -The final project should look like this: -![Final project structure](../assets/img/final_project_structure.png) \ No newline at end of file +The final filesystem project should look like this: + +``` +~/Dev/Workspace/kotlin-godot-demo tree +. +├── build +│   └── libs +├── build.gradle.kts +├── gdj +├── gradle +│   └── wrapper +│   ├── gradle-wrapper.jar +│   └── gradle-wrapper.properties +├── gradlew +├── gradlew.bat +├── icon.svg +├── kotlin-godot-demo.iml +├── project.godot +├── settings.gradle.kts +└── src + └── main + └── kotlin + └── com + └── utopiarise + └── demo + └── Simple.kt + +12 directories, 10 files +``` \ No newline at end of file diff --git a/docs/src/doc/index.md b/docs/src/doc/index.md index 1615817aef..cdf8f3a9e3 100644 --- a/docs/src/doc/index.md +++ b/docs/src/doc/index.md @@ -6,34 +6,44 @@ hide: [![GitHub](https://img.shields.io/github/license/utopia-rise/godot-kotlin-jvm?style=flat-square)](LICENSE) -Godot Kotlin/JVM is a Godot module which allows you to write your game or application logic in Kotlin on the JVM. +**Godot Kotlin/JVM** is a Godot module which allows you to write your game or application logic in Kotlin on the JVM. If you are looking for the documentation for Godot Kotlin/Native; you can find it [here](https://godot-kotlin.readthedocs.io/en/latest/). ## State + This project is in alpha, it is by no means production ready. ### What's not working -The items in this list are explicitly mentioned here as these will be implemented in future versions. Also consider the [Api Differences](user-guide/api-differences.md) section for general differences and limitations which will not be or cannot be adressed in the near forseable future or ever. -- Each registered constructor must have a unique number of arguments, constructor overloading is not yet supported -- No tool mode (you can set it already in the `@RegisterClass` annotation but it has no effect yet) -- No plugin support, you cannot use Godot Kotlin/JVM to write plugins and addons yet +The items in this list are explicitly mentioned here as these will be implemented in future versions. +Also consider the [API Differences](user-guide/api-differences.md) section for general differences +and limitations which will not be or cannot be adressed in the near forseable future or ever. + +- Each registered constructor must have a unique number of arguments, constructor overloading is not yet supported. +- No tool mode (you can set it already in the `@RegisterClass` annotation but it has no effect yet). +- No plugin support, you cannot use Godot Kotlin/JVM to write plugins and addons yet. - We support desktop OS (Linux, MacOS, Windows), Android and iOS. -### Bug reporting and Questions -If you find bugs, please report an [issue on github](https://github.com/utopia-rise/godot-kotlin-jvm/issues) - but check for duplicates first. If you have questions or need help, you can ask on [discord](https://discord.gg/zpb5Ru7v9x) in the channels `questions` and `help` respectively. If you don't have discord or don't want to use it, make a issue on github. +### Bug reporting and questions + +If you find bugs, please report an [issue on GitHub](https://github.com/utopia-rise/godot-kotlin-jvm/issues) - but check for duplicates first. If you have questions or need help, you can ask on [Discord](https://discord.gg/zpb5Ru7v9x) in the `questions` and `help` channels respectively. +If you don't have Discord or you don't want to use it, please file an issue on GitHub. ## Supported languages -The main language supported is Kotlin. We do however support Java experimentally. It should be possible to support other jvm base languages as well but this is not the focus of this project. If you want to have support for other languages, have a look at [support for other jvm based languages](contribution/support_for_other_jvm_based_languages.md). -## Supported kotlin version -This module relies on a kotlin compiler plugin for registering your classes and members to godot. As the compiler api from kotlin is not yet stable, we can only support specific kotlin version per release for now. +The main language supported is Kotlin. We do however support Java experimentally. It should be possible to support other JVM-based languages as well but this is not the focus of this project. If you want to have support for other languages, have a look at [support for other JVM-based languages](contribution/support-for-other-jvm-based-languages.md). + +## Supported Kotlin version -The current latest release is compatible with kotlin version `1.9.0`. +This module relies on a Kotlin *compiler plugin* for registering your classes and members to Godot. As the compiler API from Kotlin is not stable yet, at the moment we can only support specific Kotlin version per release. + +The current latest release is compatible with Kotlin version `1.9.0`. ## Custom engine builds -Get our pre built engine builds and export templates from the latest [GitHub release](https://github.com/utopia-rise/godot-kotlin-jvm/releases). + +Get our pre-built engine builds and export templates from the latest [GitHub releases](https://github.com/utopia-rise/godot-kotlin-jvm/releases). ## Developer discussion -Ask questions and collaborate on [Discord](https://discord.gg/zpb5Ru7v9x) \ No newline at end of file + +Please feel free to ask questions and collaborate on our [Discord](https://discord.gg/zpb5Ru7v9x) server. \ No newline at end of file diff --git a/docs/src/doc/user-guide/advanced/abstract_classes.md b/docs/src/doc/user-guide/advanced/abstract-classes.md similarity index 93% rename from docs/src/doc/user-guide/advanced/abstract_classes.md rename to docs/src/doc/user-guide/advanced/abstract-classes.md index b84f2c842c..16fa2c276a 100644 --- a/docs/src/doc/user-guide/advanced/abstract_classes.md +++ b/docs/src/doc/user-guide/advanced/abstract-classes.md @@ -1,4 +1,4 @@ -You can define and derive from any abstract class you define, as long as any of your superclasses is a godot class. +You can define and derive from any abstract class you define, as long as any of your superclasses is a Godot class. This allows you to define default functions for your inheriting classes and override them in some, but not all subclasses if you want. @@ -10,11 +10,12 @@ Under the hood, we only register your normal classes, and let them register all For this reason, the `@RegisterClass` annotation is optional for abstract classes. !!! warning - As in kotlin, you cannot instantiate abstract classes directly from any other scripting language like GDScript! In fact, godot does not even know (or care) that your abstract class exists. + As in Kotlin, you cannot instantiate abstract classes directly from any other scripting language like GDScript! In fact, godot does not even know (or care) that your abstract class exists. # Example Abstract class definition: + ```kotlin // register class annotation is optional for abstract classes abstract class AbstractClassInheritanceParent: Node() { @@ -37,6 +38,7 @@ abstract class AbstractClassInheritanceParent: Node() { ``` Child class definition: + ```kotlin @RegisterClass class AbstractClassInheritanceChild: AbstractClassInheritanceParent() { diff --git a/docs/src/doc/user-guide/advanced/commandline-args.md b/docs/src/doc/user-guide/advanced/commandline-args.md index f497d441b5..7ec6f04e95 100644 --- a/docs/src/doc/user-guide/advanced/commandline-args.md +++ b/docs/src/doc/user-guide/advanced/commandline-args.md @@ -1,13 +1,13 @@ -The following command line args can be supplied to customize the behaviour or the Godot Kotlin/JVM binding: +The following command-line arguments can be supplied to customize the behaviour or the Godot Kotlin/JVM binding: -| Argument | Default value | Description | Example | -| --- | --- | --- | --- | -| --java-vm-type | jvm | Defines the VM to run on. Possible values are `jvm` and `graal_native_image`. When set to `graal_native_image` it uses Graal native image. This has no effect on android platform. | -| --jvm-debug-port | | Defines the port to which you can attach a remote debugger. **Note:** the module `jdk.jdwp.agent` is needed in the embedded JRE if you want to debug your application. If you need `jmx`, also the module `jdk.management.agent` is needed | `--jvm-debug-port=5005` | -| --jvm-debug-address | | Defines which adresses are allowed for debugging | `--jvm-debug-address=localhost` | -| --wait-for-debugger | true | Accepted values: `true` or `false`. Defines if the jvm should suspend execution until a remote debugger is attached. Only effective if either `--jvm-debug-port` or `--jvm-debug-address` is set | `--wait-for-debugger=true` | -| --jvm-jmx-port | | Defines the jmx port. **Note:** the module `jdk.management.agent` is needed in the embedded JRE to be able to use jmx | `--jvm-jmx-port=5006` | -| --jvm-to-engine-max-string-size | 512 | Maximun size of strings sent through the buffer. When above that value, strings are sent with a slower JNI Call. A bigger size means a bigger buffer. Increase if you need a lot of long strings and don't mind using more memory. One buffer exists for each thread | `--jvm-to-engine-max-string-size=512` | -| --jvm-force-gc | | If set the JVM GC is forced to run when our own GC runs. | `--jvm-force-gc` | -| --jvm-disable-gc | | Disables our GC. **Caution:** If you disable our GC you **will** have memory leaks as all Reference types and Native Types are not Garbage collected anymore | `--jvm-disable-gc` | -| --jvm-disable-closing-leaks-warning | | Disables the output of leaked instances when closing the application | `--jvm-disable-closing-leaks-warning` | +| Argument | Default value | Description | Example | +|-------------------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------| +| --java-vm-type | jvm | Defines the VM to run on. Possible values are `jvm` and `graal_native_image`. When set to `graal_native_image` it uses Graal native image. This has no effect on android platform. | +| --jvm-debug-port | | Defines the port to which you can attach a remote debugger. **Note:** the module `jdk.jdwp.agent` is needed in the embedded JRE if you want to debug your application. If you need `jmx`, also the module `jdk.management.agent` is needed | `--jvm-debug-port=5005` | +| --jvm-debug-address | | Defines which adresses are allowed for debugging | `--jvm-debug-address=localhost` | +| --wait-for-debugger | true | Accepted values: `true` or `false`. Defines if the jvm should suspend execution until a remote debugger is attached. Only effective if either `--jvm-debug-port` or `--jvm-debug-address` is set | `--wait-for-debugger=true` | +| --jvm-jmx-port | | Defines the jmx port. **Note:** the module `jdk.management.agent` is needed in the embedded JRE to be able to use jmx | `--jvm-jmx-port=5006` | +| --jvm-to-engine-max-string-size | 512 | Maximun size of strings sent through the buffer. When above that value, strings are sent with a slower JNI Call. A bigger size means a bigger buffer. Increase if you need a lot of long strings and don't mind using more memory. One buffer exists for each thread | `--jvm-to-engine-max-string-size=512` | +| --jvm-force-gc | | If set the JVM GC is forced to run when our own GC runs. | `--jvm-force-gc` | +| --jvm-disable-gc | | Disables our GC. **Caution:** If you disable our GC you **will** have memory leaks as all Reference types and Native Types are not Garbage collected anymore | `--jvm-disable-gc` | +| --jvm-disable-closing-leaks-warning | | Disables the output of leaked instances when closing the application | `--jvm-disable-closing-leaks-warning` | diff --git a/docs/src/doc/user-guide/advanced/custom_gradle_wrapper_path.md b/docs/src/doc/user-guide/advanced/custom-gradle-wrapper-path.md similarity index 59% rename from docs/src/doc/user-guide/advanced/custom_gradle_wrapper_path.md rename to docs/src/doc/user-guide/advanced/custom-gradle-wrapper-path.md index 68f69571ea..59e38d1770 100644 --- a/docs/src/doc/user-guide/advanced/custom_gradle_wrapper_path.md +++ b/docs/src/doc/user-guide/advanced/custom-gradle-wrapper-path.md @@ -1,9 +1,10 @@ -Sometimes a project setup is more advanced and requires to have the godot project as a module inside a bigger kotlin project. For example consider the following project setup: +Sometimes a project setup is more advanced and requires to have the Godot project as a module inside a bigger Kotlin project. For example consider the following project setup: ![Example project setup](../../assets/img/custom_gradle_wrapper_path_example_project_setup.png) -The godot editor does not know anything about the project structure in parent directories. Hence it cannot find the gradle wrapper as it only looks inside it's own directory. +The Godot editor does not know anything about the project structure in parent directories. Hence it cannot find the gradle wrapper as it only looks inside it's own directory. -To accommodate for more complicated project setups, you can define the path to the gradle wrapper in the project settings. The following example would fit the projects structure above where the gradle wrapper is located a directory above the godot project: +To accommodate for more complicated project setups, you can define the path to the gradle wrapper in the project settings. +The following example would fit the projects structure above where the Gradle wrapper is located a directory above the Godot project: ![Example project setup](../../assets/img/change_gradle_wrapper_path.png) \ No newline at end of file diff --git a/docs/src/doc/user-guide/advanced/custom-src-dirs.md b/docs/src/doc/user-guide/advanced/custom-src-dirs.md index e5809d429e..00b1704f58 100644 --- a/docs/src/doc/user-guide/advanced/custom-src-dirs.md +++ b/docs/src/doc/user-guide/advanced/custom-src-dirs.md @@ -1,4 +1,4 @@ -To be able to use custom source dirs, you can do the following: +To be able to use custom source directories, you modify your Gradle build file as it follows: === "build.gradle.kts" ```kt diff --git a/docs/src/doc/user-guide/advanced/graal-vm-native-image.md b/docs/src/doc/user-guide/advanced/graal-vm-native-image.md index 99aff9d15e..8af35c57ec 100644 --- a/docs/src/doc/user-guide/advanced/graal-vm-native-image.md +++ b/docs/src/doc/user-guide/advanced/graal-vm-native-image.md @@ -6,7 +6,7 @@ On desktop platform, you can choose to build a [GraalVM native image](https://www.graalvm.org/reference-manual/native-image/). You first need to install graal-vm and its tool native image. Then, you should set `GRAALVM_HOME` environment variable to point to GraalVM's home folder. -On windows, you should add `VC_VARS_PATH` environment variable to point to vcvars bat file. This is mandatory so that we can initialize visual studio tools. (Example: `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat`) +On Windows, you should add `VC_VARS_PATH` environment variable to point to vcvars bat file. This is mandatory so that we can initialize visual studio tools. (Example: `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat`) In order to build a native image, you should add the following configuration to gradle plugin to enable building of native-image: ```kotlin diff --git a/docs/src/doc/user-guide/advanced/gradle-plugin-configuration.md b/docs/src/doc/user-guide/advanced/gradle-plugin-configuration.md index 56a7210a05..3fc164c56b 100644 --- a/docs/src/doc/user-guide/advanced/gradle-plugin-configuration.md +++ b/docs/src/doc/user-guide/advanced/gradle-plugin-configuration.md @@ -1,7 +1,10 @@ -## Disable build failure on kotlin version mismatch -As we're using a kotlin compiler plugin to register your code with godot, we can only support a specific kotlin version per release. This is due to the fact that the kotlin compiler plugin api is not stable yet. +## Disable build failure on Kotlin version mismatch -But if you are familiar with the quirks of compiler plugins and their compatibility and you need to use another kotlin version than we officially support, you can disable the version checks we have in place in our gradle plugin. To do this you have to set `godot.jvm.suppressKotlinIncompatibility` to `true` in the `gradle.properties` file: +As we're using a Kotlin compiler plugin to register your code with Godot, we can only support a specific Kotlin version per release. +This is due to the fact that the Kotlin compiler plugin API is not stable yet. This should change in the future with the new release of K2 compiler. + +But if you are familiar with the quirks of compiler plugins and their compatibility and you need to use another Kotlin version than we officially support, +you can disable the version checks we have in place in our Gradle plugin. To do this you have to set `godot.jvm.suppressKotlinIncompatibility` to `true` in the `gradle.properties` file: === "gradle.properties" ``` diff --git a/docs/src/doc/user-guide/advanced/kotlin-singleton.md b/docs/src/doc/user-guide/advanced/kotlin-singleton.md index dd270a23bd..86dd827937 100644 --- a/docs/src/doc/user-guide/advanced/kotlin-singleton.md +++ b/docs/src/doc/user-guide/advanced/kotlin-singleton.md @@ -1,5 +1,7 @@ -Sometimes you need to store some Godot objects or references in a Kotlin singleton. This can cause some leaks when the program ends because you have to manually free objects and have the references collected. -This issue is fixed by using the delegate `godotStatic` on singleton properties. Those properties will be freed once the JVM ends. They automatically handle `Object` and `Reference`. You can also freely set a new value and the previous one will be immediatly freed. +Sometimes you need to store some Godot objects or references in a Kotlin singleton. +This can cause some leaks when the program ends because you have to manually free objects and have the references collected. +This issue is fixed by using the delegate `godotStatic` on singleton properties. Those properties will be freed once the running JVM ends. +They automatically handle `Object` and `Reference`. You can also freely set a new value and the previous one will be immediatly freed. !!! warning Only use it on a singleton, otherwise all the properties of all instances are going to be kept alive until the end of the JVM. diff --git a/docs/src/doc/user-guide/api-differences.md b/docs/src/doc/user-guide/api-differences.md index 20eec56ece..0cd25906ad 100644 --- a/docs/src/doc/user-guide/api-differences.md +++ b/docs/src/doc/user-guide/api-differences.md @@ -1,5 +1,6 @@ ## Registration files and attaching scripts -Contrary to GDScript and C# you cannot attach scripts (aka source files) directly to nodes. Godot Kotlin JVM uses a different approach: registration files. These files have the extension `gdj` and are generated during compilation. These are the files you attach to nodes. + +Contrary to GDScript and C# you cannot attach scripts (aka source files) directly to nodes. Godot Kotlin/JVM uses a different approach: registration files. These files have the extension `gdj` and are generated during compilation. These are the files you attach to nodes. Have a look at the [classes](classes.md) documentation for more information. @@ -7,6 +8,7 @@ Have a look at the [classes](classes.md) documentation for more information. Contrary to GDScript, Kotlin is a compiled language. Hence, if you use a library which defines scripts you can not attach those to nodes anymore as the source files don't exist. You only have a jar of the library. While in GDScript you still have the sources when using an addon. With our registration files our compiler plugin is able to extract those from the libraries you use and provide them to you, so you can also attach scripts from libraries you use. ## Class and member registration + Contrary to what you might be used to from GDScript or C#, this binding requires you to explicitly define which classes and which members of those classes should be exposed to Godot. This requires a bit more code but enables to properly define visibility across languages and restrict access to values @@ -15,39 +17,41 @@ See the individual sections in the `user-guide` in this documentation to see how you can use them from godot and other scripting languages. ## Instance types and singletons + Creating a new instance of a Godot type can be done like any Kotlin types. ```kotlin -val Node3D = Node3D() +val node3D = Node3D() val vec = Vector3() ``` -Godot singletons are mapped as Kotlin objects. +Godot's singletons are mapped as Kotlin objects. ```kotlin Physics2DServer.areaGetTransform(area) ``` ## Core types + Godot's built-in types are passed by value (except for `Dictionary` and `VariantArray` - more on this later), so the following snippet won't work as expected. ```kotlin -val Node3D = Node3D() -Node3D.rotation.y += 10f +val node3D = Node3D() +node3D.rotation.y += 10f ``` -You are actually mutating a copy of the `rotation` property, not a reference to it. To get the desired behaviour you have to re-assign the copy back. +You are *actually mutating a copy* of the `rotation` property, not a reference to it. To get the desired behaviour you have to re-assign the copy back. ```kotlin -val rotation = Node3D.rotation +val rotation = node3D.rotation rotation.y += 10f -Node3D.rotation = rotation +node3D.rotation = rotation ``` This approach introduces a lot of boilerplate, so this binding provides a concise way of achieving the same behaviour. ```kotlin -Node3D.rotationMutate { +node3D.rotationMutate { y += 10f } ``` @@ -55,6 +59,7 @@ Node3D.rotationMutate { The snippet above is functionally equivalent to the previous one. ## Collection types + While `VariantArray` and `Dictionary` are passed by reference, the value returned by the retrieval methods (`VariantArray.get(...)` and `Dictionary.get(...)`) are not. ```kotlin @@ -75,61 +80,72 @@ dictionary.get("foo") { ``` ## Enums and constants + Godot enums are mapped to Kotlin enums, the generated enum exposes a `value` property that represents the value in Godot. Constants in Godot classes that represent an enum value (such as `Node.PAUSE_MODE_INHERIT`) are not present in this module, please use the generated enum instead (`Node.PauseMode.INHERIT`). ## Signals and exposed methods -In GDScript, signals can have any number of arguments, this is not possible in Kotlin as it is a statically typed language. At the moment, you can create signals and expose them to Godot with at most 10 parameters. + +In GDScript, signals can have any number of arguments, this is not possible in Kotlin as it is a statically typed language. +At the moment, you can create signals and expose them to Godot with at most 10 parameters. If you need more than 10 parameters, you can either use the not typesafe function `connect(signalAsString, targetObject, targetMethodAsString)` and the corresponding emit function or you can write your own typesafe extension functions like we did, to further increase the supported arg count. Keep in mind that you pass in the converted function and signal names (snake_case) to the above mentioned functions. ## Renamed symbols + To avoid confusion and conflict with Kotlin types, the following Godot symbol is renamed. - `Array` -> `VariantArray` (to avoid confusion with a built-in type in Kotlin) ## Global functions -In GDScript, some functions are always available like mathematical functions or RNG functions. The complete list is here: https://docs.godotengine.org/en/stable/classes/class_%40gdscript.html. +In GDScript, some functions are always available (such as mathematical or RNG functions). +The complete list can be found on the following [page](https://docs.godotengine.org/en/stable/classes/class_%40gdscript.html) of Godot's documentaion. -In Kotlin, they are available inside the `GD` singleton. Don't forget that some functions couldn't be reproduced in Kotlin. `load()` is available but `preload()` is not. +In Kotlin, global functions are available inside the `GD` object singleton. However, don't forget that some functions couldn't be reproduced in Kotlin. +E.g., the `load()` function is available but `preload()` is not. ## Additional functions -For comfort, some Objects got some additional functions to enjoy some Kotlin syntax sugar. You can find them all [in this folder](https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/kt/godot-library/src/main/kotlin/godot/extensions) +For comfort, some Objects got some additional functions to enjoy some Kotlin syntax sugar. +You can find them all [in this folder](https://github.com/utopia-rise/godot-kotlin-jvm/tree/master/kt/godot-library/src/main/kotlin/godot/extensions). ## Notifications You can implement [_notification](https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-private-method-notification) -and have class hierarchy notification call without using `super` call, as in GDScript and C++. -However, syntax is a bit different: +and have class hierarchy notification call without using `super` call, as in GDScript and C++. However, the syntax is a bit different: + ```kotlin - @RegisterFunction - override fun _notification() = godotNotification { - ... - } +@RegisterFunction +override fun _notification() = godotNotification { + // ... +} ``` Currently this feature except abstract classes. ## Caching -Several Godot functions take `StringName` or `NodePath` as a parameter. Extension functions have been provided `String.asStringName()`, `String.asNodePath()` and `StringName.asNodePath()`, to allow for the easy creation of these. As an optimisation, these `StringName` and `NodePath` instances are cached to reduce the overhead of creating new instances unnecessarily. +Several Godot functions take `StringName` or `NodePath` as a parameter. + +Extension functions have been provided `String.asStringName()`, `String.asNodePath()` and `StringName.asNodePath()`, to allow for the easy creation of these. +As an optimisation, these `StringName` and `NodePath` instances are cached to reduce the overhead of creating new instances unnecessarily. ```kotlin - // This first call to the extension function creates the cache entry. - val firstCall = "Test".asStringName() +// This first call to the extension function creates the cache entry. +val firstCall = "Test".asStringName() - // This second call for the same String value, will return the previously cached instance. - val secondCall = "Test".asStringName() +// This second call for the same String value, will return the previously cached instance. +val secondCall = "Test".asStringName() - // This third call will create a second entry in the cache due to the different key value. - val thirdCall = "OtherTest".asStringName() +// This third call will create a second entry in the cache due to the different key value. +val thirdCall = "OtherTest".asStringName() ``` ## Logging + If you want logs to appear both in CLI and in the Godot Editor you will have to use the print functions inside the `GD` singleton like: ```kt GD.print("Hello There!") ``` -Kotlin's print functions on the other hand will only print to CLI! They will print to Godot editor's output panel. +Kotlin's print functions, on the other hand, will only print to CLI! They will print to Godot editor's output panel. diff --git a/docs/src/doc/user-guide/classes.md b/docs/src/doc/user-guide/classes.md index 25c80c23b2..e095355cac 100644 --- a/docs/src/doc/user-guide/classes.md +++ b/docs/src/doc/user-guide/classes.md @@ -8,11 +8,14 @@ class RotatingCube: Node3D() { ``` ## Registration files + For each class you register, a corresponding registration file is generated (a `gdj` file). These are the files you attach to nodes. ### Location -By default, these files are generated into a folder called `gdj` in the root of your project. -You can however configure this inside your `build.gradle.kts`: + +By default, these files are generated into a folder called `gdj` in the root of your project. + +You can however configure the destination folder inside your `build.gradle.kts`: ```kotlin godot { @@ -21,19 +24,22 @@ godot { ``` ### Naming + Classes need to be registered with a unique name as Godot does not support namespaces (or packages in this case) for script classes. -By default, we register your classes with the name you give them. While a simple approach and enough in most cases, this can lead to naming conflicts if you have classes in different packages with the same name. For example: +By default, we register your classes with the name you give them. While beign a simple approach and enough in most cases, +this can lead to naming conflicts if you have classes in different packages with the same name. For example: - `com.package.a.MyClass` - `com.package.b.MyClass` This leads to a conflict on the Godot side as both classes are registered as `MyClass`. -So you are responsible for making sure that classes have a unique name. We do however provide you with some assistance: +So you are responsible for making sure that classes have a unique name. +We do however provide you with some assistance: -- We have compile time checks in place which should let the build fail if classes would end up having the same name -- The `@RegisterClass` annotation lets you define a custom registration name: `@RegisterClass("CustomRegistrationName")` +- We have compile time checks in place which should let the *build fail* if classes would end up having the same name. +- The `@RegisterClass` annotation lets you define a custom registration name: `@RegisterClass("CustomRegistrationName")`. - Register the class names with the fully qualified name: `com.mygame.MyClass` will be registered as: `com_mygame_MyClass`. This can be configured with: ```kotlin godot { @@ -45,7 +51,10 @@ So you are responsible for making sure that classes have a unique name. We do ho Even with all these checks and helpers in place, we cannot check the names of classes from other languages like GDScript or C#. It's your responsibility to make sure there are no naming conflicts. ### Hierarchy -Again: Godot does not have the concept of namespaces. So all classes are registered top level. It does not matter where in the folder hierarchy a script resides in, it still is accessed the same way. Hence, it does not matter if the registration files are all in one directory, or scattered across multiple directories. + +As mentioned beforehand, Godot does not have the concept of namespaces. So all classes are registered at top level. +It does not matter where in the folder hierarchy a script resides in, it still is accessed the same way. +Hence, it does not matter if the registration files are all in one directory, or scattered across multiple directories. By default, the registration files are all generated in a folder hierarchy which resembles your package hierarchy: - `com.mygame.packageA.ClassA` @@ -61,14 +70,16 @@ By default, the registration files are all generated in a folder hierarchy which └── ClassB.gdj ``` -Some do not like this hierarchical structure and especially for small games with not many scripts, this could be undesirable to work with. Hence, we let you turn of the hierarchical generation in your `build.gradle.kts`: +Some do not like this hierarchical structure and especially for small games with not many scripts, this could be undesirable to work with. +Thus, we let you turn of the hierarchical generation in your `build.gradle.kts`: + ```kotlin godot { isRegistrationFileHierarchyEnabled.set(false) } ``` -Which would result in a folder structure like this: +Which would result in a folder structure like the following: - `com.mygame.packageA.ClassA` - `com.mygame.packageB.ClassB` @@ -91,7 +102,9 @@ This could also be useful together with the option `isFqNameRegistrationEnabled` ``` ## Lifecycle -If you want to be notified when initialization and destruction of your class happens, use the `init` block and override the `_onDestroy` function respectively. + +If you want to be notified when initialization and destruction of your class' instance happens, use the `init` block +and override the `_onDestroy` function respectively. ```kt @RegisterClass @@ -107,6 +120,7 @@ class RotatingCube: Node3D() { ``` ## Instance checks + Checking if an object is an instance of a particular type can be done via the `is` operator. ```kt @@ -132,24 +146,29 @@ This also works for any type you define. override fun _ready() { val parent = getParent() require(parent is CollisionShape) - // smart cast works here as well! + // Smart Cast works here as well! parent.setShape(...) } ``` ## Constructors -Godot requires you to have a default constructor on your classes. You can define additional constructors but you have to register them by annothing them with `@RegisterConstructor`. Default constructors on the other hand are always registered. -Constructors also can have a maximum of 8 arguments and must have a unique argument count as constructor overloading is not yet supported. This limitation is only for registered constructors. +Godot requires you to have a default constructor on your classes. +You can define additional constructors but you have to register them by annothing them with `@RegisterConstructor`. +Default constructors, on the other hand, are always registered automatically. + +Constructors can also have **a maximum of 8 arguments** and must have a unique argument count as constructor overloading is not yet supported. +This limitation is only for registered constructors. ### Instantiate Kotlin script classes in GDScript -Creating an instance using the default constructor can be done by: + +From GDScript it is possible to create an instance of a Kotlin class using the default constructor: ```kt var instance := YourKotlinClass.new() ``` -While for additional constructors, `load` must be used: +Additional constructors must use the `load` function: ```kt var instance := load("res://gdj/YourClass.gdj").new(oneArg, anotherArg) @@ -160,15 +179,17 @@ var instance := load("res://gdj/YourClass.gdj").new(oneArg, anotherArg) ## Customization -You can customize to some extent how your class should be registered in Godot: -The `@RegisterClass` annotation can take two arguments: +You can customize to some extent how your class should be registered in Godot. + +The `@RegisterClass` annotation takes only one argument: -- **className**: If set, the class will be registered with the name you provide +- **className**: If set, the class will be registered with the provided name. !!! warning "Unique class names" If you specify the `className` in the annotation, you have to make sure that this name is unique! We implemented compilation checks to make sure the compilation fails if more than two classes are registered with the same name, but we cannot check class names from other scripting languages like GDScript or C#! It is also recommended installing our intellij plugin as it shows duplicated registered class names in the editor as an error. -## Tool mode +## Tool Mode + Annotate your class with `@Tool` to make it a tool class (note that `@RegisterClass` is required for this annotation to take effect). \ No newline at end of file diff --git a/docs/src/doc/user-guide/compiling-your-project.md b/docs/src/doc/user-guide/compiling-your-project.md index 0c2768ec7a..b1d913ffcf 100644 --- a/docs/src/doc/user-guide/compiling-your-project.md +++ b/docs/src/doc/user-guide/compiling-your-project.md @@ -1,27 +1,34 @@ -To compile your project, run a classic *gradle build*. By default this creates a `debug` version of your code. -Ex: -``` +To compile your project, run a classic *Gradle build*. By default this creates a `debug` version of your code. + +Example: + +```bash ./gradlew build ``` -## TARGETS +## Targets -We have two targets: `debug` and `release`. -In order to build in release, you should add `release` parameter to your gradle build command. -Ex: -``` +We have two targets: `debug` and `release`. +In order to build in release, you should add `release` parameter to your Gradle build command. + +Example: + +```bash ./gradlew build -Prelease ``` Using debug builds is recommended when developing. It adds some sanity checks that are cut off in `release`. -Release builds are recommended when retail. + +Release builds are recommended when distributing to retail. ## Write debug code -You can add code only for debug version of your project, by using `GodotJvmDefinitions`. -Ex: +You can add code only for debug version of your project, by using `GodotJvmDefinitions`. + +Example: + ```kotlin if (GodotJvmDefinitions.DEBUG) { - ... + // ... } ``` \ No newline at end of file diff --git a/docs/src/doc/user-guide/consuming-libraries.md b/docs/src/doc/user-guide/consuming-libraries.md index da61b38d95..bb2b881c82 100644 --- a/docs/src/doc/user-guide/consuming-libraries.md +++ b/docs/src/doc/user-guide/consuming-libraries.md @@ -1,15 +1,17 @@ -# Regular jvm libraries -Regular jvm libraries can be used the same way as for regular Gradle projects: +# Regular JVM libraries + +Regular JVM libraries can be used the same way as for regular Gradle projects: ```koltin -//build.gradle.kts +// build.gradle.kts dependencies { implementation("some.library:some-artifact:") } ``` -# Godot Kotlin Jvm libraries +# Godot Kotlin/JVM libraries + Can also be used the same way as for regular Gradle projects: ```koltin @@ -20,7 +22,10 @@ dependencies { } ``` -But during compilation registration files for the registered classes in these libraries are generated for you, so you can use those and attach them to nodes in the Godot Editor. These registration files for those libraries are generated to a directory called `dependencies` inside your configured root directory for registration files: +But, during compilation, registration files for the registered classes in these libraries are generated for you, +so you can use those and attach them to nodes in the Godot Editor. +These registration files for those libraries are generated to a directory called `dependencies` inside your +configured root directory for registration files: ``` [registrationFileBaseDir]/ @@ -32,4 +37,5 @@ But during compilation registration files for the registered classes in these li └── // your own registration files ``` -The folder structure configuration is the same as you configured for your own project (just inside the `dependencies/` folder). Have a look at the available options in the [classes user-guide](classes.md#registration-files) \ No newline at end of file +The folder structure configuration is the same as you configured for your own project (just inside the `dependencies/` folder). +Have a look at the available options in the [classes user-guide](classes.md#registration-files) \ No newline at end of file diff --git a/docs/src/doc/user-guide/debugging.md b/docs/src/doc/user-guide/debugging.md index 628e628e61..a33615a67b 100644 --- a/docs/src/doc/user-guide/debugging.md +++ b/docs/src/doc/user-guide/debugging.md @@ -1,4 +1,5 @@ ## Prerequisites + In order to debug your code using an embedded JRE, make sure to include the following modules: - `jdk.jdwp.agent` @@ -7,10 +8,11 @@ In order to debug your code using an embedded JRE, make sure to include the foll Example for AMD64 systems: `jlink --add-modules java.base,java.logging,jdk.jdwp.agent --output jre-amd64` Example for ARM64 systems: `jlink --add-modules java.base,java.logging,jdk.jdwp.agent --output jre-arm64` -If you're still using the jdk installed on your system though, you don't need to do this. +If you're still using the JDK installed on your system though, you don't need to do this. + +## Run and attach a Remote Debugger -## Run and attach Remote Debugger -Run your game with the commandline option `--jvm-debug-port=` and attach a remote debugger. +Run your game with the command-line option `--jvm-debug-port=` and attach a remote debugger. !!! info If you specify either `--jvm-debug-port` or `--jvm-debug-address` the execution of the game will suspend until you attach a remote debugger. You can configure this behaviour by specifying `--wait-for-debugger=true` or `--wait-for-debugger=false` diff --git a/docs/src/doc/user-guide/exporting.md b/docs/src/doc/user-guide/exporting.md index 180b23342a..13c1e5b623 100644 --- a/docs/src/doc/user-guide/exporting.md +++ b/docs/src/doc/user-guide/exporting.md @@ -8,13 +8,15 @@ To export your game, you need to add our export templates to Godot. After you've ![Select install from file](../assets/img/export_template_manager_install_from_file.png) ![Select tpz](../assets/img/export_template_manager_select_tpz.png) -After the export templates have been added, you can export your game. Your game `jar` will be included in `pck`. On desktop platforms, this also copies the jre folder of your project in the exported game folder. +After the export templates have been added, you can export your game. Your game `jar` will be included in `pck`. +On desktop platforms, this also copies the JRE folder of your project in the exported game folder. !!!danger The official export templates from Godot will not work! You have to use our export templates or build your own! Therefore, you cannot just hit the "Download and Install" button in the export template manager! ## Requirements + To export your game, you need to have an embedded JRE created. Run the following command within your project's root. - amd64 systems: @@ -31,18 +33,22 @@ The above command will create a very minimal JVM, if you need extra features you - `jdk.jdwp.agent` to enable remote debugging - `jdk.management.agent` to enable JMX. -*Special note for MacOS*: To create a universal app, you'll need both amd64 and arm64 JRE. You can create an amd64 jre -by using jlink with rosetta and an amd64 jdk on an arm64 MacOS. +*Special note for MacOS*: To create a universal app, you'll need both amd64 and arm64 JRE. You can create an amd64 JRE +by using `jlink` with rosetta and an amd64 JDK on an arm64 MacOS. -!!!warning Correct jre for desktops +!!!warning Correct JRE for desktops For desktop exports you need to make exports based on the platform you're on, as exporting will copy the generated jre folder to - your export. An MacOS jre will not work on windows, so you'll need a windows host to export for windows. + your export. An MacOS JRE will not work on Windows, so you'll need a Windows host to export for Windows. ## Specifics -`godot-bootstrap.jar` and `main.jar` are copied into `pck` during the export process. As a real file path is needed to handle them, they are copied on the first game version start from `res://` to `user://` (we check if they exist and also check the md5 hash) to only update when needed. Don't forget to remove them when writing an uninstaller for your game. +`godot-bootstrap.jar` and `main.jar` are copied into `pck` during the export process. +As a real file path is needed to handle them, they are copied on the first game version start +from `res://` to `user://` (we check if they exist and also check the md5 hash) to only update when needed. +Don't forget to remove them when writing an uninstaller for your game. ## Android + !!! warning If you plan to export your game to android, make sure the libraries you use, are actually compatible with android. @@ -55,9 +61,10 @@ In order to build for Android, set the `isAndroidExportEnabled` flag to `true` i } ``` -On android, we do not embed a JVM, we use the existing ART provided by the OS. In order for your game to load the necessary jar files, they need to be converted into dex format. Our gradle plugin will handle this for you, but you need to fulfill the following requirements: +On Android, we do not embed a JVM, we use the existing VM provided by the OS. In order for your game to load the necessary JAR files, +they need to be converted into `.dex` format. Our Gradle plugin will handle this for you, but you need to fulfill the following requirements: -- Android SDK installed +- Android SDK installed. - `d8` tool resolvable by setting the `d8ToolPath` to the file path of `d8`: ```kt godot { @@ -65,7 +72,7 @@ On android, we do not embed a JVM, we use the existing ART provided by the OS. I } ``` -- Setting the `androidCompileSdkDir` to your target sdk version (most of the time, you want to set it to the newest version available): +- Setting the `androidCompileSdkDir` to your target SDK version (most of the time, you want to set it to the newest version available): ```kt godot { androidCompileSdkDir = File("${System.getenv("ANDROID_SDK_ROOT")}/platforms/android-30") @@ -80,25 +87,26 @@ On android, we do not embed a JVM, we use the existing ART provided by the OS. I ``` !!!danger - Similar to the desktop targets, the game copies the needed jar files to the `user://` directory upon first execution or if the files have changed. On android this is the applications `files` folder. If you do IO operations on Android, never empty the whole `files` folder! Only delete what you have added or exclude the following two files when clearing the `files` folder: `godot-bootstrap-dex.jar` and `main-dex.jar`. + Similar to the desktop targets, the game copies the needed jar files to the `user://` directory upon first execution or if the files have changed. On Android this is the applications `files` folder. If you do IO operations on Android, never empty the whole `files` folder! Only delete what you have added or exclude the following two files when clearing the `files` folder: `godot-bootstrap-dex.jar` and `main-dex.jar`. ## GraalVM Native Image !!! warning - GraalVM native image is an advanced feature and requires a lot of work to support. Especially if you rely on many third party libraries. + GraalVM Native Image is an advanced feature and requires a lot of work to support. Especially if you rely on many third party libraries. In order to build for graalvm, follow `GraalVM native-image` section in [advanced user guide](./advanced/graal-vm-native-image.md). The `main.jar` and `godot-bootstrap.jar` are compiled into a single `usercode` shared library is copied into `pck` during the export process. Similar to the regular export versions, the `usercode` shared library is copied to the `user://` dir. Don't forget to delete it when creating an uninstaller. -On desktop platform default export is inferred by the `godot_kotin_configuration.json` file. You still can export for `jvm` and `native-image`, by adding feature `export-all-jvm`. In this case, the default JVM started by engine is the one from `godot_kotin_configuration.json` and can be overridden by command line. +On desktop platform default export is inferred by the `godot_kotin_configuration.json` file. You still can export for `jvm` and `native-image`, by adding feature `export-all-jvm`. In this case, the default JVM started by engine is the one from `godot_kotin_configuration.json` and can be overridden by command-line. ## iOS !!! warning IOS export is experimental. -Additionally, to the regular GraalVM configuration mentioned above, add the following in `build.gradle.kts`: +Additionally, to the regular GraalVM configuration mentioned above, add the following in `build.gradle.kts`: + ```kotlin godot { isGraalNativeImageExportEnabled.set(true) @@ -108,4 +116,4 @@ godot { ``` !!! warning - With this export you don't have a choice regarding JVM embedding in the app. Godot kotlin's gradle plugin will automatically download a iOS static JDK libraries and pack it with your code for iOS. \ No newline at end of file + With this export you don't have a choice regarding JVM embedding in the app. Godot Kotlin's Gradle plugin will automatically download a iOS static JDK libraries and pack it with your code for iOS. \ No newline at end of file diff --git a/docs/src/doc/user-guide/functions.md b/docs/src/doc/user-guide/functions.md index 4a877af336..7337b9bfbd 100644 --- a/docs/src/doc/user-guide/functions.md +++ b/docs/src/doc/user-guide/functions.md @@ -1,4 +1,5 @@ -Any Kotlin function can be registered as long as its parameters and return type can be converted to a `Variant`. To register a function annotate it with `@RegisterFunction`. +Any Kotlin function can be registered as long as its parameters and return type can be converted to a `Variant`. +To register a function annotate it with `@RegisterFunction`. ```kotlin @RegisterClass @@ -11,15 +12,26 @@ class RotatingCube: Node3D() { ``` ## Naming -Function names should follow Kotlin's style which is camelCase. For consistency with Godot's style, your functions are actually registered as snake_case. So a function `doSomething()` in Kotlin is usable in GDScript as `do_something()`. + +Function names should follow Kotlin's style which is `camelCase`. For consistency with Godot's style, +your functions are actually registered as `snake_case`. +Therefore, a function called `doSomething()` in Kotlin is usable in GDScript as `do_something()`. ## Virtual functions -Virtual functions (like `_ready`, `_process` and `_physics_process`) are declared as overridable functions. The default implementation throws a `NotImplementedException`, so you have to override it if you plan to expose a virtual function to Godot. Remember, just overriding is not enough to use that function - you have to explicitly register it as well with `@RegisterFunction`. -## Arg count -Godot limits the allowed argument count of functions to `8`. Thus, this binding also has this limitation. If you want to pass more than 8 parameters in a function, you need to wrap them in a container (like a custom container class or a `VariantArray` or `Dictionary`). +Virtual functions (like `_ready`, `_process` and `_physics_process`) are declared as overridable functions. +The default implementation throws a `NotImplementedException`, so you have to override it if you plan to expose +a virtual function to Godot. Remember, just overriding is not enough to use that function - you have to explicitly +register it as well with `@RegisterFunction`. + +## Arguments count + +Godot limits the allowed argument count of functions to `8`. Thus, this binding also has this limitation. +If you want to pass more than 8 parameters in a function, you need to wrap them in a container +(like a custom container class or a `VariantArray` or `Dictionary`). ## Customization -You can customize to some extent how your function should be registered in Godot. The `@RegisterFunction` annotation takes one argument: + +You can customize to some extent how your functions should be registered in Godot. The `@RegisterFunction` annotation takes one argument: - **rpcMode**: Default: `RPCMode.DISABLED` diff --git a/docs/src/doc/user-guide/properties.md b/docs/src/doc/user-guide/properties.md index c6630bd55b..92d3d5d49a 100644 --- a/docs/src/doc/user-guide/properties.md +++ b/docs/src/doc/user-guide/properties.md @@ -1,4 +1,5 @@ -Any property of a registered class can be registered as long as it is public, mutable and can be converted to a `Variant`. To register a property annotate it with `@RegisterProperty`. +Any property of a registered class can be registered as long as it is public, mutable and can be converted to a `Variant`. +To register a property annotate it with `@RegisterProperty`. ```kotlin @RegisterClass @@ -12,10 +13,14 @@ class RotatingCube: Node3D() { ``` ## Naming -Property names should follow Kotlin's style which is `camelCase`. For consistency with Godot's style, your properties are actually registered as `snake_case`. So a property `someFlag` in Kotlin is usable in GDScript as `some_flag`. + +Property names should follow Kotlin's style which is `camelCase`. For consistency with Godot's style, +your properties are actually registered as `snake_case`. So a property `someFlag` in Kotlin is usable in GDScript as `some_flag`. ## Exporting properties -A registered property can be exported (a.k.a make it visible in the Godot editor) by annotating it with `@Export`. A property can be exported if it is a core type, a primitive or inherits from `godot.RefCounted`. + +A registered property can be exported (a.k.a make it visible in the Godot editor) by annotating it with `@Export`. +A property can be exported if it is a core type, a primitive or inherits from `godot.RefCounted`. ```kotlin @RegisterClass @@ -26,34 +31,39 @@ class RotatingCube: Node3D() { } ``` -Exported properties can also have default values (`2f` in the example above) which will be used as a default value by the `inspector`. A default value can **only** contain compile time constants and only references to compile time constants. +Exported properties can have default values (`2f` in the example above) which will be used as a default value by the `inspector`. +A default value can **only** contain compile time constants and only references to compile time constants. !!! danger If you set a default value in code and a different value in the `inspector` the value of the latter will override the value in code after `init` and before `_enter_tree`. -## Type Hint Registration -This module provides a plethora of annotations for defining property type hints. These annotations controls how Godot display the property in the inspector. Each property hint annotation can only be added to certain types of properties. Using the wrong annotation will make the compilation fail. These will only take effect if the property is exported. +## Type hint registration + +This module provides a plethora of annotations for defining property type hints. +These annotations controls how Godot display the property in the inspector. +Each property hint annotation can only be added to certain types of properties. +Using the wrong annotation will make the compilation fail. These will only take effect if the property is exported. !!! note If you are using IntelliJ IDEA and have our plugin installed, you will get a warning about wrong annotation usages. Below is a list of currently implemented type hints: -| Annotation | Type of Property | Arguments | Short Description | -|-----------------|----------------------------|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| -| IntRange | Int | start: Int, end: Int, step: Int = -1, or: Range = Range.NONE | Provides a range of ints from start to end, with optional steps, and optional `lesser or greater` | -| FloatRange | Float | start: Float, end: Float, step: Float = -1, or: Range = Range.NONE | Provides a range of floats from start to end, with optional steps, and optional `lesser or greater` | -| DoubleRange | Double | start: Double, end: Double, step: Double = -1, or: Range = Range.NONE | Provides a range of doubles from start to end, with optional steps, and optional `lesser or greater` | -| ExpRange | Float Double | start: Float, end: Float, step: Float = -1, or: Range = Range.NONE | Provides a exponential range of doubles or floats from start to end, with optional steps, and optional `lesser or greater` | -| EnumTypeHint | Enum | | Registers an enum. The editor then provides a selection of the possible enum values | -| ExpEasing | Float Double | attenuation: Boolean = false, inOut: Boolean = true | N/A | -| EnumFlag | Set MutableSet | | Registers a flag with the enum names set as the flag names. The values in the set define which flags are set. | -| IntFlag | Int | names: vararg String | Same as enum flag but the `names` set which values can be set in the inspector and no automatic conversion to the individual flag values happen. | -| File | String | extensions: Array = [], global: Boolean = false | The inspector will show a File dialog in which you can select a File. The Path of the file will be stored in the property. | -| Dir | String | global: Boolean = false | The inspector will show a File dialog in which you can select a directory. The Path of the directory will be stored in the property. | -| MultilineText | String | | The inspector shows a multiline text input. | -| PlaceHolderText | String | | N/A | -| ColorNoAlpha | Color | | The inspector shows a color selection dialog without Alpha | +| Annotation | Type of Property | Arguments | Short Description | +|-------------------|----------------------------|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `IntRange` | Int | start: Int, end: Int, step: Int = -1, or: Range = Range.NONE | Provides a range of ints from start to end, with optional steps, and optional `lesser or greater` | +| `FloatRange` | Float | start: Float, end: Float, step: Float = -1, or: Range = Range.NONE | Provides a range of floats from start to end, with optional steps, and optional `lesser or greater` | +| `DoubleRange` | Double | start: Double, end: Double, step: Double = -1, or: Range = Range.NONE | Provides a range of doubles from start to end, with optional steps, and optional `lesser or greater` | +| `ExpRange` | Float Double | start: Float, end: Float, step: Float = -1, or: Range = Range.NONE | Provides a exponential range of doubles or floats from start to end, with optional steps, and optional `lesser or greater` | +| `EnumTypeHint` | Enum | | Registers an enum. The editor then provides a selection of the possible enum values | +| `ExpEasing` | Float Double | attenuation: Boolean = false, inOut: Boolean = true | N/A | +| `EnumFlag` | Set MutableSet | | Registers a flag with the enum names set as the flag names. The values in the set define which flags are set. | +| `IntFlag` | Int | names: vararg String | Same as enum flag but the `names` set which values can be set in the inspector and no automatic conversion to the individual flag values happen. | +| `File` | String | extensions: Array = [], global: Boolean = false | The inspector will show a File dialog in which you can select a File. The Path of the file will be stored in the property. | +| `Dir` | String | global: Boolean = false | The inspector will show a File dialog in which you can select a directory. The Path of the directory will be stored in the property. | +| `MultilineText` | String | | The inspector shows a multiline text input. | +| `PlaceHolderText` | String | | N/A | +| `ColorNoAlpha` | Color | | The inspector shows a color selection dialog without Alpha | !!! note It's not easy to track changes to these property hints on the Godot project. If one is missing or not working as expected, please file an [issue on GitHub](https://github.com/utopia-rise/godot-kotlin-jvm/issues). \ No newline at end of file diff --git a/docs/src/doc/user-guide/signals.md b/docs/src/doc/user-guide/signals.md index 33267a0304..90d898902f 100644 --- a/docs/src/doc/user-guide/signals.md +++ b/docs/src/doc/user-guide/signals.md @@ -1,8 +1,8 @@ -Use the delegate `signal` to create a signal and annotate it with `@RegisterSignal`. +To create a signal use the delegate function `signal` and annotate it with `@RegisterSignal`. !!! warning Signal parameter count In GDScript, signals can have any number of arguments, this is not possible in Kotlin as it is a statically typed language. At the moment, you can create signals and expose them to Godot with at most 10 parameters. - If you need more than 10 parameters, you can either use the not typesafe function `connect(signalAsString, targetObject, targetMethodAsString)` and the corresponding emit function or you can write your own typesafe extension functions like we did, to further increase the supported arg count. Keep in mind that you pass in the converted function and signal names (snake_case) to the above mentioned functions (see the section [Naming](#naming) below for details). + If you need more than 10 parameters, you can either use the not typesafe function `connect(signalAsString, targetObject, targetMethodAsString)` and the corresponding emit function or you can write your own typesafe extension functions like we did, to further increase the supported arg count. Keep in mind that you pass in the converted function and signal names (`snake_case`) to the above mentioned functions (see the section [Naming](#naming) below for details). ```kotlin @@ -14,16 +14,20 @@ class RotatingCube: Node3D() { ``` ## Naming -For consistency with Godot's style, the name of your signal is converted to snake_case. The signal `helloThere` is known as `hello_there` in GDScript. + +For consistency with Godot's style, the name of your signal is converted to snake_case. +The signal `helloThere` is known as `hello_there` in GDScript. ## Emitting -Every signal has a `emit` method which can be used to emit it in a typesafe way. + +Every signal has a `emit` method which can be used to emit it in a type-safe way. ```kotlin reverseChanged.emit(false) ``` ## Subscribing + A method can be subscribed/connected to a signal via `connect`. ```kt diff --git a/docs/src/doc/user-guide/supported-platforms.md b/docs/src/doc/user-guide/supported-platforms.md index 52f90f1493..de4339ee9f 100644 --- a/docs/src/doc/user-guide/supported-platforms.md +++ b/docs/src/doc/user-guide/supported-platforms.md @@ -2,6 +2,6 @@ While Kotlin and Godot supports a wide range of platforms, this module for the m - Windows X64 - Linux X64 -- MacOS X64 +- MacOS X64 / arm64 - Android (arm64v8) - iOS (arm64v8) diff --git a/docs/src/doc/user-guide/versioning.md b/docs/src/doc/user-guide/versioning.md index 34764d1622..0479793ddb 100644 --- a/docs/src/doc/user-guide/versioning.md +++ b/docs/src/doc/user-guide/versioning.md @@ -1,4 +1,4 @@ -The module uses semantic versioning for its own versions but adds a suffix for the supported godot version: +The module uses semantic versioning for its own versions but adds a suffix for the supported Godot version: Full version: `0.8.1-4.2.0`