Remove inaccessible languages.

This commit is contained in:
Relintai 2022-09-10 13:24:12 +02:00
parent e69f2592ef
commit 5bf8471893
91 changed files with 0 additions and 3496 deletions

View File

@ -1,320 +0,0 @@
.. _doc_c_sharp:
C# basics
=========
Introduction
------------
.. warning:: C# support is a new feature available since Godot 3.0.
As such, you may still run into some issues, or find spots
where the documentation could be improved.
Please report issues with C# in Godot on the
`engine GitHub page <https://github.com/godotengine/godot/issues>`_,
and any documentation issues on the
`documentation GitHub page <https://github.com/godotengine/godot-docs/issues>`_.
This page provides a brief introduction to C#, both what it is and
how to use it in Godot. Afterwards, you may want to look at
:ref:`how to use specific features <doc_c_sharp_features>`, read about the
:ref:`differences between the C# and the GDScript API <doc_c_sharp_differences>`
and (re)visit the :ref:`Scripting section <doc_scripting>` of the
step-by-step tutorial.
C# is a high-level programming language developed by Microsoft. In Godot,
it is implemented with the Mono 6.x .NET framework, including full support
for C# 8.0. Mono is an open source implementation of Microsoft's .NET Framework
based on the ECMA standards for C# and the Common Language Runtime.
A good starting point for checking its capabilities is the
`Compatibility <http://www.mono-project.com/docs/about-mono/compatibility/>`_
page in the Mono documentation.
.. note:: This is **not** a full-scale tutorial on the C# language as a whole.
If you aren't already familiar with its syntax or features,
see the
`Microsoft C# guide <https://docs.microsoft.com/en-us/dotnet/csharp/index>`_
or look for a suitable introduction elsewhere.
.. _doc_c_sharp_setup:
Setting up C# for Godot
-----------------------
Prerequisites
~~~~~~~~~~~~~
Install the latest stable version of the
`.NET SDK <https://dotnet.microsoft.com/download>`__, previously known as the
.NET Core SDK.
From Godot 3.2.3 onwards, installing Mono SDK is not a requirement anymore,
except it is required if you are building the engine from source.
Godot bundles the parts of Mono needed to run already compiled games.
However, Godot does not bundle the tools required to build and compile
games, such as MSBuild and the C# compiler. These are
included in the .NET SDK, which needs to be installed separately.
In summary, you must have installed the .NET SDK
**and** the Mono-enabled version of Godot.
Additional notes
~~~~~~~~~~~~~~~~
Be sure to install the 64-bit version of the SDK(s)
if you are using the 64-bit version of Godot.
If you are building Godot from source, install the latest stable version of
`Mono <https://www.mono-project.com/download/stable/>`__, and make sure to
follow the steps to enable Mono support in your build as outlined in the
:ref:`doc_compiling_with_mono` page.
Configuring an external editor
------------------------------
C# support in Godot's built-in script editor is minimal. Consider using an
external IDE or editor, such as `Visual Studio Code <https://code.visualstudio.com/>`__
or MonoDevelop. These provide autocompletion, debugging, and other
useful features for C#. To select an external editor in Godot,
click on **Editor → Editor Settings** and scroll down to
**Mono**. Under **Mono**, click on **Editor**, and select your
external editor of choice. Godot currently supports the following
external editors:
- Visual Studio 2019
- Visual Studio Code
- MonoDevelop
- Visual Studio for Mac
- JetBrains Rider
See the following sections for how to configure an external editor:
JetBrains Rider
~~~~~~~~~~~~~~~
After reading the "Prerequisites" section, you can download and install
`JetBrains Rider <https://www.jetbrains.com/rider/download>`__.
In Godot's **Editor → Editor Settings** menu:
- Set **Mono** -> **Editor** -> **External Editor** to **JetBrains Rider**.
- Set **Mono** -> **Builds** -> **Build Tool** to **dotnet CLI**.
In Rider:
- Set **MSBuild version** to **.NET Core**.
- Install the **Godot support** plugin.
Visual Studio Code
~~~~~~~~~~~~~~~~~~
After reading the "Prerequisites" section, you can download and install
`Visual Studio Code <https://code.visualstudio.com/download>`__ (aka VS Code).
In Godot's **Editor → Editor Settings** menu:
- Set **Mono** -> **Editor** -> **External Editor** to **Visual Studio Code**.
- Set **Mono** -> **Builds** -> **Build Tool** to **dotnet CLI**.
In Visual Studio Code:
- Install the `C# <https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp>`__ extension.
- Install the `Mono Debug <https://marketplace.visualstudio.com/items?itemName=ms-vscode.mono-debug>`__ extension.
- Install the `C# Tools for Godot <https://marketplace.visualstudio.com/items?itemName=neikeq.godot-csharp-vscode>`__ extension.
.. note:: If you are using Linux you need to install the
`Mono SDK <https://www.mono-project.com/download/stable/#download-lin>`__
for the C# tools plugin to work.
To configure a project for debugging open the Godot project folder in VS Code.
Go to the Run tab and click on **Add Configuration...**. Select **C# Godot**
from the dropdown menu. Open the ``tasks.json`` and ``launch.json`` files that
were created. Change the executable setting in ``launch.json`` and command
settings in ``tasks.json`` to your Godot executable path. Now, when you start
the debugger in VS Code, your Godot project will run.
Visual Studio (Windows only)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Download and install the latest version of
`Visual Studio <https://visualstudio.microsoft.com/downloads/>`__.
Visual Studio will include the required SDKs if you have the correct
workloads selected, so you don't need to manually install the things
listed in the "Prerequisites" section.
While installing Visual Studio, select these workloads:
- Mobile development with .NET
- .NET Core cross-platform development
In Godot's **Editor → Editor Settings** menu:
- Set **Mono** -> **Editor** -> **External Editor** to **Visual Studio**.
- Set **Mono** -> **Builds** -> **Build Tool** to **dotnet CLI**.
Next, you can download the Godot Visual Studio extension from github
`here <https://github.com/godotengine/godot-csharp-visualstudio/releases>`__.
Double click on the downloaded file and follow the installation process.
.. note:: The option to debug your game in Visual Studio may not appear after
installing the extension. To enable debugging, there is a
`workaround for Visual Studio 2019 <https://github.com/godotengine/godot-csharp-visualstudio/issues/10#issuecomment-720153256>`__.
There is
`a separate issue about this problem in Visual Studio 2022 <https://github.com/godotengine/godot-csharp-visualstudio/issues/28>`__.
.. note:: If you see an error like "Unable to find package Godot.NET.Sdk",
your NuGet configuration may be incorrect and need to be fixed.
A simple way to fix the NuGet configuration file is to regenerate it.
In a file explorer window, go to ``%AppData%\NuGet``. Rename or delete
the ``NuGet.Config`` file. When you build your Godot project again,
the file will be automatically created with default values.
Creating a C# script
--------------------
After you successfully set up C# for Godot, you should see the following option
when selecting **Attach Script** in the context menu of a node in your scene:
.. image:: img/attachcsharpscript.png
Note that while some specifics change, most concepts work the same
when using C# for scripting. If you're new to Godot, you may want to follow
the tutorials on :ref:`doc_scripting` at this point.
While some places in the documentation still lack C# examples, most concepts
can be transferred easily from GDScript.
Project setup and workflow
--------------------------
When you create the first C# script, Godot initializes the C# project files
for your Godot project. This includes generating a C# solution (``.sln``)
and a project file (``.csproj``), as well as some utility files and folders
(``.mono`` and ``Properties/AssemblyInfo.cs``).
All of these but ``.mono`` are important and should be committed to your
version control system. ``.mono`` can be safely added to the ignore list of your VCS.
When troubleshooting, it can sometimes help to delete the ``.mono`` folder
and let it regenerate.
Example
-------
Here's a blank C# script with some comments to demonstrate how it works.
.. code-block:: csharp
using Godot;
using System;
public class YourCustomClass : Node
{
// Member variables here, example:
private int a = 2;
private string b = "textvar";
public override void _Ready()
{
// Called every time the node is added to the scene.
// Initialization here.
GD.Print("Hello from C# to Godot :)");
}
public override void _Process(float delta)
{
// Called every frame. Delta is time since the last frame.
// Update game logic here.
}
}
As you can see, functions normally in global scope in GDScript like Godot's
``print`` function are available in the ``GD`` class which is part of
the ``Godot`` namespace. For a list of methods in the ``GD`` class, see the
class reference pages for
:ref:`@GDScript <class_@gdscript>` and :ref:`@GlobalScope <class_@globalscope>`.
.. note::
Keep in mind that the class you wish to attach to your node should have the same
name as the ``.cs`` file. Otherwise, you will get the following error
and won't be able to run the scene:
*"Cannot find class XXX for script res://XXX.cs"*
General differences between C# and GDScript
-------------------------------------------
The C# API uses ``PascalCase`` instead of ``snake_case`` in GDScript/C++.
Where possible, fields and getters/setters have been converted to properties.
In general, the C# Godot API strives to be as idiomatic as is reasonably possible.
For more information, see the :ref:`doc_c_sharp_differences` page.
.. warning::
You need to (re)build the project assemblies whenever you want to see new
exported variables or signals in the editor. This build can be manually
triggered by clicking the word **Build** in the top right corner of the
editor. You can also click **Mono** at the bottom of the editor window
to reveal the Mono panel, then click the **Build Project** button.
You will also need to rebuild the project assemblies to apply changes in
"tool" scripts.
Current gotchas and known issues
--------------------------------
As C# support is quite new in Godot, there are some growing pains and things
that need to be ironed out. Below is a list of the most important issues
you should be aware of when diving into C# in Godot, but if in doubt, also
take a look over the official
`issue tracker for Mono issues <https://github.com/godotengine/godot/labels/topic%3Amono>`_.
- Writing editor plugins is possible, but it is currently quite convoluted.
- State is currently not saved and restored when hot-reloading,
with the exception of exported variables.
- Attached C# scripts should refer to a class that has a class name
that matches the file name.
- There are some methods such as ``Get()``/``Set()``, ``Call()``/``CallDeferred()``
and signal connection method ``Connect()`` that rely on Godot's ``snake_case`` API
naming conventions.
So when using e.g. ``CallDeferred("AddChild")``, ``AddChild`` will not work because
the API is expecting the original ``snake_case`` version ``add_child``. However, you
can use any custom properties or methods without this limitation.
Exporting Mono projects is supported for desktop platforms (Linux, Windows and
macOS), Android, HTML5, and iOS. The only platform not supported yet is UWP.
Performance of C# in Godot
--------------------------
According to some preliminary `benchmarks <https://github.com/cart/godot3-bunnymark>`_,
the performance of C# in Godot — while generally in the same order of magnitude
— is roughly **~4×** that of GDScript in some naive cases. C++ is still
a little faster; the specifics are going to vary according to your use case.
GDScript is likely fast enough for most general scripting workloads.
C# is faster, but requires some expensive marshalling when talking to Godot.
Using NuGet packages in Godot
-----------------------------
`NuGet <https://www.nuget.org/>`_ packages can be installed and used with Godot,
as with any C# project. Many IDEs are able to add packages directly.
They can also be added manually by adding the package reference in
the ``.csproj`` file located in the project root:
.. code-block:: xml
:emphasize-lines: 2
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
...
</Project>
As of Godot 3.2.3, Godot automatically downloads and sets up newly added NuGet
packages the next time it builds the project.
Profiling your C# code
----------------------
- `Mono log profiler <https://www.mono-project.com/docs/debug+profile/profile/profiler/>`_ is available for Linux and macOS. Due to a Mono change, it does not work on Windows currently.
- External Mono profiler like `JetBrains dotTrace <https://www.jetbrains.com/profiler/>`_ can be used as described `here <https://github.com/godotengine/godot/pull/34382>`_.

