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:
99alfie
2020-03-02 13:53:07 +01:00
committed by GitHub
parent 3439f85bb2
commit 6349d303af

View File

@@ -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())