-Added new scene conversion to binary on export (disabled by default, please test)
-This method works by directly converting text to binary, so the scene does not need to be loaded and saved
This commit is contained in:
parent
01c04d611f
commit
251433847f
7 changed files with 671 additions and 251 deletions
|
@ -104,7 +104,7 @@ StringName ResourceInteractiveLoaderBinary::_get_string() {
|
||||||
|
|
||||||
uint32_t id = f->get_32();
|
uint32_t id = f->get_32();
|
||||||
if (id & 0x80000000) {
|
if (id & 0x80000000) {
|
||||||
int len = id & 0x7FFFFFFF;
|
uint len = id & 0x7FFFFFFF;
|
||||||
if (len > str_buf.size()) {
|
if (len > str_buf.size()) {
|
||||||
str_buf.resize(len);
|
str_buf.resize(len);
|
||||||
}
|
}
|
||||||
|
@ -734,6 +734,7 @@ Error ResourceInteractiveLoaderBinary::poll() {
|
||||||
for (int i = 0; i < pc; i++) {
|
for (int i = 0; i < pc; i++) {
|
||||||
|
|
||||||
StringName name = _get_string();
|
StringName name = _get_string();
|
||||||
|
|
||||||
if (name == StringName()) {
|
if (name == StringName()) {
|
||||||
error = ERR_FILE_CORRUPT;
|
error = ERR_FILE_CORRUPT;
|
||||||
ERR_FAIL_V(ERR_FILE_CORRUPT);
|
ERR_FAIL_V(ERR_FILE_CORRUPT);
|
||||||
|
@ -902,7 +903,9 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
|
||||||
|
|
||||||
ExtResource er;
|
ExtResource er;
|
||||||
er.type = get_unicode_string();
|
er.type = get_unicode_string();
|
||||||
|
|
||||||
er.path = get_unicode_string();
|
er.path = get_unicode_string();
|
||||||
|
|
||||||
external_resources.push_back(er);
|
external_resources.push_back(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,7 +1274,7 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) {
|
void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) {
|
||||||
|
|
||||||
int extra = 4 - (p_bytes % 4);
|
int extra = 4 - (p_bytes % 4);
|
||||||
if (extra < 4) {
|
if (extra < 4) {
|
||||||
|
@ -1280,7 +1283,12 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, const PropertyInfo &p_hint) {
|
void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) {
|
||||||
|
|
||||||
|
write_variant(f, p_property, resource_set, external_resources, string_map, p_hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
|
||||||
|
|
||||||
switch (p_property.get_type()) {
|
switch (p_property.get_type()) {
|
||||||
|
|
||||||
|
@ -1327,7 +1335,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
|
|
||||||
f->store_32(VARIANT_STRING);
|
f->store_32(VARIANT_STRING);
|
||||||
String val = p_property;
|
String val = p_property;
|
||||||
save_unicode_string(val);
|
save_unicode_string(f, val);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::VECTOR2: {
|
case Variant::VECTOR2: {
|
||||||
|
@ -1453,10 +1461,20 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
if (np.is_absolute())
|
if (np.is_absolute())
|
||||||
snc |= 0x8000;
|
snc |= 0x8000;
|
||||||
f->store_16(snc);
|
f->store_16(snc);
|
||||||
for (int i = 0; i < np.get_name_count(); i++)
|
for (int i = 0; i < np.get_name_count(); i++) {
|
||||||
f->store_32(get_string_index(np.get_name(i)));
|
if (string_map.has(np.get_name(i))) {
|
||||||
for (int i = 0; i < np.get_subname_count(); i++)
|
f->store_32(string_map[np.get_name(i)]);
|
||||||
f->store_32(get_string_index(np.get_subname(i)));
|
} else {
|
||||||
|
save_unicode_string(f, np.get_name(i), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < np.get_subname_count(); i++) {
|
||||||
|
if (string_map.has(np.get_subname(i))) {
|
||||||
|
f->store_32(string_map[np.get_subname(i)]);
|
||||||
|
} else {
|
||||||
|
save_unicode_string(f, np.get_subname(i), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::_RID: {
|
case Variant::_RID: {
|
||||||
|
@ -1508,8 +1526,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
continue;
|
continue;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
write_variant(E->get());
|
write_variant(f, E->get(), resource_set, external_resources, string_map);
|
||||||
write_variant(d[E->get()]);
|
write_variant(f, d[E->get()], resource_set, external_resources, string_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1520,7 +1538,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
f->store_32(uint32_t(a.size()));
|
f->store_32(uint32_t(a.size()));
|
||||||
for (int i = 0; i < a.size(); i++) {
|
for (int i = 0; i < a.size(); i++) {
|
||||||
|
|
||||||
write_variant(a[i]);
|
write_variant(f, a[i], resource_set, external_resources, string_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1532,7 +1550,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
f->store_32(len);
|
f->store_32(len);
|
||||||
PoolVector<uint8_t>::Read r = arr.read();
|
PoolVector<uint8_t>::Read r = arr.read();
|
||||||
f->store_buffer(r.ptr(), len);
|
f->store_buffer(r.ptr(), len);
|
||||||
_pad_buffer(len);
|
_pad_buffer(f, len);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::POOL_INT_ARRAY: {
|
case Variant::POOL_INT_ARRAY: {
|
||||||
|
@ -1566,7 +1584,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
||||||
f->store_32(len);
|
f->store_32(len);
|
||||||
PoolVector<String>::Read r = arr.read();
|
PoolVector<String>::Read r = arr.read();
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
save_unicode_string(r[i]);
|
save_unicode_string(f, r[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1693,10 +1711,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceFormatSaverBinaryInstance::save_unicode_string(const String &p_string) {
|
void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) {
|
||||||
|
|
||||||
CharString utf8 = p_string.utf8();
|
CharString utf8 = p_string.utf8();
|
||||||
f->store_32(utf8.length() + 1);
|
if (p_bit_on_len) {
|
||||||
|
f->store_32(utf8.length() + 1 | 0x80000000);
|
||||||
|
} else {
|
||||||
|
f->store_32(utf8.length() + 1);
|
||||||
|
}
|
||||||
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
|
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,7 +1785,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
return ERR_CANT_CREATE;
|
return ERR_CANT_CREATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_unicode_string(p_resource->get_class());
|
save_unicode_string(f, p_resource->get_class());
|
||||||
f->store_64(0); //offset to import metadata
|
f->store_64(0); //offset to import metadata
|
||||||
for (int i = 0; i < 14; i++)
|
for (int i = 0; i < 14; i++)
|
||||||
f->store_32(0); // reserved
|
f->store_32(0); // reserved
|
||||||
|
@ -1800,7 +1822,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
|
|
||||||
f->store_32(strings.size()); //string table size
|
f->store_32(strings.size()); //string table size
|
||||||
for (int i = 0; i < strings.size(); i++) {
|
for (int i = 0; i < strings.size(); i++) {
|
||||||
save_unicode_string(strings[i]);
|
save_unicode_string(f, strings[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save external resource table
|
// save external resource table
|
||||||
|
@ -1814,10 +1836,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
|
|
||||||
for (int i = 0; i < save_order.size(); i++) {
|
for (int i = 0; i < save_order.size(); i++) {
|
||||||
|
|
||||||
save_unicode_string(save_order[i]->get_save_class());
|
save_unicode_string(f, save_order[i]->get_save_class());
|
||||||
String path = save_order[i]->get_path();
|
String path = save_order[i]->get_path();
|
||||||
path = relative_paths ? local_path.path_to_file(path) : path;
|
path = relative_paths ? local_path.path_to_file(path) : path;
|
||||||
save_unicode_string(path);
|
save_unicode_string(f, path);
|
||||||
}
|
}
|
||||||
// save internal resource table
|
// save internal resource table
|
||||||
f->store_32(saved_resources.size()); //amount of internal resources
|
f->store_32(saved_resources.size()); //amount of internal resources
|
||||||
|
@ -1853,7 +1875,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
used_indices.insert(new_subindex);
|
used_indices.insert(new_subindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
save_unicode_string("local://" + itos(r->get_subindex()));
|
save_unicode_string(f, "local://" + itos(r->get_subindex()));
|
||||||
if (takeover_paths) {
|
if (takeover_paths) {
|
||||||
r->set_path(p_path + "::" + itos(r->get_subindex()), true);
|
r->set_path(p_path + "::" + itos(r->get_subindex()), true);
|
||||||
}
|
}
|
||||||
|
@ -1861,7 +1883,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
r->set_edited(false);
|
r->set_edited(false);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
save_unicode_string(r->get_path()); //actual external
|
save_unicode_string(f, r->get_path()); //actual external
|
||||||
}
|
}
|
||||||
ofs_pos.push_back(f->get_position());
|
ofs_pos.push_back(f->get_position());
|
||||||
f->store_64(0); //offset in 64 bits
|
f->store_64(0); //offset in 64 bits
|
||||||
|
@ -1875,14 +1897,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
|
||||||
ResourceData &rd = E->get();
|
ResourceData &rd = E->get();
|
||||||
|
|
||||||
ofs_table.push_back(f->get_position());
|
ofs_table.push_back(f->get_position());
|
||||||
save_unicode_string(rd.type);
|
save_unicode_string(f, rd.type);
|
||||||
f->store_32(rd.properties.size());
|
f->store_32(rd.properties.size());
|
||||||
|
|
||||||
for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) {
|
for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) {
|
||||||
|
|
||||||
Property &p = F->get();
|
Property &p = F->get();
|
||||||
f->store_32(p.name_idx);
|
f->store_32(p.name_idx);
|
||||||
write_variant(p.value, F->get().pi);
|
_write_variant(p.value, F->get().pi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,14 +140,15 @@ class ResourceFormatSaverBinaryInstance {
|
||||||
List<Property> properties;
|
List<Property> properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _pad_buffer(int p_bytes);
|
static void _pad_buffer(FileAccess *f, int p_bytes);
|
||||||
void write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
|
void _write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
|
||||||
void _find_resources(const Variant &p_variant, bool p_main = false);
|
void _find_resources(const Variant &p_variant, bool p_main = false);
|
||||||
void save_unicode_string(const String &p_string);
|
static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false);
|
||||||
int get_string_index(const String &p_string);
|
int get_string_index(const String &p_string);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
|
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
|
||||||
|
static void write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
||||||
|
|
|
@ -39,10 +39,10 @@
|
||||||
#include "io/zip_io.h"
|
#include "io/zip_io.h"
|
||||||
#include "os/file_access.h"
|
#include "os/file_access.h"
|
||||||
#include "project_settings.h"
|
#include "project_settings.h"
|
||||||
|
#include "scene/resources/scene_format_text.h"
|
||||||
#include "script_language.h"
|
#include "script_language.h"
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
#include "thirdparty/misc/md5.h"
|
#include "thirdparty/misc/md5.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static int _get_pad(int p_alignment, int p_n) {
|
static int _get_pad(int p_alignment, int p_n) {
|
||||||
|
|
||||||
|
@ -1399,3 +1399,30 @@ EditorExportPlatformPC::EditorExportPlatformPC() {
|
||||||
|
|
||||||
chmod_flags = -1;
|
chmod_flags = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
void EditorExportTextSceneToBinaryPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
|
||||||
|
|
||||||
|
String extension = p_path.get_extension().to_lower();
|
||||||
|
if (extension != "tres" && extension != "tscn") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_line("exporting " + p_path);
|
||||||
|
|
||||||
|
bool convert = GLOBAL_GET("editor/convert_text_resources_to_binary_on_export");
|
||||||
|
if (!convert)
|
||||||
|
return;
|
||||||
|
String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("file.res");
|
||||||
|
Error err = ResourceFormatLoaderText::convert_file_to_binary(p_path, tmp_path);
|
||||||
|
ERR_FAIL_COND(err != OK);
|
||||||
|
Vector<uint8_t> data = FileAccess::get_file_as_array(tmp_path);
|
||||||
|
ERR_FAIL_COND(data.size() == 0);
|
||||||
|
add_file(p_path + ".converted.res", data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorExportTextSceneToBinaryPlugin::EditorExportTextSceneToBinaryPlugin() {
|
||||||
|
|
||||||
|
GLOBAL_DEF("editor/convert_text_resources_to_binary_on_export", false);
|
||||||
|
}
|
||||||
|
|
|
@ -408,4 +408,13 @@ public:
|
||||||
EditorExportPlatformPC();
|
EditorExportPlatformPC();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EditorExportTextSceneToBinaryPlugin : public EditorExportPlugin {
|
||||||
|
|
||||||
|
GDCLASS(EditorExportTextSceneToBinaryPlugin, EditorExportPlugin)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features);
|
||||||
|
EditorExportTextSceneToBinaryPlugin();
|
||||||
|
};
|
||||||
|
|
||||||
#endif // EDITOR_IMPORT_EXPORT_H
|
#endif // EDITOR_IMPORT_EXPORT_H
|
||||||
|
|
|
@ -5718,6 +5718,11 @@ EditorNode::EditorNode() {
|
||||||
editor_plugins_force_over = memnew(EditorPluginList);
|
editor_plugins_force_over = memnew(EditorPluginList);
|
||||||
editor_plugins_force_input_forwarding = memnew(EditorPluginList);
|
editor_plugins_force_input_forwarding = memnew(EditorPluginList);
|
||||||
|
|
||||||
|
Ref<EditorExportTextSceneToBinaryPlugin> export_text_to_binary_plugin;
|
||||||
|
export_text_to_binary_plugin.instance();
|
||||||
|
|
||||||
|
EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin);
|
||||||
|
|
||||||
_edit_current();
|
_edit_current();
|
||||||
current = NULL;
|
current = NULL;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#include "scene_format_text.h"
|
#include "scene_format_text.h"
|
||||||
|
#include "core/io/resource_format_binary.h"
|
||||||
#include "os/dir_access.h"
|
#include "os/dir_access.h"
|
||||||
#include "project_settings.h"
|
#include "project_settings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -53,6 +53,60 @@ Ref<Resource> ResourceInteractiveLoaderText::get_resource() {
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error ResourceInteractiveLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
|
||||||
|
|
||||||
|
VariantParser::Token token;
|
||||||
|
VariantParser::get_token(p_stream, token, line, r_err_str);
|
||||||
|
if (token.type != VariantParser::TK_NUMBER) {
|
||||||
|
r_err_str = "Expected number (sub-resource index)";
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = token.value;
|
||||||
|
|
||||||
|
if (!p_data->resource_map.has(index)) {
|
||||||
|
Ref<DummyResource> dr;
|
||||||
|
dr.instance();
|
||||||
|
dr->set_subindex(index);
|
||||||
|
p_data->resource_map[index] = dr;
|
||||||
|
p_data->resource_set.insert(dr);
|
||||||
|
}
|
||||||
|
|
||||||
|
r_res = p_data->resource_map[index];
|
||||||
|
|
||||||
|
VariantParser::get_token(p_stream, token, line, r_err_str);
|
||||||
|
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
|
||||||
|
r_err_str = "Expected ')'";
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ResourceInteractiveLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
|
||||||
|
|
||||||
|
VariantParser::Token token;
|
||||||
|
VariantParser::get_token(p_stream, token, line, r_err_str);
|
||||||
|
if (token.type != VariantParser::TK_NUMBER) {
|
||||||
|
r_err_str = "Expected number (sub-resource index)";
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = token.value;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
|
||||||
|
|
||||||
|
r_res = p_data->rev_external_resources[id];
|
||||||
|
|
||||||
|
VariantParser::get_token(p_stream, token, line, r_err_str);
|
||||||
|
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
|
||||||
|
r_err_str = "Expected ')'";
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
|
Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
|
||||||
|
|
||||||
VariantParser::Token token;
|
VariantParser::Token token;
|
||||||
|
@ -131,6 +185,203 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream *
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) {
|
||||||
|
Ref<PackedScene> packed_scene;
|
||||||
|
packed_scene.instance();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
if (next_tag.name == "node") {
|
||||||
|
|
||||||
|
int parent = -1;
|
||||||
|
int owner = -1;
|
||||||
|
int type = -1;
|
||||||
|
int name = -1;
|
||||||
|
int instance = -1;
|
||||||
|
//int base_scene=-1;
|
||||||
|
|
||||||
|
if (next_tag.fields.has("name")) {
|
||||||
|
name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("parent")) {
|
||||||
|
NodePath np = next_tag.fields["parent"];
|
||||||
|
np.prepend_period(); //compatible to how it manages paths internally
|
||||||
|
parent = packed_scene->get_state()->add_node_path(np);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("type")) {
|
||||||
|
type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
|
||||||
|
} else {
|
||||||
|
type = SceneState::TYPE_INSTANCED; //no type? assume this was instanced
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("instance")) {
|
||||||
|
|
||||||
|
instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
|
||||||
|
|
||||||
|
if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
|
||||||
|
packed_scene->get_state()->set_base_scene(instance);
|
||||||
|
instance = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("instance_placeholder")) {
|
||||||
|
|
||||||
|
String path = next_tag.fields["instance_placeholder"];
|
||||||
|
|
||||||
|
int path_v = packed_scene->get_state()->add_value(path);
|
||||||
|
|
||||||
|
if (packed_scene->get_state()->get_node_count() == 0) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Instance Placeholder can't be used for inheritance.";
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("owner")) {
|
||||||
|
owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
|
||||||
|
} else {
|
||||||
|
if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1))
|
||||||
|
owner = 0; //if no owner, owner is root
|
||||||
|
}
|
||||||
|
|
||||||
|
int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance);
|
||||||
|
|
||||||
|
if (next_tag.fields.has("groups")) {
|
||||||
|
|
||||||
|
Array groups = next_tag.fields["groups"];
|
||||||
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
|
packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
String assign;
|
||||||
|
Variant value;
|
||||||
|
|
||||||
|
error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &parser);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error != ERR_FILE_EOF) {
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
} else {
|
||||||
|
return packed_scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assign != String()) {
|
||||||
|
int nameidx = packed_scene->get_state()->add_name(assign);
|
||||||
|
int valueidx = packed_scene->get_state()->add_value(value);
|
||||||
|
packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx);
|
||||||
|
//it's assignment
|
||||||
|
} else if (next_tag.name != String()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (next_tag.name == "connection") {
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("from")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "missing 'from' field fron connection tag";
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("to")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "missing 'to' field fron connection tag";
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("signal")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "missing 'signal' field fron connection tag";
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("method")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "missing 'method' field fron connection tag";
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath from = next_tag.fields["from"];
|
||||||
|
NodePath to = next_tag.fields["to"];
|
||||||
|
StringName method = next_tag.fields["method"];
|
||||||
|
StringName signal = next_tag.fields["signal"];
|
||||||
|
int flags = CONNECT_PERSIST;
|
||||||
|
Array binds;
|
||||||
|
|
||||||
|
if (next_tag.fields.has("flags")) {
|
||||||
|
flags = next_tag.fields["flags"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.fields.has("binds")) {
|
||||||
|
binds = next_tag.fields["binds"];
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<int> bind_ints;
|
||||||
|
for (int i = 0; i < binds.size(); i++) {
|
||||||
|
bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
packed_scene->get_state()->add_connection(
|
||||||
|
packed_scene->get_state()->add_node_path(from.simplified()),
|
||||||
|
packed_scene->get_state()->add_node_path(to.simplified()),
|
||||||
|
packed_scene->get_state()->add_name(signal),
|
||||||
|
packed_scene->get_state()->add_name(method),
|
||||||
|
flags,
|
||||||
|
bind_ints);
|
||||||
|
|
||||||
|
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error != ERR_FILE_EOF) {
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
} else {
|
||||||
|
return packed_scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (next_tag.name == "editable") {
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("path")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "missing 'path' field fron connection tag";
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath path = next_tag.fields["path"];
|
||||||
|
|
||||||
|
packed_scene->get_state()->add_editable_instance(path.simplified());
|
||||||
|
|
||||||
|
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error != ERR_FILE_EOF) {
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
} else {
|
||||||
|
return packed_scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
_printerr();
|
||||||
|
return Ref<PackedScene>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return packed_scene;
|
||||||
|
}
|
||||||
|
|
||||||
Error ResourceInteractiveLoaderText::poll() {
|
Error ResourceInteractiveLoaderText::poll() {
|
||||||
|
|
||||||
if (error != OK)
|
if (error != OK)
|
||||||
|
@ -364,231 +615,21 @@ Error ResourceInteractiveLoaderText::poll() {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Ref<PackedScene> packed_scene = _parse_node_tag(rp);
|
||||||
int add_name(const StringName& p_name);
|
|
||||||
int add_value(const Variant& p_value);
|
|
||||||
int add_node_path(const NodePath& p_path);
|
|
||||||
int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance);
|
|
||||||
void add_node_property(int p_node,int p_name,int p_value);
|
|
||||||
void add_node_group(int p_node,int p_group);
|
|
||||||
void set_base_scene(int p_idx);
|
|
||||||
void add_connection(int p_from,int p_to, int p_signal, int p_method, int p_flags,const Vector<int>& p_binds);
|
|
||||||
void add_editable_instance(const NodePath& p_path);
|
|
||||||
|
|
||||||
*/
|
if (!packed_scene.is_valid())
|
||||||
|
|
||||||
int parent = -1;
|
|
||||||
int owner = -1;
|
|
||||||
int type = -1;
|
|
||||||
int name = -1;
|
|
||||||
int instance = -1;
|
|
||||||
//int base_scene=-1;
|
|
||||||
|
|
||||||
if (next_tag.fields.has("name")) {
|
|
||||||
name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("parent")) {
|
|
||||||
NodePath np = next_tag.fields["parent"];
|
|
||||||
np.prepend_period(); //compatible to how it manages paths internally
|
|
||||||
parent = packed_scene->get_state()->add_node_path(np);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("type")) {
|
|
||||||
type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
|
|
||||||
} else {
|
|
||||||
type = SceneState::TYPE_INSTANCED; //no type? assume this was instanced
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("instance")) {
|
|
||||||
|
|
||||||
instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
|
|
||||||
|
|
||||||
if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
|
|
||||||
packed_scene->get_state()->set_base_scene(instance);
|
|
||||||
instance = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("instance_placeholder")) {
|
|
||||||
|
|
||||||
String path = next_tag.fields["instance_placeholder"];
|
|
||||||
|
|
||||||
int path_v = packed_scene->get_state()->add_value(path);
|
|
||||||
|
|
||||||
if (packed_scene->get_state()->get_node_count() == 0) {
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "Instance Placeholder can't be used for inheritance.";
|
|
||||||
_printerr();
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("owner")) {
|
|
||||||
owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
|
|
||||||
} else {
|
|
||||||
if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1))
|
|
||||||
owner = 0; //if no owner, owner is root
|
|
||||||
}
|
|
||||||
|
|
||||||
int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance);
|
|
||||||
|
|
||||||
if (next_tag.fields.has("groups")) {
|
|
||||||
|
|
||||||
Array groups = next_tag.fields["groups"];
|
|
||||||
for (int i = 0; i < groups.size(); i++) {
|
|
||||||
packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
String assign;
|
|
||||||
Variant value;
|
|
||||||
|
|
||||||
error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
if (error != ERR_FILE_EOF) {
|
|
||||||
_printerr();
|
|
||||||
} else {
|
|
||||||
resource = packed_scene;
|
|
||||||
if (!ResourceCache::has(res_path)) {
|
|
||||||
packed_scene->set_path(res_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assign != String()) {
|
|
||||||
int nameidx = packed_scene->get_state()->add_name(assign);
|
|
||||||
int valueidx = packed_scene->get_state()->add_value(value);
|
|
||||||
packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx);
|
|
||||||
//it's assignment
|
|
||||||
} else if (next_tag.name != String()) {
|
|
||||||
|
|
||||||
error = OK;
|
|
||||||
return error;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
resource = packed_scene;
|
|
||||||
error = ERR_FILE_EOF;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
} else if (next_tag.name == "connection") {
|
|
||||||
|
|
||||||
if (!is_scene) {
|
|
||||||
|
|
||||||
error_text += "found the 'connection' tag on a resource file!";
|
|
||||||
_printerr();
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
error = OK;
|
||||||
|
//get it here
|
||||||
|
resource = packed_scene;
|
||||||
|
if (!ResourceCache::has(res_path)) {
|
||||||
|
packed_scene->set_path(res_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next_tag.fields.has("from")) {
|
return ERR_FILE_EOF;
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "missing 'from' field fron connection tag";
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!next_tag.fields.has("to")) {
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "missing 'to' field fron connection tag";
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!next_tag.fields.has("signal")) {
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "missing 'signal' field fron connection tag";
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!next_tag.fields.has("method")) {
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "missing 'method' field fron connection tag";
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodePath from = next_tag.fields["from"];
|
|
||||||
NodePath to = next_tag.fields["to"];
|
|
||||||
StringName method = next_tag.fields["method"];
|
|
||||||
StringName signal = next_tag.fields["signal"];
|
|
||||||
int flags = CONNECT_PERSIST;
|
|
||||||
Array binds;
|
|
||||||
|
|
||||||
if (next_tag.fields.has("flags")) {
|
|
||||||
flags = next_tag.fields["flags"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_tag.fields.has("binds")) {
|
|
||||||
binds = next_tag.fields["binds"];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<int> bind_ints;
|
|
||||||
for (int i = 0; i < binds.size(); i++) {
|
|
||||||
bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
packed_scene->get_state()->add_connection(
|
|
||||||
packed_scene->get_state()->add_node_path(from.simplified()),
|
|
||||||
packed_scene->get_state()->add_node_path(to.simplified()),
|
|
||||||
packed_scene->get_state()->add_name(signal),
|
|
||||||
packed_scene->get_state()->add_name(method),
|
|
||||||
flags,
|
|
||||||
bind_ints);
|
|
||||||
|
|
||||||
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
if (error != ERR_FILE_EOF) {
|
|
||||||
_printerr();
|
|
||||||
} else {
|
|
||||||
resource = packed_scene;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
} else if (next_tag.name == "editable") {
|
|
||||||
|
|
||||||
if (!is_scene) {
|
|
||||||
|
|
||||||
error_text += "found the 'editable' tag on a resource file!";
|
|
||||||
_printerr();
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!next_tag.fields.has("path")) {
|
|
||||||
error = ERR_FILE_CORRUPT;
|
|
||||||
error_text = "missing 'path' field fron connection tag";
|
|
||||||
_printerr();
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodePath path = next_tag.fields["path"];
|
|
||||||
|
|
||||||
packed_scene->get_state()->add_editable_instance(path.simplified());
|
|
||||||
|
|
||||||
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
if (error != ERR_FILE_EOF) {
|
|
||||||
_printerr();
|
|
||||||
} else {
|
|
||||||
resource = packed_scene;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
error_text += "Unknown tag in file: " + next_tag.name;
|
error_text += "Unknown tag in file: " + next_tag.name;
|
||||||
_printerr();
|
_printerr();
|
||||||
error = ERR_FILE_CORRUPT;
|
error = ERR_FILE_CORRUPT;
|
||||||
|
@ -804,7 +845,6 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag)
|
||||||
|
|
||||||
if (tag.name == "gd_scene") {
|
if (tag.name == "gd_scene") {
|
||||||
is_scene = true;
|
is_scene = true;
|
||||||
packed_scene.instance();
|
|
||||||
|
|
||||||
} else if (tag.name == "gd_resource") {
|
} else if (tag.name == "gd_resource") {
|
||||||
if (!tag.fields.has("type")) {
|
if (!tag.fields.has("type")) {
|
||||||
|
@ -846,6 +886,281 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag)
|
||||||
rp.userdata = this;
|
rp.userdata = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false) {
|
||||||
|
|
||||||
|
CharString utf8 = p_string.utf8();
|
||||||
|
if (p_bit_on_len) {
|
||||||
|
f->store_32(utf8.length() + 1 | 0x80000000);
|
||||||
|
} else {
|
||||||
|
f->store_32(utf8.length() + 1);
|
||||||
|
}
|
||||||
|
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) {
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
FileAccessRef wf = FileAccess::open(p_path, FileAccess::WRITE);
|
||||||
|
if (!wf) {
|
||||||
|
return ERR_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
//save header compressed
|
||||||
|
static const uint8_t header[4] = { 'R', 'S', 'R', 'C' };
|
||||||
|
wf->store_buffer(header, 4);
|
||||||
|
|
||||||
|
wf->store_32(0); //endianness, little endian
|
||||||
|
wf->store_32(0); //64 bits file, false for now
|
||||||
|
wf->store_32(VERSION_MAJOR);
|
||||||
|
wf->store_32(VERSION_MINOR);
|
||||||
|
static const int save_format_version = 3; //use format version 3 for saving
|
||||||
|
wf->store_32(save_format_version);
|
||||||
|
|
||||||
|
bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type);
|
||||||
|
wf->store_64(0); //offset to import metadata, this is no longer used
|
||||||
|
for (int i = 0; i < 14; i++)
|
||||||
|
wf->store_32(0); // reserved
|
||||||
|
|
||||||
|
wf->store_32(0); //string table size, will not be in use
|
||||||
|
size_t ext_res_count_pos = wf->get_position();
|
||||||
|
|
||||||
|
wf->store_32(0); //zero ext resources, still parsing them
|
||||||
|
|
||||||
|
//go with external resources
|
||||||
|
|
||||||
|
DummyReadData dummy_read;
|
||||||
|
VariantParser::ResourceParser rp;
|
||||||
|
rp.ext_func = _parse_ext_resource_dummys;
|
||||||
|
rp.sub_func = _parse_sub_resource_dummys;
|
||||||
|
rp.userdata = &dummy_read;
|
||||||
|
|
||||||
|
while (next_tag.name == "ext_resource") {
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("path")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Missing 'path' in external resource tag";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("type")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Missing 'type' in external resource tag";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("id")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Missing 'id' in external resource tag";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = next_tag.fields["path"];
|
||||||
|
String type = next_tag.fields["type"];
|
||||||
|
int index = next_tag.fields["id"];
|
||||||
|
|
||||||
|
bs_save_unicode_string(wf.f, type);
|
||||||
|
bs_save_unicode_string(wf.f, path);
|
||||||
|
|
||||||
|
int lindex = dummy_read.external_resources.size();
|
||||||
|
Ref<DummyResource> dr;
|
||||||
|
dr.instance();
|
||||||
|
dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external
|
||||||
|
dummy_read.external_resources[dr] = lindex;
|
||||||
|
dummy_read.rev_external_resources[index] = dr;
|
||||||
|
|
||||||
|
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save external resource table
|
||||||
|
wf->seek(ext_res_count_pos);
|
||||||
|
wf->store_32(dummy_read.external_resources.size());
|
||||||
|
wf->seek_end();
|
||||||
|
|
||||||
|
//now, save resources to a separate file, for now
|
||||||
|
|
||||||
|
size_t sub_res_count_pos = wf->get_position();
|
||||||
|
wf->store_32(0); //zero sub resources, still parsing them
|
||||||
|
|
||||||
|
String temp_file = p_path + ".temp";
|
||||||
|
FileAccessRef wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
|
||||||
|
if (!wf2) {
|
||||||
|
return ERR_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<size_t> local_offsets;
|
||||||
|
Vector<size_t> local_pointers_pos;
|
||||||
|
|
||||||
|
while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
|
||||||
|
|
||||||
|
String type;
|
||||||
|
int id = -1;
|
||||||
|
bool main_res;
|
||||||
|
|
||||||
|
if (next_tag.name == "sub_resource") {
|
||||||
|
if (!next_tag.fields.has("type")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Missing 'type' in external resource tag";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!next_tag.fields.has("id")) {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Missing 'index' in external resource tag";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = next_tag.fields["type"];
|
||||||
|
id = next_tag.fields["id"];
|
||||||
|
main_res = false;
|
||||||
|
} else {
|
||||||
|
type = res_type;
|
||||||
|
id = 0; //used for last anyway
|
||||||
|
main_res = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_offsets.push_back(wf2->get_position());
|
||||||
|
|
||||||
|
bs_save_unicode_string(wf, "local://" + itos(id));
|
||||||
|
local_pointers_pos.push_back(wf->get_position());
|
||||||
|
wf->store_64(0); //temp local offset
|
||||||
|
|
||||||
|
bs_save_unicode_string(wf2, type);
|
||||||
|
size_t propcount_ofs = wf2->get_position();
|
||||||
|
wf2->store_32(0);
|
||||||
|
|
||||||
|
int prop_count = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
String assign;
|
||||||
|
Variant value;
|
||||||
|
|
||||||
|
error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (main_res && error == ERR_FILE_EOF) {
|
||||||
|
next_tag.name = ""; //exit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assign != String()) {
|
||||||
|
|
||||||
|
Map<StringName, int> empty_string_map; //unused
|
||||||
|
bs_save_unicode_string(wf2, assign, true);
|
||||||
|
ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
|
||||||
|
prop_count++;
|
||||||
|
|
||||||
|
} else if (next_tag.name != String()) {
|
||||||
|
|
||||||
|
error = OK;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
error_text = "Premature end of file while parsing [sub_resource]";
|
||||||
|
_printerr();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wf2->seek(propcount_ofs);
|
||||||
|
wf2->store_32(prop_count);
|
||||||
|
wf2->seek_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_tag.name == "node") {
|
||||||
|
//this is a node, must save one more!
|
||||||
|
|
||||||
|
if (!is_scene) {
|
||||||
|
|
||||||
|
error_text += "found the 'node' tag on a resource file!";
|
||||||
|
_printerr();
|
||||||
|
error = ERR_FILE_CORRUPT;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<PackedScene> packed_scene = _parse_node_tag(rp);
|
||||||
|
|
||||||
|
if (!packed_scene.is_valid())
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = OK;
|
||||||
|
//get it here
|
||||||
|
List<PropertyInfo> props;
|
||||||
|
packed_scene->get_property_list(&props);
|
||||||
|
|
||||||
|
bs_save_unicode_string(wf, "local://0");
|
||||||
|
local_pointers_pos.push_back(wf->get_position());
|
||||||
|
wf->store_64(0); //temp local offset
|
||||||
|
|
||||||
|
local_offsets.push_back(wf2->get_position());
|
||||||
|
bs_save_unicode_string(wf2, "PackedScene");
|
||||||
|
size_t propcount_ofs = wf2->get_position();
|
||||||
|
wf2->store_32(0);
|
||||||
|
|
||||||
|
int prop_count = 0;
|
||||||
|
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
|
||||||
|
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String name = E->get().name;
|
||||||
|
Variant value = packed_scene->get(name);
|
||||||
|
|
||||||
|
Map<StringName, int> empty_string_map; //unused
|
||||||
|
bs_save_unicode_string(wf2, name, true);
|
||||||
|
ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
|
||||||
|
prop_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
wf2->seek(propcount_ofs);
|
||||||
|
wf2->store_32(prop_count);
|
||||||
|
wf2->seek_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
wf2->close();
|
||||||
|
|
||||||
|
size_t offset_from = wf->get_position();
|
||||||
|
wf->seek(sub_res_count_pos); //plus one because the saved one
|
||||||
|
wf->store_32(local_offsets.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < local_offsets.size(); i++) {
|
||||||
|
wf->seek(local_pointers_pos[i]);
|
||||||
|
wf->store_64(local_offsets[i] + offset_from);
|
||||||
|
}
|
||||||
|
|
||||||
|
wf->seek_end();
|
||||||
|
|
||||||
|
Vector<uint8_t> data = FileAccess::get_file_as_array(temp_file);
|
||||||
|
wf->store_buffer(data.ptr(), data.size());
|
||||||
|
{
|
||||||
|
DirAccessRef dar = DirAccess::open(temp_file.get_base_dir());
|
||||||
|
dar->remove(temp_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
|
||||||
|
|
||||||
|
wf->close();
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) {
|
String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) {
|
||||||
|
|
||||||
error = OK;
|
error = OK;
|
||||||
|
@ -991,6 +1306,25 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const
|
||||||
return ria->rename_dependencies(f, p_path, p_map);
|
return ria->rename_dependencies(f, p_path, p_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) {
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
FileAccess *f = FileAccess::open(p_src_path, FileAccess::READ, &err);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText);
|
||||||
|
String path = p_src_path;
|
||||||
|
ria->local_path = ProjectSettings::get_singleton()->localize_path(path);
|
||||||
|
ria->res_path = ria->local_path;
|
||||||
|
//ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
|
||||||
|
ria->open(f);
|
||||||
|
return ria->save_as_binary(f, p_dst_path);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************************************/
|
/*****************************************************************************************************/
|
||||||
/*****************************************************************************************************/
|
/*****************************************************************************************************/
|
||||||
/*****************************************************************************************************/
|
/*****************************************************************************************************/
|
||||||
|
|
|
@ -78,9 +78,26 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
|
||||||
Error _parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
Error _parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
||||||
Error _parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
Error _parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
||||||
|
|
||||||
VariantParser::ResourceParser rp;
|
// for converter
|
||||||
|
class DummyResource : public Resource {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
Ref<PackedScene> packed_scene;
|
struct DummyReadData {
|
||||||
|
|
||||||
|
Map<RES, int> external_resources;
|
||||||
|
Map<int, RES> rev_external_resources;
|
||||||
|
Set<RES> resource_set;
|
||||||
|
Map<int, RES> resource_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Error _parse_sub_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_sub_resource_dummy((DummyReadData *)(p_self), p_stream, r_res, line, r_err_str); }
|
||||||
|
static Error _parse_ext_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_ext_resource_dummy((DummyReadData *)(p_self), p_stream, r_res, line, r_err_str); }
|
||||||
|
|
||||||
|
static Error _parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
||||||
|
static Error _parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str);
|
||||||
|
|
||||||
|
VariantParser::ResourceParser rp;
|
||||||
|
|
||||||
friend class ResourceFormatLoaderText;
|
friend class ResourceFormatLoaderText;
|
||||||
|
|
||||||
|
@ -89,6 +106,8 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader {
|
||||||
|
|
||||||
RES resource;
|
RES resource;
|
||||||
|
|
||||||
|
Ref<PackedScene> _parse_node_tag(VariantParser::ResourceParser &parser);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void set_local_path(const String &p_local_path);
|
virtual void set_local_path(const String &p_local_path);
|
||||||
virtual Ref<Resource> get_resource();
|
virtual Ref<Resource> get_resource();
|
||||||
|
@ -102,6 +121,7 @@ public:
|
||||||
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
|
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
|
||||||
Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map);
|
Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map);
|
||||||
|
|
||||||
|
Error save_as_binary(FileAccess *p_f, const String &p_path);
|
||||||
ResourceInteractiveLoaderText();
|
ResourceInteractiveLoaderText();
|
||||||
~ResourceInteractiveLoaderText();
|
~ResourceInteractiveLoaderText();
|
||||||
};
|
};
|
||||||
|
@ -115,6 +135,8 @@ public:
|
||||||
virtual String get_resource_type(const String &p_path) const;
|
virtual String get_resource_type(const String &p_path) const;
|
||||||
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
|
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
|
||||||
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
|
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
|
||||||
|
|
||||||
|
static Error convert_file_to_binary(const String &p_src_path, const String &p_dst_path);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverTextInstance {
|
class ResourceFormatSaverTextInstance {
|
||||||
|
|
Loading…
Reference in a new issue