View File

@ -1,358 +0,0 @@
.. _doc_c_sharp_differences:
C# API differences to GDScript
==============================
This is a (incomplete) list of API differences between C# and GDScript.
General differences
-------------------
As explained in the :ref:`doc_c_sharp`, C# generally uses ``PascalCase`` instead
of the ``snake_case`` used in GDScript and C++.
Global scope
------------
Global functions and some constants had to be moved to classes, since C#
does not allow declaring them in namespaces.
Most global constants were moved to their own enums.
Constants
^^^^^^^^^
Global constants were moved to their own enums.
For example, ``ERR_*`` constants were moved to the ``Error`` enum.
Special cases:
======================= ===========================================================
GDScript C#
======================= ===========================================================
``SPKEY`` ``GD.SpKey``
``TYPE_*`` ``Variant.Type`` enum
``OP_*`` ``Variant.Operator`` enum
======================= ===========================================================
Math functions
^^^^^^^^^^^^^^
Math global functions, like ``abs``, ``acos``, ``asin``, ``atan`` and ``atan2``, are
located under ``Mathf`` as ``Abs``, ``Acos``, ``Asin``, ``Atan`` and ``Atan2``.
The ``PI`` constant can be found as ``Mathf.Pi``.
Random functions
^^^^^^^^^^^^^^^^
Random global functions, like ``rand_range`` and ``rand_seed``, are located under ``GD``.
Example: ``GD.RandRange`` and ``GD.RandSeed``.
Other functions
^^^^^^^^^^^^^^^
Many other global functions like ``print`` and ``var2str`` are located under ``GD``.
Example: ``GD.Print`` and ``GD.Var2Str``.
Exceptions:
=========================== =======================================================
GDScript C#
=========================== =======================================================
``weakref(obj)`` ``Object.WeakRef(obj)``
``is_instance_valid(obj)`` ``Object.IsInstanceValid(obj)``
=========================== =======================================================
Tips
^^^^
Sometimes it can be useful to use the ``using static`` directive. This directive allows
to access the members and nested types of a class without specifying the class name.
Example:
.. code-block:: csharp
using static Godot.GD;
public class Test
{
static Test()
{
Print("Hello"); // Instead of GD.Print("Hello");
}
}
Export keyword
--------------
Use the ``[Export]`` attribute instead of the GDScript ``export`` keyword.
This attribute can also be provided with optional :ref:`PropertyHint<enum_@GlobalScope_PropertyHint>` and ``hintString`` parameters.
Default values can be set by assigning a value.
Example:
.. code-block:: csharp
using Godot;
public class MyNode : Node
{
[Export]
private NodePath _nodePath;
[Export]
private string _name = "default";
[Export(PropertyHint.Range, "0,100000,1000,or_greater")]
private int _income;
[Export(PropertyHint.File, "*.png,*.jpg")]
private string _icon;
}
Signal keyword
--------------
Use the ``[Signal]`` attribute to declare a signal instead of the GDScript ``signal`` keyword.
This attribute should be used on a `delegate`, whose name signature will be used to define the signal.
.. code-block:: csharp
[Signal]
delegate void MySignal(string willSendsAString);
See also: :ref:`doc_c_sharp_signals`.
`onready` keyword
-----------------
GDScript has the ability to defer the initialization of a member variable until the ready function
is called with `onready` (cf. :ref:`doc_gdscript_onready_keyword`).
For example:
.. code-block:: gdscript
onready var my_label = get_node("MyLabel")
However C# does not have this ability. To achieve the same effect you need to do this.
.. code-block:: csharp
private Label _myLabel;
public override void _Ready()
{
_myLabel = GetNode<Label>("MyLabel");
}
Singletons
----------
Singletons are available as static classes rather than using the singleton pattern.
This is to make code less verbose than it would be with an ``Instance`` property.
Example:
.. code-block:: csharp
Input.IsActionPressed("ui_down")
However, in some very rare cases this is not enough. For example, you may want
to access a member from the base class ``Godot.Object``, like ``Connect``.
For such use cases we provide a static property named ``Singleton`` that returns
the singleton instance. The type of this instance is ``Godot.Object``.
Example:
.. code-block:: csharp
Input.Singleton.Connect("joy_connection_changed", this, nameof(Input_JoyConnectionChanged));
String
------
Use ``System.String`` (``string``). Most of Godot's String methods are
provided by the ``StringExtensions`` class as extension methods.
Example:
.. code-block:: csharp
string upper = "I LIKE SALAD FORKS";
string lower = upper.ToLower();
There are a few differences, though:
* ``erase``: Strings are immutable in C#, so we cannot modify the string
passed to the extension method. For this reason, ``Erase`` was added as an
extension method of ``StringBuilder`` instead of string.
Alternatively, you can use ``string.Remove``.
* ``IsSubsequenceOf``/``IsSubsequenceOfi``: An additional method is provided,
which is an overload of ``IsSubsequenceOf``, allowing you to explicitly specify
case sensitivity:
.. code-block:: csharp
str.IsSubsequenceOf("ok"); // Case sensitive
str.IsSubsequenceOf("ok", true); // Case sensitive
str.IsSubsequenceOfi("ok"); // Case insensitive
str.IsSubsequenceOf("ok", false); // Case insensitive
* ``Match``/``Matchn``/``ExprMatch``: An additional method is provided besides
``Match`` and ``Matchn``, which allows you to explicitly specify case sensitivity:
.. code-block:: csharp
str.Match("*.txt"); // Case sensitive
str.ExprMatch("*.txt", true); // Case sensitive
str.Matchn("*.txt"); // Case insensitive
str.ExprMatch("*.txt", false); // Case insensitive
Basis
-----
Structs cannot have parameterless constructors in C#. Therefore, ``new Basis()``
initializes all primitive members to their default value. Use ``Basis.Identity``
for the equivalent of ``Basis()`` in GDScript and C++.
The following method was converted to a property with a different name:
==================== ==============================================================
GDScript C#
==================== ==============================================================
``get_scale()`` ``Scale``
==================== ==============================================================
Transform2D
-----------
Structs cannot have parameterless constructors in C#. Therefore, ``new Transform2D()``
initializes all primitive members to their default value.
Please use ``Transform2D.Identity`` for the equivalent of ``Transform2D()`` in GDScript and C++.
The following methods were converted to properties with their respective names changed:
==================== ==============================================================
GDScript C#
==================== ==============================================================
``get_rotation()`` ``Rotation``
``get_scale()`` ``Scale``
==================== ==============================================================
Plane
-----
The following method was converted to a property with a *slightly* different name:
================ ==================================================================
GDScript C#
================ ==================================================================
``center()`` ``Center``
================ ==================================================================
Rect2
-----
The following field was converted to a property with a *slightly* different name:
================ ==================================================================
GDScript C#
================ ==================================================================
``end`` ``End``
================ ==================================================================
The following method was converted to a property with a different name:
================ ==================================================================
GDScript C#
================ ==================================================================
``get_area()`` ``Area``
================ ==================================================================
Quat
----
Structs cannot have parameterless constructors in C#. Therefore, ``new Quat()``
initializes all primitive members to their default value.
Please use ``Quat.Identity`` for the equivalent of ``Quat()`` in GDScript and C++.
The following methods were converted to a property with a different name:
===================== =============================================================
GDScript C#
===================== =============================================================
``length()`` ``Length``
``length_squared()`` ``LengthSquared``
===================== =============================================================
Array
-----
*This is temporary. PoolArrays will need their own types to be used the way they are meant to.*
===================== ==============================================================
GDScript C#
===================== ==============================================================
``Array`` ``Godot.Collections.Array``
``PoolIntArray`` ``int[]``
``PoolByteArray`` ``byte[]``
``PoolFloatArray`` ``float[]``
``PoolStringArray`` ``String[]``
``PoolColorArray`` ``Color[]``
``PoolVector2Array`` ``Vector2[]``
``PoolVector3Array`` ``Vector3[]``
===================== ==============================================================
``Godot.Collections.Array<T>`` is a type-safe wrapper around ``Godot.Collections.Array``.
Use the ``Godot.Collections.Array<T>(Godot.Collections.Array)`` constructor to create one.
Dictionary
----------
Use ``Godot.Collections.Dictionary``.
``Godot.Collections.Dictionary<T>`` is a type-safe wrapper around ``Godot.Collections.Dictionary``.
Use the ``Godot.Collections.Dictionary<T>(Godot.Collections.Dictionary)`` constructor to create one.
Variant
-------
``System.Object`` (``object``) is used instead of ``Variant``.
Communicating with other scripting languages
--------------------------------------------
This is explained extensively in :ref:`doc_cross_language_scripting`.
Yield
-----
Something similar to GDScript's ``yield`` with a single parameter can be achieved with
C#'s `yield keyword <https://docs.microsoft.com/en-US/dotnet/csharp/language-reference/keywords/yield>`_.
The equivalent of yield on signal can be achieved with async/await and ``Godot.Object.ToSignal``.
Example:
.. code-block:: csharp
await ToSignal(timer, "timeout");
GD.Print("After timeout");
Other differences
-----------------
``preload``, as it works in GDScript, is not available in C#.
Use ``GD.Load`` or ``ResourceLoader.Load`` instead.
Other differences:
================ ==================================================================
GDScript C#
================ ==================================================================
``Color8`` ``Color.Color8``
``is_inf`` ``float.IsInfinity``
``is_nan`` ``float.IsNaN``
``dict2inst`` TODO
``inst2dict`` TODO
================ ==================================================================

View File

@ -1,245 +0,0 @@
.. _doc_c_sharp_features:
C# features
===========
This page provides an overview of the commonly used features of both C# and Godot
and how they are used together.
.. _doc_c_sharp_features_type_conversion_and_casting:
Type conversion and casting
---------------------------
C# is a statically typed language. Therefore, you can't do the following:
.. code-block:: csharp
var mySprite = GetNode("MySprite");
mySprite.SetFrame(0);
The method ``GetNode()`` returns a ``Node`` instance.
You must explicitly convert it to the desired derived type, ``Sprite`` in this case.
For this, you have various options in C#.
**Casting and Type Checking**
Throws ``InvalidCastException`` if the returned node cannot be cast to Sprite.
You would use it instead of the ``as`` operator if you are pretty sure it won't fail.
.. code-block:: csharp
Sprite mySprite = (Sprite)GetNode("MySprite");
mySprite.SetFrame(0);
**Using the AS operator**
The ``as`` operator returns ``null`` if the node cannot be cast to Sprite,
and for that reason, it cannot be used with value types.
.. code-block:: csharp
Sprite mySprite = GetNode("MySprite") as Sprite;
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);
**Using the generic methods**
Generic methods are also provided to make this type conversion transparent.
``GetNode<T>()`` casts the node before returning it. It will throw an ``InvalidCastException`` if the node cannot be cast to the desired type.
.. code-block:: csharp
Sprite mySprite = GetNode<Sprite>("MySprite");
mySprite.SetFrame(0);
``GetNodeOrNull<T>()`` uses the ``as`` operator and will return ``null`` if the node cannot be cast to the desired type.
.. code-block:: csharp
Sprite mySprite = GetNodeOrNull<Sprite>("MySprite");
// Only call SetFrame() if mySprite is not null
mySprite?.SetFrame(0);
**Type checking using the IS operator**
To check if the node can be cast to Sprite, you can use the ``is`` operator.
The ``is`` operator returns false if the node cannot be cast to Sprite,
otherwise it returns true.
.. code-block:: csharp
if (GetNode("MySprite") is Sprite)
{
// Yup, it's a sprite!
}
For more advanced type checking, you can look into `Pattern Matching <https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching>`_.
.. _doc_c_sharp_signals:
C# signals
----------
For a complete C# example, see the **Handling a signal** section in the step by step :ref:`doc_scripting` tutorial.
Declaring a signal in C# is done with the ``[Signal]`` attribute on a delegate.
.. code-block:: csharp
[Signal]
delegate void MySignal();
[Signal]
delegate void MySignalWithArguments(string foo, int bar);
These signals can then be connected either in the editor or from code with ``Connect``.
If you want to connect a signal in the editor, you need to (re)build the project assemblies to see the new signal. This build can be manually triggered by clicking the “Build” button at the top right corner of the editor window.
.. code-block:: csharp
public void MyCallback()
{
GD.Print("My callback!");
}
public void MyCallbackWithArguments(string foo, int bar)
{
GD.Print("My callback with: ", foo, " and ", bar, "!");
}
public void SomeFunction()
{
instance.Connect("MySignal", this, "MyCallback");
instance.Connect(nameof(MySignalWithArguments), this, "MyCallbackWithArguments");
}
Emitting signals is done with the ``EmitSignal`` method.
.. code-block:: csharp
public void SomeFunction()
{
EmitSignal(nameof(MySignal));
EmitSignal("MySignalWithArguments", "hello there", 28);
}
Notice that you can always reference a signal name with the ``nameof`` keyword (applied on the delegate itself).
It is possible to bind values when establishing a connection by passing a Godot array.
.. code-block:: csharp
public int Value { get; private set; } = 0;
private void ModifyValue(int modifier)
{
Value += modifier;
}
public void SomeFunction()
{
var plusButton = (Button)GetNode("PlusButton");
var minusButton = (Button)GetNode("MinusButton");
plusButton.Connect("pressed", this, "ModifyValue", new Godot.Collections.Array { 1 });
minusButton.Connect("pressed", this, "ModifyValue", new Godot.Collections.Array { -1 });
}
Signals support parameters and bound values of all the `built-in types <https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/built-in-types-table>`_ and Classes derived from :ref:`Godot.Object <class_Object>`.
Consequently, any ``Node`` or ``Reference`` will be compatible automatically, but custom data objects will need to extend from `Godot.Object` or one of its subclasses.
.. code-block:: csharp
public class DataObject : Godot.Object
{
public string Field1 { get; set; }
public string Field2 { get; set; }
}
Finally, signals can be created by calling ``AddUserSignal``, but be aware that it should be executed before any use of said signals (with ``Connect`` or ``EmitSignal``).
.. code-block:: csharp
public void SomeFunction()
{
AddUserSignal("MyOtherSignal");
EmitSignal("MyOtherSignal");
}
Preprocessor defines
--------------------
Godot has a set of defines that allow you to change your C# code
depending on the environment you are compiling to.
.. note:: If you created your project before Godot 3.2, you have to modify
or regenerate your `csproj` file to use this feature
(compare ``<DefineConstants>`` with a new 3.2+ project).
Examples
~~~~~~~~
For example, you can change code based on the platform:
.. code-block:: csharp
public override void _Ready()
{
#if GODOT_SERVER
// Don't try to load meshes or anything, this is a server!
LaunchServer();
#elif GODOT_32 || GODOT_MOBILE || GODOT_WEB
// Use simple objects when running on less powerful systems.
SpawnSimpleObjects();
#else
SpawnComplexObjects();
#endif
}
Or you can detect which engine your code is in, useful for making cross-engine libraries:
.. code-block:: csharp
public void MyPlatformPrinter()
{
#if GODOT
GD.Print("This is Godot.");
#elif UNITY_5_3_OR_NEWER
print("This is Unity.");
#else
throw new InvalidWorkflowException("Only Godot and Unity are supported.");
#endif
}
Full list of defines
~~~~~~~~~~~~~~~~~~~~
* ``GODOT`` is always defined for Godot projects.
* One of ``GODOT_64`` or ``GODOT_32`` is defined depending on if the architecture is 64-bit or 32-bit.
* One of ``GODOT_X11``, ``GODOT_WINDOWS``, ``GODOT_OSX``,
``GODOT_ANDROID``, ``GODOT_IOS``, ``GODOT_HTML5``, or ``GODOT_SERVER``
depending on the OS. These names may change in the future.
These are created from the ``get_name()`` method of the
:ref:`OS <class_OS>` singleton, but not every possible OS
the method returns is an OS that Godot with Mono runs on.
When **exporting**, the following may also be defined depending on the export features:
* One of ``GODOT_PC``, ``GODOT_MOBILE``, or ``GODOT_WEB`` depending on the platform type.
* One of ``GODOT_ARM64_V8A`` or ``GODOT_ARMEABI_V7A`` on Android only depending on the architecture.
* One of ``GODOT_ARM64`` or ``GODOT_ARMV7`` on iOS only depending on the architecture.
* Any of ``GODOT_S3TC``, ``GODOT_ETC``, and ``GODOT_ETC2`` depending on the texture compression type.
* Any custom features added in the export menu will be capitalized and prefixed: ``foo`` -> ``GODOT_FOO``.
To see an example project, see the OS testing demo:
https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test

