Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Завантажувачі власних форматів ресурсів
Вступ
ResourceFormatLoader — це заводський інтерфейс для завантаження файлів. Ресурси є основними контейнерами. Коли load буде викликано за тим самим шляхом до файлу знову, посилатиметься на попередній завантажений ресурс. Природно, завантажені ресурси повинні бути без стану.
Цей посібник передбачає, що читач знає, як створювати модулі C++ і типи даних Godot. Якщо ні, зверніться до цього посібника: Спеціальні модулі в C++
Посилання
ResourceLoader
для чого?
Додавання нової підтримки для багатьох форматів файлів
Формати звукових даних
Формати відео
Моделі машинного навчання
Що ні?
Растрові зображення
Для завантаження зображень слід використовувати ImageFormatLoader.
Посилання
Створення ResourceFormatLoader
Кожен формат файлу складається з контейнера даних і ResourceFormatLoader.
ResourceFormatLoaders — це класи, які повертають усі необхідні метадані для підтримки нових розширень у Godot. Клас має повертати назву формату та рядок розширення.
Крім того, ResourceFormatLoaders повинні перетворювати шляхи до файлів у ресурси за допомогою функції load. Щоб завантажити ресурс, load має прочитати та обробити серіалізацію даних.
#pragma once
#include "core/io/resource_loader.h"
class ResourceFormatLoaderJson : public ResourceFormatLoader {
GDCLASS(ResourceFormatLoaderJson, ResourceFormatLoader);
public:
virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
virtual void get_recognized_extensions(List<String> *r_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
};
#include "resource_loader_json.h"
#include "resource_json.h"
RES ResourceFormatLoaderJson::load(const String &p_path, const String &p_original_path, Error *r_error) {
Ref<JsonResource> json = memnew(JsonResource);
if (r_error) {
*r_error = OK;
}
Error err = json->load_file(p_path);
return json;
}
void ResourceFormatLoaderJson::get_recognized_extensions(List<String> *r_extensions) const {
if (!r_extensions->find("json")) {
r_extensions->push_back("json");
}
}
String ResourceFormatLoaderJson::get_resource_type(const String &p_path) const {
return "Resource";
}
bool ResourceFormatLoaderJson::handles_type(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Resource");
}
Створення ResourceFormatSaver
Якщо ви хочете мати можливість редагувати та зберігати ресурс, ви можете реалізувати ResourceFormatSaver:
#pragma once
#include "core/io/resource_saver.h"
class ResourceFormatSaverJson : public ResourceFormatSaver {
GDCLASS(ResourceFormatSaverJson, ResourceFormatSaver);
public:
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
virtual bool recognize(const RES &p_resource) const;
virtual void get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const;
};
#include "resource_saver_json.h"
#include "resource_json.h"
#include "scene/resources/resource_format_text.h"
Error ResourceFormatSaverJson::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
Ref<JsonResource> json = memnew(JsonResource);
Error error = json->save_file(p_path, p_resource);
return error;
}
bool ResourceFormatSaverJson::recognize(const RES &p_resource) const {
return Object::cast_to<JsonResource>(*p_resource) != NULL;
}
void ResourceFormatSaverJson::get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const {
if (Object::cast_to<JsonResource>(*p_resource)) {
r_extensions->push_back("json");
}
}
Створення власних типів даних
Godot може не мати належної заміни в межах своїх Типи сердечників чи керованих ресурсів. Godot потребує нового зареєстрованого типу даних, щоб розуміти додаткові двійкові формати, такі як моделі машинного навчання.
Ось приклад створення спеціального типу даних:
#pragma once
#include "core/io/json.h"
#include "core/variant_parser.h"
class JsonResource : public Resource {
GDCLASS(JsonResource, Resource);
protected:
static void _bind_methods() {
ClassDB::bind_method(D_METHOD("set_dict", "dict"), &JsonResource::set_dict);
ClassDB::bind_method(D_METHOD("get_dict"), &JsonResource::get_dict);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "content"), "set_dict", "get_dict");
}
private:
Dictionary content;
public:
Error load_file(const String &p_path);
Error save_file(const String &p_path, const RES &p_resource);
void set_dict(const Dictionary &p_dict);
Dictionary get_dict();
};
#include "resource_json.h"
Error JsonResource::load_file(const String &p_path) {
Error error;
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error);
if (error != OK) {
if (file) {
file->close();
}
return error;
}
String json_string = String("");
while (!file->eof_reached()) {
json_string += file->get_line();
}
file->close();
String error_string;
int error_line;
JSON json;
Variant result;
error = json.parse(json_string, result, error_string, error_line);
if (error != OK) {
file->close();
return error;
}
content = Dictionary(result);
return OK;
}
Error JsonResource::save_file(const String &p_path, const RES &p_resource) {
Error error;
FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &error);
if (error != OK) {
if (file) {
file->close();
}
return error;
}
Ref<JsonResource> json_ref = p_resource.get_ref_ptr();
JSON json;
file->store_string(json.print(json_ref->get_dict(), " "));
file->close();
return OK;
}
void JsonResource::set_dict(const Dictionary &p_dict) {
content = p_dict;
}
Dictionary JsonResource::get_dict() {
return content;
}
міркування
Деякі бібліотеки можуть не визначати певні загальні процедури, такі як обробка вводу-виводу. Тому потрібні переклади викликів Godot.
Наприклад, ось код для перетворення викликів FileAccess у std::istream.
#include "core/io/file_access.h"
#include <istream>
#include <streambuf>
class GodotFileInStreamBuf : public std::streambuf {
public:
GodotFileInStreamBuf(FileAccess *fa) {
_file = fa;
}
int underflow() {
if (_file->eof_reached()) {
return EOF;
} else {
size_t pos = _file->get_position();
uint8_t ret = _file->get_8();
_file->seek(pos); // Required since get_8() advances the read head.
return ret;
}
}
int uflow() {
return _file->eof_reached() ? EOF : _file->get_8();
}
private:
FileAccess *_file;
};
Посилання
Реєстрація нового формату файлу
Godot реєструє ResourcesFormatLoader за допомогою обробника ResourceLoader. Обробник автоматично вибирає відповідний завантажувач під час виклику load.
void register_json_types();
void unregister_json_types();
#include "register_types.h"
#include "core/class_db.h"
#include "resource_loader_json.h"
#include "resource_saver_json.h"
#include "resource_json.h"
static Ref<ResourceFormatLoaderJson> json_loader;
static Ref<ResourceFormatSaverJson> json_saver;
void register_json_types() {
ClassDB::register_class<JsonResource>();
json_loader.instantiate();
ResourceLoader::add_resource_format_loader(json_loader);
json_saver.instantiate();
ResourceSaver::add_resource_format_saver(json_saver);
}
void unregister_json_types() {
ResourceLoader::remove_resource_format_loader(json_loader);
json_loader.unref();
ResourceSaver::remove_resource_format_saver(json_saver);
json_saver.unref();
}
Посилання
Завантаження на GDScript
Збережіть файл під назвою demo.json із таким вмістом і розмістіть його в кореневій папці проекту:
{
"savefilename": "demo.json",
"demo": [
"welcome",
"to",
"godot",
"resource",
"loaders"
]
}
Потім приєднайте наступний скрипт до будь-якого вузла:
extends Node
@onready var json_resource = load("res://demo.json")
func _ready():
print(json_resource.get_dict())