mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
replaced erroneous sourcecode parts, added resource saver (#2750)
* replaced erroneous sourcecode parts, added resource saver * changed spaces to tabs * changed tabs to 4space+tab(s) * Update development/cpp/custom_resource_format_loaders.rst Co-Authored-By: Hugo Locurcio <hugo.locurcio@hugo.pro> Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
This commit is contained in:
@@ -57,55 +57,100 @@ read and handle data serialization.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#ifndef MY_JSON_LOADER_H
|
||||
#define MY_JSON_LOADER_H
|
||||
/* resource_loader_json.h */
|
||||
|
||||
#include "core/io/resource_loader.h"
|
||||
#ifndef RESOURCE_LOADER_JSON_H
|
||||
#define RESOURCE_LOADER_JSON_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;
|
||||
#include "core/io/resource_loader.h"
|
||||
|
||||
ResourceFormatLoaderMyJson();
|
||||
virtual ~ResourceFormatLoaderMyJson() {}
|
||||
};
|
||||
#endif // MY_JSON_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> *p_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
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "my_json_loader.h"
|
||||
#include "my_json.h"
|
||||
/* resource_loader_json.cpp */
|
||||
|
||||
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");
|
||||
}
|
||||
#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> *p_extensions) const {
|
||||
if (!p_extensions->find("json"))
|
||||
p_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"));
|
||||
}
|
||||
|
||||
Creating a ResourceFormatSaver
|
||||
------------------------------
|
||||
|
||||
If you'd like to be able to edit and save a resource, you can implement a ResourceFormatSaver:
|
||||
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
/* 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> *p_extensions) const;
|
||||
};
|
||||
#endif // RESOURCE_SAVER_JSON_H
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
/* 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> *p_extensions) const {
|
||||
if (Object::cast_to<JsonResource>(*p_resource))
|
||||
p_extensions->push_back("json");
|
||||
}
|
||||
|
||||
Creating custom data types
|
||||
--------------------------
|
||||
|
||||
@@ -117,58 +162,95 @@ Here is an example of how to create a custom datatype
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#ifndef MY_JSON_H
|
||||
#define MY_JSON_H
|
||||
/* resource_json.h */
|
||||
|
||||
#include "core/dictionary.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/reference.h"
|
||||
#include "core/variant.h"
|
||||
#include "core/variant_parser.h"
|
||||
#ifndef RESOURCE_JSON_H
|
||||
#define RESOURCE_JSON_H
|
||||
|
||||
class MyJson : public Resource {
|
||||
GDCLASS(MyJson, Resource);
|
||||
#include "core/io/json.h"
|
||||
#include "core/variant_parser.h"
|
||||
|
||||
protected:
|
||||
static void _bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("to_string"), &MyJson::to_string);
|
||||
}
|
||||
class JsonResource : public Resource {
|
||||
GDCLASS(JsonResource, Resource);
|
||||
|
||||
private:
|
||||
Dictionary dict;
|
||||
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);
|
||||
|
||||
public:
|
||||
Error set_file(const String &p_path) {
|
||||
Error error_file;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error_file);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "content", PROPERTY_HINT_NONE, ""), "set_dict", "get_dict");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
private:
|
||||
Dictionary content;
|
||||
|
||||
String to_string() const {
|
||||
return String(*this);
|
||||
}
|
||||
public:
|
||||
Error load_file(const String &p_path);
|
||||
Error save_file(const String &p_path, const RES &p_resource);
|
||||
|
||||
operator String() const {
|
||||
JSON a;
|
||||
return a.print(dict);
|
||||
}
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
};
|
||||
#endif // RESOURCE_JSON_H
|
||||
|
||||
MyJson() {};
|
||||
~MyJson() {};
|
||||
};
|
||||
#endif // MY_JSON_H
|
||||
.. code:: cpp
|
||||
|
||||
/* 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 Error::OK;
|
||||
}
|
||||
|
||||
void JsonResource::set_dict(const Dictionary &p_dict) {
|
||||
content = p_dict;
|
||||
}
|
||||
|
||||
Dictionary JsonResource::get_dict() {
|
||||
return content;
|
||||
}
|
||||
|
||||
Considerations
|
||||
~~~~~~~~~~~~~~
|
||||
@@ -181,32 +263,32 @@ calls into ``std::istream``.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <istream>
|
||||
#include <streambuf>
|
||||
#include <istream>
|
||||
#include <streambuf>
|
||||
|
||||
class GodotFileInStreamBuf : public std::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();
|
||||
}
|
||||
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;
|
||||
};
|
||||
private:
|
||||
FileAccess *_file;
|
||||
};
|
||||
|
||||
|
||||
References
|
||||
@@ -225,23 +307,42 @@ when ``load`` is called.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* register_types.cpp */
|
||||
#include "register_types.h"
|
||||
#include "core/class_db.h"
|
||||
/* register_types.h */
|
||||
|
||||
#include "my_json_loader.h"
|
||||
#include "my_json.h"
|
||||
void register_json_types();
|
||||
void unregister_json_types();
|
||||
|
||||
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>();
|
||||
}
|
||||
.. code:: cpp
|
||||
|
||||
void unregister_my_json_types() {
|
||||
memdelete(my_json_loader);
|
||||
}
|
||||
/* 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();
|
||||
}
|
||||
|
||||
References
|
||||
~~~~~~~~~~
|
||||
@@ -253,8 +354,9 @@ Loading it on GDScript
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
/* example .json file */
|
||||
{
|
||||
"savefilename" : "demo.mjson",
|
||||
"savefilename" : "demo.json",
|
||||
"demo": [
|
||||
"welcome",
|
||||
"to",
|
||||
@@ -268,6 +370,7 @@ Loading it on GDScript
|
||||
|
||||
extends Node
|
||||
|
||||
onready var json_resource = load("res://demo.json")
|
||||
|
||||
func _ready():
|
||||
var myjson = load("res://demo.mjson")
|
||||
print(myjson.to_string())
|
||||
print(json_resource.get_dict())
|
||||
|
||||
Reference in New Issue
Block a user