View File

@ -1,324 +0,0 @@
.. _doc_c_sharp_styleguide:
C# style guide
==============
Having well-defined and consistent coding conventions is important for every project, and Godot
is no exception to this rule.
This page contains a coding style guide, which is followed by developers of and contributors to Godot
itself. As such, it is mainly intended for those who want to contribute to the project, but since
the conventions and guidelines mentioned in this article are those most widely adopted by the users
of the language, we encourage you to do the same, especially if you do not have such a guide yet.
.. note:: This article is by no means an exhaustive guide on how to follow the standard coding
conventions or best practices. If you feel unsure of an aspect which is not covered here,
please refer to more comprehensive documentation, such as
`C# Coding Conventions <https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions>`_ or
`Framework Design Guidelines <https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines>`_.
Language specification
----------------------
Godot currently uses **C# version 7.0** in its engine and example source code. So, before we move to
a newer version, care must be taken to avoid mixing language features only available in C# 7.1 or
later.
For detailed information on C# features in different versions, please see
`What's New in C# <https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/>`_.
Formatting
----------
General guidelines
~~~~~~~~~~~~~~~~~~
* Use line feed (**LF**) characters to break lines, not CRLF or CR.
* Use one line feed character at the end of each file, except for `csproj` files.
* Use **UTF-8** encoding without a `byte order mark <https://en.wikipedia.org/wiki/Byte_order_mark>`_.
* Use **4 spaces** instead of tabs for indentation (which is referred to as "soft tabs").
* Consider breaking a line into several if it's longer than 100 characters.
Line breaks and blank lines
~~~~~~~~~~~~~~~~~~~~~~~~~~~
For a general indentation rule, follow `the "Allman Style" <https://en.wikipedia.org/wiki/Indentation_style#Allman_style>`_
which recommends placing the brace associated with a control statement on the next line, indented to
the same level:
.. code-block:: csharp
// Use this style:
if (x > 0)
{
DoSomething();
}
// NOT this:
if (x > 0) {
DoSomething();
}
However, you may choose to omit line breaks inside brackets:
* For simple property accessors.
* For simple object, array, or collection initializers.
* For abstract auto property, indexer, or event declarations.
.. code-block:: csharp
// You may put the brackets in a single line in following cases:
public interface MyInterface
{
int MyProperty { get; set; }
}
public class MyClass : ParentClass
{
public int Value
{
get { return 0; }
set
{
ArrayValue = new [] {value};
}
}
}
Insert a blank line:
* After a list of ``using`` statements.
* Between method, properties, and inner type declarations.
* At the end of each file.
Field and constant declarations can be grouped together according to relevance. In that case, consider
inserting a blank line between the groups for easier reading.
Avoid inserting a blank line:
* After ``{``, the opening brace.
* Before ``}``, the closing brace.
* After a comment block or a single-line comment.
* Adjacent to another blank line.
.. code-block:: csharp
using System;
using Godot;
// Blank line after `using` list.
public class MyClass
{ // No blank line after `{`.
public enum MyEnum
{
Value,
AnotherValue // No blank line before `}`.
}
// Blank line around inner types.
public const int SomeConstant = 1;
public const int AnotherConstant = 2;
private Vector3 _x; // Related constants or fields can be
private Vector3 _y; // grouped together.
private float _width;
private float _height;
public int MyProperty { get; set; }
// Blank line around properties.
public void MyMethod()
{
// Some comment.
AnotherMethod(); // No blank line after a comment.
}
// Blank line around methods.
public void AnotherMethod()
{
}
}
Using spaces
~~~~~~~~~~~~
Insert a space:
* Around a binary and tertiary operator.
* Between an opening parenthesis and ``if``, ``for``, ``foreach``, ``catch``, ``while``, ``lock`` or ``using`` keywords.
* Before and within a single line accessor block.
* Between accessors in a single line accessor block.
* After a comma which is not at the end of a line.
* After a semicolon in a ``for`` statement.
* After a colon in a single line ``case`` statement.
* Around a colon in a type declaration.
* Around a lambda arrow.
* After a single-line comment symbol (``//``), and before it if used at the end of a line.
Do not use a space:
* After type cast parentheses.
* Within single line initializer braces.
The following example shows a proper use of spaces, according to some of the above mentioned conventions:
.. code-block:: csharp
public class MyClass<A, B> : Parent<A, B>
{
public float MyProperty { get; set; }
public float AnotherProperty
{
get { return MyProperty; }
}
public void MyMethod()
{
int[] values = {1, 2, 3, 4}; // No space within initializer brackets.
int sum = 0;
// Single line comment.
for (int i = 0; i < values.Length; i++)
{
switch (i)
{
case 3: return;
default:
sum += i > 2 ? 0 : 1;
break;
}
}
i += (int)MyProperty; // No space after a type cast.
}
}
Naming conventions
------------------
Use **PascalCase** for all namespaces, type names and member level identifiers (i.e. methods, properties,
constants, events), except for private fields:
.. code-block:: csharp
namespace ExampleProject
{
public class PlayerCharacter
{
public const float DefaultSpeed = 10f;
public float CurrentSpeed { get; set; }
protected int HitPoints;
private void CalculateWeaponDamage()
{
}
}
}
Use **camelCase** for all other identifiers (i.e. local variables, method arguments), and use
an underscore (``_``) as a prefix for private fields (but not for methods or properties, as explained above):
.. code-block:: csharp
private Vector3 _aimingAt; // Use a `_` prefix for private fields.
private void Attack(float attackStrength)
{
Enemy targetFound = FindTarget(_aimingAt);
targetFound?.Hit(attackStrength);
}
There's an exception with acronyms which consist of two letters, like ``UI``, which should be written in
uppercase letters where PascalCase would be expected, and in lowercase letters otherwise.
Note that ``id`` is **not** an acronym, so it should be treated as a normal identifier:
.. code-block:: csharp
public string Id { get; }
public UIManager UI
{
get { return uiManager; }
}
It is generally discouraged to use a type name as a prefix of an identifier, like ``string strText``
or ``float fPower``, for example. An exception is made, however, for interfaces, which
**should**, in fact, have an uppercase letter ``I`` prefixed to their names, like ``IInventoryHolder`` or ``IDamageable``.
Lastly, consider choosing descriptive names and do not try to shorten them too much if it affects
readability.
For instance, if you want to write code to find a nearby enemy and hit it with a weapon, prefer:
.. code-block:: csharp
FindNearbyEnemy()?.Damage(weaponDamage);
Rather than:
.. code-block:: csharp
FindNode()?.Change(wpnDmg);
Member variables
----------------
Don't declare member variables if they are only used locally in a method, as it
makes the code more difficult to follow. Instead, declare them as local
variables in the method's body.
Local variables
---------------
Declare local variables as close as possible to their first use. This makes it
easier to follow the code, without having to scroll too much to find where the
variable was declared.
Implicitly typed local variables
--------------------------------
Consider using implicitly typing (``var``) for declaration of a local variable, but do so
**only when the type is evident** from the right side of the assignment:
.. code-block:: csharp
// You can use `var` for these cases:
var direction = new Vector2(1, 0);
var value = (int)speed;
var text = "Some value";
for (var i = 0; i < 10; i++)
{
}
// But not for these:
var value = GetValue();
var velocity = direction * 1.5;
// It's generally a better idea to use explicit typing for numeric values, especially with
// the existence of the `real_t` alias in Godot, which can either be double or float
// depending on the build configuration.
var value = 1.5;
Other considerations
--------------------
* Use explicit access modifiers.
* Use properties instead of non-private fields.
* Use modifiers in this order:
``public``/``protected``/``private``/``internal``/``virtual``/``override``/``abstract``/``new``/``static``/``readonly``.
* Avoid using fully-qualified names or ``this.`` prefix for members when it's not necessary.
* Remove unused ``using`` statements and unnecessary parentheses.
* Consider omitting the default initial value for a type.
* Consider using null-conditional operators or type initializers to make the code more compact.
* Use safe cast when there is a possibility of the value being a different type, and use direct cast otherwise.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -1,11 +0,0 @@
C#
===
.. toctree::
:maxdepth: 1
:name: toc-learn-scripting-C#
c_sharp_basics
c_sharp_features
c_sharp_differences
c_sharp_style_guide

View File

@ -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', 'x11', 'linux', 'osx']))
opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", '', ['', 'windows', 'x11', '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 ('x11', 'linux'):
env['target_path'] += 'x11/'
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))

