resource_format_text.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. /*************************************************************************/
  2. /* resource_format_text.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "resource_format_text.h"
  31. #include "core/config/project_settings.h"
  32. #include "core/io/resource_format_binary.h"
  33. #include "core/os/dir_access.h"
  34. #include "core/version.h"
  35. //version 2: changed names for basis, aabb, Vectors, etc.
  36. #define FORMAT_VERSION 2
  37. #include "core/os/dir_access.h"
  38. #include "core/version.h"
  39. #define _printerr() ERR_PRINT(String(res_path + ":" + itos(lines) + " - Parse Error: " + error_text).utf8().get_data());
  40. ///
  41. void ResourceLoaderText::set_local_path(const String &p_local_path) {
  42. res_path = p_local_path;
  43. }
  44. Ref<Resource> ResourceLoaderText::get_resource() {
  45. return resource;
  46. }
  47. Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  48. VariantParser::Token token;
  49. VariantParser::get_token(p_stream, token, line, r_err_str);
  50. if (token.type != VariantParser::TK_NUMBER) {
  51. r_err_str = "Expected number (sub-resource index)";
  52. return ERR_PARSE_ERROR;
  53. }
  54. int index = token.value;
  55. if (!p_data->resource_map.has(index)) {
  56. Ref<DummyResource> dr;
  57. dr.instance();
  58. dr->set_subindex(index);
  59. p_data->resource_map[index] = dr;
  60. p_data->resource_set.insert(dr);
  61. }
  62. r_res = p_data->resource_map[index];
  63. VariantParser::get_token(p_stream, token, line, r_err_str);
  64. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  65. r_err_str = "Expected ')'";
  66. return ERR_PARSE_ERROR;
  67. }
  68. return OK;
  69. }
  70. Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  71. VariantParser::Token token;
  72. VariantParser::get_token(p_stream, token, line, r_err_str);
  73. if (token.type != VariantParser::TK_NUMBER) {
  74. r_err_str = "Expected number (sub-resource index)";
  75. return ERR_PARSE_ERROR;
  76. }
  77. int id = token.value;
  78. ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
  79. r_res = p_data->rev_external_resources[id];
  80. VariantParser::get_token(p_stream, token, line, r_err_str);
  81. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  82. r_err_str = "Expected ')'";
  83. return ERR_PARSE_ERROR;
  84. }
  85. return OK;
  86. }
  87. Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  88. VariantParser::Token token;
  89. VariantParser::get_token(p_stream, token, line, r_err_str);
  90. if (token.type != VariantParser::TK_NUMBER) {
  91. r_err_str = "Expected number (sub-resource index)";
  92. return ERR_PARSE_ERROR;
  93. }
  94. int index = token.value;
  95. ERR_FAIL_COND_V(!int_resources.has(index), ERR_INVALID_PARAMETER);
  96. r_res = int_resources[index];
  97. VariantParser::get_token(p_stream, token, line, r_err_str);
  98. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  99. r_err_str = "Expected ')'";
  100. return ERR_PARSE_ERROR;
  101. }
  102. return OK;
  103. }
  104. Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  105. VariantParser::Token token;
  106. VariantParser::get_token(p_stream, token, line, r_err_str);
  107. if (token.type != VariantParser::TK_NUMBER) {
  108. r_err_str = "Expected number (sub-resource index)";
  109. return ERR_PARSE_ERROR;
  110. }
  111. int id = token.value;
  112. if (!ignore_resource_parsing) {
  113. if (!ext_resources.has(id)) {
  114. r_err_str = "Can't load cached ext-resource #" + itos(id);
  115. return ERR_PARSE_ERROR;
  116. }
  117. String path = ext_resources[id].path;
  118. String type = ext_resources[id].type;
  119. if (ext_resources[id].cache.is_valid()) {
  120. r_res = ext_resources[id].cache;
  121. } else if (use_sub_threads) {
  122. RES res = ResourceLoader::load_threaded_get(path);
  123. if (res.is_null()) {
  124. if (ResourceLoader::get_abort_on_missing_resources()) {
  125. error = ERR_FILE_CORRUPT;
  126. error_text = "[ext_resource] referenced nonexistent resource at: " + path;
  127. _printerr();
  128. return error;
  129. } else {
  130. ResourceLoader::notify_dependency_error(local_path, path, type);
  131. }
  132. } else {
  133. ext_resources[id].cache = res;
  134. r_res = res;
  135. }
  136. } else {
  137. error = ERR_FILE_CORRUPT;
  138. error_text = "[ext_resource] referenced non-loaded resource at: " + path;
  139. _printerr();
  140. return error;
  141. }
  142. } else {
  143. r_res = RES();
  144. }
  145. VariantParser::get_token(p_stream, token, line, r_err_str);
  146. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  147. r_err_str = "Expected ')'";
  148. return ERR_PARSE_ERROR;
  149. }
  150. return OK;
  151. }
  152. Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) {
  153. Ref<PackedScene> packed_scene;
  154. packed_scene.instance();
  155. while (true) {
  156. if (next_tag.name == "node") {
  157. int parent = -1;
  158. int owner = -1;
  159. int type = -1;
  160. int name = -1;
  161. int instance = -1;
  162. int index = -1;
  163. //int base_scene=-1;
  164. if (next_tag.fields.has("name")) {
  165. name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
  166. }
  167. if (next_tag.fields.has("parent")) {
  168. NodePath np = next_tag.fields["parent"];
  169. np.prepend_period(); //compatible to how it manages paths internally
  170. parent = packed_scene->get_state()->add_node_path(np);
  171. }
  172. if (next_tag.fields.has("type")) {
  173. type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
  174. } else {
  175. type = SceneState::TYPE_INSTANCED; //no type? assume this was instanced
  176. }
  177. if (next_tag.fields.has("instance")) {
  178. instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
  179. if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
  180. packed_scene->get_state()->set_base_scene(instance);
  181. instance = -1;
  182. }
  183. }
  184. if (next_tag.fields.has("instance_placeholder")) {
  185. String path = next_tag.fields["instance_placeholder"];
  186. int path_v = packed_scene->get_state()->add_value(path);
  187. if (packed_scene->get_state()->get_node_count() == 0) {
  188. error = ERR_FILE_CORRUPT;
  189. error_text = "Instance Placeholder can't be used for inheritance.";
  190. _printerr();
  191. return Ref<PackedScene>();
  192. }
  193. instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
  194. }
  195. if (next_tag.fields.has("owner")) {
  196. owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
  197. } else {
  198. if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1)) {
  199. owner = 0; //if no owner, owner is root
  200. }
  201. }
  202. if (next_tag.fields.has("index")) {
  203. index = next_tag.fields["index"];
  204. }
  205. int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance, index);
  206. if (next_tag.fields.has("groups")) {
  207. Array groups = next_tag.fields["groups"];
  208. for (int i = 0; i < groups.size(); i++) {
  209. packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
  210. }
  211. }
  212. while (true) {
  213. String assign;
  214. Variant value;
  215. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &parser);
  216. if (error) {
  217. if (error != ERR_FILE_EOF) {
  218. _printerr();
  219. return Ref<PackedScene>();
  220. } else {
  221. error = OK;
  222. return packed_scene;
  223. }
  224. }
  225. if (assign != String()) {
  226. int nameidx = packed_scene->get_state()->add_name(assign);
  227. int valueidx = packed_scene->get_state()->add_value(value);
  228. packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx);
  229. //it's assignment
  230. } else if (next_tag.name != String()) {
  231. break;
  232. }
  233. }
  234. } else if (next_tag.name == "connection") {
  235. if (!next_tag.fields.has("from")) {
  236. error = ERR_FILE_CORRUPT;
  237. error_text = "missing 'from' field from connection tag";
  238. return Ref<PackedScene>();
  239. }
  240. if (!next_tag.fields.has("to")) {
  241. error = ERR_FILE_CORRUPT;
  242. error_text = "missing 'to' field from connection tag";
  243. return Ref<PackedScene>();
  244. }
  245. if (!next_tag.fields.has("signal")) {
  246. error = ERR_FILE_CORRUPT;
  247. error_text = "missing 'signal' field from connection tag";
  248. return Ref<PackedScene>();
  249. }
  250. if (!next_tag.fields.has("method")) {
  251. error = ERR_FILE_CORRUPT;
  252. error_text = "missing 'method' field from connection tag";
  253. return Ref<PackedScene>();
  254. }
  255. NodePath from = next_tag.fields["from"];
  256. NodePath to = next_tag.fields["to"];
  257. StringName method = next_tag.fields["method"];
  258. StringName signal = next_tag.fields["signal"];
  259. int flags = Object::CONNECT_PERSIST;
  260. Array binds;
  261. if (next_tag.fields.has("flags")) {
  262. flags = next_tag.fields["flags"];
  263. }
  264. if (next_tag.fields.has("binds")) {
  265. binds = next_tag.fields["binds"];
  266. }
  267. Vector<int> bind_ints;
  268. for (int i = 0; i < binds.size(); i++) {
  269. bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
  270. }
  271. packed_scene->get_state()->add_connection(
  272. packed_scene->get_state()->add_node_path(from.simplified()),
  273. packed_scene->get_state()->add_node_path(to.simplified()),
  274. packed_scene->get_state()->add_name(signal),
  275. packed_scene->get_state()->add_name(method),
  276. flags,
  277. bind_ints);
  278. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
  279. if (error) {
  280. if (error != ERR_FILE_EOF) {
  281. _printerr();
  282. return Ref<PackedScene>();
  283. } else {
  284. error = OK;
  285. return packed_scene;
  286. }
  287. }
  288. } else if (next_tag.name == "editable") {
  289. if (!next_tag.fields.has("path")) {
  290. error = ERR_FILE_CORRUPT;
  291. error_text = "missing 'path' field from connection tag";
  292. _printerr();
  293. return Ref<PackedScene>();
  294. }
  295. NodePath path = next_tag.fields["path"];
  296. packed_scene->get_state()->add_editable_instance(path.simplified());
  297. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
  298. if (error) {
  299. if (error != ERR_FILE_EOF) {
  300. _printerr();
  301. return Ref<PackedScene>();
  302. } else {
  303. error = OK;
  304. return packed_scene;
  305. }
  306. }
  307. } else {
  308. error = ERR_FILE_CORRUPT;
  309. _printerr();
  310. return Ref<PackedScene>();
  311. }
  312. }
  313. }
  314. Error ResourceLoaderText::load() {
  315. if (error != OK) {
  316. return error;
  317. }
  318. while (true) {
  319. if (next_tag.name != "ext_resource") {
  320. break;
  321. }
  322. if (!next_tag.fields.has("path")) {
  323. error = ERR_FILE_CORRUPT;
  324. error_text = "Missing 'path' in external resource tag";
  325. _printerr();
  326. return error;
  327. }
  328. if (!next_tag.fields.has("type")) {
  329. error = ERR_FILE_CORRUPT;
  330. error_text = "Missing 'type' in external resource tag";
  331. _printerr();
  332. return error;
  333. }
  334. if (!next_tag.fields.has("id")) {
  335. error = ERR_FILE_CORRUPT;
  336. error_text = "Missing 'id' in external resource tag";
  337. _printerr();
  338. return error;
  339. }
  340. String path = next_tag.fields["path"];
  341. String type = next_tag.fields["type"];
  342. int index = next_tag.fields["id"];
  343. if (path.find("://") == -1 && path.is_rel_path()) {
  344. // path is relative to file being loaded, so convert to a resource path
  345. path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
  346. }
  347. if (remaps.has(path)) {
  348. path = remaps[path];
  349. }
  350. ExtResource er;
  351. er.path = path;
  352. er.type = type;
  353. if (use_sub_threads) {
  354. Error err = ResourceLoader::load_threaded_request(path, type, use_sub_threads, ResourceFormatLoader::CACHE_MODE_REUSE, local_path);
  355. if (err != OK) {
  356. if (ResourceLoader::get_abort_on_missing_resources()) {
  357. error = ERR_FILE_CORRUPT;
  358. error_text = "[ext_resource] referenced broken resource at: " + path;
  359. _printerr();
  360. return error;
  361. } else {
  362. ResourceLoader::notify_dependency_error(local_path, path, type);
  363. }
  364. }
  365. } else {
  366. RES res = ResourceLoader::load(path, type);
  367. if (res.is_null()) {
  368. if (ResourceLoader::get_abort_on_missing_resources()) {
  369. error = ERR_FILE_CORRUPT;
  370. error_text = "[ext_resource] referenced nonexistent resource at: " + path;
  371. _printerr();
  372. return error;
  373. } else {
  374. ResourceLoader::notify_dependency_error(local_path, path, type);
  375. }
  376. } else {
  377. #ifdef TOOLS_ENABLED
  378. //remember ID for saving
  379. res->set_id_for_path(local_path, index);
  380. #endif
  381. }
  382. er.cache = res;
  383. }
  384. ext_resources[index] = er;
  385. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  386. if (error) {
  387. _printerr();
  388. }
  389. resource_current++;
  390. }
  391. //these are the ones that count
  392. resources_total -= resource_current;
  393. resource_current = 0;
  394. while (true) {
  395. if (next_tag.name != "sub_resource") {
  396. break;
  397. }
  398. if (!next_tag.fields.has("type")) {
  399. error = ERR_FILE_CORRUPT;
  400. error_text = "Missing 'type' in external resource tag";
  401. _printerr();
  402. return error;
  403. }
  404. if (!next_tag.fields.has("id")) {
  405. error = ERR_FILE_CORRUPT;
  406. error_text = "Missing 'index' in external resource tag";
  407. _printerr();
  408. return error;
  409. }
  410. String type = next_tag.fields["type"];
  411. int id = next_tag.fields["id"];
  412. String path = local_path + "::" + itos(id);
  413. //bool exists=ResourceCache::has(path);
  414. Ref<Resource> res;
  415. bool do_assign = false;
  416. if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) {
  417. //reuse existing
  418. Resource *r = ResourceCache::get(path);
  419. if (r && r->get_class() == type) {
  420. res = Ref<Resource>(r);
  421. res->reset_state();
  422. do_assign = true;
  423. }
  424. }
  425. if (res.is_null()) { //not reuse
  426. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && ResourceCache::has(path)) { //only if it doesn't exist
  427. //cached, do not assign
  428. Resource *r = ResourceCache::get(path);
  429. res = Ref<Resource>(r);
  430. } else {
  431. //create
  432. Object *obj = ClassDB::instance(type);
  433. if (!obj) {
  434. error_text += "Can't create sub resource of type: " + type;
  435. _printerr();
  436. error = ERR_FILE_CORRUPT;
  437. return error;
  438. }
  439. Resource *r = Object::cast_to<Resource>(obj);
  440. if (!r) {
  441. error_text += "Can't create sub resource of type, because not a resource: " + type;
  442. _printerr();
  443. error = ERR_FILE_CORRUPT;
  444. return error;
  445. }
  446. res = Ref<Resource>(r);
  447. do_assign = true;
  448. }
  449. }
  450. resource_current++;
  451. while (true) {
  452. String assign;
  453. Variant value;
  454. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
  455. if (error) {
  456. _printerr();
  457. return error;
  458. }
  459. if (assign != String()) {
  460. if (do_assign) {
  461. res->set(assign, value);
  462. }
  463. //it's assignment
  464. } else if (next_tag.name != String()) {
  465. error = OK;
  466. break;
  467. } else {
  468. error = ERR_FILE_CORRUPT;
  469. error_text = "Premature end of file while parsing [sub_resource]";
  470. _printerr();
  471. return error;
  472. }
  473. }
  474. int_resources[id] = res; //always assign int resources
  475. if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
  476. res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
  477. }
  478. if (progress && resources_total > 0) {
  479. *progress = resource_current / float(resources_total);
  480. }
  481. }
  482. while (true) {
  483. if (next_tag.name != "resource") {
  484. break;
  485. }
  486. if (is_scene) {
  487. error_text += "found the 'resource' tag on a scene file!";
  488. _printerr();
  489. error = ERR_FILE_CORRUPT;
  490. return error;
  491. }
  492. if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(local_path)) {
  493. Resource *r = ResourceCache::get(local_path);
  494. if (r->get_class() == res_type) {
  495. r->reset_state();
  496. resource = Ref<Resource>(r);
  497. }
  498. }
  499. if (!resource.is_valid()) {
  500. Object *obj = ClassDB::instance(res_type);
  501. if (!obj) {
  502. error_text += "Can't create sub resource of type: " + res_type;
  503. _printerr();
  504. error = ERR_FILE_CORRUPT;
  505. return error;
  506. }
  507. Resource *r = Object::cast_to<Resource>(obj);
  508. if (!r) {
  509. error_text += "Can't create sub resource of type, because not a resource: " + res_type;
  510. _printerr();
  511. error = ERR_FILE_CORRUPT;
  512. return error;
  513. }
  514. resource = Ref<Resource>(r);
  515. }
  516. resource_current++;
  517. while (true) {
  518. String assign;
  519. Variant value;
  520. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
  521. if (error) {
  522. if (error != ERR_FILE_EOF) {
  523. _printerr();
  524. } else {
  525. error = OK;
  526. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
  527. if (!ResourceCache::has(res_path)) {
  528. resource->set_path(res_path);
  529. }
  530. resource->set_as_translation_remapped(translation_remapped);
  531. }
  532. }
  533. return error;
  534. }
  535. if (assign != String()) {
  536. resource->set(assign, value);
  537. //it's assignment
  538. } else if (next_tag.name != String()) {
  539. error = ERR_FILE_CORRUPT;
  540. error_text = "Extra tag found when parsing main resource file";
  541. _printerr();
  542. return error;
  543. } else {
  544. error = OK;
  545. if (progress && resources_total > 0) {
  546. *progress = resource_current / float(resources_total);
  547. }
  548. return error;
  549. }
  550. }
  551. }
  552. //for scene files
  553. if (next_tag.name == "node") {
  554. if (!is_scene) {
  555. error_text += "found the 'node' tag on a resource file!";
  556. _printerr();
  557. error = ERR_FILE_CORRUPT;
  558. return error;
  559. }
  560. Ref<PackedScene> packed_scene = _parse_node_tag(rp);
  561. if (!packed_scene.is_valid()) {
  562. return error;
  563. }
  564. error = OK;
  565. //get it here
  566. resource = packed_scene;
  567. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && !ResourceCache::has(res_path)) {
  568. packed_scene->set_path(res_path);
  569. }
  570. resource_current++;
  571. if (progress && resources_total > 0) {
  572. *progress = resource_current / float(resources_total);
  573. }
  574. return error;
  575. } else {
  576. error_text += "Unknown tag in file: " + next_tag.name;
  577. _printerr();
  578. error = ERR_FILE_CORRUPT;
  579. return error;
  580. }
  581. }
  582. int ResourceLoaderText::get_stage() const {
  583. return resource_current;
  584. }
  585. int ResourceLoaderText::get_stage_count() const {
  586. return resources_total; //+ext_resources;
  587. }
  588. void ResourceLoaderText::set_translation_remapped(bool p_remapped) {
  589. translation_remapped = p_remapped;
  590. }
  591. ResourceLoaderText::ResourceLoaderText() {}
  592. ResourceLoaderText::~ResourceLoaderText() {
  593. memdelete(f);
  594. }
  595. void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) {
  596. open(p_f);
  597. ignore_resource_parsing = true;
  598. ERR_FAIL_COND(error != OK);
  599. while (next_tag.name == "ext_resource") {
  600. if (!next_tag.fields.has("type")) {
  601. error = ERR_FILE_CORRUPT;
  602. error_text = "Missing 'type' in external resource tag";
  603. _printerr();
  604. return;
  605. }
  606. if (!next_tag.fields.has("id")) {
  607. error = ERR_FILE_CORRUPT;
  608. error_text = "Missing 'index' in external resource tag";
  609. _printerr();
  610. return;
  611. }
  612. String path = next_tag.fields["path"];
  613. String type = next_tag.fields["type"];
  614. if (path.find("://") == -1 && path.is_rel_path()) {
  615. // path is relative to file being loaded, so convert to a resource path
  616. path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
  617. }
  618. if (p_add_types) {
  619. path += "::" + type;
  620. }
  621. p_dependencies->push_back(path);
  622. Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  623. if (err) {
  624. print_line(error_text + " - " + itos(lines));
  625. error_text = "Unexpected end of file";
  626. _printerr();
  627. error = ERR_FILE_CORRUPT;
  628. }
  629. }
  630. }
  631. Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map) {
  632. open(p_f, true);
  633. ERR_FAIL_COND_V(error != OK, error);
  634. ignore_resource_parsing = true;
  635. //FileAccess
  636. FileAccess *fw = nullptr;
  637. String base_path = local_path.get_base_dir();
  638. uint64_t tag_end = f->get_position();
  639. while (true) {
  640. Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  641. if (err != OK) {
  642. if (fw) {
  643. memdelete(fw);
  644. }
  645. error = ERR_FILE_CORRUPT;
  646. ERR_FAIL_V(error);
  647. }
  648. if (next_tag.name != "ext_resource") {
  649. //nothing was done
  650. if (!fw) {
  651. return OK;
  652. }
  653. break;
  654. } else {
  655. if (!fw) {
  656. fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
  657. if (is_scene) {
  658. fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
  659. } else {
  660. fw->store_line("[gd_resource type=\"" + res_type + "\" load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
  661. }
  662. }
  663. if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) {
  664. memdelete(fw);
  665. error = ERR_FILE_CORRUPT;
  666. ERR_FAIL_V(error);
  667. }
  668. String path = next_tag.fields["path"];
  669. int index = next_tag.fields["id"];
  670. String type = next_tag.fields["type"];
  671. bool relative = false;
  672. if (!path.begins_with("res://")) {
  673. path = base_path.plus_file(path).simplify_path();
  674. relative = true;
  675. }
  676. if (p_map.has(path)) {
  677. String np = p_map[path];
  678. path = np;
  679. }
  680. if (relative) {
  681. //restore relative
  682. path = base_path.path_to_file(path);
  683. }
  684. fw->store_line("[ext_resource path=\"" + path + "\" type=\"" + type + "\" id=" + itos(index) + "]");
  685. tag_end = f->get_position();
  686. }
  687. }
  688. f->seek(tag_end);
  689. uint8_t c = f->get_8();
  690. if (c == '\n' && !f->eof_reached()) {
  691. // Skip first newline character since we added one
  692. c = f->get_8();
  693. }
  694. while (!f->eof_reached()) {
  695. fw->store_8(c);
  696. c = f->get_8();
  697. }
  698. f->close();
  699. bool all_ok = fw->get_error() == OK;
  700. memdelete(fw);
  701. if (!all_ok) {
  702. return ERR_CANT_CREATE;
  703. }
  704. DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
  705. da->remove(p_path);
  706. da->rename(p_path + ".depren", p_path);
  707. memdelete(da);
  708. return OK;
  709. }
  710. void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) {
  711. error = OK;
  712. lines = 1;
  713. f = p_f;
  714. stream.f = f;
  715. is_scene = false;
  716. ignore_resource_parsing = false;
  717. resource_current = 0;
  718. VariantParser::Tag tag;
  719. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  720. if (err) {
  721. error = err;
  722. _printerr();
  723. return;
  724. }
  725. if (tag.fields.has("format")) {
  726. int fmt = tag.fields["format"];
  727. if (fmt > FORMAT_VERSION) {
  728. error_text = "Saved with newer format version";
  729. _printerr();
  730. error = ERR_PARSE_ERROR;
  731. return;
  732. }
  733. }
  734. if (tag.name == "gd_scene") {
  735. is_scene = true;
  736. } else if (tag.name == "gd_resource") {
  737. if (!tag.fields.has("type")) {
  738. error_text = "Missing 'type' field in 'gd_resource' tag";
  739. _printerr();
  740. error = ERR_PARSE_ERROR;
  741. return;
  742. }
  743. res_type = tag.fields["type"];
  744. } else {
  745. error_text = "Unrecognized file type: " + tag.name;
  746. _printerr();
  747. error = ERR_PARSE_ERROR;
  748. return;
  749. }
  750. if (tag.fields.has("load_steps")) {
  751. resources_total = tag.fields["load_steps"];
  752. } else {
  753. resources_total = 0;
  754. }
  755. if (!p_skip_first_tag) {
  756. err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  757. if (err) {
  758. error_text = "Unexpected end of file";
  759. _printerr();
  760. error = ERR_FILE_CORRUPT;
  761. }
  762. }
  763. rp.ext_func = _parse_ext_resources;
  764. rp.sub_func = _parse_sub_resources;
  765. rp.func = nullptr;
  766. rp.userdata = this;
  767. }
  768. static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false) {
  769. CharString utf8 = p_string.utf8();
  770. if (p_bit_on_len) {
  771. f->store_32((utf8.length() + 1) | 0x80000000);
  772. } else {
  773. f->store_32(utf8.length() + 1);
  774. }
  775. f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
  776. }
  777. Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) {
  778. if (error) {
  779. return error;
  780. }
  781. FileAccessRef wf = FileAccess::open(p_path, FileAccess::WRITE);
  782. if (!wf) {
  783. return ERR_CANT_OPEN;
  784. }
  785. //save header compressed
  786. static const uint8_t header[4] = { 'R', 'S', 'R', 'C' };
  787. wf->store_buffer(header, 4);
  788. wf->store_32(0); //endianness, little endian
  789. wf->store_32(0); //64 bits file, false for now
  790. wf->store_32(VERSION_MAJOR);
  791. wf->store_32(VERSION_MINOR);
  792. static const int save_format_version = 3; //use format version 3 for saving
  793. wf->store_32(save_format_version);
  794. bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type);
  795. wf->store_64(0); //offset to import metadata, this is no longer used
  796. for (int i = 0; i < 14; i++) {
  797. wf->store_32(0); // reserved
  798. }
  799. wf->store_32(0); //string table size, will not be in use
  800. size_t ext_res_count_pos = wf->get_position();
  801. wf->store_32(0); //zero ext resources, still parsing them
  802. //go with external resources
  803. DummyReadData dummy_read;
  804. VariantParser::ResourceParser rp;
  805. rp.ext_func = _parse_ext_resource_dummys;
  806. rp.sub_func = _parse_sub_resource_dummys;
  807. rp.userdata = &dummy_read;
  808. while (next_tag.name == "ext_resource") {
  809. if (!next_tag.fields.has("path")) {
  810. error = ERR_FILE_CORRUPT;
  811. error_text = "Missing 'path' in external resource tag";
  812. _printerr();
  813. return error;
  814. }
  815. if (!next_tag.fields.has("type")) {
  816. error = ERR_FILE_CORRUPT;
  817. error_text = "Missing 'type' in external resource tag";
  818. _printerr();
  819. return error;
  820. }
  821. if (!next_tag.fields.has("id")) {
  822. error = ERR_FILE_CORRUPT;
  823. error_text = "Missing 'id' in external resource tag";
  824. _printerr();
  825. return error;
  826. }
  827. String path = next_tag.fields["path"];
  828. String type = next_tag.fields["type"];
  829. int index = next_tag.fields["id"];
  830. bs_save_unicode_string(wf.f, type);
  831. bs_save_unicode_string(wf.f, path);
  832. int lindex = dummy_read.external_resources.size();
  833. Ref<DummyResource> dr;
  834. dr.instance();
  835. dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external
  836. dummy_read.external_resources[dr] = lindex;
  837. dummy_read.rev_external_resources[index] = dr;
  838. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  839. if (error) {
  840. _printerr();
  841. return error;
  842. }
  843. }
  844. // save external resource table
  845. wf->seek(ext_res_count_pos);
  846. wf->store_32(dummy_read.external_resources.size());
  847. wf->seek_end();
  848. //now, save resources to a separate file, for now
  849. size_t sub_res_count_pos = wf->get_position();
  850. wf->store_32(0); //zero sub resources, still parsing them
  851. String temp_file = p_path + ".temp";
  852. FileAccessRef wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
  853. if (!wf2) {
  854. return ERR_CANT_OPEN;
  855. }
  856. Vector<size_t> local_offsets;
  857. Vector<size_t> local_pointers_pos;
  858. while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
  859. String type;
  860. int id = -1;
  861. bool main_res;
  862. if (next_tag.name == "sub_resource") {
  863. if (!next_tag.fields.has("type")) {
  864. error = ERR_FILE_CORRUPT;
  865. error_text = "Missing 'type' in external resource tag";
  866. _printerr();
  867. return error;
  868. }
  869. if (!next_tag.fields.has("id")) {
  870. error = ERR_FILE_CORRUPT;
  871. error_text = "Missing 'index' in external resource tag";
  872. _printerr();
  873. return error;
  874. }
  875. type = next_tag.fields["type"];
  876. id = next_tag.fields["id"];
  877. main_res = false;
  878. } else {
  879. type = res_type;
  880. id = 0; //used for last anyway
  881. main_res = true;
  882. }
  883. local_offsets.push_back(wf2->get_position());
  884. bs_save_unicode_string(wf, "local://" + itos(id));
  885. local_pointers_pos.push_back(wf->get_position());
  886. wf->store_64(0); //temp local offset
  887. bs_save_unicode_string(wf2, type);
  888. size_t propcount_ofs = wf2->get_position();
  889. wf2->store_32(0);
  890. int prop_count = 0;
  891. while (true) {
  892. String assign;
  893. Variant value;
  894. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
  895. if (error) {
  896. if (main_res && error == ERR_FILE_EOF) {
  897. next_tag.name = ""; //exit
  898. break;
  899. }
  900. _printerr();
  901. return error;
  902. }
  903. if (assign != String()) {
  904. Map<StringName, int> empty_string_map; //unused
  905. bs_save_unicode_string(wf2, assign, true);
  906. ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
  907. prop_count++;
  908. } else if (next_tag.name != String()) {
  909. error = OK;
  910. break;
  911. } else {
  912. error = ERR_FILE_CORRUPT;
  913. error_text = "Premature end of file while parsing [sub_resource]";
  914. _printerr();
  915. return error;
  916. }
  917. }
  918. wf2->seek(propcount_ofs);
  919. wf2->store_32(prop_count);
  920. wf2->seek_end();
  921. }
  922. if (next_tag.name == "node") {
  923. //this is a node, must save one more!
  924. if (!is_scene) {
  925. error_text += "found the 'node' tag on a resource file!";
  926. _printerr();
  927. error = ERR_FILE_CORRUPT;
  928. return error;
  929. }
  930. Ref<PackedScene> packed_scene = _parse_node_tag(rp);
  931. if (!packed_scene.is_valid()) {
  932. return error;
  933. }
  934. error = OK;
  935. //get it here
  936. List<PropertyInfo> props;
  937. packed_scene->get_property_list(&props);
  938. bs_save_unicode_string(wf, "local://0");
  939. local_pointers_pos.push_back(wf->get_position());
  940. wf->store_64(0); //temp local offset
  941. local_offsets.push_back(wf2->get_position());
  942. bs_save_unicode_string(wf2, "PackedScene");
  943. size_t propcount_ofs = wf2->get_position();
  944. wf2->store_32(0);
  945. int prop_count = 0;
  946. for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
  947. if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
  948. continue;
  949. }
  950. String name = E->get().name;
  951. Variant value = packed_scene->get(name);
  952. Map<StringName, int> empty_string_map; //unused
  953. bs_save_unicode_string(wf2, name, true);
  954. ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
  955. prop_count++;
  956. }
  957. wf2->seek(propcount_ofs);
  958. wf2->store_32(prop_count);
  959. wf2->seek_end();
  960. }
  961. wf2->close();
  962. size_t offset_from = wf->get_position();
  963. wf->seek(sub_res_count_pos); //plus one because the saved one
  964. wf->store_32(local_offsets.size());
  965. for (int i = 0; i < local_offsets.size(); i++) {
  966. wf->seek(local_pointers_pos[i]);
  967. wf->store_64(local_offsets[i] + offset_from);
  968. }
  969. wf->seek_end();
  970. Vector<uint8_t> data = FileAccess::get_file_as_array(temp_file);
  971. wf->store_buffer(data.ptr(), data.size());
  972. {
  973. DirAccessRef dar = DirAccess::open(temp_file.get_base_dir());
  974. dar->remove(temp_file);
  975. }
  976. wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
  977. wf->close();
  978. return OK;
  979. }
  980. String ResourceLoaderText::recognize(FileAccess *p_f) {
  981. error = OK;
  982. lines = 1;
  983. f = p_f;
  984. stream.f = f;
  985. ignore_resource_parsing = true;
  986. VariantParser::Tag tag;
  987. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  988. if (err) {
  989. _printerr();
  990. return "";
  991. }
  992. if (tag.fields.has("format")) {
  993. int fmt = tag.fields["format"];
  994. if (fmt > FORMAT_VERSION) {
  995. error_text = "Saved with newer format version";
  996. _printerr();
  997. return "";
  998. }
  999. }
  1000. if (tag.name == "gd_scene") {
  1001. return "PackedScene";
  1002. }
  1003. if (tag.name != "gd_resource") {
  1004. return "";
  1005. }
  1006. if (!tag.fields.has("type")) {
  1007. error_text = "Missing 'type' field in 'gd_resource' tag";
  1008. _printerr();
  1009. return "";
  1010. }
  1011. return tag.fields["type"];
  1012. }
  1013. /////////////////////
  1014. RES ResourceFormatLoaderText::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
  1015. if (r_error) {
  1016. *r_error = ERR_CANT_OPEN;
  1017. }
  1018. Error err;
  1019. FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
  1020. ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
  1021. ResourceLoaderText loader;
  1022. String path = p_original_path != "" ? p_original_path : p_path;
  1023. loader.cache_mode = p_cache_mode;
  1024. loader.use_sub_threads = p_use_sub_threads;
  1025. loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
  1026. loader.progress = r_progress;
  1027. loader.res_path = loader.local_path;
  1028. //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
  1029. loader.open(f);
  1030. err = loader.load();
  1031. if (r_error) {
  1032. *r_error = err;
  1033. }
  1034. if (err == OK) {
  1035. return loader.get_resource();
  1036. } else {
  1037. return RES();
  1038. }
  1039. }
  1040. void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
  1041. if (p_type == "") {
  1042. get_recognized_extensions(p_extensions);
  1043. return;
  1044. }
  1045. if (p_type == "PackedScene") {
  1046. p_extensions->push_back("tscn");
  1047. } else {
  1048. p_extensions->push_back("tres");
  1049. }
  1050. }
  1051. void ResourceFormatLoaderText::get_recognized_extensions(List<String> *p_extensions) const {
  1052. p_extensions->push_back("tscn");
  1053. p_extensions->push_back("tres");
  1054. }
  1055. bool ResourceFormatLoaderText::handles_type(const String &p_type) const {
  1056. return true;
  1057. }
  1058. String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
  1059. String ext = p_path.get_extension().to_lower();
  1060. if (ext == "tscn") {
  1061. return "PackedScene";
  1062. } else if (ext != "tres") {
  1063. return String();
  1064. }
  1065. //for anyhting else must test..
  1066. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1067. if (!f) {
  1068. return ""; //could not rwead
  1069. }
  1070. ResourceLoaderText loader;
  1071. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1072. loader.res_path = loader.local_path;
  1073. //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
  1074. String r = loader.recognize(f);
  1075. return ClassDB::get_compatibility_remapped_class(r);
  1076. }
  1077. void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
  1078. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1079. if (!f) {
  1080. ERR_FAIL();
  1081. }
  1082. ResourceLoaderText loader;
  1083. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1084. loader.res_path = loader.local_path;
  1085. //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
  1086. loader.get_dependencies(f, p_dependencies, p_add_types);
  1087. }
  1088. Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
  1089. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1090. if (!f) {
  1091. ERR_FAIL_V(ERR_CANT_OPEN);
  1092. }
  1093. ResourceLoaderText loader;
  1094. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1095. loader.res_path = loader.local_path;
  1096. //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
  1097. return loader.rename_dependencies(f, p_path, p_map);
  1098. }
  1099. ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = nullptr;
  1100. Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) {
  1101. Error err;
  1102. FileAccess *f = FileAccess::open(p_src_path, FileAccess::READ, &err);
  1103. ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_src_path + "'.");
  1104. ResourceLoaderText loader;
  1105. const String &path = p_src_path;
  1106. loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
  1107. loader.res_path = loader.local_path;
  1108. //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
  1109. loader.open(f);
  1110. return loader.save_as_binary(f, p_dst_path);
  1111. }
  1112. /*****************************************************************************************************/
  1113. /*****************************************************************************************************/
  1114. /*****************************************************************************************************/
  1115. /*****************************************************************************************************/
  1116. /*****************************************************************************************************/
  1117. /*****************************************************************************************************/
  1118. /*****************************************************************************************************/
  1119. /*****************************************************************************************************/
  1120. /*****************************************************************************************************/
  1121. /*****************************************************************************************************/
  1122. String ResourceFormatSaverTextInstance::_write_resources(void *ud, const RES &p_resource) {
  1123. ResourceFormatSaverTextInstance *rsi = (ResourceFormatSaverTextInstance *)ud;
  1124. return rsi->_write_resource(p_resource);
  1125. }
  1126. String ResourceFormatSaverTextInstance::_write_resource(const RES &res) {
  1127. if (external_resources.has(res)) {
  1128. return "ExtResource( " + itos(external_resources[res]) + " )";
  1129. } else {
  1130. if (internal_resources.has(res)) {
  1131. return "SubResource( " + itos(internal_resources[res]) + " )";
  1132. } else if (res->get_path().length() && res->get_path().find("::") == -1) {
  1133. if (res->get_path() == local_path) { //circular reference attempt
  1134. return "null";
  1135. }
  1136. //external resource
  1137. String path = relative_paths ? local_path.path_to_file(res->get_path()) : res->get_path();
  1138. return "Resource( \"" + path + "\" )";
  1139. } else {
  1140. ERR_FAIL_V_MSG("null", "Resource was not pre cached for the resource section, bug?");
  1141. //internal resource
  1142. }
  1143. }
  1144. }
  1145. void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, bool p_main) {
  1146. switch (p_variant.get_type()) {
  1147. case Variant::OBJECT: {
  1148. RES res = p_variant;
  1149. if (res.is_null() || external_resources.has(res)) {
  1150. return;
  1151. }
  1152. if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
  1153. if (res->get_path() == local_path) {
  1154. ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
  1155. return;
  1156. }
  1157. int index = external_resources.size();
  1158. external_resources[res] = index;
  1159. return;
  1160. }
  1161. if (resource_set.has(res)) {
  1162. return;
  1163. }
  1164. List<PropertyInfo> property_list;
  1165. res->get_property_list(&property_list);
  1166. property_list.sort();
  1167. List<PropertyInfo>::Element *I = property_list.front();
  1168. while (I) {
  1169. PropertyInfo pi = I->get();
  1170. if (pi.usage & PROPERTY_USAGE_STORAGE) {
  1171. Variant v = res->get(I->get().name);
  1172. if (pi.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
  1173. RES sres = v;
  1174. if (sres.is_valid()) {
  1175. NonPersistentKey npk;
  1176. npk.base = res;
  1177. npk.property = pi.name;
  1178. non_persistent_map[npk] = sres;
  1179. resource_set.insert(sres);
  1180. saved_resources.push_back(sres);
  1181. }
  1182. } else {
  1183. _find_resources(v);
  1184. }
  1185. }
  1186. I = I->next();
  1187. }
  1188. resource_set.insert(res); //saved after, so the children it needs are available when loaded
  1189. saved_resources.push_back(res);
  1190. } break;
  1191. case Variant::ARRAY: {
  1192. Array varray = p_variant;
  1193. int len = varray.size();
  1194. for (int i = 0; i < len; i++) {
  1195. const Variant &v = varray.get(i);
  1196. _find_resources(v);
  1197. }
  1198. } break;
  1199. case Variant::DICTIONARY: {
  1200. Dictionary d = p_variant;
  1201. List<Variant> keys;
  1202. d.get_key_list(&keys);
  1203. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  1204. Variant v = d[E->get()];
  1205. _find_resources(v);
  1206. }
  1207. } break;
  1208. default: {
  1209. }
  1210. }
  1211. }
  1212. Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  1213. if (p_path.ends_with(".tscn")) {
  1214. packed_scene = p_resource;
  1215. }
  1216. Error err;
  1217. f = FileAccess::open(p_path, FileAccess::WRITE, &err);
  1218. ERR_FAIL_COND_V_MSG(err, ERR_CANT_OPEN, "Cannot save file '" + p_path + "'.");
  1219. FileAccessRef _fref(f);
  1220. local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1221. relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
  1222. skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
  1223. bundle_resources = p_flags & ResourceSaver::FLAG_BUNDLE_RESOURCES;
  1224. takeover_paths = p_flags & ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
  1225. if (!p_path.begins_with("res://")) {
  1226. takeover_paths = false;
  1227. }
  1228. // save resources
  1229. _find_resources(p_resource, true);
  1230. if (packed_scene.is_valid()) {
  1231. //add instances to external resources if saving a packed scene
  1232. for (int i = 0; i < packed_scene->get_state()->get_node_count(); i++) {
  1233. if (packed_scene->get_state()->is_node_instance_placeholder(i)) {
  1234. continue;
  1235. }
  1236. Ref<PackedScene> instance = packed_scene->get_state()->get_node_instance(i);
  1237. if (instance.is_valid() && !external_resources.has(instance)) {
  1238. int index = external_resources.size();
  1239. external_resources[instance] = index;
  1240. }
  1241. }
  1242. }
  1243. {
  1244. String title = packed_scene.is_valid() ? "[gd_scene " : "[gd_resource ";
  1245. if (packed_scene.is_null()) {
  1246. title += "type=\"" + p_resource->get_class() + "\" ";
  1247. }
  1248. int load_steps = saved_resources.size() + external_resources.size();
  1249. /*
  1250. if (packed_scene.is_valid()) {
  1251. load_steps+=packed_scene->get_node_count();
  1252. }
  1253. //no, better to not use load steps from nodes, no point to that
  1254. */
  1255. if (load_steps > 1) {
  1256. title += "load_steps=" + itos(load_steps) + " ";
  1257. }
  1258. title += "format=" + itos(FORMAT_VERSION) + "";
  1259. f->store_string(title);
  1260. f->store_line("]\n"); //one empty line
  1261. }
  1262. #ifdef TOOLS_ENABLED
  1263. //keep order from cached ids
  1264. Set<int> cached_ids_found;
  1265. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  1266. int cached_id = E->key()->get_id_for_path(local_path);
  1267. if (cached_id < 0 || cached_ids_found.has(cached_id)) {
  1268. E->get() = -1; //reset
  1269. } else {
  1270. E->get() = cached_id;
  1271. cached_ids_found.insert(cached_id);
  1272. }
  1273. }
  1274. //create IDs for non cached resources
  1275. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  1276. if (cached_ids_found.has(E->get())) { //already cached, go on
  1277. continue;
  1278. }
  1279. int attempt = 1; //start from one, more readable format
  1280. while (cached_ids_found.has(attempt)) {
  1281. attempt++;
  1282. }
  1283. cached_ids_found.insert(attempt);
  1284. E->get() = attempt;
  1285. //update also in resource
  1286. Ref<Resource> res = E->key();
  1287. res->set_id_for_path(local_path, attempt);
  1288. }
  1289. #else
  1290. //make sure to start from one, as it makes format more readable
  1291. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  1292. E->get() = E->get() + 1;
  1293. }
  1294. #endif
  1295. Vector<ResourceSort> sorted_er;
  1296. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  1297. ResourceSort rs;
  1298. rs.resource = E->key();
  1299. rs.index = E->get();
  1300. sorted_er.push_back(rs);
  1301. }
  1302. sorted_er.sort();
  1303. for (int i = 0; i < sorted_er.size(); i++) {
  1304. String p = sorted_er[i].resource->get_path();
  1305. f->store_string("[ext_resource path=\"" + p + "\" type=\"" + sorted_er[i].resource->get_save_class() + "\" id=" + itos(sorted_er[i].index) + "]\n"); //bundled
  1306. }
  1307. if (external_resources.size()) {
  1308. f->store_line(String()); //separate
  1309. }
  1310. Set<int> used_indices;
  1311. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  1312. RES res = E->get();
  1313. if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) {
  1314. if (res->get_subindex() != 0) {
  1315. if (used_indices.has(res->get_subindex())) {
  1316. res->set_subindex(0); //repeated
  1317. } else {
  1318. used_indices.insert(res->get_subindex());
  1319. }
  1320. }
  1321. }
  1322. }
  1323. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  1324. RES res = E->get();
  1325. ERR_CONTINUE(!resource_set.has(res));
  1326. bool main = (E->next() == nullptr);
  1327. if (main && packed_scene.is_valid()) {
  1328. break; //save as a scene
  1329. }
  1330. if (main) {
  1331. f->store_line("[resource]");
  1332. } else {
  1333. String line = "[sub_resource ";
  1334. if (res->get_subindex() == 0) {
  1335. int new_subindex = 1;
  1336. if (used_indices.size()) {
  1337. new_subindex = used_indices.back()->get() + 1;
  1338. }
  1339. res->set_subindex(new_subindex);
  1340. used_indices.insert(new_subindex);
  1341. }
  1342. int idx = res->get_subindex();
  1343. line += "type=\"" + res->get_class() + "\" id=" + itos(idx);
  1344. f->store_line(line + "]");
  1345. if (takeover_paths) {
  1346. res->set_path(p_path + "::" + itos(idx), true);
  1347. }
  1348. internal_resources[res] = idx;
  1349. #ifdef TOOLS_ENABLED
  1350. res->set_edited(false);
  1351. #endif
  1352. }
  1353. List<PropertyInfo> property_list;
  1354. res->get_property_list(&property_list);
  1355. //property_list.sort();
  1356. for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) {
  1357. if (skip_editor && PE->get().name.begins_with("__editor")) {
  1358. continue;
  1359. }
  1360. if (PE->get().usage & PROPERTY_USAGE_STORAGE) {
  1361. String name = PE->get().name;
  1362. Variant value;
  1363. if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
  1364. NonPersistentKey npk;
  1365. npk.base = res;
  1366. npk.property = name;
  1367. if (non_persistent_map.has(npk)) {
  1368. value = non_persistent_map[npk];
  1369. }
  1370. } else {
  1371. value = res->get(name);
  1372. }
  1373. Variant default_value = ClassDB::class_get_default_property_value(res->get_class(), name);
  1374. if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) {
  1375. continue;
  1376. }
  1377. if (PE->get().type == Variant::OBJECT && value.is_zero() && !(PE->get().usage & PROPERTY_USAGE_STORE_IF_NULL)) {
  1378. continue;
  1379. }
  1380. String vars;
  1381. VariantWriter::write_to_string(value, vars, _write_resources, this);
  1382. f->store_string(name.property_name_encode() + " = " + vars + "\n");
  1383. }
  1384. }
  1385. if (E->next()) {
  1386. f->store_line(String());
  1387. }
  1388. }
  1389. if (packed_scene.is_valid()) {
  1390. //if this is a scene, save nodes and connections!
  1391. Ref<SceneState> state = packed_scene->get_state();
  1392. for (int i = 0; i < state->get_node_count(); i++) {
  1393. StringName type = state->get_node_type(i);
  1394. StringName name = state->get_node_name(i);
  1395. int index = state->get_node_index(i);
  1396. NodePath path = state->get_node_path(i, true);
  1397. NodePath owner = state->get_node_owner_path(i);
  1398. Ref<PackedScene> instance = state->get_node_instance(i);
  1399. String instance_placeholder = state->get_node_instance_placeholder(i);
  1400. Vector<StringName> groups = state->get_node_groups(i);
  1401. String header = "[node";
  1402. header += " name=\"" + String(name).c_escape() + "\"";
  1403. if (type != StringName()) {
  1404. header += " type=\"" + String(type) + "\"";
  1405. }
  1406. if (path != NodePath()) {
  1407. header += " parent=\"" + String(path.simplified()).c_escape() + "\"";
  1408. }
  1409. if (owner != NodePath() && owner != NodePath(".")) {
  1410. header += " owner=\"" + String(owner.simplified()).c_escape() + "\"";
  1411. }
  1412. if (index >= 0) {
  1413. header += " index=\"" + itos(index) + "\"";
  1414. }
  1415. if (groups.size()) {
  1416. groups.sort_custom<StringName::AlphCompare>();
  1417. String sgroups = " groups=[\n";
  1418. for (int j = 0; j < groups.size(); j++) {
  1419. sgroups += "\"" + String(groups[j]).c_escape() + "\",\n";
  1420. }
  1421. sgroups += "]";
  1422. header += sgroups;
  1423. }
  1424. f->store_string(header);
  1425. if (instance_placeholder != String()) {
  1426. String vars;
  1427. f->store_string(" instance_placeholder=");
  1428. VariantWriter::write_to_string(instance_placeholder, vars, _write_resources, this);
  1429. f->store_string(vars);
  1430. }
  1431. if (instance.is_valid()) {
  1432. String vars;
  1433. f->store_string(" instance=");
  1434. VariantWriter::write_to_string(instance, vars, _write_resources, this);
  1435. f->store_string(vars);
  1436. }
  1437. f->store_line("]");
  1438. for (int j = 0; j < state->get_node_property_count(i); j++) {
  1439. String vars;
  1440. VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this);
  1441. f->store_string(String(state->get_node_property_name(i, j)).property_name_encode() + " = " + vars + "\n");
  1442. }
  1443. if (i < state->get_node_count() - 1) {
  1444. f->store_line(String());
  1445. }
  1446. }
  1447. for (int i = 0; i < state->get_connection_count(); i++) {
  1448. if (i == 0) {
  1449. f->store_line("");
  1450. }
  1451. String connstr = "[connection";
  1452. connstr += " signal=\"" + String(state->get_connection_signal(i)) + "\"";
  1453. connstr += " from=\"" + String(state->get_connection_source(i).simplified()) + "\"";
  1454. connstr += " to=\"" + String(state->get_connection_target(i).simplified()) + "\"";
  1455. connstr += " method=\"" + String(state->get_connection_method(i)) + "\"";
  1456. int flags = state->get_connection_flags(i);
  1457. if (flags != Object::CONNECT_PERSIST) {
  1458. connstr += " flags=" + itos(flags);
  1459. }
  1460. Array binds = state->get_connection_binds(i);
  1461. f->store_string(connstr);
  1462. if (binds.size()) {
  1463. String vars;
  1464. VariantWriter::write_to_string(binds, vars, _write_resources, this);
  1465. f->store_string(" binds= " + vars);
  1466. }
  1467. f->store_line("]");
  1468. }
  1469. Vector<NodePath> editable_instances = state->get_editable_instances();
  1470. for (int i = 0; i < editable_instances.size(); i++) {
  1471. if (i == 0) {
  1472. f->store_line("");
  1473. }
  1474. f->store_line("[editable path=\"" + editable_instances[i].operator String() + "\"]");
  1475. }
  1476. }
  1477. if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
  1478. f->close();
  1479. return ERR_CANT_CREATE;
  1480. }
  1481. f->close();
  1482. //memdelete(f);
  1483. return OK;
  1484. }
  1485. Error ResourceFormatSaverText::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  1486. if (p_path.ends_with(".sct") && p_resource->get_class() != "PackedScene") {
  1487. return ERR_FILE_UNRECOGNIZED;
  1488. }
  1489. ResourceFormatSaverTextInstance saver;
  1490. return saver.save(p_path, p_resource, p_flags);
  1491. }
  1492. bool ResourceFormatSaverText::recognize(const RES &p_resource) const {
  1493. return true; // all recognized!
  1494. }
  1495. void ResourceFormatSaverText::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
  1496. if (p_resource->get_class() == "PackedScene") {
  1497. p_extensions->push_back("tscn"); //text scene
  1498. } else {
  1499. p_extensions->push_back("tres"); //text resource
  1500. }
  1501. }
  1502. ResourceFormatSaverText *ResourceFormatSaverText::singleton = nullptr;
  1503. ResourceFormatSaverText::ResourceFormatSaverText() {
  1504. singleton = this;
  1505. }