自定义资源格式加载程序¶
介绍¶
ResourceFormatLoader是用于加载文件资源的工厂接口。资源是主要容器。当再次在同一文件路径上调用LOAD时,将引用先前加载的资源。当然,加载的资源必须是无状态的。
本指南假定读者知道如何创建C++模块和Godot数据类型。如果没有,请参阅本指南。 C++中的自定义模块 .
为何?¶
添加对多种文件格式的新支持
音频格式
视频格式
机器学习模型
创建ResourceFormatLoader¶
每个文件格式由一个数据容器和一个 ResourceFormatLoader
.
resourceformatloader通常是简单的类,它返回在godot中支持新扩展所需的所有元数据。类必须返回格式名和扩展字符串。
此外,ResourceFormatLoader必须使用 load
功能。要加载资源, load
必须读取并处理数据序列化。
#ifndef MY_JSON_LOADER_H
#define MY_JSON_LOADER_H
#include "core/io/resource_loader.h"
class ResourceFormatLoaderMyJson : public 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> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
ResourceFormatLoaderMyJson();
virtual ~ResourceFormatLoaderMyJson() {}
};
#endif // MY_JSON_LOADER_H
#include "my_json_loader.h"
#include "my_json.h"
ResourceFormatLoaderMyJson::ResourceFormatLoaderMyJson() {
}
RES ResourceFormatLoaderMyJson::load(const String &p_path, const String &p_original_path, Error *r_error) {
MyJson *my = memnew(MyJson);
if (r_error)
*r_error = OK;
Error err = my->set_file(p_path);
return Ref<MyJson>(my);
}
void ResourceFormatLoaderMyJson::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("mjson");
}
String ResourceFormatLoaderMyJson::get_resource_type(const String &p_path) const {
if (p_path.get_extension().to_lower() == "mjson")
return "MyJson";
return "";
}
bool ResourceFormatLoaderMyJson::handles_type(const String &p_type) const {
return (p_type == "MyJson");
}
创建自定义数据类型¶
Godot在其内部可能没有合适的替代品。 核心类型 或管理资源。Godot需要一个新的注册数据类型来理解其他二进制格式,如机器学习模型。
下面是如何创建自定义数据类型的示例
#ifndef MY_JSON_H
#define MY_JSON_H
#include "core/dictionary.h"
#include "core/io/json.h"
#include "core/reference.h"
#include "core/variant.h"
#include "core/variant_parser.h"
class MyJson : public Resource {
GDCLASS(MyJson, Resource);
protected:
static void _bind_methods() {
ClassDB::bind_method(D_METHOD("to_string"), &MyJson::to_string);
}
private:
Dictionary dict;
public:
Error set_file(const String &p_path) {
Error error_file;
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error_file);
String buf = String("");
while (!file->eof_reached()) {
buf += file->get_line();
}
String err_string;
int err_line;
JSON cmd;
Variant ret;
Error err = cmd.parse(buf, ret, err_string, err_line);
dict = Dictionary(ret);
file->close();
return OK;
}
String to_string() const {
return String(*this);
}
operator String() const {
JSON a;
return a.print(dict);
}
MyJson() {};
~MyJson() {};
};
#endif // MY_JSON_H
考虑事项¶
有些库可能没有定义某些公共例程,如IO处理。因此,需要进行godot调用翻译。
例如,下面是用于翻译的代码 FileAccess
调入 std::istream
.
#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
被称为。
/* register_types.cpp */
#include "register_types.h"
#include "core/class_db.h"
#include "my_json_loader.h"
#include "my_json.h"
static ResourceFormatLoaderMyJson *my_json_loader = NULL;
void register_my_json_types() {
my_json_loader = memnew(ResourceFormatLoaderMyJson);
ResourceLoader::add_resource_format_loader(my_json_loader);
ClassDB::register_class<MyJson>();
}
void unregister_my_json_types() {
memdelete(my_json_loader);
}
在gdscript上加载¶
{
"savefilename" : "demo.mjson",
"demo": [
"welcome",
"to",
"godot",
"resource",
"loaders"
]
}
extends Node
func _ready():
var myjson = load("res://demo.mjson")
print(myjson.to_string())