Merge pull request #6318 from mhilbrunner/nuke-old-pages
Remove old renderer backend comparison and GDNative tutorial pages
@@ -107,7 +107,6 @@ Scripting
|
||||
- :ref:`doc_debugger_panel`
|
||||
- :ref:`doc_creating_script_templates`
|
||||
- :ref:`doc_evaluating_expressions`
|
||||
- :ref:`doc_what_is_gdnative`
|
||||
- :ref:`doc_gdscript_warning_system` (split from :ref:`doc_gdscript_static_typing`)
|
||||
|
||||
User Interface (UI)
|
||||
@@ -305,7 +304,6 @@ Miscellaneous
|
||||
- :ref:`doc_jitter_stutter`
|
||||
- :ref:`doc_running_code_in_the_editor`
|
||||
- :ref:`doc_change_scenes_manually`
|
||||
- :ref:`doc_gles2_gles3_differences`
|
||||
|
||||
Compiling
|
||||
^^^^^^^^^
|
||||
|
||||
@@ -82,8 +82,7 @@ we recommend that you first do some due diligence yourself. Searching through
|
||||
discussions on `open issues <https://github.com/godotengine/godot/issues>`_ is a
|
||||
great way to start your troubleshooting.
|
||||
|
||||
As for new languages, support is possible via third parties using the GDNative /
|
||||
NativeScript / PluginScript facilities. (See the question about plugins below.)
|
||||
As for new languages, support is possible via third parties with GDExtensions. (See the question about plugins below.)
|
||||
Work is currently underway, for example, on unofficial bindings for Godot
|
||||
to `Python <https://github.com/touilleMan/godot-python>`_ and `Nim <https://github.com/pragmagic/godot-nim>`_.
|
||||
|
||||
@@ -366,10 +365,9 @@ For extending Godot, like creating Godot Editor plugins or adding support
|
||||
for additional languages, take a look at :ref:`EditorPlugins <doc_making_plugins>`
|
||||
and tool scripts.
|
||||
|
||||
Also, see the official blog posts on these topics:
|
||||
Also, see the official blog post on GDExtension, a way to develop native extensions for Godot:
|
||||
|
||||
* `A look at the GDNative architecture <https://godotengine.org/article/look-gdnative-architecture>`_
|
||||
* `GDNative is here! <https://godotengine.org/article/dlscript-here>`_
|
||||
* `Introducing GDNative's successor, GDExtension <https://godotengine.org/article/introducing-gd-extensions>`_
|
||||
|
||||
You can also take a look at the GDScript implementation, the Godot modules,
|
||||
as well as the `unofficial Python support <https://github.com/touilleMan/godot-python>`_ for Godot.
|
||||
@@ -547,7 +545,7 @@ The vast majority of games do not need this and Godot provides handy helpers
|
||||
to do the job for most cases when you do.
|
||||
|
||||
If a game that really needs to process such large amount of objects is
|
||||
needed, our recommendation is to use C++ and GDNative for the high
|
||||
needed, our recommendation is to use C++ and GDExtension for the high
|
||||
performance parts and GDScript (or C#) for the rest of the game.
|
||||
|
||||
How can I support Godot development or contribute?
|
||||
|
||||
@@ -413,7 +413,7 @@ Scripting
|
||||
- Supports all platforms.
|
||||
- Using an external editor is recommended to benefit from IDE functionality.
|
||||
|
||||
**GDNative (C, C++, Rust, D, ...):**
|
||||
**GDExtension (C, C++, Rust, D, ...):**
|
||||
|
||||
- When you need it, link to native libraries for higher performance and third-party integrations.
|
||||
|
||||
|
||||
@@ -106,22 +106,25 @@ feature request, or one that is not precise enough to be worked on.
|
||||
|
||||
- *2D*: relates to 2D-specific issues. Should be coupled with one of the labels below, and should not be coupled with *3D*.
|
||||
- *3D*: relates to 3D-specific issues. Should be coupled with one of the labels below, and should not be coupled with *2D*.
|
||||
- *Animation*: relates to the Animation system, editors and importers.
|
||||
- *Assetlib*: relates to issues with the asset library.
|
||||
- *Audio*: relates to the audio features (low and high level).
|
||||
- *Buildsystem*: relates to building issues, either linked to the SCons
|
||||
buildsystem or to compiler peculiarities.
|
||||
- *Codestyle*: relates to the programming style used within the codebase.
|
||||
- *Core*: anything related to the core engine. It might be further
|
||||
split later on as it's a pretty big topic.
|
||||
- *Core*: anything related to the core engine. Specific topics are split off separately as they crop up.
|
||||
- *Dotnet*: relates to the C# / Dotnet bindings.
|
||||
- *Editor*: relates to issues in the editor (mainly UI).
|
||||
- *GDNative*: relates to the GDNative module.
|
||||
- *Export*: relates to the export system and templates.
|
||||
- *GDExtension*: relates to the GDExtension system for native extensions.
|
||||
- *GDScript*: relates to GDScript.
|
||||
- *GUI*: relates to GUI (Control) nodes.
|
||||
- *Import*: relates to the resource import system.
|
||||
- *Input*: relates to input system.
|
||||
- *Mono*: relates to the C# / Mono bindings.
|
||||
- *Navigation*: relates to the navigation system (including A* and navmeshes).
|
||||
- *Network*: relates to networking.
|
||||
- *Network*: relates to (lot-level) networking.
|
||||
- *Multiplayer*: relates to multiplayer (high-level networking) systems.
|
||||
- *Particles*: particles, particle systems and their editors.
|
||||
- *Physics*: relates to the physics engine (2D/3D).
|
||||
- *Plugin*: relates to problems encountered while writing plugins.
|
||||
- *Porting*: relates to some specific platforms or exporting projects.
|
||||
|
||||
@@ -20,7 +20,7 @@ reasons:
|
||||
|
||||
To get your pull request merged, it needs to follow the C++ usage guidelines
|
||||
outlined here. Of course, you can use features not allowed here in your own C++
|
||||
modules or GDNative scripts.
|
||||
modules or GDExtensions.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ a lot of them:
|
||||
|
||||
::
|
||||
|
||||
scons p=windows target=release tools=no module_arkit_enabled=no module_assimp_enabled=no module_bmp_enabled=no module_bullet_enabled=no module_camera_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gdnative_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_jsonrpc_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opensimplex_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_svg_enabled=no module_tga_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_upnp_enabled=no module_vhacd_enabled=no module_vorbis_enabled=no module_webrtc_enabled=no module_websocket_enabled=no module_xatlas_unwrap_enabled=no
|
||||
scons p=windows target=release tools=no module_arkit_enabled=no module_assimp_enabled=no module_bmp_enabled=no module_bullet_enabled=no module_camera_enabled=no module_csg_enabled=no module_dds_enabled=no module_enet_enabled=no module_etc_enabled=no module_gridmap_enabled=no module_hdr_enabled=no module_jsonrpc_enabled=no module_mbedtls_enabled=no module_mobile_vr_enabled=no module_opensimplex_enabled=no module_pvr_enabled=no module_recast_enabled=no module_regex_enabled=no module_squish_enabled=no module_svg_enabled=no module_tga_enabled=no module_theora_enabled=no module_tinyexr_enabled=no module_upnp_enabled=no module_vhacd_enabled=no module_vorbis_enabled=no module_webrtc_enabled=no module_websocket_enabled=no module_xatlas_unwrap_enabled=no
|
||||
|
||||
If this proves not to work for your use case, you should review the list of
|
||||
modules and see which ones you actually still need for your game (e.g. you
|
||||
@@ -191,7 +191,6 @@ following:
|
||||
module_dds_enabled = "no"
|
||||
module_enet_enabled = "no"
|
||||
module_etc_enabled = "no"
|
||||
module_gdnative_enabled = "no"
|
||||
module_gridmap_enabled = "no"
|
||||
module_hdr_enabled = "no"
|
||||
module_jsonrpc_enabled = "no"
|
||||
|
||||
@@ -156,7 +156,7 @@ can link to them instead by adding them as submodules (from within the modules/t
|
||||
Please note that Git submodules are not used in the Godot repository. If
|
||||
you are developing a module to be merged into the main Godot repository, you should not
|
||||
use submodules. If your module doesn't get merged in, you can always try to implement
|
||||
the external library as a GDNative C++ plugin.
|
||||
the external library as a GDExtension.
|
||||
|
||||
To add include directories for the compiler to look at you can append it to the
|
||||
environment's paths:
|
||||
|
||||
@@ -397,7 +397,7 @@ Improving the build system for development
|
||||
|
||||
This shared library support is not designed to support distributing a module
|
||||
to other users without recompiling the engine. For that purpose, use
|
||||
:ref:`GDNative <doc_what_is_gdnative>` instead.
|
||||
a GDExtension instead.
|
||||
|
||||
So far, we defined a clean SCsub that allows us to add the sources
|
||||
of our new module as part of the Godot binary.
|
||||
|
||||
@@ -28,21 +28,9 @@ Launch Godot and create a new project.
|
||||
You need the .NET Core 3.1 SDK, and an editor such as VS Code.
|
||||
See :ref:`doc_c_sharp_setup`.
|
||||
|
||||
.. tab:: GDNative C++
|
||||
.. tab:: C++
|
||||
|
||||
Download :download:`dodge_assets_with_gdnative.zip
|
||||
<files/dodge_assets_with_gdnative.zip>`.
|
||||
The archive contains the images and sounds you'll be using
|
||||
to make the game. It also contains a starter GDNative project
|
||||
including a ``SConstruct`` file, a ``dodge_the_creeps.gdnlib``
|
||||
file, a ``player.gdns`` file, and an ``entry.cpp`` file.
|
||||
|
||||
Ensure that you have the required dependencies to use GDNative C++.
|
||||
You need a C++ compiler such as GCC or Clang or MSVC that supports C++14.
|
||||
On Windows you can download Visual Studio 2019 and select the C++ workload.
|
||||
You also need SCons to use the build system (the SConstruct file).
|
||||
Then you need to `download the Godot C++ bindings <https://github.com/godotengine/godot-cpp>`_
|
||||
and place them in your project.
|
||||
The C++ part of this tutorial wasn't rewritten for the new GDExtension system yet.
|
||||
|
||||
Your project folder should look like this.
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ GDScript lets you write code using an indentation-based syntax,
|
||||
yet it detects types and offers a static language's quality of auto-completion.
|
||||
It is also optimized for gameplay code with built-in types like Vectors and Colors.
|
||||
|
||||
Note that with GDNative, you can write high-performance code using compiled
|
||||
Note that with GDExtension, you can write high-performance code using compiled
|
||||
languages like C, C++, Rust, or Python (using the Cython compiler)
|
||||
without recompiling the engine.
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Godot-specific and tightly integrated language with a lightweight syntax, or
|
||||
:ref:`C# <toc-learn-scripting-C#>`, which is popular in the games industry.
|
||||
These are the two main scripting languages we support.
|
||||
|
||||
With the :ref:`GDNative <toc-tutorials-gdnative>` technology, you can also write
|
||||
With the GDExtension technology, you can also write
|
||||
gameplay or high-performance algorithms in C or C++ without recompiling the
|
||||
engine. You can use this technology to integrate third-party libraries and other
|
||||
Software Development Kits (SDK) in the engine.
|
||||
@@ -84,11 +84,6 @@ Software Development Kits (SDK) in the engine.
|
||||
Of course, you can also directly add modules and features to the engine, as it's
|
||||
completely free and open-source.
|
||||
|
||||
.. seealso:: These are the five officially supported programming languages. The
|
||||
community maintains support for many more. For more information,
|
||||
see :ref:`GDNative third-party bindings
|
||||
<doc_what_is_gdnative_third_party_bindings>`.
|
||||
|
||||
.. doc_learning_programming
|
||||
|
||||
What do I need to know to use Godot?
|
||||
|
||||
@@ -24,9 +24,8 @@ Available scripting languages
|
||||
-----------------------------
|
||||
|
||||
Godot offers **four gameplay programming languages**: GDScript, C#,
|
||||
and, via its GDNative technology, C and C++. There are more
|
||||
:ref:`community-supported languages <doc_what_is_gdnative_third_party_bindings>`,
|
||||
but these are the official ones.
|
||||
and, via its GDExtension technology, C and C++. There are more
|
||||
community-supported languages, but these are the official ones.
|
||||
|
||||
You can use multiple languages in a single project. For instance, in a team, you
|
||||
could code gameplay logic in GDScript as it's fast to write, and use C# or C++ to
|
||||
@@ -125,10 +124,10 @@ or ClojureCLR. However, C# is the only officially supported .NET option.
|
||||
in GDScript, C#, or C++ won't have a significant impact on
|
||||
performance.
|
||||
|
||||
C and C++ via GDNative
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
C and C++ via GDExtension
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
GDNative allows you to write game code in C or C++ without needing to recompile
|
||||
GDExtension allows you to write game code in C or C++ without needing to recompile
|
||||
or even restart Godot.
|
||||
|
||||
.. image:: img/scripting_cpp.png
|
||||
@@ -136,10 +135,10 @@ or even restart Godot.
|
||||
You can use any version of the language or mix compiler brands and versions for
|
||||
the generated shared libraries, thanks to our use of an internal C API Bridge.
|
||||
|
||||
GDNative is the best choice for performance. You don't need to use it
|
||||
GDExtension is the best choice for performance. You don't need to use it
|
||||
throughout an entire game, as you can write other parts in GDScript or C#.
|
||||
|
||||
When working with GDNative, the available types, functions, and properties
|
||||
When working with GDExtension, the available types, functions, and properties
|
||||
closely resemble Godot's actual C++ API.
|
||||
|
||||
Summary
|
||||
|
||||
@@ -27,9 +27,6 @@ To create a new project:
|
||||
|
||||
.. image:: img/editor_ui_intro_project_manager_04.png
|
||||
|
||||
.. seealso:: For more information about rendering backends, see
|
||||
:ref:`doc_gles2_gles3_differences`.
|
||||
|
||||
Using the file browser
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Due to limitations on the Godot or Web platform side, the following features
|
||||
are currently missing:
|
||||
|
||||
- No C#/Mono support.
|
||||
- No GDNative support.
|
||||
- No GDExtension support.
|
||||
- No debugging support. This means GDScript debugging/profiling, live scene
|
||||
editing, the Remote Scene tree dock and other features that rely on the debugger
|
||||
protocol will not work.
|
||||
|
||||
@@ -146,9 +146,9 @@ See `Hardened Runtime <https://developer.apple.com/documentation/security/harden
|
||||
+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Allow Unsigned Executable Memory [4]_ | Allows creating writable and executable memory without JIT restrictions. If you are using add-ons with dynamic or self-modifying native code, enable them according to the add-on documentation. |
|
||||
+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Allow DYLD Environment Variables [4]_ | Allows app to uss dynamic linker environment variables to inject code. f you are using add-ons with dynamic or self-modifying native code, enable them according to the add-on documentation. |
|
||||
| Allow DYLD Environment Variables [4]_ | Allows app to uss dynamic linker environment variables to inject code. If you are using add-ons with dynamic or self-modifying native code, enable them according to the add-on documentation. |
|
||||
+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Disable Library Validation | Allows app to load arbitrary libraries and frameworks. Enabled it if you are using GDNative add-ons and ad-hoc signature, or want to support user-provided external add-ons. |
|
||||
| Disable Library Validation | Allows app to load arbitrary libraries and frameworks. Enable it if you are using GDExtension add-ons or ad-hoc signing, or want to support user-provided external add-ons. |
|
||||
+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Audio Input | Enable if you need to use the microphone or other audio input sources, if it's enabled you should also provide usage message in the `privacy/microphone_usage_description` option. |
|
||||
+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -61,13 +61,11 @@ game in the default browser for testing.
|
||||
You can choose the **Export Type** to select which features will be available:
|
||||
|
||||
- *Regular*: is the most compatible across browsers, will not support threads,
|
||||
nor GDNative.
|
||||
nor GDExtension.
|
||||
- *Threads*: will require the browser to support `SharedArrayBuffer
|
||||
<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer>`__.
|
||||
See `Can I use SharedArrayBuffer <https://caniuse.com/sharedarraybuffer>`__
|
||||
for details.
|
||||
- *GDNative*: enables GDNative support but makes the binary bigger and slower
|
||||
to load.
|
||||
|
||||
If you plan to use :ref:`VRAM compression <doc_import_images>` make sure that
|
||||
**Vram Texture Compression** is enabled for the targeted platforms (enabling
|
||||
@@ -147,15 +145,6 @@ across browsers is still limited.
|
||||
Browsers also require that the web page is served with specific
|
||||
`cross-origin isolation headers <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy>`__.
|
||||
|
||||
GDNative
|
||||
~~~~~~~~
|
||||
|
||||
As mentioned :ref:`above <doc_javascript_export_options>` GDNative is only
|
||||
available if the appropriate **Export Type** is set.
|
||||
|
||||
The export will also copy the required GDNative ``.wasm`` files to the output
|
||||
folder (and must be uploaded to your server along with your game).
|
||||
|
||||
Full screen and mouse capture
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ will be able to work as fast as possible.
|
||||
Godot usually takes care of such low-level details for you. For example, the
|
||||
Server APIs make sure data is optimized for caching already for things like
|
||||
rendering and physics. Still, you should be especially aware of caching when
|
||||
using :ref:`GDNative <toc-tutorials-gdnative>`.
|
||||
writing GDExtensions.
|
||||
|
||||
Languages
|
||||
=========
|
||||
@@ -198,7 +198,7 @@ C++
|
||||
Godot is written in C++. Using C++ will usually result in the fastest code.
|
||||
However, on a practical level, it is the most difficult to deploy to end users'
|
||||
machines on different platforms. Options for using C++ include
|
||||
:ref:`GDNative <toc-tutorials-gdnative>` and
|
||||
GDExtensions and
|
||||
:ref:`custom modules <doc_custom_modules_in_c++>`.
|
||||
|
||||
Threads
|
||||
@@ -225,10 +225,10 @@ SceneTree
|
||||
|
||||
Although Nodes are an incredibly powerful and versatile concept, be aware that
|
||||
every node has a cost. Built-in functions such as `_process()` and
|
||||
`_physics_process()` propagate through the tree. This housekeeping can reduce
|
||||
performance when you have a very large numbers of nodes (how many exactly
|
||||
depends on the target platform and can range from thousands to tens of
|
||||
thousands so ensure that you profile performance on all target platforms
|
||||
`_physics_process()` propagate through the tree. This housekeeping can reduce
|
||||
performance when you have a very large numbers of nodes (how many exactly
|
||||
depends on the target platform and can range from thousands to tens of
|
||||
thousands so ensure that you profile performance on all target platforms
|
||||
during development).
|
||||
|
||||
Each node is handled individually in the Godot renderer. Therefore, a smaller
|
||||
|
||||
@@ -33,7 +33,7 @@ see the :ref:`Animating thousands of fish <doc_animating_thousands_of_fish>` tut
|
||||
to the shader can be provided via textures (there are floating-point :ref:`Image<class_Image>` formats
|
||||
which are ideal for this).
|
||||
|
||||
Another alternative is to use GDNative and C++, which should be extremely efficient (it's possible
|
||||
Another alternative is to use a GDExtension and C++, which should be extremely efficient (it's possible
|
||||
to set the entire state for all objects using linear memory via the
|
||||
:ref:`RenderingServer.multimesh_set_buffer() <class_RenderingServer_method_multimesh_set_buffer>`
|
||||
function). This way, the array can be created with multiple threads, then set in one call, providing
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
.. _doc_gles2_gles3_differences:
|
||||
|
||||
Differences between GLES2 and GLES3
|
||||
===================================
|
||||
|
||||
This page documents the differences between GLES2 and GLES3 that are by design and are not the result
|
||||
of bugs. There may be differences that are unintentional, but they should be reported as bugs.
|
||||
|
||||
.. note:: "GLES2" and "GLES3" are the names used in Godot for the two OpenGL-based rendering backends.
|
||||
In terms of graphics APIs, the GLES2 backend maps to OpenGL 2.1 on desktop, OpenGL ES 2.0 on
|
||||
mobile and WebGL 1.0 on the web. The GLES3 backend maps to OpenGL 3.3 on desktop, OpenGL ES
|
||||
3.0 on mobile and WebGL 2.0 on the web.
|
||||
|
||||
Particles
|
||||
---------
|
||||
|
||||
GLES2 cannot use the :ref:`GPUParticles3D <class_GPUParticles3D>` or :ref:`GPUParticles2D <class_GPUParticles2D>` nodes
|
||||
as they require advanced GPU features. Instead, use :ref:`CPUParticles3D <class_CPUParticles3D>` or
|
||||
:ref:`CPUParticles2D <class_CPUParticles2D>`, which provides a similar interface to a
|
||||
:ref:`ParticleProcessMaterial <class_ParticleProcessMaterial>`.
|
||||
|
||||
.. tip:: Particles and GPUParticles2D can be converted to their CPU equivalent node with the "Convert to
|
||||
CPUParticles" option in the editor.
|
||||
|
||||
``SCREEN_TEXTURE`` mip-maps
|
||||
---------------------------
|
||||
|
||||
In GLES2, ``SCREEN_TEXTURE`` (accessed via a :ref:`ShaderMaterial <class_ShaderMaterial>`) does not have
|
||||
computed mip-maps. So when accessing at a different LOD, the texture will not appear blurry.
|
||||
|
||||
``DEPTH_TEXTURE``
|
||||
-----------------
|
||||
|
||||
While GLES2 supports ``DEPTH_TEXTURE`` in shaders, it may not work on some old hardware (especially mobile).
|
||||
|
||||
Color space
|
||||
-----------
|
||||
|
||||
GLES2 and GLES3 are in different color spaces. This means that colors will appear slightly
|
||||
different between them especially when lighting is used.
|
||||
|
||||
If your game is going to use both GLES2 and GLES3, you can use an ``if``
|
||||
statement check and see if the output is in sRGB, using ``OUTPUT_IS_SRGB``. ``OUTPUT_IS_SRGB`` is
|
||||
``true`` in GLES2 and ``false`` in GLES3.
|
||||
|
||||
HDR
|
||||
---
|
||||
|
||||
GLES2 is not capable of using High Dynamic Range (HDR) rendering features. If HDR is set for your
|
||||
project, or for a given viewport, Godot will still use Low Dynamic Range (LDR) which limits
|
||||
viewport values to the ``0-1`` range.
|
||||
|
||||
The Viewport **Debanding** property and associated project setting will also have
|
||||
no effect when HDR is disabled. This means debanding can't be used in GLES2.
|
||||
|
||||
StandardMaterial3D features
|
||||
---------------------------
|
||||
|
||||
In GLES2, the following advanced rendering features in the :ref:`StandardMaterial3D <class_StandardMaterial3D>` are missing:
|
||||
|
||||
- Refraction
|
||||
- Subsurface scattering
|
||||
- Anisotropy
|
||||
- Clearcoat
|
||||
- Depth mapping
|
||||
|
||||
When using StandardMaterial3Ds they will not even appear in the editor.
|
||||
|
||||
In custom :ref:`ShaderMaterials <class_ShaderMaterial>`, you can set values for these features but they
|
||||
will be non-functional. For example, you will still be able to set the ``SSS`` built-in (which normally adds
|
||||
subsurface scattering) in your shader, but nothing will happen.
|
||||
|
||||
Environment features
|
||||
--------------------
|
||||
|
||||
In GLES2, the following features in the :ref:`Environment <class_Environment>` are missing:
|
||||
|
||||
- Auto exposure
|
||||
- Tonemapping
|
||||
- Screen space reflections
|
||||
- Screen space ambient occlusion
|
||||
|
||||
That means that in GLES2 environments you can only set:
|
||||
|
||||
- Sky (including procedural sky)
|
||||
- Ambient light
|
||||
- Fog
|
||||
- Depth of field
|
||||
- Glow (also known as bloom)
|
||||
- Adjustment
|
||||
|
||||
See :ref:`doc_environment_and_post_processing` for more information.
|
||||
|
||||
Glow
|
||||
----
|
||||
|
||||
Many GLES2 devices only have a maximum of eight texture units. On such devices, you
|
||||
can only use the first six levels of glow; the seventh one won't do anything.
|
||||
|
||||
GIProbes
|
||||
--------
|
||||
|
||||
.. FIXME: Removed references to no longer existing classes in master/4.0 version to
|
||||
silence warning, but the whole page will likely end up rewritten or removed
|
||||
in 4.0.
|
||||
|
||||
GIProbes do not work in GLES2. Instead use Baked Lightmaps.
|
||||
For a description of how baked lightmaps work see the :ref:`Baked Lightmaps tutorial <doc_baked_lightmaps>`.
|
||||
|
||||
Contact shadows
|
||||
---------------
|
||||
|
||||
The ``shadow_contact`` property of lights is not supported in GLES2 and so does nothing.
|
||||
|
||||
Light performance
|
||||
-----------------
|
||||
|
||||
In GLES2, performance scales poorly with several lights, as each light is processed in a separate render
|
||||
pass (in opposition to GLES3 which is all done in a single pass). Try to limit scenes to as few lights as
|
||||
possible in order to achieve greatest performance.
|
||||
|
||||
Texture compression
|
||||
-------------------
|
||||
|
||||
On mobile, GLES2 requires ETC texture compression, while GLES3 requires ETC2. ETC2 is enabled by default,
|
||||
so if exporting to mobile using GLES2 make sure to set the project setting
|
||||
``rendering/vram_compression/import_etc`` and then reimport textures.
|
||||
|
||||
.. warning::
|
||||
|
||||
Since ETC doesn't support transparency, you must reimport textures that contain
|
||||
an alpha channel to use the Uncompressed, Lossy or Lossless compression mode
|
||||
(instead of Video RAM). This can be done in the Import dock after selecting
|
||||
them in the FileSystem dock.
|
||||
|
||||
Blend shapes
|
||||
------------
|
||||
|
||||
In GLES2, blend shapes are implemented on the CPU instead of the GPU.
|
||||
Accordingly, they may not perform as well as blend shapes in GLES3. To avoid
|
||||
performance issues when using blend shapes in GLES2, try to minimize the number
|
||||
of blend shapes that are updated each frame.
|
||||
|
||||
Shading language
|
||||
----------------
|
||||
|
||||
GLES3 provides many built-in functions that GLES2 does not. Below is a list of functions
|
||||
that are not available or are have limited support in GLES2.
|
||||
|
||||
For a complete list of built-in GLSL functions see the :ref:`Shading Language doc <doc_shading_language>`.
|
||||
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| Function | |
|
||||
+=============================================================================================+==================================================+
|
||||
| vec_type **modf** ( vec_type x, out vec_type i ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_int_type **floatBitsToInt** ( vec_type x ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_uint_type **floatBitsToUint** ( vec_type x ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_type **intBitsToFloat** ( vec_int_type x ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_type **uintBitsToFloat** ( vec_uint_type x ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| ivec2 **textureSize** ( sampler2D_type s, int lod ) | See workaround below |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| ivec2 **textureSize** ( samplerCube s, int lod ) | See workaround below |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec4_type **texture** ( sampler_type s, vec_type uv [, float bias] ) | **bias** not available in vertex shader |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec4_type **textureProj** ( sampler_type s, vec_type uv [, float bias] ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec4_type **textureLod** ( sampler_type s, vec_type uv, float lod ) | Only available in vertex shader on some hardware |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec4_type **textureProjLod** ( sampler_type s, vec_type uv, float lod ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec4_type **textureGrad** ( sampler_type s, vec_type uv, vec_type dPdx, vec_type dPdy ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_type **dFdx** ( vec_type p ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_type **dFdy** ( vec_type p ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
| vec_type **fwidth** ( vec_type p ) | |
|
||||
+---------------------------------------------------------------------------------------------+--------------------------------------------------+
|
||||
|
||||
.. note:: Functions not in GLES2's GLSL were added with Godots own shader standard library. These functions may perform worse in GLES2 compared to GLES3.
|
||||
|
||||
``textureSize()`` workaround
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
GLES2 does not support ``textureSize()``. You can get the size of a texture the old fashioned way by passing in a
|
||||
uniform with the texture size yourself.
|
||||
|
||||
.. code-block:: glsl
|
||||
|
||||
// In the shader:
|
||||
uniform sampler2D textureName;
|
||||
uniform vec2 textureName_size;
|
||||
|
||||
::
|
||||
|
||||
# In GDScript:
|
||||
material_name.set_shader_param("textureName", my_texture)
|
||||
material_name.set_shader_param("textureName_size", my_texture_size)
|
||||
|
||||
Built in variables and render modes
|
||||
-----------------------------------
|
||||
|
||||
Godot also provides many built-in variables and render modes. Some cannot be supported in GLES2. Below is a list of
|
||||
built-in variables and render modes that, when written to, will have no effect or could even cause issues when using
|
||||
the GLES2 backend.
|
||||
|
||||
+----------------------------+
|
||||
| Variable / Render Mode |
|
||||
+============================+
|
||||
| ``ensure_correct_normals`` |
|
||||
+----------------------------+
|
||||
| ``INSTANCE_ID`` |
|
||||
+----------------------------+
|
||||
| ``DEPTH`` |
|
||||
+----------------------------+
|
||||
| ``ANISOTROPY`` |
|
||||
+----------------------------+
|
||||
| ``ANISOTROPY_FLOW`` |
|
||||
+----------------------------+
|
||||
| ``SSS_STRENGTH`` |
|
||||
+----------------------------+
|
||||
@@ -1,109 +0,0 @@
|
||||
#!python
|
||||
import os
|
||||
|
||||
opts = Variables([], ARGUMENTS)
|
||||
|
||||
# Gets the standard flags CC, CCX, etc.
|
||||
env = DefaultEnvironment()
|
||||
|
||||
# Define our options
|
||||
opts.Add(EnumVariable('target', "Compilation target", 'debug', ['d', 'debug', 'r', 'release']))
|
||||
opts.Add(EnumVariable('platform', "Compilation platform", '', ['', 'windows', 'linuxbsd', 'linux', 'osx']))
|
||||
opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", '', ['', 'windows', 'linuxbsd', 'linux', 'osx']))
|
||||
opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no'))
|
||||
opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'demo/bin/'))
|
||||
opts.Add(PathVariable('target_name', 'The library name.', 'libgdexample', PathVariable.PathAccept))
|
||||
|
||||
# Local dependency paths, adapt them to your setup
|
||||
godot_headers_path = "godot-cpp/godot-headers/"
|
||||
cpp_bindings_path = "godot-cpp/"
|
||||
cpp_library = "libgodot-cpp"
|
||||
|
||||
# only support 64 at this time..
|
||||
bits = 64
|
||||
|
||||
# Updates the environment with the option variables.
|
||||
opts.Update(env)
|
||||
|
||||
# Process some arguments
|
||||
if env['use_llvm']:
|
||||
env['CC'] = 'clang'
|
||||
env['CXX'] = 'clang++'
|
||||
|
||||
if env['p'] != '':
|
||||
env['platform'] = env['p']
|
||||
|
||||
if env['platform'] == '':
|
||||
print("No valid target platform selected.")
|
||||
quit()
|
||||
|
||||
# For the 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
|
||||
|
||||
# Check our platform specifics
|
||||
if env['platform'] == "osx":
|
||||
env['target_path'] += 'osx/'
|
||||
cpp_library += '.osx'
|
||||
env.Append(CCFLAGS=['-arch', 'x86_64'])
|
||||
env.Append(CXXFLAGS=['-std=c++17'])
|
||||
env.Append(LINKFLAGS=['-arch', 'x86_64'])
|
||||
if env['target'] in ('debug', 'd'):
|
||||
env.Append(CCFLAGS=['-g', '-O2'])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-g', '-O3'])
|
||||
|
||||
elif env['platform'] in ('linuxbsd', 'linux'):
|
||||
env['target_path'] += 'linuxbsd/'
|
||||
cpp_library += '.linux'
|
||||
env.Append(CCFLAGS=['-fPIC'])
|
||||
env.Append(CXXFLAGS=['-std=c++17'])
|
||||
if env['target'] in ('debug', 'd'):
|
||||
env.Append(CCFLAGS=['-g3', '-Og'])
|
||||
else:
|
||||
env.Append(CCFLAGS=['-g', '-O3'])
|
||||
|
||||
elif env['platform'] == "windows":
|
||||
env['target_path'] += 'win64/'
|
||||
cpp_library += '.windows'
|
||||
# This makes sure to keep the session environment variables on windows,
|
||||
# that way you can run scons in a vs 2017 prompt and it will find all the required tools
|
||||
env.Append(ENV=os.environ)
|
||||
|
||||
env.Append(CPPDEFINES=['WIN32', '_WIN32', '_WINDOWS', '_CRT_SECURE_NO_WARNINGS'])
|
||||
env.Append(CCFLAGS=['-W3', '-GR'])
|
||||
env.Append(CXXFLAGS='/std:c++17')
|
||||
if env['target'] in ('debug', 'd'):
|
||||
env.Append(CPPDEFINES=['_DEBUG'])
|
||||
env.Append(CCFLAGS=['-EHsc', '-MDd', '-ZI'])
|
||||
env.Append(LINKFLAGS=['-DEBUG'])
|
||||
else:
|
||||
env.Append(CPPDEFINES=['NDEBUG'])
|
||||
env.Append(CCFLAGS=['-O2', '-EHsc', '-MD'])
|
||||
|
||||
if env['target'] in ('debug', 'd'):
|
||||
cpp_library += '.debug'
|
||||
else:
|
||||
cpp_library += '.release'
|
||||
|
||||
cpp_library += '.' + str(bits)
|
||||
|
||||
# make sure our binding library is properly includes
|
||||
env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/'])
|
||||
env.Append(LIBPATH=[cpp_bindings_path + 'bin/'])
|
||||
env.Append(LIBS=[cpp_library])
|
||||
|
||||
# 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')
|
||||
|
||||
library = env.SharedLibrary(target=env['target_path'] + env['target_name'] , source=sources)
|
||||
|
||||
Default(library)
|
||||
|
||||
# Generates help for the -h scons option.
|
||||
Help(opts.GenerateHelpText(env))
|
||||
@@ -1,555 +0,0 @@
|
||||
.. _doc_gdnative_c_example:
|
||||
|
||||
GDNative C example
|
||||
==================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This tutorial introduces the bare minimum required to create GDNative
|
||||
modules. This should be your starting point into the world of GDNative.
|
||||
Understanding the contents of this tutorial will help you in understanding all
|
||||
that is to come after this.
|
||||
|
||||
Before we begin, you can download the source code to the example object we
|
||||
describe below in the `GDNative-demos repository
|
||||
<https://github.com/GodotNativeTools/GDNative-demos/tree/master/c/simple>`_.
|
||||
|
||||
This example project also contains a SConstruct file that makes compiling a
|
||||
little easier, but in this tutorial we'll be doing things by hand to
|
||||
understand the process.
|
||||
|
||||
:ref:`GDNative <class_GDNative>` can be used to create several types of
|
||||
additions to Godot, using interfaces such as
|
||||
:ref:`PluginScript <class_PluginScript>` or
|
||||
:ref:`ARVRInterfaceGDNative <class_ARVRInterfaceGDNative>`. In this tutorial we
|
||||
are going to look at creating a :ref:`NativeScript <class_NativeScript>`
|
||||
module. NativeScript allows you to write logic in C or C++ in a similar fashion
|
||||
as you would write a GDScript file. We'll be creating the C equivalent of this
|
||||
GDScript:
|
||||
|
||||
::
|
||||
|
||||
extends Reference
|
||||
|
||||
var data
|
||||
|
||||
func _ready():
|
||||
data = "World from GDScript!"
|
||||
|
||||
func get_data():
|
||||
return data
|
||||
|
||||
Future tutorials will focus on the other types of GDNative modules and explain
|
||||
when and how to use each of them.
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Before we start you'll need a few things:
|
||||
|
||||
1) A Godot executable for your target version.
|
||||
2) A C compiler. On Linux, install ``gcc`` or ``clang`` from your package
|
||||
manager. On macOS, you can install Xcode from the Mac App Store. On Windows,
|
||||
you can use Visual Studio 2015 or later, or MinGW-w64.
|
||||
3) A Git clone of the `godot-headers
|
||||
repository <https://github.com/godotengine/godot-headers.git>`_: these are
|
||||
the C headers for Godot's public API exposed to GDNative.
|
||||
|
||||
For the latter, we suggest that you create a dedicated folder for this GDNative
|
||||
example project, open a terminal in that folder and execute:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
git clone https://github.com/godotengine/godot-headers.git
|
||||
|
||||
This will download the required files into that folder.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you plan to use Git for your GDNative project, you can also add
|
||||
``godot-headers`` as a Git submodule.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``godot-headers`` repository has different branches. As Godot evolves,
|
||||
so does GDNative. While we try to preserve compatibility between version,
|
||||
you should always build your GDNative module against headers matching the
|
||||
Godot stable branch (e.g. ``3.1``) and ideally actual release (e.g.
|
||||
``3.1.1-stable``) that you use.
|
||||
GDNative modules built against older versions of the Godot headers *may*
|
||||
work with newer versions of the engine, but not the other way around.
|
||||
|
||||
The ``master`` branch of the ``godot-headers`` repository is kept in line with
|
||||
the ``master`` branch of Godot and thus contains the GDNative class and
|
||||
structure definitions that will work with the latest development builds.
|
||||
|
||||
If you want to write a GDNative module for a stable version of Godot, look at
|
||||
the available Git tags (with ``git tags``) for the one matching your engine
|
||||
version. In the ``godot-headers`` repository, such tags are prefixed with
|
||||
``godot-``, so you can e.g. checkout the ``godot-3.1.1-stable`` tag for use with
|
||||
Godot 3.1.1. In your cloned repository, you can do:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
git checkout godot-3.1.1-stable
|
||||
|
||||
If a tag matching your stable release is missing for any reason, you can fall
|
||||
back to the matching stable branch (e.g. ``3.1``), which you would also check
|
||||
out with ``git checkout 3.1``.
|
||||
|
||||
If you are building Godot from source with your own changes that impact
|
||||
GDNative, you can find the updated class and structure definition in
|
||||
``<godotsource>/modules/gdnative/include``
|
||||
|
||||
Our C source
|
||||
------------
|
||||
|
||||
Let's start by writing our main code. Eventually, we want to end up with a file
|
||||
structure that looks along those lines:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+ <your development folder>
|
||||
+ godot-headers
|
||||
- <lots of files here>
|
||||
+ simple
|
||||
+ bin
|
||||
- libsimple.dll/so/dylib
|
||||
- libsimple.gdnlib
|
||||
- simple.gdns
|
||||
main.tscn
|
||||
project.godot
|
||||
+ src
|
||||
- simple.c
|
||||
|
||||
Open up Godot and create a new project called "simple" alongside your
|
||||
``godot-headers`` Git clone. This will create the ``simple`` folder and
|
||||
``project.godot`` file. Then manually create a ``src`` folder alongside the
|
||||
``simple`` folder, and a ``bin`` subfolder in the ``simple`` folder.
|
||||
|
||||
We're going to start by having a look at what our ``simple.c`` file contains.
|
||||
Now, for our example here we're making a single C source file without a header
|
||||
to keep things simple. Once you start writing bigger projects it is advisable
|
||||
to break your project up into multiple files. That however falls outside of the
|
||||
scope of this tutorial.
|
||||
|
||||
We'll be looking at the source code bit by bit so all the parts below should all
|
||||
be put together into one big file. Each section will be explained as we add it.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#include <gdnative_api_struct.gen.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const godot_gdnative_core_api_struct *api = NULL;
|
||||
const godot_gdnative_ext_nativescript_api_struct *nativescript_api = NULL;
|
||||
|
||||
The above code includes the GDNative API struct header and a standard header
|
||||
that we will use further down for string operations.
|
||||
It then defines two pointers to two different structs. GDNative supports a large
|
||||
collection of functions for calling back into the main Godot executable. In
|
||||
order for your module to have access to these functions, GDNative provides your
|
||||
application with a struct containing pointers to all these functions.
|
||||
|
||||
To keep this implementation modular and easily extendable, the core functions
|
||||
are available directly through the "core" API struct, but additional functions
|
||||
have their own "GDNative structs" that are accessible through extensions.
|
||||
|
||||
In our example, we access one of these extension to gain access to the functions
|
||||
specifically needed for NativeScript.
|
||||
|
||||
A NativeScript behaves like any other script in Godot. Because the NativeScript
|
||||
API is rather low level, it requires the library to specify many things more
|
||||
verbosely than other scripting systems, such as GDScript. When a NativeScript
|
||||
instance gets created, a library-given constructor gets called. When that
|
||||
instance gets destroyed, the given destructor will be executed.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *simple_constructor(godot_object *p_instance, void *p_method_data);
|
||||
void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data);
|
||||
godot_variant simple_get_data(godot_object *p_instance, void *p_method_data,
|
||||
void *p_user_data, int p_num_args, godot_variant **p_args);
|
||||
|
||||
These are forward declarations for the functions we'll be implementing for our
|
||||
object. A constructor and destructor is needed. Additionally, the object will
|
||||
have a single method called ``get_data``.
|
||||
|
||||
Next up is the first of the entry points Godot will call when our dynamic
|
||||
library is loaded. These methods are all prefixed with ``godot_`` (you can
|
||||
change this later on) followed by their name. ``gdnative_init`` is a function
|
||||
that initializes our dynamic library. Godot will give it a pointer to a
|
||||
structure that contains various bits of information we may find useful among
|
||||
which the pointers to our API structures.
|
||||
|
||||
For any additional API structures we need to loop through our extensions array
|
||||
and check the type of extension.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *p_options) {
|
||||
api = p_options->api_struct;
|
||||
|
||||
// Now find our extensions.
|
||||
for (int i = 0; i < api->num_extensions; i++) {
|
||||
switch (api->extensions[i]->type) {
|
||||
case GDNATIVE_EXT_NATIVESCRIPT: {
|
||||
nativescript_api = (godot_gdnative_ext_nativescript_api_struct *)api->extensions[i];
|
||||
}; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Next up is ``gdnative_terminate`` which is called before the library is
|
||||
unloaded. Godot will unload the library when no object uses it anymore. Here,
|
||||
you can do any cleanup you may need to do. For our example, we're simply going
|
||||
to clear our API pointers.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *p_options) {
|
||||
api = NULL;
|
||||
nativescript_api = NULL;
|
||||
}
|
||||
|
||||
Finally, we have ``nativescript_init`` which is the most important function we'll
|
||||
need today. This function will be called by Godot as part of loading a GDNative
|
||||
library and communicates back to the engine what objects we make available.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void GDN_EXPORT godot_nativescript_init(void *p_handle) {
|
||||
godot_instance_create_func create = { NULL, NULL, NULL };
|
||||
create.create_func = &simple_constructor;
|
||||
|
||||
godot_instance_destroy_func destroy = { NULL, NULL, NULL };
|
||||
destroy.destroy_func = &simple_destructor;
|
||||
|
||||
nativescript_api->godot_nativescript_register_class(p_handle, "SIMPLE", "Reference",
|
||||
create, destroy);
|
||||
|
||||
godot_instance_method get_data = { NULL, NULL, NULL };
|
||||
get_data.method = &simple_get_data;
|
||||
|
||||
godot_method_attributes attributes = { GODOT_METHOD_RPC_MODE_DISABLED };
|
||||
|
||||
nativescript_api->godot_nativescript_register_method(p_handle, "SIMPLE", "get_data",
|
||||
attributes, get_data);
|
||||
}
|
||||
|
||||
We first tell the engine which classes are implemented by calling
|
||||
``nativescript_register_class``. The first parameter here is the handle pointer
|
||||
given to us. The second is the name of our object class. The third is the type
|
||||
of object in Godot that we 'inherit' from; this is not true inheritance but it's
|
||||
close enough. Finally, our fourth and fifth parameters are descriptions for our
|
||||
constructor and destructor.
|
||||
|
||||
We then tell Godot about our methods (well our one method in this case), by
|
||||
calling ``nativescript_register_method`` for each method of our class. In our
|
||||
case, that is just ``get_data``. Our first parameter is yet again our handle
|
||||
pointer. The second is again the name of the object class we're registering. The
|
||||
third is the name of our function as it will be known to GDScript. The fourth is
|
||||
our attributes setting (see ``godot_method_rpc_mode`` enum in
|
||||
``godot-headers/nativescript/godot_nativescript.h`` for possible values). The
|
||||
fifth and final parameter is a description of which function to call when the
|
||||
method gets called.
|
||||
|
||||
The description struct ``instance_method`` contains the function pointer to the
|
||||
function itself as first field. The other two fields in these structs are for
|
||||
specifying per-method userdata. The second is the ``method_data`` field which is
|
||||
passed on every function call as the ``p_method_data`` argument. This is useful
|
||||
to reuse one function for different methods on possibly multiple different
|
||||
script-classes. If the ``method_data`` value is a pointer to memory that needs
|
||||
to be freed, the third ``free_func`` field can contain a pointer to a function
|
||||
that will free that memory. That free function gets called when the script
|
||||
itself (not instance!) gets unloaded (so usually at library-unload time).
|
||||
|
||||
Now, it's time to start working on the functions of our object. First, we define
|
||||
a structure that we use to store the member data of an instance of our GDNative
|
||||
class.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
typedef struct user_data_struct {
|
||||
char data[256];
|
||||
} user_data_struct;
|
||||
|
||||
And then, we define our constructor. All we do in our constructor is allocate
|
||||
memory for our structure and fill it with some data. Note that we use Godot's
|
||||
memory functions so the memory gets tracked and then return the pointer to our
|
||||
new structure. This pointer will act as our instance identifier in case multiple
|
||||
objects are instantiated.
|
||||
|
||||
This pointer will be passed to any of our functions related to our object as a
|
||||
parameter called ``p_user_data``, and can both be used to identify our instance
|
||||
and to access its member data.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void *simple_constructor(godot_object *p_instance, void *p_method_data) {
|
||||
user_data_struct *user_data = api->godot_alloc(sizeof(user_data_struct));
|
||||
strcpy(user_data->data, "World from GDNative!");
|
||||
|
||||
return user_data;
|
||||
}
|
||||
|
||||
Our destructor is called when Godot is done with our object and we free our
|
||||
instances' member data.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data) {
|
||||
api->godot_free(p_user_data);
|
||||
}
|
||||
|
||||
And finally, we implement our ``get_data`` function. Data is always sent and
|
||||
returned as variants so in order to return our data, which is a string, we first
|
||||
need to convert our C string to a Godot string object, and then copy that string
|
||||
object into the variant we are returning.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
godot_variant simple_get_data(godot_object *p_instance, void *p_method_data,
|
||||
void *p_user_data, int p_num_args, godot_variant **p_args) {
|
||||
godot_string data;
|
||||
godot_variant ret;
|
||||
user_data_struct *user_data = (user_data_struct *)p_user_data;
|
||||
|
||||
api->godot_string_new(&data);
|
||||
api->godot_string_parse_utf8(&data, user_data->data);
|
||||
api->godot_variant_new_string(&ret, &data);
|
||||
api->godot_string_destroy(&data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Strings are heap-allocated in Godot, so they have a destructor which frees the
|
||||
memory. Destructors are named ``godot_TYPENAME_destroy``. When a Variant gets
|
||||
created with a String, it references the String. That means that the original
|
||||
String can be "destroyed" to decrease the ref-count. If that does not happen the
|
||||
String memory will leak since the ref-count will never be zero and the memory
|
||||
never deallocated. The returned variant gets automatically destroyed by Godot.
|
||||
|
||||
.. note::
|
||||
|
||||
In more complex operations it can be confusing the keep track of which value
|
||||
needs to be deallocated and which does not. As a general rule: call
|
||||
``godot_TYPENAME_destroy`` when a C++ destructor would be called instead.
|
||||
The String destructor would be called in C++ after the Variant was created,
|
||||
so the same is necessary in C.
|
||||
|
||||
The variant we return is destroyed automatically by Godot.
|
||||
|
||||
And that is the whole source code of our module.
|
||||
|
||||
Compiling
|
||||
---------
|
||||
|
||||
We now need to compile our source code. As mentioned our example project on
|
||||
GitHub contains a SCons configuration that does all the hard work for you, but
|
||||
for our tutorial here we are going to call the compilers directly.
|
||||
|
||||
Assuming you are sticking to the folder structure suggested above, it is best to
|
||||
open a terminal session in the ``src`` folder and execute the commands from
|
||||
there. Make sure to create the ``bin`` folder before you proceed.
|
||||
|
||||
On Linux:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
gcc -std=c11 -fPIC -c -I../godot-headers simple.c -o simple.o
|
||||
gcc -rdynamic -shared simple.o -o ../simple/bin/libsimple.so
|
||||
|
||||
On macOS:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
clang -std=c11 -fPIC -c -I../godot-headers simple.c -o simple.os
|
||||
clang -dynamiclib simple.os -o ../simple/bin/libsimple.dylib
|
||||
|
||||
On Windows:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
cl /Fosimple.obj /c simple.c /nologo -EHsc -DNDEBUG /MD /I. /I..\godot-headers
|
||||
link /nologo /dll /out:..\simple\bin\libsimple.dll /implib:..\simple\bin\libsimple.lib simple.obj
|
||||
|
||||
.. note::
|
||||
|
||||
On the Windows build you also end up with a ``libsimple.lib`` library. This
|
||||
is a library that you can compile into a project to provide access to the
|
||||
DLL. We get it as a byproduct and we do not need it :)
|
||||
When exporting your game for release this file will be ignored.
|
||||
|
||||
Creating the GDNativeLibrary (``.gdnlib``) file
|
||||
-----------------------------------------------
|
||||
|
||||
With our module compiled, we now need to create a corresponding
|
||||
:ref:`GDNativeLibrary <class_GDNativeLibrary>` resource with ``.gdnlib``
|
||||
extension which we place alongside our dynamic libraries. This file tells Godot
|
||||
what dynamic libraries are part of our module and need to be loaded per
|
||||
platform.
|
||||
|
||||
We can use Godot to generate this file, so open the "simple" project in the
|
||||
editor.
|
||||
|
||||
Start by clicking the create resource button in the Inspector:
|
||||
|
||||
.. image:: img/new_resource.gif
|
||||
|
||||
And select ``GDNativeLibrary``:
|
||||
|
||||
.. image:: img/gdnativelibrary_resource.png
|
||||
|
||||
You should see a contextual editor appear in the bottom panel. Use the "Expand
|
||||
Bottom Panel" button in the bottom right to expand it to full height:
|
||||
|
||||
.. image:: img/gdnativelibrary_editor.png
|
||||
|
||||
General properties
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the Inspector, you have various properties to control loading the library.
|
||||
|
||||
If *Load Once* is enabled, our library is loaded only once and each individual
|
||||
script that uses our library will use the same data. Any variable you define
|
||||
globally will be accessible from any instance of your object you create. If
|
||||
*Load Once* is disabled, a new copy of the library is loaded into memory each
|
||||
time a script accesses the library.
|
||||
|
||||
If *Singleton* is enabled, our library is automatically loaded and a function
|
||||
called ``godot_gdnative_singleton`` is called. We'll leave that for another
|
||||
tutorial.
|
||||
|
||||
The *Symbol Prefix* is a prefix for our core functions, such as ``godot_`` in
|
||||
``godot_nativescript_init`` seen earlier. If you use multiple GDNative libraries
|
||||
that you wish to statically link, you will have to use different prefixes. This
|
||||
again is a subject to dive into deeper in a separate tutorial, it is only needed
|
||||
at this time for deployment to iOS as this platform does not like dynamic
|
||||
libraries.
|
||||
|
||||
*Reloadable* defines whether the library should be reloaded when the editor
|
||||
loses and gains focus, typically to pick up new or modified symbols from any
|
||||
change made to the library externally.
|
||||
|
||||
Platform libraries
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The GDNativeLibrary editor plugin lets you configure two things for each
|
||||
platform and architecture that you aim to support.
|
||||
|
||||
The *Dynamic Library* column (``entry`` section in the saved file) tells us for
|
||||
each platform and feature combination which dynamic library has to be loaded.
|
||||
This also informs the exporter which files need to be exported when exporting to
|
||||
a specific platform.
|
||||
|
||||
The *Dependencies* column (also ``dependencies`` section) tells Godot what other
|
||||
files need to be exported for each platform in order for our library to work.
|
||||
Say that your GDNative module uses another DLL to implement functionality from a
|
||||
3rd party library, this is where you list that DLL.
|
||||
|
||||
For our example, we only built libraries for Linux, macOS and/or Windows, so you
|
||||
can link them in the relevant fields by clicking the folder button. If you built
|
||||
all three libraries, you should have something like this:
|
||||
|
||||
.. image:: img/gdnativelibrary_editor_complete.png
|
||||
|
||||
Saving the resource
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We can then save our GDNativeLibrary resource as ``bin/libsimple.gdnlib`` with
|
||||
the Save button in the Inspector:
|
||||
|
||||
.. image:: img/gdnativelibrary_save.png
|
||||
|
||||
The file is saved in a text-based format and should have contents similar to
|
||||
this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[general]
|
||||
|
||||
singleton=false
|
||||
load_once=true
|
||||
symbol_prefix="godot_"
|
||||
reloadable=true
|
||||
|
||||
[entry]
|
||||
|
||||
Linux.64="res://bin/libsimple.so"
|
||||
OSX.64="res://bin/libsimple.dylib"
|
||||
OSX.32="res://bin/libsimple.dylib"
|
||||
Windows.64="res://bin/libsimple.dll"
|
||||
|
||||
[dependencies]
|
||||
|
||||
Linux.64=[ ]
|
||||
OSX.64=[ ]
|
||||
OSX.32=[ ]
|
||||
Windows.64=[ ]
|
||||
|
||||
Creating the NativeScript (``.gdns``) file
|
||||
------------------------------------------
|
||||
|
||||
With our ``.gdnlib`` file we've told Godot how to load our library, now we need
|
||||
to tell it about our "SIMPLE" object class. We do this by creating a
|
||||
:ref:`NativeScript <class_NativeScript>` resource file with ``.gdns`` extension.
|
||||
|
||||
Like done for the GDNativeLibrary resource, click the button to create a new
|
||||
resource in the Inspector and select ``NativeScript``:
|
||||
|
||||
.. image:: img/nativescript_resource.png
|
||||
|
||||
The inspector will show a few properties that we need to fill. As *Class Name*
|
||||
we enter "SIMPLE" which is the object class name that we declared in our C
|
||||
source when calling ``godot_nativescript_register_class``. We also need to
|
||||
select our ``.gdnlib`` file by clicking on *Library* and selecting *Load*:
|
||||
|
||||
.. image:: img/nativescript_library.png
|
||||
|
||||
.. note::
|
||||
|
||||
The *Class Name* must have the same spelling as the one given in ``godot_nativescript_init``
|
||||
when registering the class.
|
||||
|
||||
|
||||
Finally, click on the save icon and save this as ``bin/simple.gdns``:
|
||||
|
||||
.. image:: img/save_gdns.gif
|
||||
|
||||
Now it's time to build our scene. Add a Control node to your scene as your root
|
||||
and call it ``main``. Then add a Button and a Label as child nodes. Place them
|
||||
somewhere nice on screen and give your button a name.
|
||||
|
||||
.. image:: img/c_main_scene_layout.png
|
||||
|
||||
Select the control node and attach a script to it:
|
||||
|
||||
.. image:: img/add_main_script.gif
|
||||
|
||||
Next link up the ``pressed`` signal on the button to your script:
|
||||
|
||||
.. image:: img/connect_button_signal.gif
|
||||
|
||||
Don't forget to save your scene, call it ``main.tscn``.
|
||||
|
||||
Now we can implement our ``main.gd`` code:
|
||||
|
||||
::
|
||||
|
||||
extends Control
|
||||
|
||||
# load the Simple library
|
||||
@onready var data = preload("res://bin/simple.gdns").new()
|
||||
|
||||
func _on_Button_pressed():
|
||||
$Label.text = "Data = " + data.get_data()
|
||||
|
||||
After all that, our project should work. The first time you run it Godot will
|
||||
ask you what your main scene is and you select your ``main.tscn`` file and
|
||||
presto:
|
||||
|
||||
.. image:: img/c_sample_result.png
|
||||
@@ -1,662 +0,0 @@
|
||||
.. _doc_gdnative_cpp_example:
|
||||
|
||||
GDNative C++ example
|
||||
====================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This tutorial builds on top of the information given in the
|
||||
:ref:`GDNative C example <doc_gdnative_c_example>`, so we highly recommend you
|
||||
read that first.
|
||||
|
||||
The C++ bindings for GDNative are built on top of the NativeScript GDNative API
|
||||
and provide a nicer way to "extend" nodes in Godot using C++. This is equivalent
|
||||
to writing scripts in GDScript, but in C++ instead.
|
||||
|
||||
You can download the full example we'll be creating in this tutorial `on
|
||||
GitHub <https://github.com/BastiaanOlij/gdnative_cpp_example>`__.
|
||||
|
||||
Setting up the project
|
||||
----------------------
|
||||
|
||||
There are a few prerequisites you'll need:
|
||||
|
||||
- a Godot 3.x 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:`Compiling <toc-devel-compiling>` as the build tools are identical
|
||||
to the ones you need to compile Godot from source.
|
||||
|
||||
You can download these repositories from GitHub or let Git do the work for you.
|
||||
Note that these repositories now have different branches for different versions
|
||||
of Godot. GDNative modules written for an earlier version of Godot will work in
|
||||
newer versions (with the exception of one breaking change in ARVR interfaces
|
||||
between 3.0 and 3.1) but not vice versa, so make sure you download the correct
|
||||
branch. Also, note that the version of Godot you use to generate the ``api.json``
|
||||
with becomes your minimum version.
|
||||
|
||||
.. note::
|
||||
|
||||
`GDExtension <https://godotengine.org/article/introducing-gd-extensions>`__
|
||||
has been merged in the ``master`` branch of godot-cpp,
|
||||
but it is only compatible with the upcoming Godot 4.0.
|
||||
Therefore, you need to use the ``3.x`` branch of godot-cpp to use GDNative
|
||||
and follow this example.
|
||||
|
||||
This tutorial covers only GDNative in Godot 3.x, *not* GDExtension in Godot 4.0.
|
||||
|
||||
If you are versioning your project using Git, it is a good idea to add them as
|
||||
Git submodules:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mkdir gdnative_cpp_example
|
||||
cd gdnative_cpp_example
|
||||
git init
|
||||
git submodule add -b 3.x https://github.com/godotengine/godot-cpp
|
||||
cd godot-cpp
|
||||
git submodule update --init
|
||||
|
||||
If you decide to just download the repositories or clone them into your project
|
||||
folder, make sure to keep the folder layout identical to the one described here,
|
||||
as much of the code we'll be showcasing here assumes the project follows this
|
||||
layout.
|
||||
|
||||
Do make sure you clone recursive to pull in both repositories:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mkdir gdnative_cpp_example
|
||||
cd gdnative_cpp_example
|
||||
git clone --recursive -b 3.x https://github.com/godotengine/godot-cpp
|
||||
|
||||
.. note::
|
||||
|
||||
``godot-cpp`` now includes ``godot-headers`` as a nested submodule, if you've
|
||||
manually downloaded them please make sure to place ``godot-headers`` inside
|
||||
of the ``godot-cpp`` folder.
|
||||
|
||||
You don't have to do it this way, but we've found it easiest to manage. If you
|
||||
decide to download the repositories or clone them 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 gdnative_cpp_example
|
||||
git submodule update --init --recursive
|
||||
|
||||
This will clone these two repositories into 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, simply
|
||||
call the Godot executable:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
godot --gdnative-generate-json-api api.json
|
||||
|
||||
Place the resulting ``api.json`` file in the project folder and add
|
||||
``use_custom_api_file=yes custom_api_file=../api.json`` 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):
|
||||
|
||||
To speed up compilation, add `-jN` at the end of the SCons command line where `N`
|
||||
is the number of CPU threads you have on your system. The example below uses 4 threads.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
cd godot-cpp
|
||||
scons platform=<platform> generate_bindings=yes -j4
|
||||
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 GDNative module'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 GDNative 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 GDNative module.
|
||||
|
||||
In the ``src`` folder, we'll start with creating our header file for the
|
||||
GDNative node we'll be creating. We will name it ``gdexample.h``:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
#ifndef GDEXAMPLE_H
|
||||
#define GDEXAMPLE_H
|
||||
|
||||
#include <Godot.hpp>
|
||||
#include <Sprite2D.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class GDExample : public Sprite2D {
|
||||
GODOT_CLASS(GDExample, Sprite2D)
|
||||
|
||||
private:
|
||||
float time_passed;
|
||||
|
||||
public:
|
||||
static void _register_methods();
|
||||
|
||||
GDExample();
|
||||
~GDExample();
|
||||
|
||||
void _init(); // our initializer called by Godot
|
||||
|
||||
void _process(float delta);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
There are a few things of note to the above. We're including ``Godot.hpp`` which
|
||||
contains all our basic definitions. After that, 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 GDNative 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
|
||||
``GODOT_CLASS`` 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 obviously 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 ``_register_methods``, which is a static function that Godot will
|
||||
call to find out which methods can be called on our NativeScript 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. The
|
||||
third is our ``_init`` function which is called after Godot has properly set up
|
||||
our object.
|
||||
|
||||
.. warning::
|
||||
|
||||
The ``_init`` function has to exist even if you don't place any code in it.
|
||||
Otherwise, the class won't be instantiable.
|
||||
|
||||
Let's implement our functions by creating our ``gdexample.cpp`` file:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
#include "gdexample.h"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void GDExample::_register_methods() {
|
||||
register_method("_process", &GDExample::_process);
|
||||
}
|
||||
|
||||
GDExample::GDExample() {
|
||||
}
|
||||
|
||||
GDExample::~GDExample() {
|
||||
// add your cleanup here
|
||||
}
|
||||
|
||||
void GDExample::_init() {
|
||||
// initialize any variables here
|
||||
time_passed = 0.0;
|
||||
}
|
||||
|
||||
void GDExample::_process(float 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 that the ``register_method`` call
|
||||
**must** expose the ``_process`` method, otherwise Godot will not be able to use
|
||||
it. However, we do not have to tell Godot about our constructor, destructor and
|
||||
``_init`` functions.
|
||||
|
||||
The other method of note is 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. What stands out is calling
|
||||
``owner->set_position`` to call one of the built-in methods of our Sprite2D. This
|
||||
is because our class is a container class; ``owner`` points to the actual Sprite2D
|
||||
node our script relates to.
|
||||
|
||||
There is one more C++ file we need; we'll name it ``gdlibrary.cpp``. Our
|
||||
GDNative plugin can contain multiple NativeScripts, 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 NativeScripts in our
|
||||
GDNative plugin.
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
#include "gdexample.h"
|
||||
|
||||
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
|
||||
godot::Godot::gdnative_init(o);
|
||||
}
|
||||
|
||||
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
|
||||
godot::Godot::gdnative_terminate(o);
|
||||
}
|
||||
|
||||
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
|
||||
godot::Godot::nativescript_init(handle);
|
||||
|
||||
godot::register_class<godot::GDExample>();
|
||||
}
|
||||
|
||||
Note that we are not using the ``godot`` namespace here, since the three
|
||||
functions implemented here need to be defined without a namespace.
|
||||
|
||||
The ``godot_gdnative_init`` and ``godot_gdnative_terminate`` 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.
|
||||
|
||||
The important function is the third function called ``godot_nativescript_init``.
|
||||
We first call a function in our bindings library that does its usual stuff.
|
||||
After that, we call the function ``register_class`` for each of our classes in
|
||||
our library.
|
||||
|
||||
Compiling the plugin
|
||||
--------------------
|
||||
|
||||
We cannot easily write by hand a ``SConstruct`` file that SCons would use for
|
||||
building. For the purpose of this example, just use
|
||||
:download:`this hardcoded SConstruct file <files/cpp_example/SConstruct>` we've
|
||||
prepared. 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 3.0 documentation.
|
||||
|
||||
Once you've downloaded the ``SConstruct`` file, place it in your GDNative module
|
||||
folder besides ``godot-cpp``, ``src`` and ``demo``, then run:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
scons platform=<platform>
|
||||
|
||||
You should now be able to find the module in ``demo/bin/<platform>``.
|
||||
|
||||
.. 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=release`` switch.
|
||||
|
||||
Using the GDNative module
|
||||
-------------------------
|
||||
|
||||
Before we jump back into Godot, we need to create two more files in
|
||||
``demo/bin/``. Both can be created using the Godot editor, but it may be faster
|
||||
to create them directly.
|
||||
|
||||
The first one is a file that lets Godot know what dynamic libraries should be
|
||||
loaded for each platform and is called ``gdexample.gdnlib``.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[general]
|
||||
|
||||
singleton=false
|
||||
load_once=true
|
||||
symbol_prefix="godot_"
|
||||
reloadable=false
|
||||
|
||||
[entry]
|
||||
|
||||
Linux.64="res://bin/linux/libgdexample.so"
|
||||
Windows.64="res://bin/win64/libgdexample.dll"
|
||||
OSX.64="res://bin/osx/libgdexample.dylib"
|
||||
|
||||
[dependencies]
|
||||
|
||||
Linux.64=[]
|
||||
Windows.64=[]
|
||||
OSX.64=[]
|
||||
|
||||
This file contains a ``general`` section that controls how the module is loaded.
|
||||
It also contains a prefix section which should be left on ``godot_`` for now. If
|
||||
you change this, you'll need to rename various functions that are used as entry
|
||||
points. This was added for the iPhone platform because it doesn't allow dynamic
|
||||
libraries to be deployed, yet GDNative modules are linked statically.
|
||||
|
||||
The ``entry`` 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 GDNative
|
||||
plugin implements someone else's library and requires you to supply a
|
||||
third-party dynamic library with your project.
|
||||
|
||||
If you double click on the ``gdexample.gdnlib`` file within Godot, you'll see
|
||||
there are far more options to set:
|
||||
|
||||
.. image:: img/gdnative_library.png
|
||||
|
||||
The second file we need to create is a file used by each NativeScript we've
|
||||
added to our plugin. We'll name it ``gdexample.gdns`` for our gdexample
|
||||
NativeScript.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[gd_resource type="NativeScript" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://bin/gdexample.gdnlib" type="GDNativeLibrary" id=1]
|
||||
|
||||
[resource]
|
||||
|
||||
resource_name = "gdexample"
|
||||
class_name = "GDExample"
|
||||
library = ExtResource( 1 )
|
||||
|
||||
This is a standard Godot resource; you could just create it directly in your
|
||||
scene, but saving it to a file makes it much easier to reuse it in other places.
|
||||
This resource points to our gdnlib file, so that Godot can know which dynamic
|
||||
library contains our NativeScript. It also defines the ``class_name`` which
|
||||
identifies the NativeScript in our plugin we want to use.
|
||||
|
||||
Time to jump back into Godot. We load up the main scene we created way back in
|
||||
the beginning and now add a Sprite2D to our scene:
|
||||
|
||||
.. image:: img/gdnative_cpp_nodes.png
|
||||
|
||||
We're going to assign the Godot logo to this sprite as our texture, disable the
|
||||
``centered`` property and drag our ``gdexample.gdns`` file onto the ``script``
|
||||
property of the sprite:
|
||||
|
||||
.. image:: img/gdnative_cpp_sprite.png
|
||||
|
||||
We're finally ready to run the project:
|
||||
|
||||
.. image:: img/gdnative_cpp_animated.gif
|
||||
|
||||
Adding properties
|
||||
-----------------
|
||||
|
||||
GDScript allows you to add properties to your script using the ``export``
|
||||
keyword. In GDNative you have to register the properties and there are two ways
|
||||
of doing this. You can either bind directly to a member or use a setter and
|
||||
getter function.
|
||||
|
||||
.. note::
|
||||
|
||||
There is a third option, just like in GDScript you can directly implement the
|
||||
``_get_property_list``, ``_get`` and ``_set`` methods of an object but that
|
||||
goes far beyond the scope of this tutorial.
|
||||
|
||||
We'll examine both starting with the direct bind. Lets add a property that
|
||||
allows us to control the amplitude of our wave.
|
||||
|
||||
In our ``gdexample.h`` file we simply need to add a member variable like so:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
...
|
||||
private:
|
||||
float time_passed;
|
||||
float amplitude;
|
||||
...
|
||||
|
||||
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:: C++
|
||||
|
||||
void GDExample::_register_methods() {
|
||||
register_method("_process", &GDExample::_process);
|
||||
register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
|
||||
}
|
||||
|
||||
void GDExample::_init() {
|
||||
// initialize any variables here
|
||||
time_passed = 0.0;
|
||||
amplitude = 10.0;
|
||||
}
|
||||
|
||||
void GDExample::_process(float 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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``reloadable`` property in the ``gdexample.gdnlib`` file must be set to
|
||||
``true`` for the Godot editor to automatically pick up the newly added
|
||||
property.
|
||||
|
||||
However, this setting should be used with care, especially when tool classes
|
||||
are used, as the editor might hold objects then that have script instances
|
||||
attached to them that are managed by a GDNative library.
|
||||
|
||||
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:: C++
|
||||
|
||||
...
|
||||
float amplitude;
|
||||
float speed;
|
||||
...
|
||||
void _process(float delta);
|
||||
void set_speed(float p_speed);
|
||||
float get_speed();
|
||||
...
|
||||
|
||||
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:: C++
|
||||
|
||||
void GDExample::_register_methods() {
|
||||
register_method("_process", &GDExample::_process);
|
||||
register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
|
||||
register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);
|
||||
}
|
||||
|
||||
void GDExample::_init() {
|
||||
// initialize any variables here
|
||||
time_passed = 0.0;
|
||||
amplitude = 10.0;
|
||||
speed = 1.0;
|
||||
}
|
||||
|
||||
void GDExample::_process(float 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(float p_speed) {
|
||||
speed = p_speed;
|
||||
}
|
||||
|
||||
float GDExample::get_speed() {
|
||||
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.
|
||||
|
||||
For this example, there is no obvious advantage of using a setter and getter.
|
||||
A good reason for a setter would be if you wanted to react on the variable being changed.
|
||||
If you don't need to do something like that, binding the variable is enough.
|
||||
|
||||
Getters and setters become far more useful in more complex scenarios where you
|
||||
need to make additional choices based on the state of your object.
|
||||
|
||||
.. note::
|
||||
|
||||
For simplicity, we've left out the optional parameters in the
|
||||
register_property<class, type> method call. These parameters are
|
||||
``rpc_mode``, ``usage``, ``hint`` and ``hint_string``. These can be used to
|
||||
further configure how properties are displayed and set on the Godot side.
|
||||
|
||||
Modern C++ compilers are able to infer the class and variable type and allow
|
||||
you to omit the ``<GDExample, float>`` part of our ``register_property``
|
||||
method. We've had mixed experiences with this however.
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
Last but not least, signals fully work in GDNative as well. Having your module
|
||||
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:: C++
|
||||
|
||||
some_other_node->connect("the_signal", this, "my_method");
|
||||
|
||||
Note that you can only call ``my_method`` if you've previously registered it in
|
||||
your ``_register_methods`` method.
|
||||
|
||||
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:: C++
|
||||
|
||||
...
|
||||
float time_passed;
|
||||
float time_emit;
|
||||
float 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 ``_register_methods`` method, we need to declare our signal. This is done
|
||||
as follows:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
void GDExample::_register_methods() {
|
||||
register_method("_process", &GDExample::_process);
|
||||
register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
|
||||
register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);
|
||||
|
||||
register_signal<GDExample>((char *)"position_changed", "node", GODOT_VARIANT_TYPE_OBJECT, "new_pos", GODOT_VARIANT_TYPE_VECTOR2);
|
||||
}
|
||||
|
||||
Here, our ``register_signal`` method can be a single call first taking the
|
||||
signals name, then having pairs of values specifying the parameter name and
|
||||
type of each parameter we'll send along with this signal.
|
||||
|
||||
Next, we'll need to change our ``_process`` method:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
void GDExample::_process(float 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 GDNative 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.name + " 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++.
|
||||
|
||||
To edit and recompile the plugin while the Godot editor
|
||||
remains open, re-run the project after the library has finished building.
|
||||
|
Before Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 625 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 149 KiB |
@@ -1,10 +0,0 @@
|
||||
GDNative
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:name: toc-tutorials-gdnative
|
||||
|
||||
what_is_gdnative
|
||||
gdnative_c_example
|
||||
gdnative_cpp_example
|
||||
@@ -1,106 +0,0 @@
|
||||
.. _doc_what_is_gdnative:
|
||||
|
||||
What is GDNative?
|
||||
=================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
**GDNative** is a Godot-specific technology that lets the engine interact with
|
||||
native `shared libraries <https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries>`__
|
||||
at run-time. You can use it to run native code without compiling it with the engine.
|
||||
|
||||
.. note:: GDNative is *not* a scripting language and has no relation to
|
||||
:ref:`GDScript <doc_gdscript>`.
|
||||
|
||||
Differences between GDNative and C++ modules
|
||||
--------------------------------------------
|
||||
|
||||
You can use both GDNative and :ref:`C++ modules <doc_custom_modules_in_c++>` 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.
|
||||
|
||||
Advantages of GDNative
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Unlike modules, GDNative 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 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:
|
||||
|
||||
- GDNative 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 GDNative 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 run-time.
|
||||
- GDNative 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 GDNative.
|
||||
|
||||
Advantages of C++ modules
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
We recommend :ref:`C++ modules <doc_custom_modules_in_c++>` in cases where
|
||||
GDNative isn't enough:
|
||||
|
||||
- C++ modules provide deeper integration into the engine. GDNative's access is
|
||||
limited to what the scripting API exposes.
|
||||
- You can use C++ modules to provide additional features in a project without
|
||||
carrying native library files around. This extends to exported projects.
|
||||
- C++ modules are supported on all platforms. In contrast, GDNative has only
|
||||
limited support on HTML5 (cannot be used together with multi-threading), and
|
||||
is not supported on Universal Windows Platform (UWP).
|
||||
- C++ modules can be faster than GDNative, especially when the code requires a
|
||||
lot of communication through the scripting API.
|
||||
|
||||
Supported languages
|
||||
-------------------
|
||||
|
||||
The Godot developers officially support the following language bindings for
|
||||
GDNative:
|
||||
|
||||
- C++ :ref:`(tutorial) <doc_gdnative_cpp_example>`
|
||||
- C :ref:`(tutorial) <doc_gdnative_c_example>`
|
||||
|
||||
.. note::
|
||||
|
||||
There are no plans to support additional languages with GDNative 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-d/godot-d>`__
|
||||
- `Kotlin <https://github.com/utopia-rise/godot-kotlin-jvm>`__
|
||||
- `Nim <https://github.com/pragmagic/godot-nim>`__
|
||||
- `Python <https://github.com/touilleMan/godot-python>`__
|
||||
- `Rust <https://github.com/godot-rust/godot-rust>`__
|
||||
|
||||
.. 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.
|
||||
|
||||
Version compatibility
|
||||
---------------------
|
||||
|
||||
:ref:`Unlike Godot itself <doc_release_policy>`, GDNative has stricter version
|
||||
compatibility requirements as it relies on low-level *ptrcalls* to function.
|
||||
|
||||
GDNative add-ons compiled for a given Godot version are only guaranteed to work
|
||||
with the same minor release series. For example, a GDNative add-on compiled for
|
||||
Godot 3.4 will only work with Godot 3.4, 3.4.1, 3.4.2… but not Godot 3.3 or 3.5.
|
||||
@@ -11,8 +11,7 @@ sections. For instance, to learn about inputs, we recommend you to read
|
||||
Programming languages
|
||||
---------------------
|
||||
|
||||
The sections below each focus on a given programming language or, in GDNative's
|
||||
case, an interface that works with multiple languages.
|
||||
The sections below each focus on a given programming language.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
@@ -20,7 +19,6 @@ case, an interface that works with multiple languages.
|
||||
|
||||
gdscript/index
|
||||
c_sharp/index
|
||||
gdnative/index
|
||||
|
||||
Core features
|
||||
-------------
|
||||
|
||||
@@ -856,10 +856,6 @@ A large number of built-in functions are supported, conforming to GLSL ES 3.0.
|
||||
When vec_type (float), vec_int_type, vec_uint_type, vec_bool_type nomenclature
|
||||
is used, it can be scalar or vector.
|
||||
|
||||
.. note:: For a list of the functions that are not available in the GLES2
|
||||
backend, please see the :ref:`Differences between GLES2 and GLES3 doc
|
||||
<doc_gles2_gles3_differences>`.
|
||||
|
||||
+-----------------------------------------------------------------------------+---------------------------------------------------------------------+
|
||||
| Function | Description / Return value |
|
||||
+=============================================================================+=====================================================================+
|
||||
|
||||