mirror of
https://github.com/stan220/godot-docs.git
synced 2026-09-08 19:29:06 +00:00
Split C++ (godot-cpp) and GDExtension system info into separate categories, children of Scripting.
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
env = SConscript("godot-cpp/SConstruct")
|
||||
|
||||
# For reference:
|
||||
# - CCFLAGS are compilation flags shared between C and C++
|
||||
# - CFLAGS are for C-specific compilation flags
|
||||
# - CXXFLAGS are for C++-specific compilation flags
|
||||
# - CPPFLAGS are for pre-processor flags
|
||||
# - CPPDEFINES are for pre-processor defines
|
||||
# - LINKFLAGS are for linking flags
|
||||
|
||||
# tweak this if you want to use different folders, or more folders, to store your source code in.
|
||||
env.Append(CPPPATH=["src/"])
|
||||
sources = Glob("src/*.cpp")
|
||||
|
||||
if env["platform"] == "macos":
|
||||
library = env.SharedLibrary(
|
||||
"demo/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
|
||||
env["platform"], env["target"], env["platform"], env["target"]
|
||||
),
|
||||
source=sources,
|
||||
)
|
||||
elif env["platform"] == "ios":
|
||||
if env["ios_simulator"]:
|
||||
library = env.StaticLibrary(
|
||||
"demo/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.StaticLibrary(
|
||||
"demo/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]),
|
||||
source=sources,
|
||||
)
|
||||
else:
|
||||
library = env.SharedLibrary(
|
||||
"demo/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
Default(library)
|
||||
@@ -2148,5 +2148,5 @@ quite straightforward and not very verbose.
|
||||
|
||||
If you want to create actual extensions, it is preferred to use the C++ bindings
|
||||
instead, as it takes away all of the boilerplate from your code. Check the
|
||||
:ref:`GDExtension C++ example <doc_gdextension_cpp_example>` to see how you can
|
||||
:ref:`godot-cpp documentation <doc_godot_cpp>` to see how you can
|
||||
do this.
|
||||
|
||||
@@ -1,717 +0,0 @@
|
||||
.. _doc_gdextension_cpp_example:
|
||||
|
||||
GDExtension C++ example
|
||||
=======================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The C++ bindings for GDExtension are built on top of the C GDExtension API
|
||||
and provide a nicer way to "extend" nodes and other built-in classes in Godot using C++.
|
||||
This new system allows the extension of Godot to nearly the same
|
||||
level as statically linked C++ modules.
|
||||
|
||||
You can download the included example in the test folder of the godot-cpp
|
||||
repository `on GitHub <https://github.com/godotengine/godot-cpp>`__.
|
||||
|
||||
Setting up the project
|
||||
----------------------
|
||||
|
||||
There are a few prerequisites you'll need:
|
||||
|
||||
- a Godot 4 executable,
|
||||
- a C++ compiler,
|
||||
- SCons as a build tool,
|
||||
- a copy of the `godot-cpp
|
||||
repository <https://github.com/godotengine/godot-cpp>`__.
|
||||
|
||||
See also :ref:`Configuring an IDE <toc-devel-configuring_an_ide>`
|
||||
and :ref:`Compiling <toc-devel-compiling>` as the build tools are identical
|
||||
to the ones you need to compile Godot from source.
|
||||
|
||||
You can download the `godot-cpp repository <https://github.com/godotengine/godot-cpp>`__ from GitHub or let Git do the work for you.
|
||||
Note that this repository has different branches for different versions
|
||||
of Godot. GDExtensions will not work in older versions of Godot (only Godot 4 and up) and vice versa, so make sure you download the correct branch.
|
||||
|
||||
.. note::
|
||||
To use `GDExtension <https://godotengine.org/article/introducing-gd-extensions>`__
|
||||
you need to use the godot-cpp branch that matches the version of Godot that you are
|
||||
targeting. For example, if you're targeting Godot 4.1, use the ``4.1`` branch. Throughout
|
||||
this tutorial we use ``4.x``, which will need to be replaced with the version of Godot you
|
||||
are targeting.
|
||||
|
||||
The ``master`` branch is the development branch which is updated regularly
|
||||
to work with Godot's ``master`` branch.
|
||||
|
||||
.. warning::
|
||||
Our long-term goal is that GDExtensions targeting an earlier version of Godot will work
|
||||
in later minor versions, but not vice-versa. For example, a GDExtension targeting Godot 4.1
|
||||
should work just fine in Godot 4.2, but one targeting Godot 4.2 won't work in Godot 4.1.
|
||||
|
||||
However, GDExtension is currently *experimental*, which means that we may break compatibility
|
||||
in order to fix major bugs or include critical features. For example, GDExtensions created
|
||||
for Godot 4.0 aren't compatible with Godot 4.1
|
||||
(see :ref:`updating_your_gdextension_for_godot_4_1`).
|
||||
|
||||
If you are versioning your project using Git, it is recommended to add it as
|
||||
a Git submodule:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mkdir gdextension_cpp_example
|
||||
cd gdextension_cpp_example
|
||||
git init
|
||||
git submodule add -b 4.x https://github.com/godotengine/godot-cpp
|
||||
cd godot-cpp
|
||||
git submodule update --init
|
||||
|
||||
Alternatively, you can also clone it to the project folder:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mkdir gdextension_cpp_example
|
||||
cd gdextension_cpp_example
|
||||
git clone -b 4.x https://github.com/godotengine/godot-cpp
|
||||
|
||||
.. note::
|
||||
|
||||
If you decide to download the repository or clone it into your folder,
|
||||
make sure to keep the folder layout the same as we've setup here. Much of
|
||||
the code we'll be showcasing here assumes the project has this layout.
|
||||
|
||||
If you cloned the example from the link specified in the introduction, the
|
||||
submodules are not automatically initialized. You will need to execute the
|
||||
following commands:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
cd gdextension_cpp_example
|
||||
git submodule update --init
|
||||
|
||||
This will initialize the repository in your project folder.
|
||||
|
||||
Building the C++ bindings
|
||||
-------------------------
|
||||
|
||||
Now that we've downloaded our prerequisites, it is time to build the C++
|
||||
bindings.
|
||||
|
||||
The repository contains a copy of the metadata for the current Godot release,
|
||||
but if you need to build these bindings for a newer version of Godot, call
|
||||
the Godot executable:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
godot --dump-extension-api
|
||||
|
||||
The resulting ``extension_api.json`` file will be created in the executable's
|
||||
directory. Copy it to the project folder and add ``custom_api_file=<PATH_TO_FILE>``
|
||||
to the scons command below.
|
||||
|
||||
To generate and compile the bindings, use this command (replacing ``<platform>``
|
||||
with ``windows``, ``linux`` or ``macos`` depending on your OS):
|
||||
|
||||
The build process automatically detects the number of CPU threads to use for
|
||||
parallel builds. To specify a number of CPU threads to use, add ``-jN`` at the
|
||||
end of the SCons command line where ``N`` is the number of CPU threads to use.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
cd godot-cpp
|
||||
scons platform=<platform> custom_api_file=<PATH_TO_FILE>
|
||||
cd ..
|
||||
|
||||
This step will take a while. When it is completed, you should have static
|
||||
libraries that can be compiled into your project stored in ``godot-cpp/bin/``.
|
||||
|
||||
.. note::
|
||||
|
||||
You may need to add ``bits=64`` to the command on Windows or Linux.
|
||||
|
||||
Creating a simple plugin
|
||||
------------------------
|
||||
|
||||
Now it's time to build an actual plugin. We'll start by creating an empty Godot
|
||||
project in which we'll place a few files.
|
||||
|
||||
Open Godot and create a new project. For this example, we will place it in a
|
||||
folder called ``demo`` inside our GDExtension's folder structure.
|
||||
|
||||
In our demo project, we'll create a scene containing a Node called "Main" and
|
||||
we'll save it as ``main.tscn``. We'll come back to that later.
|
||||
|
||||
Back in the top-level GDExtension module folder, we're also going to create a
|
||||
subfolder called ``src`` in which we'll place our source files.
|
||||
|
||||
You should now have ``demo``, ``godot-cpp``, and ``src``
|
||||
directories in your GDExtension module.
|
||||
|
||||
Your folder structure should now look like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
gdextension_cpp_example/
|
||||
|
|
||||
+--demo/ # game example/demo to test the extension
|
||||
|
|
||||
+--godot-cpp/ # C++ bindings
|
||||
|
|
||||
+--src/ # source code of the extension we are building
|
||||
|
||||
In the ``src`` folder, we'll start with creating our header file for the
|
||||
GDExtension node we'll be creating. We will name it ``gdexample.h``:
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: gdextension_cpp_example/src/gdexample.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <godot_cpp/classes/sprite2d.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class GDExample : public Sprite2D {
|
||||
GDCLASS(GDExample, Sprite2D)
|
||||
|
||||
private:
|
||||
double time_passed;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
GDExample();
|
||||
~GDExample();
|
||||
|
||||
void _process(double delta) override;
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
There are a few things of note to the above. We include ``sprite2d.hpp`` which
|
||||
contains bindings to the Sprite2D class. We'll be extending this class in our
|
||||
module.
|
||||
|
||||
We're using the namespace ``godot``, since everything in GDExtension is defined
|
||||
within this namespace.
|
||||
|
||||
Then we have our class definition, which inherits from our Sprite2D through a
|
||||
container class. We'll see a few side effects of this later on. The
|
||||
``GDCLASS`` macro sets up a few internal things for us.
|
||||
|
||||
After that, we declare a single member variable called ``time_passed``.
|
||||
|
||||
In the next block we're defining our methods, we have our constructor
|
||||
and destructor defined, but there are two other functions that will likely look
|
||||
familiar to some, and one new method.
|
||||
|
||||
The first is ``_bind_methods``, which is a static function that Godot will
|
||||
call to find out which methods can be called and which properties it exposes.
|
||||
The second is our ``_process`` function, which will work exactly the same
|
||||
as the ``_process`` function you're used to in GDScript.
|
||||
|
||||
Let's implement our functions by creating our ``gdexample.cpp`` file:
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: gdextension_cpp_example/src/gdexample.cpp
|
||||
|
||||
#include "gdexample.h"
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void GDExample::_bind_methods() {
|
||||
}
|
||||
|
||||
GDExample::GDExample() {
|
||||
// Initialize any variables here.
|
||||
time_passed = 0.0;
|
||||
}
|
||||
|
||||
GDExample::~GDExample() {
|
||||
// Add your cleanup here.
|
||||
}
|
||||
|
||||
void GDExample::_process(double delta) {
|
||||
time_passed += delta;
|
||||
|
||||
Vector2 new_position = Vector2(10.0 + (10.0 * sin(time_passed * 2.0)), 10.0 + (10.0 * cos(time_passed * 1.5)));
|
||||
|
||||
set_position(new_position);
|
||||
}
|
||||
|
||||
This one should be straightforward. We're implementing each method of our class
|
||||
that we defined in our header file.
|
||||
|
||||
Note our ``_process`` function, which keeps track of how much time has passed
|
||||
and calculates a new position for our sprite using a sine and cosine function.
|
||||
|
||||
There is one more C++ file we need; we'll name it ``register_types.cpp``. Our
|
||||
GDExtension plugin can contain multiple classes, each with their own header
|
||||
and source file like we've implemented ``GDExample`` up above. What we need now
|
||||
is a small bit of code that tells Godot about all the classes in our
|
||||
GDExtension plugin.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: gdextension_cpp_example/src/register_types.cpp
|
||||
|
||||
#include "register_types.h"
|
||||
|
||||
#include "gdexample.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_example_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
|
||||
GDREGISTER_RUNTIME_CLASS(GDExample);
|
||||
}
|
||||
|
||||
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// Initialization.
|
||||
GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
|
||||
init_obj.register_initializer(initialize_example_module);
|
||||
init_obj.register_terminator(uninitialize_example_module);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
}
|
||||
|
||||
The ``initialize_example_module`` and ``uninitialize_example_module`` functions get
|
||||
called respectively when Godot loads our plugin and when it unloads it. All
|
||||
we're doing here is parse through the functions in our bindings module to
|
||||
initialize them, but you might have to set up more things depending on your
|
||||
needs. We call the ``GDREGISTER_RUNTIME_CLASS`` macro for each of our classes
|
||||
in our library. This will make them run only in game, like the default for GDScript.
|
||||
|
||||
The important function is the third function called ``example_library_init``.
|
||||
We first call a function in our bindings library that creates an initialization object.
|
||||
This object registers the initialization and termination functions of the GDExtension.
|
||||
Furthermore, it sets the level of initialization (core, servers, scene, editor, level).
|
||||
|
||||
At last, we need the header file for the ``register_types.cpp`` named
|
||||
``register_types.h``.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: gdextension_cpp_example/src/register_types.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_example_module(ModuleInitializationLevel p_level);
|
||||
void uninitialize_example_module(ModuleInitializationLevel p_level);
|
||||
|
||||
Compiling the plugin
|
||||
--------------------
|
||||
|
||||
To compile the project we need to define how SCons using should compile it
|
||||
using a ``SConstruct`` file which references the one in ``godot-cpp``.
|
||||
Writing it from scratch is outside the scope of this tutorial, but you can
|
||||
:download:`the SConstruct file we prepared <files/cpp_example/SConstruct>`.
|
||||
We'll cover a more customizable, detailed example on how to use these
|
||||
build files in a subsequent tutorial.
|
||||
|
||||
.. note::
|
||||
|
||||
This ``SConstruct`` file was written to be used with the latest ``godot-cpp``
|
||||
master, you may need to make small changes using it with older versions or
|
||||
refer to the ``SConstruct`` file in the Godot 4.x documentation.
|
||||
|
||||
Once you've downloaded the ``SConstruct`` file, place it in your GDExtension folder
|
||||
structure alongside ``godot-cpp``, ``src`` and ``demo``, then run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
scons platform=<platform>
|
||||
|
||||
You should now be able to find the module in ``demo/bin/<platform>``.
|
||||
|
||||
When building for iOS, package the module as a static `.xcframework`, you can use
|
||||
following commands to do so:
|
||||
|
||||
::
|
||||
|
||||
# compile simulator and device modules
|
||||
scons arch=universal ios_simulator=yes platform=ios target=<target>
|
||||
scons arch=arm64 ios_simulator=no platform=ios target=<target>
|
||||
|
||||
# assemble xcframeworks
|
||||
xcodebuild -create-xcframework -library demo/bin/libgdexample.ios.<target>.a -library demo/bin/libgdexample.ios.<target>.simulator.a -output demo/bin/libgdexample.ios.<target>.xcframework
|
||||
xcodebuild -create-xcframework -library godot-cpp/bin/libgodot-cpp.ios.<target>.arm64.a -library godot-cpp/bin/libgodot-cpp.ios.<target>.universal.simulator.a -output demo/bin/libgodot-cpp.ios.<target>.xcframework
|
||||
|
||||
.. note::
|
||||
|
||||
Here, we've compiled both godot-cpp and our gdexample library as debug
|
||||
builds. For optimized builds, you should compile them using the
|
||||
``target=template_release`` switch.
|
||||
|
||||
Using the GDExtension module
|
||||
----------------------------
|
||||
|
||||
Before we jump back into Godot, we need to create one more file in
|
||||
``demo/bin/``.
|
||||
|
||||
This file lets Godot know what dynamic libraries should be
|
||||
loaded for each platform and the entry function for the module. It is called ``gdexample.gdextension``.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "example_library_init"
|
||||
compatibility_minimum = "4.1"
|
||||
reloadable = true
|
||||
|
||||
[libraries]
|
||||
|
||||
macos.debug = "res://bin/libgdexample.macos.template_debug.framework"
|
||||
macos.release = "res://bin/libgdexample.macos.template_release.framework"
|
||||
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
|
||||
ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
|
||||
windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll"
|
||||
windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll"
|
||||
windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll"
|
||||
windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll"
|
||||
linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so"
|
||||
linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so"
|
||||
linux.debug.arm64 = "res://bin/libgdexample.linux.template_debug.arm64.so"
|
||||
linux.release.arm64 = "res://bin/libgdexample.linux.template_release.arm64.so"
|
||||
linux.debug.rv64 = "res://bin/libgdexample.linux.template_debug.rv64.so"
|
||||
linux.release.rv64 = "res://bin/libgdexample.linux.template_release.rv64.so"
|
||||
android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so"
|
||||
android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so"
|
||||
android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so"
|
||||
android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
|
||||
|
||||
[dependencies]
|
||||
ios.debug = {
|
||||
"res://bin/libgodot-cpp.ios.template_debug.xcframework": ""
|
||||
}
|
||||
ios.release = {
|
||||
"res://bin/libgodot-cpp.ios.template_release.xcframework": ""
|
||||
}
|
||||
|
||||
This file contains a ``configuration`` section that controls the entry function of the module.
|
||||
You should also set the minimum compatible Godot version with ``compatibility_minimum``,
|
||||
which prevents older version of Godot from trying to load your extension.
|
||||
The ``reloadable`` flag enables automatic reloading of your extension by the editor every time you recompile it,
|
||||
without needing to restart the editor. This only works if you compile your extension in debug mode (default).
|
||||
|
||||
The ``libraries`` section is the important bit: it tells Godot the location of the
|
||||
dynamic library in the project's filesystem for each supported platform. It will
|
||||
also result in *just* that file being exported when you export the project,
|
||||
which means the data pack won't contain libraries that are incompatible with the
|
||||
target platform.
|
||||
|
||||
Finally, the ``dependencies`` section allows you to name additional dynamic
|
||||
libraries that should be included as well. This is important when your GDExtension
|
||||
plugin implements someone else's library and requires you to supply a
|
||||
third-party dynamic library with your project.
|
||||
|
||||
Here is another overview to check the correct file structure:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
gdextension_cpp_example/
|
||||
|
|
||||
+--demo/ # game example/demo to test the extension
|
||||
| |
|
||||
| +--main.tscn
|
||||
| |
|
||||
| +--bin/
|
||||
| |
|
||||
| +--gdexample.gdextension
|
||||
|
|
||||
+--godot-cpp/ # C++ bindings
|
||||
|
|
||||
+--src/ # source code of the extension we are building
|
||||
| |
|
||||
| +--register_types.cpp
|
||||
| +--register_types.h
|
||||
| +--gdexample.cpp
|
||||
| +--gdexample.h
|
||||
|
||||
Time to jump back into Godot. We load up the main scene we created way back in
|
||||
the beginning and now add a newly available GDExample node to the scene:
|
||||
|
||||
.. image:: img/gdextension_cpp_nodes.webp
|
||||
|
||||
We're going to assign the Godot logo to this node as our texture, disable the
|
||||
``centered`` property:
|
||||
|
||||
.. image:: img/gdextension_cpp_sprite.webp
|
||||
|
||||
We're finally ready to run the project:
|
||||
|
||||
.. video:: img/gdextension_cpp_animated.webm
|
||||
:alt: Screen recording of a game window, with Godot logo moving in the top-left corner
|
||||
:autoplay:
|
||||
:loop:
|
||||
:muted:
|
||||
:align: default
|
||||
|
||||
Adding properties
|
||||
-----------------
|
||||
|
||||
GDScript allows you to add properties to your script using the ``export``
|
||||
keyword. In GDExtension you have to register the properties with a getter and
|
||||
setter function or directly implement the ``_get_property_list``, ``_get`` and
|
||||
``_set`` methods of an object (but that goes far beyond the scope of this
|
||||
tutorial).
|
||||
|
||||
Lets add a property that allows us to control the amplitude of our wave.
|
||||
|
||||
In our ``gdexample.h`` file we need to add a member variable and getter and setter
|
||||
functions:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
...
|
||||
private:
|
||||
double time_passed;
|
||||
double amplitude;
|
||||
|
||||
public:
|
||||
void set_amplitude(const double p_amplitude);
|
||||
double get_amplitude() const;
|
||||
...
|
||||
|
||||
In our ``gdexample.cpp`` file we need to make a number of changes, we will only
|
||||
show the methods we end up changing, don't remove the lines we're omitting:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void GDExample::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_amplitude"), &GDExample::get_amplitude);
|
||||
ClassDB::bind_method(D_METHOD("set_amplitude", "p_amplitude"), &GDExample::set_amplitude);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amplitude"), "set_amplitude", "get_amplitude");
|
||||
}
|
||||
|
||||
GDExample::GDExample() {
|
||||
// Initialize any variables here.
|
||||
time_passed = 0.0;
|
||||
amplitude = 10.0;
|
||||
}
|
||||
|
||||
void GDExample::_process(double delta) {
|
||||
time_passed += delta;
|
||||
|
||||
Vector2 new_position = Vector2(
|
||||
amplitude + (amplitude * sin(time_passed * 2.0)),
|
||||
amplitude + (amplitude * cos(time_passed * 1.5))
|
||||
);
|
||||
|
||||
set_position(new_position);
|
||||
}
|
||||
|
||||
void GDExample::set_amplitude(const double p_amplitude) {
|
||||
amplitude = p_amplitude;
|
||||
}
|
||||
|
||||
double GDExample::get_amplitude() const {
|
||||
return amplitude;
|
||||
}
|
||||
|
||||
Once you compile the module with these changes in place, you will see that a
|
||||
property has been added to our interface. You can now change this property and
|
||||
when you run your project, you will see that our Godot icon travels along a
|
||||
larger figure.
|
||||
|
||||
Let's do the same but for the speed of our animation and use a setter and getter
|
||||
function. Our ``gdexample.h`` header file again only needs a few more lines of
|
||||
code:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
...
|
||||
double amplitude;
|
||||
double speed;
|
||||
...
|
||||
void _process(double delta) override;
|
||||
void set_speed(const double p_speed);
|
||||
double get_speed() const;
|
||||
...
|
||||
|
||||
This requires a few more changes to our ``gdexample.cpp`` file, again we're only
|
||||
showing the methods that have changed so don't remove anything we're omitting:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void GDExample::_bind_methods() {
|
||||
...
|
||||
ClassDB::bind_method(D_METHOD("get_speed"), &GDExample::get_speed);
|
||||
ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &GDExample::set_speed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_speed", "get_speed");
|
||||
}
|
||||
|
||||
GDExample::GDExample() {
|
||||
time_passed = 0.0;
|
||||
amplitude = 10.0;
|
||||
speed = 1.0;
|
||||
}
|
||||
|
||||
void GDExample::_process(double delta) {
|
||||
time_passed += speed * delta;
|
||||
|
||||
Vector2 new_position = Vector2(
|
||||
amplitude + (amplitude * sin(time_passed * 2.0)),
|
||||
amplitude + (amplitude * cos(time_passed * 1.5))
|
||||
);
|
||||
|
||||
set_position(new_position);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
void GDExample::set_speed(const double p_speed) {
|
||||
speed = p_speed;
|
||||
}
|
||||
|
||||
double GDExample::get_speed() const {
|
||||
return speed;
|
||||
}
|
||||
|
||||
Now when the project is compiled, we'll see another property called speed.
|
||||
Changing its value will make the animation go faster or slower.
|
||||
Furthermore, we added a property range which describes in which range the value can be.
|
||||
The first two arguments are the minimum and maximum value and the third is the step size.
|
||||
|
||||
.. note::
|
||||
|
||||
For simplicity, we've only used the hint_range of the property method.
|
||||
There are a lot more options to choose from. These can be used to
|
||||
further configure how properties are displayed and set on the Godot side.
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
Last but not least, signals fully work in GDExtension as well. Having your extension
|
||||
react to a signal given out by another object requires you to call ``connect``
|
||||
on that object. We can't think of a good example for our wobbling Godot icon, we
|
||||
would need to showcase a far more complete example.
|
||||
|
||||
This is the required syntax:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
some_other_node->connect("the_signal", Callable(this, "my_method"));
|
||||
|
||||
To connect our signal ``the_signal`` from some other node with our method
|
||||
``my_method``, we need to provide the ``connect`` method with the name of the signal
|
||||
and a ``Callable``. The ``Callable`` holds information about an object on which a method
|
||||
can be called. In our case, it associates our current object instance ``this`` with the
|
||||
method ``my_method`` of the object. Then the ``connect`` method will add this to the
|
||||
observers of ``the_signal``. Whenever ``the_signal`` is now emitted, Godot knows which
|
||||
method of which object it needs to call.
|
||||
|
||||
Note that you can only call ``my_method`` if you've previously registered it in
|
||||
your ``_bind_methods`` method. Otherwise Godot will not know about the existence
|
||||
of ``my_method``.
|
||||
|
||||
To learn more about ``Callable``, check out the class reference here: :ref:`Callable <class_Callable>`.
|
||||
|
||||
Having your object sending out signals is more common. For our wobbling
|
||||
Godot icon, we'll do something silly just to show how it works. We're going to
|
||||
emit a signal every time a second has passed and pass the new location along.
|
||||
|
||||
In our ``gdexample.h`` header file, we need to define a new member ``time_emit``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
...
|
||||
double time_passed;
|
||||
double time_emit;
|
||||
double amplitude;
|
||||
...
|
||||
|
||||
This time, the changes in ``gdexample.cpp`` are more elaborate. First,
|
||||
you'll need to set ``time_emit = 0.0;`` in either our ``_init`` method or in our
|
||||
constructor. We'll look at the other 2 needed changes one by one.
|
||||
|
||||
In our ``_bind_methods`` method, we need to declare our signal. This is done
|
||||
as follows:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void GDExample::_bind_methods() {
|
||||
...
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_speed", "get_speed");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("position_changed", PropertyInfo(Variant::OBJECT, "node"), PropertyInfo(Variant::VECTOR2, "new_pos")));
|
||||
}
|
||||
|
||||
Here, our ``ADD_SIGNAL`` macro can be a single call with a ``MethodInfo`` argument.
|
||||
``MethodInfo``'s first parameter will be the signal's name, and its remaining parameters
|
||||
are ``PropertyInfo`` types which describe the essentials of each of the method's parameters.
|
||||
``PropertyInfo`` parameters are defined with the data type of the parameter, and then the name
|
||||
that the parameter will have by default.
|
||||
|
||||
So here, we add a signal, with a ``MethodInfo`` which names the signal "position_changed". The
|
||||
``PropertyInfo`` parameters describe two essential arguments, one of type ``Object``, the other
|
||||
of type ``Vector2``, respectively named "node" and "new_pos".
|
||||
|
||||
Next, we'll need to change our ``_process`` method:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void GDExample::_process(double delta) {
|
||||
time_passed += speed * delta;
|
||||
|
||||
Vector2 new_position = Vector2(
|
||||
amplitude + (amplitude * sin(time_passed * 2.0)),
|
||||
amplitude + (amplitude * cos(time_passed * 1.5))
|
||||
);
|
||||
|
||||
set_position(new_position);
|
||||
|
||||
time_emit += delta;
|
||||
if (time_emit > 1.0) {
|
||||
emit_signal("position_changed", this, new_position);
|
||||
|
||||
time_emit = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
After a second has passed, we emit our signal and reset our counter. We can add
|
||||
our parameter values directly to ``emit_signal``.
|
||||
|
||||
Once the GDExtension library is compiled, we can go into Godot and select our sprite
|
||||
node. In the **Node** dock, we can find our new signal and link it up by pressing
|
||||
the **Connect** button or double-clicking the signal. We've added a script on
|
||||
our main node and implemented our signal like this:
|
||||
|
||||
.. code-block:: gdscript
|
||||
|
||||
extends Node
|
||||
|
||||
func _on_Sprite2D_position_changed(node, new_pos):
|
||||
print("The position of " + node.get_class() + " is now " + str(new_pos))
|
||||
|
||||
Every second, we output our position to the console.
|
||||
|
||||
Next steps
|
||||
----------
|
||||
|
||||
We hope the above example showed you the basics. You can
|
||||
build upon this example to create full-fledged scripts to control nodes in Godot
|
||||
using C++.
|
||||
@@ -1,200 +0,0 @@
|
||||
.. _doc_gdextension_docs_system:
|
||||
|
||||
GDExtension documentation system
|
||||
================================
|
||||
|
||||
.. note::
|
||||
|
||||
Adding documentation for GDExtensions is only possible for Godot 4.3 and later. The support can be integrated into your project
|
||||
regardless because the snippet will check if you use the appropriate godot-cpp version.
|
||||
If you set the ``compatibility_minimum`` to 4.2 and you load a project with the extension through a 4.2 editor, the
|
||||
documentation page for that class will be empty. The extension itself will still work.
|
||||
|
||||
The GDExtension documentation system works in a similar manner to the built-in engine documentation. It uses a series of
|
||||
XML files (one per class) to document the exposed constructors, properties, methods, constants, signals, and theme items of each class.
|
||||
|
||||
.. note::
|
||||
|
||||
We are assuming you are using the project files explained in the :ref:`GDExtension C++ Example <doc_gdextension_cpp_example>`
|
||||
with the following structure:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
gdextension_cpp_example/ # GDExtension directory
|
||||
|
|
||||
+--demo/ # game example/demo to test the extension
|
||||
| |
|
||||
| +--main.tscn
|
||||
| |
|
||||
| +--bin/
|
||||
| |
|
||||
| +--gdexample.gdextension
|
||||
|
|
||||
+--godot-cpp/ # C++ bindings
|
||||
|
|
||||
+--src/ # source code of the extension we are building
|
||||
| |
|
||||
| +--register_types.cpp
|
||||
| +--register_types.h
|
||||
| +--gdexample.cpp
|
||||
| +--gdexample.h
|
||||
|
||||
Inside the Godot demo project directory of your GDExtension directory, run the following terminal command:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
# Replace "godot" with the full path to a Godot editor binary
|
||||
# if Godot is not installed in your `PATH`.
|
||||
godot --doctool ../ --gdextension-docs
|
||||
|
||||
This command calls upon the Godot editor binary to generate documentation via the ``--doctool``
|
||||
and ``--gdextension-docs`` commands. The ``../`` addition is to let Godot know where the GDExtension
|
||||
SConstruct file is located. By calling this command, Godot generates a ``doc_classes`` directory inside the
|
||||
project directory in which it generates XML files for the GDExtension classes. Those files
|
||||
can then be edited to add information about member variables, methods, signals, and more.
|
||||
|
||||
To add the now edited documentation to the GDExtension and let the editor load it,
|
||||
you need to add the following lines to your SConstruct file:
|
||||
|
||||
.. code-block:: py
|
||||
|
||||
if env["target"] in ["editor", "template_debug"]:
|
||||
try:
|
||||
doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
|
||||
sources.append(doc_data)
|
||||
except AttributeError:
|
||||
print("Not including class reference as we're targeting a pre-4.3 baseline.")
|
||||
|
||||
The if-statement checks if we are compiling the GDExtension library with the ``editor`` and ``template_debug``
|
||||
flags. SCons then tries to load all the XML files inside the ``doc_classes`` directory and appends them
|
||||
to the ``sources`` variable which already includes all the source files of your extension. If it fails
|
||||
it means we are currently trying to compile the library when the ``godot_cpp`` is set to a version before 4.3.
|
||||
|
||||
After loading the extension in a 4.3 Godot editor or later and open the documentation of your extension class
|
||||
either by :kbd:`Ctrl + Click` in the script editor or the Editor help dialog you will see something like this:
|
||||
|
||||
.. image:: img/gdextension_docs_generation.webp
|
||||
|
||||
Documentation styling
|
||||
---------------------
|
||||
|
||||
To style specific parts of text you can use BBCode tags similarly to how they can be used in :ref:`RichTextLabels <doc_bbcode_in_richtextlabel>`.
|
||||
You can set text as bold, italic, underlined, colored, codeblocks etc. by embedding them in tags like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[b]this text will be shown as bold[/b]
|
||||
|
||||
Currently they supported tags for the GDExtension documentation system are:
|
||||
|
||||
.. list-table::
|
||||
:class: wrap-normal
|
||||
:width: 100%
|
||||
:widths: 60 40
|
||||
|
||||
* - Tag
|
||||
- Example
|
||||
|
||||
* - | **b**
|
||||
| Makes ``{text}`` use the bold (or bold italics) font of ``RichTextLabel``.
|
||||
|
||||
- ``[b]{text}[/b]``
|
||||
|
||||
* - | **i**
|
||||
| Makes ``{text}`` use the italics (or bold italics) font of ``RichTextLabel``.
|
||||
|
||||
- ``[i]{text}[/i]``
|
||||
|
||||
* - | **u**
|
||||
| Makes ``{text}`` underlined.
|
||||
|
||||
- ``[u]{text}[/u]``
|
||||
|
||||
* - | **s**
|
||||
| Makes ``{text}`` strikethrough.
|
||||
|
||||
- ``[s]{text}[/s]``
|
||||
|
||||
* - | **kbd**
|
||||
| Makes ``{text}`` use a grey beveled background, indicating a keyboard shortcut.
|
||||
|
||||
- ``[kbd]{text}[/kbd]``
|
||||
|
||||
* - | **code**
|
||||
| Makes inline ``{text}`` use the mono font and styles the text color and background like code.
|
||||
|
||||
- ``[code]{text}[/code]``
|
||||
|
||||
* - | **codeblocks**
|
||||
| Makes multiline ``{text}`` use the mono font and styles the text color and background like code.
|
||||
| The addition of the ``[gdscript]`` tag highlights the GDScript specific syntax.
|
||||
|
||||
- | ``[codeblocks]``
|
||||
| ``[gdscript]``
|
||||
| ``{text}``
|
||||
| ``[/gdscript]``
|
||||
| ``[/codeblocks]``
|
||||
|
||||
* - | **center**
|
||||
| Makes ``{text}`` horizontally centered.
|
||||
| Same as ``[p align=center]``.
|
||||
|
||||
- ``[center]{text}[/center]``
|
||||
|
||||
* - | **url**
|
||||
| Creates a hyperlink (underlined and clickable text). Can contain optional ``{text}`` or display ``{link}`` as is.
|
||||
|
||||
- | ``[url]{link}[/url]``
|
||||
| ``[url={link}]{text}[/url]``
|
||||
|
||||
* - | **img**
|
||||
| Inserts an image from the ``{path}`` (can be any valid :ref:`class_Texture2D` resource).
|
||||
| If ``{width}`` is provided, the image will try to fit that width maintaining
|
||||
the aspect ratio.
|
||||
| If both ``{width}`` and ``{height}`` are provided, the image will be scaled
|
||||
to that size.
|
||||
| Add ``%`` to the end of ``{width}`` or ``{height}`` value to specify it as percentages of the control width instead of pixels.
|
||||
| If ``{valign}`` configuration is provided, the image will try to align to the
|
||||
surrounding text, see :ref:`doc_bbcode_in_richtextlabel_image_and_table_alignment`.
|
||||
| Supports configuration options, see :ref:`doc_bbcode_in_richtextlabel_image_options`.
|
||||
|
||||
- | ``[img]{path}[/img]``
|
||||
| ``[img={width}]{path}[/img]``
|
||||
| ``[img={width}x{height}]{path}[/img]``
|
||||
| ``[img={valign}]{path}[/img]``
|
||||
| ``[img {options}]{path}[/img]``
|
||||
|
||||
* - | **color**
|
||||
| Changes the color of ``{text}``. Color must be provided by a common name (see
|
||||
:ref:`doc_bbcode_in_richtextlabel_named_colors`) or using the HEX format (e.g.
|
||||
``#ff00ff``, see :ref:`doc_bbcode_in_richtextlabel_hex_colors`).
|
||||
|
||||
- ``[color={code/name}]{text}[/color]``
|
||||
|
||||
|
||||
Publishing documentation online
|
||||
-------------------------------
|
||||
|
||||
You may want to publish an online reference for your GDExtension, similar to this website.
|
||||
The most important step is to build reStructuredText (``.rst``) files from your XML class reference:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# You need a version.py file, so download it first.
|
||||
curl -sSLO https://raw.githubusercontent.com/godotengine/godot/refs/heads/master/version.py
|
||||
|
||||
# Edit version.py according to your project before proceeding.
|
||||
# Then, run the rst generator. You'll need to have Python installed for this command to work.
|
||||
curl -sSL https://raw.githubusercontent.com/godotengine/godot/master/doc/tools/make_rst.py | python3 - -o "docs/classes" -l "en" doc_classes
|
||||
|
||||
Your ``.rst`` files will now be available in ``docs/classes/``. From here, you can use
|
||||
any documentation builder that supports reStructuredText syntax to create a website from them.
|
||||
|
||||
`godot-docs <https://github.com/godotengine/godot-docs>`_ uses `Sphinx <https://www.sphinx-doc.org/en/master/>`_. You can use the repository as a basis to build your own documentation system. The following guide describes the basic steps, but they are not exhaustive: You will need a bit of personal insight to make it work.
|
||||
|
||||
1. Add `godot-docs <https://github.com/godotengine/godot-docs>`_ as a submodule to your ``docs/`` folder.
|
||||
2. Copy over its ``conf.py``, ``index.rst``, ``.readthedocs.yaml`` files into ``/docs/``. You may later decide to copy over and edit more of godot-docs' files, like ``_templates/layout.html``.
|
||||
3. Modify these files according to your project. This mostly involves adjusting paths to point to the ``godot-docs`` subfolder, as well as strings to reflect it's your project rather than Godot you're building the docs for.
|
||||
4. Create an account on `readthedocs.org <http://readthedocs.org>`_. Import your project, and modify its base ``.readthedocs.yaml`` file path to ``/docs/.readthedocs.yaml``.
|
||||
|
||||
Once you have completed all these steps, your documentation should be available at ``<repo-name>.readthedocs.io``.
|
||||
@@ -9,7 +9,7 @@ Introduction
|
||||
The ``.gdextension`` file in your project contains the instructions for how to load
|
||||
the GDExtension. The instructions are separated into specific sections. This page
|
||||
should give you a quick overview of the different options available to you. For an introduction
|
||||
how to get started with GDExtensions take a look at the :ref:`GDExtension C++ Example <doc_gdextension_cpp_example>`.
|
||||
how to get started with C++ (godot-cpp), take a look at the :ref:`GDExtension C++ Example <doc_godot_cpp_getting_started>`.
|
||||
|
||||
Configuration section
|
||||
---------------------
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB |
@@ -1,14 +1,26 @@
|
||||
:allow_comments: False
|
||||
|
||||
GDExtension
|
||||
===========
|
||||
.. _doc_gdextension:
|
||||
|
||||
The GDExtension system
|
||||
======================
|
||||
|
||||
**GDExtension** is a Godot-specific technology that lets the engine interact with
|
||||
native `shared libraries <https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries>`__
|
||||
at runtime. You can use it to run native code without compiling it with the engine.
|
||||
|
||||
.. note:: GDExtension is *not* a scripting language and has no relation to
|
||||
:ref:`GDScript <doc_gdscript>`.
|
||||
|
||||
This section describes how GDExtension works, and is generally aimed at people wanting to make a GDExtension from
|
||||
scratch, for example to create language bindings. If you want to use existing language bindings, please refer to other
|
||||
articles instead, such as the articles about :ref:`C++ (godot-cpp) <doc_godot_cpp>` or one of the
|
||||
:ref:`community-made ones <doc_what_is_gdnative_third_party_bindings>`.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:name: toc-tutorials-gdnative
|
||||
:name: toc-tutorials-gdextension
|
||||
|
||||
what_is_gdextension
|
||||
gdextension_cpp_example
|
||||
gdextension_c_example
|
||||
gdextension_file
|
||||
gdextension_docs_system
|
||||
gdextension_c_example
|
||||
|
||||
@@ -3,130 +3,20 @@
|
||||
What is GDExtension?
|
||||
====================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
**GDExtension** is a Godot-specific technology that lets the engine interact with
|
||||
native `shared libraries <https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries>`__
|
||||
at runtime. You can use it to run native code without compiling it with the engine.
|
||||
|
||||
.. note:: GDExtension is *not* a scripting language and has no relation to
|
||||
:ref:`GDScript <doc_gdscript>`.
|
||||
There are three primary methods with which this is achieved:
|
||||
|
||||
Differences between GDExtension and C++ modules
|
||||
-----------------------------------------------
|
||||
* ``gdextension_interface.h``: A set of C functions that Godot and a GDExtension can use to communicate.
|
||||
* ``extension_api.json``: A list of C functions that are exposed from Godot APIs (:ref:`Core Features <doc_scripting_core_features>`).
|
||||
* :ref:`*.gdextension <doc_gdextension_file>`: A file format read by Godot to load a GDExtension.
|
||||
|
||||
You can use both GDExtension and :ref:`C++ modules <doc_custom_modules_in_cpp>` to
|
||||
run C or C++ code in a Godot project.
|
||||
|
||||
They also both allow you to integrate third-party libraries into Godot. The one
|
||||
you should choose depends on your needs.
|
||||
|
||||
.. warning::
|
||||
|
||||
GDExtension is currently *experimental*, which means that we may
|
||||
break compatibility in order to fix major bugs or include critical features.
|
||||
|
||||
Advantages of GDExtension
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Unlike modules, GDExtension doesn't require compiling the engine's source code,
|
||||
making it easier to distribute your work. It gives you access to most of the API
|
||||
available to GDScript and C#, allowing you to code game logic with full control
|
||||
regarding performance. It's ideal if you need high-performance code you'd like
|
||||
to distribute as an add-on in the :ref:`asset library <doc_what_is_assetlib>`.
|
||||
|
||||
Also:
|
||||
|
||||
- GDExtension is not limited to C and C++. Thanks to :ref:`third-party bindings
|
||||
<doc_what_is_gdnative_third_party_bindings>`, you can use it with many other
|
||||
languages.
|
||||
- You can use the same compiled GDExtension library in the editor and exported
|
||||
project. With C++ modules, you have to recompile all the export templates you
|
||||
plan to use if you require its functionality at runtime.
|
||||
- GDExtension only requires you to compile your library, not the whole engine.
|
||||
That's unlike C++ modules, which are statically compiled into the engine.
|
||||
Every time you change a module, you need to recompile the engine. Even with
|
||||
incremental builds, this process is slower than using GDExtension.
|
||||
|
||||
Advantages of C++ modules
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We recommend :ref:`C++ modules <doc_custom_modules_in_cpp>` in cases where
|
||||
GDExtension isn't enough:
|
||||
|
||||
- C++ modules provide deeper integration into the engine. GDExtension's access
|
||||
is not as deep as static modules.
|
||||
- You can use C++ modules to provide additional features in a project without
|
||||
carrying native library files around. This extends to exported projects.
|
||||
|
||||
.. note::
|
||||
|
||||
If you notice that specific systems are not accessible via GDExtension
|
||||
but are via custom modules, feel free to open an issue on the
|
||||
`godot-cpp repository <https://github.com/godotengine/godot-cpp>`__
|
||||
to discuss implementation options for exposing the missing functionality.
|
||||
|
||||
Supported languages
|
||||
-------------------
|
||||
|
||||
The Godot developers officially support the following language bindings for
|
||||
GDExtension:
|
||||
|
||||
- C++ :ref:`(tutorial) <doc_gdextension_cpp_example>`
|
||||
|
||||
.. note::
|
||||
|
||||
There are no plans to support additional languages with GDExtension officially.
|
||||
That said, the community offers several bindings for other languages (see
|
||||
below).
|
||||
|
||||
.. _doc_what_is_gdnative_third_party_bindings:
|
||||
|
||||
The bindings below are developed and maintained by the community:
|
||||
|
||||
.. Binding developers: Feel free to open a pull request to add your binding if it's well-developed enough to be used in a project.
|
||||
.. Please keep languages sorted in alphabetical order.
|
||||
|
||||
- `D <https://github.com/godot-dlang/godot-dlang>`__
|
||||
- `Go <https://github.com/grow-graphics/gd>`__
|
||||
- `Nim <https://github.com/godot-nim/gdext-nim>`__
|
||||
- `Rust <https://github.com/godot-rust/gdext>`__
|
||||
- `Swift <https://github.com/migueldeicaza/SwiftGodot>`__
|
||||
- `Odin <https://github.com/dresswithpockets/odin-godot>`__
|
||||
|
||||
.. note::
|
||||
|
||||
Not all bindings mentioned here may be production-ready. Make sure to
|
||||
research options thoroughly before starting a project with one of those.
|
||||
Also, double-check whether the binding is compatible with the Godot version
|
||||
you're using.
|
||||
|
||||
.. _doc_what_is_gdextension_version_compatibility:
|
||||
Most people create GDExtensions with some existing language binding, such as :ref:`godot-cpp (for C++) <doc_godot_cpp>`,
|
||||
or one of the :ref:`community-made ones <doc_what_is_gdnative_third_party_bindings>`.
|
||||
|
||||
Version compatibility
|
||||
---------------------
|
||||
|
||||
Usually, GDExtensions targeting an earlier version of Godot will work in later
|
||||
minor versions, but not vice-versa. For example, a GDExtension targeting Godot 4.2
|
||||
should work just fine in Godot 4.3, but one targeting Godot 4.3 won't work in Godot 4.2.
|
||||
|
||||
For this reason, when creating GDExtensions, you may want to target the lowest version of
|
||||
Godot that has the features you need, *not* the most recent version of Godot. This can
|
||||
save you from needing to create multiple builds for different versions of Godot.
|
||||
|
||||
However, GDExtension is currently *experimental*, which means that we may
|
||||
break compatibility in order to fix major bugs or include critical features.
|
||||
For example, GDExtensions created for Godot 4.0 aren't compatible with Godot
|
||||
4.1 (see :ref:`updating_your_gdextension_for_godot_4_1`).
|
||||
|
||||
GDExtensions are also only compatible with engine builds that use the same
|
||||
level of floating-point precision the extension was compiled for. This means
|
||||
that if you use an engine build with double-precision floats, the extension must
|
||||
also be compiled for double-precision floats and use an ``extension_api.json``
|
||||
file generated by your custom engine build. See :ref:`doc_large_world_coordinates`
|
||||
for details.
|
||||
|
||||
Generally speaking, if you build a custom version of Godot, you should generate an
|
||||
``extension_api.json`` from it for your GDExtensions, because it may have some differences
|
||||
from official Godot builds.
|
||||
See :ref:`godot-cpp Version Compatibility <doc_what_is_gdextension_version_compatibility>`, which applies to all GDExtensions.
|
||||
|
||||
Reference in New Issue
Block a user