|
33 | 33 | #include "core/config/project_settings.h" |
34 | 34 | #include "core/io/dir_access.h" |
35 | 35 | #include "core/io/missing_resource.h" |
36 | | -#include "core/io/resource_format_binary.h" |
37 | 36 | #include "core/object/script_language.h" |
38 | | -#include "core/version.h" |
39 | 37 |
|
40 | 38 | // Version 2: Changed names for Basis, AABB, Vectors, etc. |
41 | 39 | // Version 3: New string ID for ext/subresources, breaks forward compat. |
|
44 | 42 | // For compat, save as version 3 if not using PackedVector4Array or no big PackedByteArray. |
45 | 43 | #define FORMAT_VERSION_COMPAT 3 |
46 | 44 |
|
47 | | -#define BINARY_FORMAT_VERSION 4 |
48 | | - |
49 | | -#include "core/io/dir_access.h" |
50 | | -#include "core/version.h" |
51 | | - |
52 | 45 | #define _printerr() ERR_PRINT(String(res_path + ":" + itos(lines) + " - Parse Error: " + error_text).utf8().get_data()); |
53 | 46 |
|
54 | 47 | /// |
@@ -1127,298 +1120,6 @@ void ResourceLoaderText::open(Ref<FileAccess> p_f, bool p_skip_first_tag) { |
1127 | 1120 | rp.userdata = this; |
1128 | 1121 | } |
1129 | 1122 |
|
1130 | | -static void bs_save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len = false) { |
1131 | | - CharString utf8 = p_string.utf8(); |
1132 | | - if (p_bit_on_len) { |
1133 | | - p_f->store_32((utf8.length() + 1) | 0x80000000); |
1134 | | - } else { |
1135 | | - p_f->store_32(utf8.length() + 1); |
1136 | | - } |
1137 | | - p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1); |
1138 | | -} |
1139 | | - |
1140 | | -Error ResourceLoaderText::save_as_binary(const String &p_path) { |
1141 | | - if (error) { |
1142 | | - return error; |
1143 | | - } |
1144 | | - |
1145 | | - Ref<FileAccess> wf = FileAccess::open(p_path, FileAccess::WRITE); |
1146 | | - if (wf.is_null()) { |
1147 | | - return ERR_CANT_OPEN; |
1148 | | - } |
1149 | | - |
1150 | | - //save header compressed |
1151 | | - static const uint8_t header[4] = { 'R', 'S', 'R', 'C' }; |
1152 | | - wf->store_buffer(header, 4); |
1153 | | - |
1154 | | - wf->store_32(0); //endianness, little endian |
1155 | | - wf->store_32(0); //64 bits file, false for now |
1156 | | - wf->store_32(VERSION_MAJOR); |
1157 | | - wf->store_32(VERSION_MINOR); |
1158 | | - static const int save_format_version = BINARY_FORMAT_VERSION; |
1159 | | - wf->store_32(save_format_version); |
1160 | | - |
1161 | | - bs_save_unicode_string(wf, is_scene ? "PackedScene" : resource_type); |
1162 | | - wf->store_64(0); //offset to import metadata, this is no longer used |
1163 | | - |
1164 | | - wf->store_32(ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS | ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS); |
1165 | | - |
1166 | | - wf->store_64(res_uid); |
1167 | | - |
1168 | | - for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) { |
1169 | | - wf->store_32(0); // reserved |
1170 | | - } |
1171 | | - |
1172 | | - wf->store_32(0); //string table size, will not be in use |
1173 | | - uint64_t ext_res_count_pos = wf->get_position(); |
1174 | | - |
1175 | | - wf->store_32(0); //zero ext resources, still parsing them |
1176 | | - |
1177 | | - //go with external resources |
1178 | | - |
1179 | | - DummyReadData dummy_read; |
1180 | | - VariantParser::ResourceParser rp_new; |
1181 | | - rp_new.ext_func = _parse_ext_resource_dummys; |
1182 | | - rp_new.sub_func = _parse_sub_resource_dummys; |
1183 | | - rp_new.userdata = &dummy_read; |
1184 | | - |
1185 | | - while (next_tag.name == "ext_resource") { |
1186 | | - if (!next_tag.fields.has("path")) { |
1187 | | - error = ERR_FILE_CORRUPT; |
1188 | | - error_text = "Missing 'path' in external resource tag"; |
1189 | | - _printerr(); |
1190 | | - return error; |
1191 | | - } |
1192 | | - |
1193 | | - if (!next_tag.fields.has("type")) { |
1194 | | - error = ERR_FILE_CORRUPT; |
1195 | | - error_text = "Missing 'type' in external resource tag"; |
1196 | | - _printerr(); |
1197 | | - return error; |
1198 | | - } |
1199 | | - |
1200 | | - if (!next_tag.fields.has("id")) { |
1201 | | - error = ERR_FILE_CORRUPT; |
1202 | | - error_text = "Missing 'id' in external resource tag"; |
1203 | | - _printerr(); |
1204 | | - return error; |
1205 | | - } |
1206 | | - |
1207 | | - String path = next_tag.fields["path"]; |
1208 | | - String type = next_tag.fields["type"]; |
1209 | | - String id = next_tag.fields["id"]; |
1210 | | - ResourceUID::ID uid = ResourceUID::INVALID_ID; |
1211 | | - if (next_tag.fields.has("uid")) { |
1212 | | - String uidt = next_tag.fields["uid"]; |
1213 | | - uid = ResourceUID::get_singleton()->text_to_id(uidt); |
1214 | | - } |
1215 | | - |
1216 | | - bs_save_unicode_string(wf, type); |
1217 | | - bs_save_unicode_string(wf, path); |
1218 | | - wf->store_64(uid); |
1219 | | - |
1220 | | - int lindex = dummy_read.external_resources.size(); |
1221 | | - Ref<DummyResource> dr; |
1222 | | - dr.instantiate(); |
1223 | | - dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external |
1224 | | - dummy_read.external_resources[dr] = lindex; |
1225 | | - dummy_read.rev_external_resources[id] = dr; |
1226 | | - |
1227 | | - error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp_new); |
1228 | | - |
1229 | | - if (error) { |
1230 | | - _printerr(); |
1231 | | - return error; |
1232 | | - } |
1233 | | - } |
1234 | | - |
1235 | | - // save external resource table |
1236 | | - wf->seek(ext_res_count_pos); |
1237 | | - wf->store_32(dummy_read.external_resources.size()); |
1238 | | - wf->seek_end(); |
1239 | | - |
1240 | | - //now, save resources to a separate file, for now |
1241 | | - |
1242 | | - uint64_t sub_res_count_pos = wf->get_position(); |
1243 | | - wf->store_32(0); //zero sub resources, still parsing them |
1244 | | - |
1245 | | - String temp_file = p_path + ".temp"; |
1246 | | - Vector<uint64_t> local_offsets; |
1247 | | - Vector<uint64_t> local_pointers_pos; |
1248 | | - { |
1249 | | - Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE); |
1250 | | - if (wf2.is_null()) { |
1251 | | - return ERR_CANT_OPEN; |
1252 | | - } |
1253 | | - |
1254 | | - while (next_tag.name == "sub_resource" || next_tag.name == "resource") { |
1255 | | - String type; |
1256 | | - String id; |
1257 | | - bool main_res; |
1258 | | - |
1259 | | - if (next_tag.name == "sub_resource") { |
1260 | | - if (!next_tag.fields.has("type")) { |
1261 | | - error = ERR_FILE_CORRUPT; |
1262 | | - error_text = "Missing 'type' in external resource tag"; |
1263 | | - _printerr(); |
1264 | | - return error; |
1265 | | - } |
1266 | | - |
1267 | | - if (!next_tag.fields.has("id")) { |
1268 | | - error = ERR_FILE_CORRUPT; |
1269 | | - error_text = "Missing 'id' in external resource tag"; |
1270 | | - _printerr(); |
1271 | | - return error; |
1272 | | - } |
1273 | | - |
1274 | | - type = next_tag.fields["type"]; |
1275 | | - id = next_tag.fields["id"]; |
1276 | | - main_res = false; |
1277 | | - |
1278 | | - if (!dummy_read.resource_map.has(id)) { |
1279 | | - Ref<DummyResource> dr; |
1280 | | - dr.instantiate(); |
1281 | | - dr->set_scene_unique_id(id); |
1282 | | - dummy_read.resource_map[id] = dr; |
1283 | | - uint32_t im_size = dummy_read.resource_index_map.size(); |
1284 | | - dummy_read.resource_index_map.insert(dr, im_size); |
1285 | | - } |
1286 | | - |
1287 | | - } else { |
1288 | | - type = res_type; |
1289 | | - String uid_text = ResourceUID::get_singleton()->id_to_text(res_uid); |
1290 | | - id = type + "_" + uid_text.replace("uid://", "").replace("<invalid>", "0"); |
1291 | | - main_res = true; |
1292 | | - } |
1293 | | - |
1294 | | - local_offsets.push_back(wf2->get_position()); |
1295 | | - |
1296 | | - bs_save_unicode_string(wf, "local://" + id); |
1297 | | - local_pointers_pos.push_back(wf->get_position()); |
1298 | | - wf->store_64(0); //temp local offset |
1299 | | - |
1300 | | - bs_save_unicode_string(wf2, type); |
1301 | | - uint64_t propcount_ofs = wf2->get_position(); |
1302 | | - wf2->store_32(0); |
1303 | | - |
1304 | | - int prop_count = 0; |
1305 | | - |
1306 | | - while (true) { |
1307 | | - String assign; |
1308 | | - Variant value; |
1309 | | - |
1310 | | - error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp_new); |
1311 | | - |
1312 | | - if (error) { |
1313 | | - if (main_res && error == ERR_FILE_EOF) { |
1314 | | - next_tag.name = ""; //exit |
1315 | | - break; |
1316 | | - } |
1317 | | - |
1318 | | - _printerr(); |
1319 | | - return error; |
1320 | | - } |
1321 | | - |
1322 | | - if (!assign.is_empty()) { |
1323 | | - HashMap<StringName, int> empty_string_map; //unused |
1324 | | - bs_save_unicode_string(wf2, assign, true); |
1325 | | - ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); |
1326 | | - prop_count++; |
1327 | | - |
1328 | | - } else if (!next_tag.name.is_empty()) { |
1329 | | - error = OK; |
1330 | | - break; |
1331 | | - } else { |
1332 | | - error = ERR_FILE_CORRUPT; |
1333 | | - error_text = "Premature end of file while parsing [sub_resource]"; |
1334 | | - _printerr(); |
1335 | | - return error; |
1336 | | - } |
1337 | | - } |
1338 | | - |
1339 | | - wf2->seek(propcount_ofs); |
1340 | | - wf2->store_32(prop_count); |
1341 | | - wf2->seek_end(); |
1342 | | - } |
1343 | | - |
1344 | | - if (next_tag.name == "node") { |
1345 | | - // This is a node, must save one more! |
1346 | | - |
1347 | | - if (!is_scene) { |
1348 | | - error_text += "found the 'node' tag on a resource file!"; |
1349 | | - _printerr(); |
1350 | | - error = ERR_FILE_CORRUPT; |
1351 | | - return error; |
1352 | | - } |
1353 | | - |
1354 | | - Ref<PackedScene> packed_scene = _parse_node_tag(rp_new); |
1355 | | - |
1356 | | - if (!packed_scene.is_valid()) { |
1357 | | - return error; |
1358 | | - } |
1359 | | - |
1360 | | - error = OK; |
1361 | | - //get it here |
1362 | | - List<PropertyInfo> props; |
1363 | | - packed_scene->get_property_list(&props); |
1364 | | - |
1365 | | - String id = "PackedScene_" + ResourceUID::get_singleton()->id_to_text(res_uid).replace("uid://", "").replace("<invalid>", "0"); |
1366 | | - bs_save_unicode_string(wf, "local://" + id); |
1367 | | - local_pointers_pos.push_back(wf->get_position()); |
1368 | | - wf->store_64(0); //temp local offset |
1369 | | - |
1370 | | - local_offsets.push_back(wf2->get_position()); |
1371 | | - bs_save_unicode_string(wf2, "PackedScene"); |
1372 | | - uint64_t propcount_ofs = wf2->get_position(); |
1373 | | - wf2->store_32(0); |
1374 | | - |
1375 | | - int prop_count = 0; |
1376 | | - |
1377 | | - for (const PropertyInfo &E : props) { |
1378 | | - if (!(E.usage & PROPERTY_USAGE_STORAGE)) { |
1379 | | - continue; |
1380 | | - } |
1381 | | - |
1382 | | - String name = E.name; |
1383 | | - Variant value = packed_scene->get(name); |
1384 | | - |
1385 | | - HashMap<StringName, int> empty_string_map; //unused |
1386 | | - bs_save_unicode_string(wf2, name, true); |
1387 | | - ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); |
1388 | | - prop_count++; |
1389 | | - } |
1390 | | - |
1391 | | - wf2->seek(propcount_ofs); |
1392 | | - wf2->store_32(prop_count); |
1393 | | - wf2->seek_end(); |
1394 | | - } |
1395 | | - } |
1396 | | - |
1397 | | - uint64_t offset_from = wf->get_position(); |
1398 | | - wf->seek(sub_res_count_pos); //plus one because the saved one |
1399 | | - wf->store_32(local_offsets.size()); |
1400 | | - |
1401 | | - for (int i = 0; i < local_offsets.size(); i++) { |
1402 | | - wf->seek(local_pointers_pos[i]); |
1403 | | - wf->store_64(local_offsets[i] + offset_from); |
1404 | | - } |
1405 | | - |
1406 | | - wf->seek_end(); |
1407 | | - |
1408 | | - Vector<uint8_t> data = FileAccess::get_file_as_bytes(temp_file); |
1409 | | - wf->store_buffer(data.ptr(), data.size()); |
1410 | | - { |
1411 | | - Ref<DirAccess> dar = DirAccess::open(temp_file.get_base_dir()); |
1412 | | - ERR_FAIL_COND_V(dar.is_null(), FAILED); |
1413 | | - |
1414 | | - dar->remove(temp_file); |
1415 | | - } |
1416 | | - |
1417 | | - wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end |
1418 | | - |
1419 | | - return OK; |
1420 | | -} |
1421 | | - |
1422 | 1123 | Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) { |
1423 | 1124 | if (error) { |
1424 | 1125 | return error; |
@@ -1835,29 +1536,6 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const |
1835 | 1536 |
|
1836 | 1537 | ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = nullptr; |
1837 | 1538 |
|
1838 | | -Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) { |
1839 | | - Error err; |
1840 | | - Ref<FileAccess> f = FileAccess::open(p_src_path, FileAccess::READ, &err); |
1841 | | - |
1842 | | - ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_src_path + "'."); |
1843 | | - |
1844 | | - ResourceLoaderText loader; |
1845 | | - const String &path = p_src_path; |
1846 | | - loader.local_path = ProjectSettings::get_singleton()->localize_path(path); |
1847 | | - loader.res_path = loader.local_path; |
1848 | | - loader.open(f); |
1849 | | - return loader.save_as_binary(p_dst_path); |
1850 | | -} |
1851 | | - |
1852 | | -/*****************************************************************************************************/ |
1853 | | -/*****************************************************************************************************/ |
1854 | | -/*****************************************************************************************************/ |
1855 | | -/*****************************************************************************************************/ |
1856 | | -/*****************************************************************************************************/ |
1857 | | -/*****************************************************************************************************/ |
1858 | | -/*****************************************************************************************************/ |
1859 | | -/*****************************************************************************************************/ |
1860 | | -/*****************************************************************************************************/ |
1861 | 1539 | /*****************************************************************************************************/ |
1862 | 1540 |
|
1863 | 1541 | String ResourceFormatSaverTextInstance::_write_resources(void *ud, const Ref<Resource> &p_resource) { |
|
0 commit comments