View File

@ -1,555 +0,0 @@
.. _doc_gdnative_c_example:
GDNative C example
==================
Introduction
------------
This tutorial will introduce you to 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/godotengine/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 --branch=3.4
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.4``) and ideally actual release (e.g.
``3.4.4-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.4.4-stable`` tag for use with
Godot 3.4.4. In your cloned repository, you can do:
.. code-block:: none
git checkout godot-3.4.4-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.4``), which you would also check
out with ``git checkout 3.4``.
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]
OSX.64="res://bin/libsimple.dylib"
OSX.32="res://bin/libsimple.dylib"
Windows.64="res://bin/libsimple.dll"
X11.64="res://bin/libsimple.so"
[dependencies]
OSX.64=[ ]
OSX.32=[ ]
Windows.64=[ ]
X11.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

View File

@ -1,657 +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 ``osx`` 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``, ``godot-headers``, 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 <Sprite.hpp>
namespace godot {
class GDExample : public Sprite {
GODOT_CLASS(GDExample, Sprite)
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 ``Sprite.hpp`` which
contains bindings to the Sprite 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 Sprite 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. It has to exist even if you don't place any code in it.
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 simply 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 Sprite. This
is because our class is a container class; ``owner`` points to the actual Sprite
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``, ``godot-headers`` 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]
X11.64="res://bin/x11/libgdexample.so"
Windows.64="res://bin/win64/libgdexample.dll"
OSX.64="res://bin/osx/libgdexample.dylib"
[dependencies]
X11.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 Sprite 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_Sprite_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
----------
The above is only a simple example, but we hope it shows 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

View File

@ -1,10 +0,0 @@
GDNative
========
.. toctree::
:maxdepth: 1
:name: toc-tutorials-gdnative
what_is_gdnative
gdnative_c_example
gdnative_cpp_example

View File

@ -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.

View File

@ -19,9 +19,6 @@ case, an interface that works with multiple languages.
:name: toc-learn-scripting
gdscript/index
visual_script/index
c_sharp/index
gdnative/index
Core features
-------------

View File

@ -1,112 +0,0 @@
.. _doc_custom_visualscript_nodes:
Custom VisualScript nodes
=========================
.. warning::
`Godot 4.0 will remove VisualScript from core entirely. <https://godotengine.org/article/godot-4-will-discontinue-visual-scripting>`__
As a result, creating new projects using visual scripting in Godot is not recommended.
Future Godot 4.x releases may have VisualScript reimplemented as an extension.
While Godot 3.x will keep VisualScript supported, we recommend
:ref:`trying out GDScript <toc-learn-scripting-gdscript>` instead,
especially if you intend to migrate your project to Godot 4.
Custom nodes are written in GDScript and can then be used in VisualScript.
This is useful for offloading complex code to GDScript and reusing it.
Creating a custom node
----------------------
Create a new script that extends :ref:`class_VisualScriptCustomNode` and put a ``tool`` keyword at the top. This is needed for the script to run in the editor.
There are some functions that can be implemented to set parameters of the custom node.
Only add functions that are needed, a ``_has_input_sequence_port`` function is not necessary if it should return ``false`` for example.
The most important part of a custom node is the ``_step`` function. The logic of the node is defined there.
The ``inputs`` parameter holds the value of the input ports.
The ``outputs`` parameter is an array where the indices represent the output port ids. It can be modified to set the values of the output ports.
``start_mode`` can be checked to see if it is the first time ``_step`` is called.
``working_mem`` is persistent each ``_step`` call. It can be used to store information.
If you want to throw an error, for example if the input types are incorrect, you can return the error message as a string.
When everything goes right, return the id of the sequence port which should be called next. If your custom node doesn't have any, just return 0.
Example:
::
tool
extends VisualScriptCustomNode
# The name of the custom node as it appears in the search.
func _get_caption():
return "Get Input Direction 2D"
func _get_category():
return "Input"
# The text displayed after the input port / sequence arrow.
func _get_text():
return ""
func _get_input_value_port_count():
return 0
# The types of the inputs per index starting from 0.
func _get_input_value_port_type(idx):
return TYPE_OBJECT
func _get_output_value_port_count():
return 1
# The types of outputs per index starting from 0.
func _get_output_value_port_type(idx):
return TYPE_VECTOR2
# The text displayed before each output node per index.
func _get_output_value_port_name(idx):
return "Direction"
func _has_input_sequence_port():
return true
# The number of output sequence ports to use
# (has to be at least one if you have an input sequence port).
func _get_output_sequence_port_count():
return 1
func _step(inputs, outputs, start_mode, working_mem):
# start_mode can be checked to see if it is the first time _step is called.
# This is useful if you only want to do an operation once.
# working_memory is persistent between _step calls.
# The inputs array contains the value of the input ports.
var x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
var y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
# The outputs array is used to set the data of the output ports.
outputs[0] = Vector2(x, y)
# Return the error string if an error occurred, else the id of the next sequence port.
return 0
Using a custom node
-------------------
To use the script, add a ``CustomNode``, select it and drag your custom node script into the ``script`` property shown in the inspector.
.. image:: img/visual_script_custom_node_set_script.png
Result:
.. image:: img/visual_script_custom_node_result.png

View File

@ -1,131 +0,0 @@
.. _doc_getting_started_visual_script:
Getting started with Visual Scripting
=====================================
As with everything in Godot, we prioritize a good experience over copying or integrating third party solutions
which might not fit nicely in the current workflow. This led us to write our own version of how we believe
this feature would work best with the engine.
In Godot, a Visual Script fits smoothly together with regular scripts in the Editor tab
.. image:: img/visual_script1.png
In fact, Visual Scripting integrates so well to Godot that it's hard to believe it was added only
in version 3.0. This is because, when editing, the rest of Godot panels and docks act like a
palette from where you can drag and drop all sorts of information to the script canvas:
.. image:: img/visual_script2.png
Creating a script
-----------------
Creating scripts works the same as with other scripting languages: Select any node in the scene
and push the "New Script" button at the top right corner of the Scene Tree dock:
.. image:: img/visual_script3.png
Once it opens, the script type "Visual Script" must be selected from the drop down list. The script extension
must be ".vs" (for Visual Script!).
.. image:: img/visual_script4.png
Finally, the Script Editor will open, allowing you to start editing the visual script:
.. image:: img/visual_script5.png
Adding a function
-----------------
Unlike other visual scripting implementations, Visual Scripting in Godot is heavily based on functions.
This happens because it uses the same interface to communicate with the engine as other scripting engines.
In Godot, the scripting interface is universal and all implementations conform to it.
A function is an individual canvas with nodes connected.
A single script can contain many functions, each of which will have a canvas of its own, allowing for more organization.
There are three main ways to add functions in a script:
Overriding a virtual function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Most types of nodes and other types of objects in Godot contain virtual functions. These are functions that
will be called (run your code) when something happens and can be looked up in the reference. Virtual functions
are listed when pressing the "Override" icon in the member panel:
.. image:: img/visual_script6.png
In the following example, a function will be executed when the node is loaded and added to the running scene.
For this, the _ready() virtual method will be overridden:
.. image:: img/visual_script7.png
Finally, a canvas appears for this function, showing the override:
.. image:: img/visual_script8.png
As some functions expect you to return a value, they will also add a return node where such value is supposed to be
provided:
.. image:: img/visual_script9.png
Connecting a signal to a function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Nodes in a tree emit signals when something happens. Godot uses signals for all sorts of things.
A typical example would be a button that emits a "pressed" signal when actually pressed.
For this, a node must be selected and the Node tab opened. This will allow inspecting the signals.
Once they are displayed, connect the "pressed" signal:
.. image:: img/visual_script10.png
This will open the connection dialog. In this dialog, you must select the node where the signal will be
connected to, and the function that will receive the signal:
.. image:: img/visual_script11.png
If this is done right, a new function will be created in our script and a signal will automatically be
connected to it:
.. image:: img/visual_script12.png
Creating a function manually
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The last way to create functions is to do it manually. In general, this is not as common unless you
really need it. Custom functions work when another (or the same) script calls them manually.
The main use cases for this are breaking a larger function up into several manageable chunks and reusing your visual code.
To create a function manually, push the big "Plus" button, and a new function will be added
with a default name:
.. image:: img/visual_script13.png
This will add a new function, which can be renamed by simply double clicking its name:
.. image:: img/visual_script14.png
To edit the "arguments" this function can get (the values you pass to it when you call this function),
simply click the Function node and check the inspector:
.. image:: img/visual_script15.png
More on that will be explained later in this document.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,21 +0,0 @@
VisualScript
============
.. warning::
`Godot 4.0 will remove VisualScript from core entirely. <https://godotengine.org/article/godot-4-will-discontinue-visual-scripting>`__
As a result, creating new projects using visual scripting in Godot is not recommended.
Future Godot 4.x releases may have VisualScript reimplemented as an extension.
While Godot 3.x will keep VisualScript supported, we recommend
:ref:`trying out GDScript <toc-learn-scripting-gdscript>` instead,
especially if you intend to migrate your project to Godot 4.
.. toctree::
:maxdepth: 3
:name: toc-learn-scripting-visual_script
what_is_visual_scripting
getting_started
nodes_purposes
custom_visualscript_nodes

View File

@ -1,510 +0,0 @@
.. _doc_nodes_purposes_visual_script:
Nodes and terminology
=====================
Before continuing, it must be noted that the *Node* terminology needs to be used with care.
When referring to *Visual Script Nodes* (or generally *Nodes*) this text will refer to the little boxes you connect with lines, which are part of a graph.
When referring to *Scene Nodes*, it is implied that the elements that make up a Scene are being referred, which are part of a tree. Their naming is similar but their function is different.
When referring to *Node* here, it will be implied that a *Visual Script Node* is referred to unless indicated otherwise.
.. image:: img/visual_script16.png
Node properties
---------------
Like in most visual scripting implementations, each node has editable properties. In Godot, though, we try to avoid
bloating the nodes with editable controls for the sake of readability.
Nodes still display the required information as text, but editing is done via the *Inspector*. To edit them,
select any node and edit its properties in the *Inspector*.
Ports and connections
---------------------
Programming in Godot Visual Scripting is done via *Nodes* and *Port Connections* inside each function.
Ports
~~~~~
Nodes in Godot Visual Scripting have *Ports*. These are endpoints that appear to the
left and right of nodes and which can be used to make *Connections*:
There are two types of *Ports*: *Sequence* and *Data*.
.. image:: img/visual_script17.png
*Sequence Ports* indicate the order in which operations are executed.
Typically when a *Node* is done processing, it will go to the next node from one of the ports at the right.
If nothing is connected, the function may end, or another output *Sequence Port* might be tried (this depends on the node).
Thanks to this, you can follow the logic flow within a function by following the white lines.
Not every *Node* has *Sequence Ports*. In fact, most do not.
*Data Ports* ports contain typed values. Types can be any regular Godot types,
such as a boolean, an integer, a string, a Vector3, an array, any Object or Scene Node, etc.
A *Data Port* on the right side of a node is considered an output, while,
a port on the left side is an input. Connecting them allows information to flow to the next node.
Not all *Data Port* types are compatible and will allow connections, though.
Pay special attention to colors and icons, as each type has a different representation:
.. image:: img/visual_script18.png
Connections
~~~~~~~~~~~
Connecting is a relatively simple process. Drag an *Output Port* towards an *Input Port*.
.. image:: img/visual_script_connect.gif
Disconnecting takes a bit more practice. Disconnecting in *Data Ports* happens by
dragging the *Input* away, while for *Sequence Ports*, this happens by dragging the *Output* away.
.. image:: img/visual_script_disconnect.gif
This may seem strange at first, but it happens because *Data Ports* are 1:N
(A single output port can connect to many inputs), while *Sequence Ports* are N:1
(Many sequence outputs can be connected to a single input).
Connecting to empty space (drag to connect but unpress over empty space) is also context sensitive, it will supply
a list of most common operations. For sequences, it will be conditional nodes:
.. image:: img/visual_script52.png
While, for data, a contextual set/get/call menu will open:
.. image:: img/visual_script53.png
Adding nodes
------------
Finally! We got to the fun part! But, before explaining in more detail what each type of node does,
let's take a short look at how nodes are most commonly added and dealt with.
Accessing scene nodes
~~~~~~~~~~~~~~~~~~~~~
One of the most common tasks is accessing Scene Tree Nodes (again, not to mistake with *Visual Script Nodes*).
Dragging from the Scene Tree and dropping into the canvas will ask you to *call a method* (sometimes referred to as *member function*) on this node.
.. image:: img/visual_script19.png
While accessing properties is desired in most cases (more on that below), sometimes *calling methods* can be useful too.
Methods execute specific actions on objects. In the above case, the mouse pointer can be warped to a position in local
coordinates to the control. Another common use case is queueing a node for deletion, which is done with the *queue_free* method.
.. image:: img/visual_script20.png
Care must be taken that this only works if the scene being edited contains your *Visual Script* in one of the nodes! Otherwise, a warning will be shown.
Accessing scene node properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is the most common way to edit *Scene Nodes* in Visual Scripting. Select a *Scene Node* from the *Scene Tree*, go to the Inspector, find *the Name* of the property you want to edit (hint, *not* the value!) and drag it to the canvas:
.. image:: img/visual_script21.png
The result is that this value can be changed from your script by writing to a *Data Port*.
If instead reading this value is desired, drag the node again but hold :kbd:`Ctrl` (or :kbd:`Cmd` on macOS). This will create a getter:
.. image:: img/visual_script22.png
In this case, the value can be read from a *Data Port*.
Variables
~~~~~~~~~
Variables are memory containers local to the script which can hold a value. This value can be read from any of the functions of the script or from other scripts via the method described in the previous step.
To add a Variable, push the "+" button on the *Variables* section of the Members panel. Double-click the new variable to rename it:
.. image:: img/visual_script23.png
Right-clicking the variable allows you to configure its properties:
.. image:: img/visual_script24.png
.. image:: img/visual_script25.png
As it can be seen above, the type and initial value of the variable can be changed, as well as some property hints.
Ticking the "Export" option makes the variable visible in the Inspector when selecting the node. This also makes it available to other scripts via the method described in the previous step.
.. image:: img/visual_script28.png
To use the variable in the script, simply drag it to the canvas to create a getter:
.. image:: img/visual_script26.png
Likewise, hold :kbd:`Ctrl` (or :kbd:`Cmd` on macOS) to drop a setter:
.. image:: img/visual_script27.png
Signals
~~~~~~~
It is also possible to create your own signals in a script and use them. For this, do the same steps you did for variables in the previous step, except for *Signals*:
.. image:: img/visual_script29.png
A signal can also be edited via the right-click menu to customize its arguments:
.. image:: img/visual_script30.png
The signal you have created will appear in the Inspector, along with the built-in node signals. This allows you to connect it from another script from another *Scene Node*:
.. image:: img/visual_script31.png
Finally, to emit the signal, simply drag it to the canvas:
.. image:: img/visual_script32.png
Remember that emitting a signal is a sequenced operation, so it must come from a Sequence port.
Adding more nodes
-----------------
Now that the basics are covered, let's discuss the large amount of utility nodes available for your canvas!
Below the member panel, exists the list of all available node types:
.. image:: img/visual_script33.png
Pressing :kbd:`Ctrl + F` (or :kbd:`Cmd + F` on macOS) allows you to search the list.
Any of them can be dragged to the scene. Unlike nodes (e.g. dragging a property
from the Inspector sets the context to the node being edited automatically), these are added without any "contextual" information, so this has to be done manually.
.. image:: img/visual_script34.png
Remember that you can check the class reference for what each node does, as they are documented there. That mentioned,
a brief overview of node types follows:
Constants
~~~~~~~~~
Constant nodes are nodes that provide values that, while not changing over time, can be useful as reference values.
Most of the time they are integer or float.
.. image:: img/visual_script36.png
The first one is "Constant", which allows you to select any value of any type as constant, from an integer (42) to a String ("Hello!"). In general, this node is not used that often because of default input values in *Data Ports*, but it's good to know it exists.
The second is the GlobalConstant node, which contains a long list of constants for global types in Godot. In there
you can find some useful constants to refer to key names, joystick or mouse buttons, etc.
The third one is MathConstant, which provides typical mathematical constants, such as PI, E, etc.
Data
~~~~
Data nodes deal with all sorts of access to information. Any information in Godot is accessed via these nodes, so
they are some of the most important ones to use and pretty diverse.
.. image:: img/visual_script37.png
There are many types of nodes of interest here, so a short attempt to describe them will follow:
Action
^^^^^^
Action nodes are vital when dealing with input from a device. You can read more about actions in the (@TODO ACTION TUTE LINK).
In the following example below, the control is moved to the right when the "move_right" action is pressed.
.. image:: img/visual_script38.png
Engine Singleton
^^^^^^^^^^^^^^^^
Engine singletons are global interfaces (meaning they can be accessed without a reference; unlike Scene Nodes, they are always available).
They have several purposes, but in general, they are useful for low-level access or OS-related access.
.. image:: img/visual_script39.png
Remember that dragging a connection to empty space will help you call functions or set/get properties on these:
.. image:: img/visual_script40.png
Local Variables
^^^^^^^^^^^^^^^
These are nodes you can use as temporary storage for your graphs. Make sure they all have the same name and type when using them and they will reference the same piece of memory.
.. image:: img/visual_script41.png
As it can be seen above, there are two nodes available: A simple getter, and a sequenced setter (setting requires a sequence port).
Scene Node
^^^^^^^^^^
This is just a reference to a node in the tree, but it's easier to use this node by dragging the actual node
from the scene tree to the canvas (this will create it and configure it).
Self
^^^^
In some rare occasions, it may be desired to pass this Scene Node as argument.
It can be used to call functions and set/get properties, or drag nodes (or event the node itself that has the script) from the Scene Tree to the canvas for this.
SceneTree
^^^^^^^^^
This node is similar to the Singleton node because it references the SceneTree, which contains the active scene.
SceneTree, however, only works when the node is sitting in the scene and active, otherwise accessing it will
return an error.
SceneTree allows for many low-level things, like setting stretch options, calling groups, make timers, or even
load another scene. It's a good class to get familiar with.
Preload
^^^^^^^
This does the same function as preload() in GDScript. It maintains this resource loaded and ready to use. Rather than
instancing the node, it's simpler to drag the desired resource from the filesystem dock to the canvas.
Resource Path
^^^^^^^^^^^^^
This node is a simple helper to get a string with a path to a resource you can pick. It's useful in functions that
load things from disk.
Comment
^^^^^^^
A Comment node works as a node you can resize to put around other nodes. It will not try to get focus or be brought
to top when selecting it. It can also be used to write text on it.
.. image:: img/visual_script42.png
Flow Control
~~~~~~~~~~~~
Flow control nodes allow the execution to take different branches, usually depending on a
given condition.
.. image:: img/visual_script43.png
Condition
^^^^^^^^^
This is a simple node that checks a bool port. If ``true``, it will go via the "true" sequence port. If ``false``,
the second. After going for either of them, it goes via the "done" port. Leaving sequence
ports disconnected is fine if not all of them are used.
Iterator
^^^^^^^^
Some data types in Godot (ie, arrays, dictionaries) are iterable. This means that a bit of code can run
for each element that it has.
The Iterator node goes through all elements and, for each of them, it goes via the "each" sequence port,
making the element available in the "elem" data port.
When done, it goes via the "exit" sequence port.
Return
^^^^^^
Some functions can return values. In general for virtual ones, Godot will add the Return node for you.
A return node forces the function to end.
Sequence
^^^^^^^^
This node is useful mostly for organizing your graph. It calls its sequence ports in order.
TypeCast
^^^^^^^^
This is a useful and commonly used node. You can use it to cast arguments or other objects
to the type you desire. Afterwards, you can even drag the object output to get full completion.
.. image:: img/visual_script55.png
It is also possible to cast to a script, which will allow complete script properties and functions:
.. image:: img/visual_script54.png
Switch
^^^^^^
The Switch node is similar to the Condition node, but it matches many values at the same time.
While
^^^^^
This is a more primitive form of iteration. "repeat" sequence output will be called as long as
the condition in the "cond" data port is met.
Functions
~~~~~~~~~
Functions are simple helpers, most of the time deterministic. They take some arguments as
input and return an output. They are almost never sequenced.
Built-In
^^^^^^^^
There is a list of built-in helpers. The list is almost identical to the one from :ref:`GDScript<class_@GDScript>`. Most of them are mathematical functions, but others can be useful helpers. Make sure to take a look at the list
at some point.
By Type
^^^^^^^
Those are the methods available to basic types. For example, if you want a dot-product, you can search for "dot" instead of the Vector3 category.
In most cases just search the list of nodes, it should be faster.
Call
^^^^
This is the generic calling node. It is rarely used directly but by dragging to empty space on an already configured node.
Constructors
^^^^^^^^^^^^
These are all the functions needed to create Godot basic datatypes. For example, If you need to create a Vector3 out of 3 floats, a constructor must be used.
.. image:: img/visual_script44.png
Destructor
^^^^^^^^^^
This is the opposite to Constructor, it allows to separate any basic type (ie, Vector3) into its sub-elements.
.. image:: img/visual_script45.png
Emit Signal
^^^^^^^^^^^
Emits signals from any object. In general it's not that useful, as dragging a signal to the canvas works better.
Get/Set
^^^^^^^
Generic Getter/Setter node. Dragging properties from the Inspector works better, as they appear properly configured on drop.
Wait
^^^^
The Wait nodes will suspend execution of the function until something happens (many frames can pass until resuming, in fact).
Default nodes allow you to wait for a frame to pass, a fixed frame or a given amount of time until execution is resumed.
Yield
^^^^^
This node completely suspends the execution of the script, and it will make the function return a value that can be used to resume execution.
Yield Signal
^^^^^^^^^^^^
Same as Yield, but will wait until a given signal is emitted.
Index
~~~~~
Generic indexing operator, not often used but it's good that it exists just in case.
Operators
~~~~~~~~~
These are mostly generic operators, such as addition, multiplication, comparison, etc.
By default, these mostly accept any datatype (and will throw an error at run-time if the types
fed do not match those expected by the operator). It is always recommended to set the right
type for operators to catch errors faster and make the graph easier to read.
.. image:: img/visual_script46.png
Expression Node
^^^^^^^^^^^^^^^
Among the operators, the *Expression* node is the most powerful. If well used, it allows you to enormously simplify
visual scripts that are math or logic heavy. Type any expression on it and it will be executed in real-time.
Expression nodes can:
- Perform math and logic expressions based on custom inputs (eg: "a*5+b", where a and b are custom inputs):
.. image:: img/visual_script47.png
- Access local variables or properties:
.. image:: img/visual_script48.png
- Use most of the existing built-in functions that are available to GDScript, such as ``sin()``, ``cos()``, ``print()``, as well as constructors, such as ``Vector3(x, y, z)``, ``Rect2(...)``, etc.:
.. image:: img/visual_script49.png
- Call API functions:
.. image:: img/visual_script50.png
- Use sequenced mode, which makes more sense in case of respecting the processing order:
.. image:: img/visual_script51.png

View File

@ -1,24 +0,0 @@
.. _doc_what_is_visual_script:
What is Visual Scripting
========================
Visual Scripting is a tool designed to make the entry barrier to programming
much lower. As code is more visual, it needs less abstract thinking to be
understood. Any artist, animator, game designer, etc. can look at it and quickly
grasp the flow of logic.
The reason it does not make existing programming obsolete is, simply, that it does not scale as well.
It takes considerably more time to create code with it, and it's often more difficult
to modify than just writing a few characters.
With the misunderstanding cleared up, the question that remains is what are the practical
uses for Visual Scripting.
The most common use cases are as follows:
* Game development beginners who want to learn an engine but have no programming experience yet.
* Artists and Game Designers who have no experience in programming and want to create quick prototypes or simple games.
* Programmers working in a team that want to make part of the game logic available to Artists or Game Designers in order to offload some of their work.
These scenarios are far more common than one might think, so this is why Godot has added this feature.