Merge branch 'master' into 3.2

This commit is contained in:
Rémi Verschelde
2020-06-22 11:16:25 +02:00
62 changed files with 989 additions and 369 deletions

View File

@@ -75,7 +75,11 @@ need to be created:
register_types.h
register_types.cpp
With the following contents:
.. important::
These files must be in the top-level folder of your module (next to your
``SCsub`` and ``config.py`` files) for the module to be registered properly.
These files should contain the following:
.. code-block:: cpp
@@ -124,8 +128,8 @@ installation commands for Linux below, for reference.
apt-cache search festvox-* <-- Displays list of voice packages
sudo apt-get install festvox-don festvox-rablpc16k festvox-kallpc16k festvox-kdlpc16k <-- Installs voices
.. note::
**Important:** The voices that Festival uses (and any other potential external/3rd-party
.. important::
The voices that Festival uses (and any other potential external/3rd-party
resource) all have varying licenses and terms of use; some (if not most) of them may be
be problematic with Godot, even if the Festival Library itself is MIT License compatible.
Please be sure to check the licenses and terms of use.
@@ -148,8 +152,8 @@ can link to them instead by adding them as submodules (from within the modules/t
git submodule add https://github.com/festvox/festival
git submodule add https://github.com/festvox/speech_tools
.. note::
**Important:** Please note that Git submodules are not used in the Godot repository. If
.. important::
Please note that Git submodules are not used in the Godot repository. If
you are developing a module to be merged into the main Godot repository, you should not
use submodules. If your module doesn't get merged in, you can always try to implement
the external library as a GDNative C++ plugin.

View File

@@ -0,0 +1,246 @@
.. _doc_common_engine_methods_and_macros:
Common engine methods and macros
================================
Godot's C++ codebase makes use of dozens of custom methods and macros which are
used in almost every file. This page is geared towards beginner contributors,
but it can also be useful for those writing custom C++ modules.
Print text
----------
.. code-block:: cpp
// Prints a message to standard output.
print_line("Message");
// Prints a message to standard output, but only when the engine
// is started with the `--verbose` command line argument.
print_verbose("Message");
// Prints a formatted error or warning message with a trace.
ERR_PRINT("Message");
WARN_PRINT("Message");
// Prints an error or warning message only once per session.
// This can be used to avoid spamming the console output.
ERR_PRINT_ONCE("Message");
WARN_PRINT_ONCE("Message");
If you need to add placeholders in your messages, use format strings as
described below.
Format a string
---------------
The ``vformat()`` function returns a formatted :ref:`class_String`. It behaves
in a way similar to C's ``sprintf()``:
.. code-block:: cpp
vformat("My name is %s.", "Godette");
vformat("%d bugs on the wall!", 1234);
vformat("Pi is approximately %f.", 3.1416);
// Converts the resulting String into a `const char *`.
// You may need to do this if passing the result as an argument
// to a method that expects a `const char *` instead of a String.
vformat("My name is %s.", "Godette").c_str();
In most cases, try to use ``vformat()`` instead of string concatenation as it
makes for more readable code.
Convert an integer or float to a string
---------------------------------------
This is mainly useful when printing numbers directly.
.. code-block:: cpp
// Prints "42" using integer-to-string conversion.
print_line(itos(42));
// Prints "123.45" using real-to-string conversion.
print_line(rtos(123.45));
Internationalize a string
-------------------------
There are two types of internationalization in Godot's codebase:
- ``TTR()``: **Editor ("tools") translations** will only be processed in the
editor. If an user uses the same text in one of their projects, it won't be
translated if they provide a translation for it. When contributing to the
engine, this is generally the macro you should use for localizable strings.
- ``RTR()``: **Run-time translations** will be automatically localized in
projects if they provide a translation for the given string. This kind of
translation shouldn't be used in editor-only code.
.. code-block:: cpp
// Returns the translated string that matches the user's locale settings.
// Translations are located in `editor/translations`.
// The localization template is generated automatically; don't modify it.
TTR("Exit the editor?");
To insert placeholders in localizable strings, wrap the localization macro in a
``vformat()`` call as follows:
.. code-block:: cpp
String file_path = "example.txt";
vformat(TTR("Couldn't open \"%s\" for reading."), file_path);
.. note::
When using ``vformat()`` and a translation macro together, always wrap the
translation macro in ``vformat()``, not the other way around. Otherwise, the
string will never match the translation as it will have the placeholder
already replaced when it's passed to TranslationServer.
Clamp a value
-------------
Godot has provides macros for clamping a value with a lower bound (``MAX``), an
upper bound (``MIN``) or both (``CLAMP``):
.. code-block:: cpp
int a = 3;
int b = 5;
MAX(b, 6); // 6
MIN(2, a); // 2
CLAMP(a, 10, 30); // 10
This works with any type that can be compared to other values (like ``int`` and
``float``).
Microbenchmarking
-----------------
If you want to benchmark a piece of code but don't know how to use a profiler,
use this snippet:
.. code-block:: cpp
uint64_t begin = OS::get_singleton()->get_ticks_usec();
// Your code here...
uint64_t end = OS::get_singleton()->get_ticks_usec();
print_line(vformat("Snippet took %d microseconds", end - begin));
This will print the time spent between the ``begin`` declaration and the ``end``
declaration.
.. note::
You may have to ``#include "core/os/os.h"`` if it's not present already.
When opening a pull request, make sure to remove this snippet as well as the
include if it wasn't there previously.
Get project/editor settings
---------------------------
There are four macros available for this:
.. code-block:: cpp
// Returns the specified project setting's value,
// defaulting to `false` if it doesn't exist.
GLOBAL_DEF("section/subsection/value", false);
// Returns the specified editor setting's value,
// defaulting to "Untitled" if it doesn't exist.
EDITOR_DEF("section/subsection/value", "Untitled");
If a default value has been specified elsewhere, don't specify it again to avoid
repetition:
.. code-block:: cpp
// Returns the value of the project setting.
GLOBAL_GET("section/subsection/value");
// Returns the value of the editor setting.
EDITOR_GET("section/subsection/value");
It's recommended to use ``GLOBAL_DEF``/``EDITOR_DEF`` only once per setting and
use ``GLOBAL_GET``/``EDITOR_GET`` in all other places where it's referenced.
Error macros
------------
Godot features many error macros to make error reporting more convenient.
.. warning::
Conditions in error macros work in the **opposite** way of GDScript's
built-in ``assert()`` function. An error is reached if the condition inside
evaluates to ``true``, not ``false``.
.. note::
Only variants with custom messages are documented here, as these should
always be used in new contributions. Make sure the custom message provided
includes enough information for people to diagnose the issue, even if they
don't know C++. In case a method was passed invalid arguments, you can print
the invalid value in question to ease debugging.
For internal error checking where displaying a human-readable message isn't
necessary, remove ``_MSG`` at the end of the macro name and don't supply a
message argument.
Also, always try to return processable data so the engine can keep running
well.
.. code-block:: cpp
// Conditionally prints an error message and returns from the function.
// Use this in methods which don't return a value.
ERR_FAIL_COND_MSG(!mesh.is_valid(), vformat("Couldn't load mesh at: %s", path));
// Conditionally prints an error message and returns `0` from the function.
// Use this in methods which must return a value.
ERR_FAIL_COND_V_MSG(rect.x < 0 || rect.y < 0, 0,
"Couldn't calculate the rectangle's area.");
// Prints an error message if `index` is < 0 or >= `SomeEnum::QUALITY_MAX`,
// then returns from the function.
ERR_FAIL_INDEX_MSG(index, SomeEnum::QUALITY_MAX,
vformat("Invalid quality: %d. See SomeEnum for allowed values.", index));
// Prints an error message if `index` is < 0 >= `some_array.size()`,
// then returns `-1` from the function.
ERR_FAIL_INDEX_V_MSG(index, some_array.size(), -1,
vformat("Item %d is out of bounds.", index));
// Unconditionally prints an error message and returns from the function.
// Only use this if you need to perform complex error checking.
if (!complex_error_checking_routine()) {
ERR_FAIL_MSG("Couldn't reload the filesystem cache.");
}
// Unconditionally prints an error message and returns `false` from the function.
// Only use this if you need to perform complex error checking.
if (!complex_error_checking_routine()) {
ERR_FAIL_V_MSG(false, "Couldn't parse the input arguments.");
}
// Crashes the engine. This should generally never be used
// except for testing crash handling code. Godot's philosophy
// is to never crash, both in the editor and in exported projects.
CRASH_NOW_MSG("Can't predict the future! Aborting.");
.. seealso::
See `core/error_macros.h <https://github.com/godotengine/godot/blob/master/core/error_macros.h>`__
in Godot's codebase for more information about each error macro.
Some functions return an error code (materialized by a return type of
``Error``). This value can be returned directly from an error macro.
See the list of available error codes in
`core/error_list.h <https://github.com/godotengine/godot/blob/master/core/error_list.h>`__.

View File

@@ -119,7 +119,11 @@ need to be created:
register_types.h
register_types.cpp
With the following contents:
.. important::
These files must be in the top-level folder of your module (next to your
``SCsub`` and ``config.py`` files) for the module to be registered properly.
These files should contain the following:
.. code-block:: cpp
@@ -347,7 +351,7 @@ library that will be dynamically loaded when starting our game's binary.
# next to the Godot binary.
shared_lib = module_env.SharedLibrary(target='#bin/summator', source=sources)
# Finally, notify the main env it has our shared lirary as a new dependency.
# Finally, notify the main env it has our shared library as a new dependency.
# To do so, SCons wants the name of the lib with it custom suffixes
# (e.g. ".x11.tools.64") but without the final ".so".
# We pass this along with the directory of our library to the main env.
@@ -365,8 +369,9 @@ during runtime with the ``LD_LIBRARY_PATH`` environment variable:
export LD_LIBRARY_PATH="$PWD/bin/"
./bin/godot*
**note**: Pay attention you have to ``export`` the environ variable otherwise
you won't be able to play your project from within the editor.
.. note::
You have to ``export`` the environment variable otherwise
you won't be able to play your project from within the editor.
On top of that, it would be nice to be able to select whether to compile our
module as shared library (for development) or as a part of the Godot binary

View File

@@ -7,6 +7,7 @@ Engine development
introduction_to_godot_development
configuring_an_ide/index
common_engine_methods_and_macros
core_types
variant_class
object_class

View File

@@ -66,13 +66,13 @@ Registering functions is one:
.. code-block:: cpp
ClassDB::register_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomMethod);
ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomMethod);
Default values for arguments can be passed in reverse order:
.. code-block:: cpp
ClassDB::register_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomType::method, DEFVAL(-1)); // default value for arg2name
ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomType::method, DEFVAL(-1)); // default value for arg2name
``D_METHOD`` is a macro that converts "methodname" to a StringName for more
efficiency. Argument names are used for introspection, but when
@@ -223,7 +223,7 @@ languages). Connecting to them is rather easy:
obj->connect("enter_tree", this, "_node_entered_tree")
The method ``_node_entered_tree`` must be registered to the class using
``ClassDB::register_method`` (explained before).
``ClassDB::bind_method`` (explained before).
Adding signals to a class is done in ``_bind_methods``, using the
``ADD_SIGNAL`` macro, for example: