Общие методы и макросы движка

Кодовая база Godot на C++ использует десятки пользовательских методов и макросов, которые используются практически в каждом файле. Эта страница ориентирована на начинающих разработчиков, но может быть полезна и тем, кто пишет собственные модули на C++.

Форматировать строку

Функция vformat() возвращает отформатированную строку String. Она работает аналогично функции sprintf() в языке C:

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").utf8().get_data();

В большинстве случаев старайтесь использовать vformat() вместо конкатенации строк, так как это делает код более читаемым.

Преобразовать целое число или число с плавающей точкой в строку

Это не требуется при печати чисел с помощью print_line(), но для некоторых других случаев использования вам все равно может потребоваться выполнить ручное преобразование.

// Stores the string "42" using integer-to-string conversion.
String int_to_string = itos(42);

// Stores the string "123.45" using real-to-string conversion.
String real_to_string = rtos(123.45);

Интернационализировать строку

В кодовой базе Godot существует 2 типа интернационализации:

  • TTR(): Переводы редактора («инструментов») будут обрабатываться только в редакторе. Если пользователь использует тот же текст в одном из своих проектов, он не будет переведён, даже если он предоставит перевод. При работе над движком этот макрос обычно следует использовать для локализуемых строк.

  • RTR(): Переводы во время выполнения будут автоматически локализованы в проектах, если они предоставляют перевод для заданной строки. Такой перевод не следует использовать в коде, доступном только в редакторе.

// 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?");

Чтобы вставить заполнители в локализуемые строки, заключите макрос локализации в вызов vformat() следующим образом:

String file_path = "example.txt";
vformat(TTR("Couldn't open \"%s\" for reading."), file_path);

Примечание

При совместном использовании vformat() и макроса перевода всегда заключайте макрос перевода в vformat(), а не наоборот. В противном случае строка никогда не будет соответствовать переводу, так как в ней уже будет заменён заполнитель при передаче в TranslationServer.

Зафиксировать значение

Godot предоставляет макросы для ограничения значения нижней границей (MAX), верхней границей (MIN) или обеими границами (CLAMP):

int a = 3;
int b = 5;

MAX(b, 6); // 6
MIN(2, a); // 2
CLAMP(a, 10, 30); // 10

Это работает с любым типом, который можно сравнить с другими значениями (например, int и float).

Микробенчмаркинг

Если вы хотите протестировать фрагмент кода, но не знаете, как использовать профилировщик, воспользуйтесь этим фрагментом:

uint64_t begin = Time::get_singleton()->get_ticks_usec();

// Your code here...

uint64_t end = Time::get_singleton()->get_ticks_usec();
print_line(vformat("Snippet took %d microseconds", end - begin));

Это выведет время, прошедшее между объявлением begin и объявлением end.

Примечание

Возможно, вам придется #include "core/os/time.h", если его еще нет.

Открывая запрос на извлечение, обязательно удалите этот фрагмент, а также включение, если его там не было ранее.

Получить настройки проекта/редактора

Для этого доступны четыре макроса:

// 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");

Если где-то уже указано значение по умолчанию, не указывайте его снова, чтобы избежать повторения:

// Returns the value of the project setting.
GLOBAL_GET("section/subsection/value");
// Returns the value of the editor setting.
EDITOR_GET("section/subsection/value");

Рекомендуется использовать GLOBAL_DEF/EDITOR_DEF только один раз для каждой настройки и использовать GLOBAL_GET/EDITOR_GET во всех остальных местах, где на них ссылаются.

Макросы ошибок

Godot располагает множеством макросов ошибок, что делает создание отчетов об ошибках более удобным.

Предупреждение

Условия в макросах ошибок работают противоположно встроенной функции assert() в GDScript. Ошибка возникает, если условие внутри принимает значение true, а не false.

Примечание

Здесь описаны только варианты с пользовательскими сообщениями, поскольку их следует всегда использовать в новых дополнениях. Убедитесь, что предоставленное пользовательское сообщение содержит достаточно информации, чтобы пользователи могли диагностировать проблему, даже не зная C++. Если методу были переданы недопустимые аргументы, вы можете вывести соответствующее недопустимое значение для упрощения отладки.

Для внутренней проверки ошибок, когда отображение понятного человеку сообщения не требуется, удалите _MSG в конце имени макроса и не указывайте аргумент сообщения.

Кроме того, всегда старайтесь возвращать обрабатываемые данные, чтобы система могла продолжать работать без сбоев.

// 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.");

См. также

Дополнительную информацию о каждом макросе ошибки см. в файле core/error/error_macros.h в кодовой базе Godot.

Некоторые функции возвращают код ошибки (материализованный как возвращаемый тип Error). Это значение можно вернуть непосредственно из макроса ошибки. Список доступных кодов ошибок см. в файле core/error/error_list.h.