Benutzerdefinierte Ressourcenformat -Lader¶
Einführung¶
ResourceFormatLoader ist eine Factory-Schnittstelle zum Laden von Datei-Assets. Ressourcen sind Primärcontainer. Wird load erneut auf demselben Dateipfad aufgerufen, wird auf die zuvor geladene Ressource verwiesen. Geladene Ressourcen müssen natürlich zustandslos sein.
In diesem Handbuch wird davon ausgegangen, dass der Leser weiß, wie C++ - Module und Godot-Datentypen erstellt werden. Wenn nicht, lesen Sie dieses Handbuch doc_custom_modules_in_c ++.
Referenzen¶
Wofür?¶
Unterstützung für viele Dateiformate hinzufügt
Audio Formate
Video Formate
Modelle für maschinelles Lernen
Was nicht?¶
Rasterbilder
ImageFormatLoader sollte zum Laden von Bildern verwendet werden.
Referenzen¶
Erstellen eines ResourceFormatLoaders¶
Jedes Dateiformat besteht aus einem Datencontainer und einem ResourceFormatLoader
.
ResourceFormatLoaders sind normalerweise einfache Klassen, die alle erforderlichen Metadaten zur Unterstützung neuer Erweiterungen in Godot zurückgeben. Die Klasse muss den Formatnamen und den Erweiterungsnamen zurückgeben.
Außerdem müssen ResourceFormatLoaders Dateipfade mit der Funktion load
in Ressourcen konvertieren. Um eine Ressource zu laden, muss load
die Datenserialisierung lesen und verarbeiten.
/* resource_loader_json.h */
#ifndef RESOURCE_LOADER_JSON_H
#define RESOURCE_LOADER_JSON_H
#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;
};
#endif // RESOURCE_LOADER_JSON_H
/* resource_loader_json.cpp */
#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");
}
Erstellen eines ResourceFormatSaver¶
Wenn Sie eine Ressource bearbeiten und speichern möchten, können Sie einen ResourceFormatSaver
implementieren:
/* resource_saver_json.h */
#ifndef RESOURCE_SAVER_JSON_H
#define RESOURCE_SAVER_JSON_H
#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;
};
#endif // RESOURCE_SAVER_JSON_H
/* resource_saver_json.cpp */
#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");
}
}
Benutzerdefinierte Datentypen erstellen¶
Godot hat möglicherweise keinen geeigneten Ersatz in seinen Kerntypen oder verwalteten Ressourcen. Godot benötigt einen neuen registrierten Datentyp, um zusätzliche Binärformate wie maschinelle Lernmodelle zu verstehen.
Hier ist ein Beispiel zum Erstellen eines benutzerdefinierten Datentyps:
/* resource_json.h */
#ifndef RESOURCE_JSON_H
#define RESOURCE_JSON_H
#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();
};
#endif // RESOURCE_JSON_H
/* resource_json.cpp */
#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;
}
Überlegungen¶
Einige Bibliotheken definieren möglicherweise bestimmte allgemeine Routinen wie die I/O-Behandlung nicht. Daher sind Godot-Call-Übersetzungen erforderlich.
Hier ist zum Beispiel der Code für die Übersetzung von FileAccess
Aufrufen in std::istream
.
#include "core/os/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;
};
Referenzen¶
Registrierung des neuen Dateiformats¶
Godot registriert ResourcesFormatLoader
bei einem ResourceLoader
-Handler. Der Handler wählt automatisch den richtigen Lader aus, wenn load
aufgerufen wird.
/* register_types.h */
void register_json_types();
void unregister_json_types();
/* register_types.cpp */
#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.instance();
ResourceLoader::add_resource_format_loader(json_loader);
json_saver.instance();
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();
}
Referenzen¶
Lade es in GDScript¶
Speichern Sie eine Datei mit dem Namen demo.json
mit dem folgenden Inhalt und legen Sie sie im Wurzelordner des Projekts ab:
{
"savefilename": "demo.json",
"demo": [
"welcome",
"to",
"godot",
"resource",
"loaders"
]
}
Anschließend fügen Sie die folgenden beiden Funktionen hinzu:
extends Node
onready var json_resource = load("res://demo.json")
func _ready():
print(json_resource.get_dict())