Клас об’єкта
Дивись також
На цій сторінці описано реалізацію C++ об’єктів у Godot. Шукаєте посилання на клас об’єктів? Have a look here.
Загальне визначення
Object є базовим класом майже для всього. Більшість класів у Godot прямо чи опосередковано успадковують від нього. Об’єкти надають відображення та властивості, які можна редагувати, а їх оголошення — це питання використання одного макросу, подібного до цього:
class CustomObject : public Object {
GDCLASS(CustomObject, Object); // this is required to inherit
};
Це додає Objects велику функціональність. Наприклад:
obj = memnew(CustomObject);
print_line("Object class: ", obj->get_class()); // print object class
obj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.
Посилання:
Реєстрація об'єкта
ClassDB — це статичний клас, який містить увесь список зареєстрованих класів, успадкованих від Object, а також динамічні прив’язки до всіх їхніх властивостей методів і цілочисельних констант.
Реєстрація на заняття здійснюється за телефонами:
ClassDB::register_class<MyCustomClass>()
Його реєстрація дозволить створювати екземпляри класу за допомогою сценаріїв, коду або створювати їх повторно під час десеріалізації.
Реєстрація як віртуальна — це те саме, але її не можна створити.
ClassDB::register_virtual_class<MyCustomClass>()
Похідні від об’єктів класи можуть перевизначати статичну функцію static void _bind_methods(). Коли зареєстровано один клас, ця статична функція викликається для реєстрації всіх методів об’єкта, властивостей, констант тощо. Вона викликається лише один раз. Якщо створений екземпляр похідного класу Object, але не зареєстрований, він буде автоматично зареєстрований як віртуальний.
Усередині _bind_methods є кілька речей, які можна зробити. Функція реєстрації одна:
ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method);
Значення за замовчуванням для аргументів можна передати як параметри в кінці:
ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method, DEFVAL(-1), DEFVAL(-2)); // Default values for arg2name (-1) and arg3name (-2).
Значення за замовчуванням потрібно надавати в такому ж порядку, як вони оголошені, пропускаючи необхідні аргументи та надаючи значення за замовчуванням для необов’язкових. Це відповідає синтаксису для оголошення методів у C++.
D_METHOD – це макрос, який перетворює "methodname" на StringName для більшої ефективності. Назви аргументів використовуються для самоаналізу, але під час компіляції після випуску макрос ігнорує їх, тому рядки не використовуються та оптимізовані.
Щоб отримати більше прикладів, перевірте _bind_methods елемента Control або Object.
Якщо ви просто додаєте модулі та функціональні можливості, які, як очікується, не будуть задокументовані настільки ретельно, макрос D_METHOD() можна безпечно проігнорувати, а рядок, що передає назву, можна передати для стислості.
Посилання:
Константи
Класи часто мають такі переліки, як:
enum SomeMode {
MODE_FIRST,
MODE_SECOND
};
Щоб вони працювали під час прив’язки до методів, enum має бути оголошено конвертованим у int. Для цього надається макрос:
VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.
Константи також можна зв’язати всередині _bind_methods за допомогою:
BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);
Властивості (встановити/отримати)
Властивості експорту об’єктів, властивості корисні для наступного:
Серіалізація та десеріалізація об’єкта.
Створення списку редагованих значень для похідного класу Object.
Властивості зазвичай визначаються класом PropertyInfo() і створюються як:
PropertyInfo(type, name, hint, hint_string, usage_flags)
Приклад:
PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)
Це цілочисельна властивість під назвою "сума". Підказка — це діапазон, який змінюється від 0 до 49 із кроком 1 (цілі числа). Його можна використовувати лише для редактора (редагування значення візуально), але не буде серіалізовано.
Ще один приклад:
PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")
Це властивість рядка, може приймати будь-який рядок, але редактор дозволятиме лише визначені підказки. Оскільки прапорці використання не вказано, стандартними є PROPERTY_USAGE_STORAGE та PROPERTY_USAGE_EDITOR.
У object.h є багато підказок і позначок використання, перевірте їх.
Властивості також можуть працювати як властивості C# і доступ до них можна отримати зі сценарію за допомогою індексування, але таке використання зазвичай не рекомендується, оскільки використання функцій є кращим для читабельності. Багато властивостей також пов’язані з категоріями, такими як «анімація/кадр», які також унеможливлюють індексування без використання оператора [].
За допомогою _bind_methods() властивості можна створювати та зв’язувати, доки існують функції set/get. приклад:
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")
Це створює властивість за допомогою сеттера та геттера.
Властивості прив’язки за допомогою _set/_get/_get_property_list
Існує додатковий метод створення властивостей, коли потрібна більша гнучкість (тобто додавання або видалення властивостей у контексті).
Наступні функції можна перевизначати в похідному класі Object, вони НЕ є віртуальними, НЕ робіть їх віртуальними, вони викликаються для кожного перевизначення, а попередні не анулюються (багаторівневий виклик).
protected:
void _get_property_list(List<PropertyInfo> *r_props) const; // return list of properties
bool _get(const StringName &p_property, Variant &r_value) const; // return true if property was found
bool _set(const StringName &p_property, const Variant &p_value); // return true if property was found
Це також трохи менш ефективно, оскільки p_property потрібно порівнювати з бажаними іменами в послідовному порядку.
Динамічний кастинг
Godot забезпечує динамічне приведення між класами, похідними від об’єктів, наприклад:
void somefunc(Object *some_obj) {
Button *button = Object::cast_to<Button>(some_obj);
}
Якщо приведення не вдається, повертається NULL. Ця система використовує RTTI, але вона також працює добре (хоча трохи повільніше), коли RTTI вимкнено. Це корисно на платформах, де ідеально підходить малий двійковий розмір, наприклад HTML5 або консолі (з малим обсягом пам’яті).
Сигнали
Для об’єктів може бути визначений набір сигналів (подібно до делегатів в інших мовах). Цей приклад показує, як підключитися до них:
obj->connect(<signal>, target_instance, target_method)
// for example:
obj->connect("enter_tree", this, "_node_entered_tree")
Метод _node_entered_tree має бути зареєстрований у класі за допомогою ClassDB::bind_method (пояснено раніше).
Додавання сигналів до класу виконується в _bind_methods за допомогою макросу ADD_SIGNAL, наприклад:
ADD_SIGNAL(MethodInfo("been_killed"))
Сповіщення
Усі об’єкти в Godot мають метод _notification, який дозволяє йому відповідати на зворотні виклики рівня механізму, які можуть бути пов’язані з ним. Більше інформації можна знайти на сторінці Сповіщення Godot.
Посилання
RefCounted успадковується від Object і містить кількість посилань. Це основа для підрахованих типів об’єктів. Оголошувати їх потрібно за допомогою шаблону Ref<>. Наприклад:
class MyReference: public RefCounted {
GDCLASS(MyReference, RefCounted);
};
Ref<MyReference> myref(memnew(MyReference));
myref враховує посилання. Його буде звільнено, коли на нього більше не вказуватимуть шаблони Ref<>.
Посилання:
Ресурси
Resource успадковується від RefCounted, тому всі ресурси підраховуються посиланнями. Ресурси можуть додатково містити шлях, який посилається на файл на диску. Це можна встановити за допомогою resource.set_path(path), хоча зазвичай це робить завантажувач ресурсів. Жодні два різні ресурси не можуть мати однаковий шлях; спроба зробити це призведе до помилки.
Ресурси без шляху теж підходять.
Посилання:
Завантаження ресурсів
Ресурси можна завантажувати за допомогою API ResourceLoader, наприклад:
Ref<Resource> res = ResourceLoader::load("res://someresource.res")
Якщо посилання на цей ресурс було завантажено раніше та знаходиться в пам’яті, завантажувач ресурсів поверне це посилання. Це означає, що з файлу, на який посилається на диску, одночасно може бути завантажений лише один ресурс.
resourceinteractiveloader (ще не написано)
Посилання:
Економія ресурсів
Збереження ресурсу можна виконати за допомогою API збереження ресурсів:
ResourceSaver::save("res://someresource.res", instance)
Екземпляр буде збережено, а підресурси, які мають шлях до файлу, будуть збережені як посилання на цей ресурс. Підресурси без шляху буде об’єднано зі збереженим ресурсом і призначеними підідентифікаторами, як-от res://someresource.res::1. Це також допомагає кешувати їх під час завантаження.