resource_format_text.cpp 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425
  1. /**************************************************************************/
  2. /* resource_format_text.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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/dir_access.h"
  33. #include "core/io/missing_resource.h"
  34. #include "core/io/resource_format_binary.h"
  35. #include "core/object/script_language.h"
  36. #include "core/version.h"
  37. // Version 2: Changed names for Basis, AABB, Vectors, etc.
  38. // Version 3: New string ID for ext/subresources, breaks forward compat.
  39. #define FORMAT_VERSION 3
  40. // Version 4: PackedByteArray can be base64 encoded, and PackedVector4Array was added.
  41. // Parsing only, for forward compat with 4.3+.
  42. #define FORMAT_VERSION_READABLE 4
  43. #define BINARY_FORMAT_VERSION 4
  44. #include "core/io/dir_access.h"
  45. #include "core/version.h"
  46. #define _printerr() ERR_PRINT(String(res_path + ":" + itos(lines) + " - Parse Error: " + error_text).utf8().get_data());
  47. ///
  48. Ref<Resource> ResourceLoaderText::get_resource() {
  49. return resource;
  50. }
  51. Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  52. VariantParser::Token token;
  53. VariantParser::get_token(p_stream, token, line, r_err_str);
  54. if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
  55. r_err_str = "Expected number (old style) or string (sub-resource index)";
  56. return ERR_PARSE_ERROR;
  57. }
  58. if (p_data->no_placeholders) {
  59. r_res.unref();
  60. } else {
  61. String unique_id = token.value;
  62. if (!p_data->resource_map.has(unique_id)) {
  63. r_err_str = "Found unique_id reference before mapping, sub-resources stored out of order in resource file";
  64. return ERR_PARSE_ERROR;
  65. }
  66. r_res = p_data->resource_map[unique_id];
  67. }
  68. VariantParser::get_token(p_stream, token, line, r_err_str);
  69. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  70. r_err_str = "Expected ')'";
  71. return ERR_PARSE_ERROR;
  72. }
  73. return OK;
  74. }
  75. Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  76. VariantParser::Token token;
  77. VariantParser::get_token(p_stream, token, line, r_err_str);
  78. if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
  79. r_err_str = "Expected number (old style sub-resource index) or String (ext-resource ID)";
  80. return ERR_PARSE_ERROR;
  81. }
  82. if (p_data->no_placeholders) {
  83. r_res.unref();
  84. } else {
  85. String id = token.value;
  86. ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
  87. r_res = p_data->rev_external_resources[id];
  88. }
  89. VariantParser::get_token(p_stream, token, line, r_err_str);
  90. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  91. r_err_str = "Expected ')'";
  92. return ERR_PARSE_ERROR;
  93. }
  94. return OK;
  95. }
  96. Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  97. VariantParser::Token token;
  98. VariantParser::get_token(p_stream, token, line, r_err_str);
  99. if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
  100. r_err_str = "Expected number (old style sub-resource index) or string";
  101. return ERR_PARSE_ERROR;
  102. }
  103. String id = token.value;
  104. ERR_FAIL_COND_V(!int_resources.has(id), ERR_INVALID_PARAMETER);
  105. r_res = int_resources[id];
  106. VariantParser::get_token(p_stream, token, line, r_err_str);
  107. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  108. r_err_str = "Expected ')'";
  109. return ERR_PARSE_ERROR;
  110. }
  111. return OK;
  112. }
  113. Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
  114. VariantParser::Token token;
  115. VariantParser::get_token(p_stream, token, line, r_err_str);
  116. if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
  117. r_err_str = "Expected number (old style sub-resource index) or String (ext-resource ID)";
  118. return ERR_PARSE_ERROR;
  119. }
  120. String id = token.value;
  121. Error err = OK;
  122. if (!ignore_resource_parsing) {
  123. if (!ext_resources.has(id)) {
  124. r_err_str = "Can't load cached ext-resource id: " + id;
  125. return ERR_PARSE_ERROR;
  126. }
  127. String path = ext_resources[id].path;
  128. String type = ext_resources[id].type;
  129. Ref<ResourceLoader::LoadToken> &load_token = ext_resources[id].load_token;
  130. if (load_token.is_valid()) { // If not valid, it's OK since then we know this load accepts broken dependencies.
  131. Ref<Resource> res = ResourceLoader::_load_complete(*load_token.ptr(), &err);
  132. if (res.is_null()) {
  133. if (!ResourceLoader::is_cleaning_tasks()) {
  134. if (ResourceLoader::get_abort_on_missing_resources()) {
  135. error = ERR_FILE_MISSING_DEPENDENCIES;
  136. error_text = "[ext_resource] referenced non-existent resource at: " + path;
  137. _printerr();
  138. err = error;
  139. } else {
  140. ResourceLoader::notify_dependency_error(local_path, path, type);
  141. }
  142. }
  143. } else {
  144. #ifdef TOOLS_ENABLED
  145. //remember ID for saving
  146. res->set_id_for_path(local_path, id);
  147. #endif
  148. r_res = res;
  149. }
  150. } else {
  151. r_res = Ref<Resource>();
  152. }
  153. }
  154. VariantParser::get_token(p_stream, token, line, r_err_str);
  155. if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
  156. r_err_str = "Expected ')'";
  157. return ERR_PARSE_ERROR;
  158. }
  159. return err;
  160. }
  161. Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) {
  162. Ref<PackedScene> packed_scene;
  163. packed_scene.instantiate();
  164. while (true) {
  165. if (next_tag.name == "node") {
  166. int parent = -1;
  167. int owner = -1;
  168. int type = -1;
  169. int name = -1;
  170. int instance = -1;
  171. int index = -1;
  172. //int base_scene=-1;
  173. if (next_tag.fields.has("name")) {
  174. name = packed_scene->get_state()->add_name(next_tag.fields["name"]);
  175. }
  176. if (next_tag.fields.has("parent")) {
  177. NodePath np = next_tag.fields["parent"];
  178. np.prepend_period(); //compatible to how it manages paths internally
  179. parent = packed_scene->get_state()->add_node_path(np);
  180. }
  181. if (next_tag.fields.has("type")) {
  182. type = packed_scene->get_state()->add_name(next_tag.fields["type"]);
  183. } else {
  184. type = SceneState::TYPE_INSTANTIATED; //no type? assume this was instantiated
  185. }
  186. HashSet<StringName> path_properties;
  187. if (next_tag.fields.has("node_paths")) {
  188. Vector<String> paths = next_tag.fields["node_paths"];
  189. for (int i = 0; i < paths.size(); i++) {
  190. path_properties.insert(paths[i]);
  191. }
  192. }
  193. if (next_tag.fields.has("instance")) {
  194. instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]);
  195. if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) {
  196. packed_scene->get_state()->set_base_scene(instance);
  197. instance = -1;
  198. }
  199. }
  200. if (next_tag.fields.has("instance_placeholder")) {
  201. String path = next_tag.fields["instance_placeholder"];
  202. int path_v = packed_scene->get_state()->add_value(path);
  203. if (packed_scene->get_state()->get_node_count() == 0) {
  204. error = ERR_FILE_CORRUPT;
  205. error_text = "Instance Placeholder can't be used for inheritance.";
  206. _printerr();
  207. return Ref<PackedScene>();
  208. }
  209. instance = path_v | SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
  210. }
  211. if (next_tag.fields.has("owner")) {
  212. owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
  213. } else {
  214. if (parent != -1 && !(type == SceneState::TYPE_INSTANTIATED && instance == -1)) {
  215. owner = 0; //if no owner, owner is root
  216. }
  217. }
  218. if (next_tag.fields.has("index")) {
  219. index = next_tag.fields["index"];
  220. }
  221. int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance, index);
  222. if (next_tag.fields.has("groups")) {
  223. Array groups = next_tag.fields["groups"];
  224. for (int i = 0; i < groups.size(); i++) {
  225. packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i]));
  226. }
  227. }
  228. while (true) {
  229. String assign;
  230. Variant value;
  231. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &parser);
  232. if (error) {
  233. if (error == ERR_FILE_MISSING_DEPENDENCIES) {
  234. // Resource loading error, just skip it.
  235. } else if (error != ERR_FILE_EOF) {
  236. _printerr();
  237. return Ref<PackedScene>();
  238. } else {
  239. error = OK;
  240. return packed_scene;
  241. }
  242. }
  243. if (!assign.is_empty()) {
  244. StringName assign_name = assign;
  245. int nameidx = packed_scene->get_state()->add_name(assign_name);
  246. int valueidx = packed_scene->get_state()->add_value(value);
  247. packed_scene->get_state()->add_node_property(node_id, nameidx, valueidx, path_properties.has(assign_name));
  248. //it's assignment
  249. } else if (!next_tag.name.is_empty()) {
  250. break;
  251. }
  252. }
  253. } else if (next_tag.name == "connection") {
  254. if (!next_tag.fields.has("from")) {
  255. error = ERR_FILE_CORRUPT;
  256. error_text = "missing 'from' field from connection tag";
  257. return Ref<PackedScene>();
  258. }
  259. if (!next_tag.fields.has("to")) {
  260. error = ERR_FILE_CORRUPT;
  261. error_text = "missing 'to' field from connection tag";
  262. return Ref<PackedScene>();
  263. }
  264. if (!next_tag.fields.has("signal")) {
  265. error = ERR_FILE_CORRUPT;
  266. error_text = "missing 'signal' field from connection tag";
  267. return Ref<PackedScene>();
  268. }
  269. if (!next_tag.fields.has("method")) {
  270. error = ERR_FILE_CORRUPT;
  271. error_text = "missing 'method' field from connection tag";
  272. return Ref<PackedScene>();
  273. }
  274. NodePath from = next_tag.fields["from"];
  275. NodePath to = next_tag.fields["to"];
  276. StringName method = next_tag.fields["method"];
  277. StringName signal = next_tag.fields["signal"];
  278. int flags = Object::CONNECT_PERSIST;
  279. int unbinds = 0;
  280. Array binds;
  281. if (next_tag.fields.has("flags")) {
  282. flags = next_tag.fields["flags"];
  283. }
  284. if (next_tag.fields.has("binds")) {
  285. binds = next_tag.fields["binds"];
  286. }
  287. if (next_tag.fields.has("unbinds")) {
  288. unbinds = next_tag.fields["unbinds"];
  289. }
  290. Vector<int> bind_ints;
  291. for (int i = 0; i < binds.size(); i++) {
  292. bind_ints.push_back(packed_scene->get_state()->add_value(binds[i]));
  293. }
  294. packed_scene->get_state()->add_connection(
  295. packed_scene->get_state()->add_node_path(from.simplified()),
  296. packed_scene->get_state()->add_node_path(to.simplified()),
  297. packed_scene->get_state()->add_name(signal),
  298. packed_scene->get_state()->add_name(method),
  299. flags,
  300. unbinds,
  301. bind_ints);
  302. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
  303. if (error) {
  304. if (error != ERR_FILE_EOF) {
  305. _printerr();
  306. return Ref<PackedScene>();
  307. } else {
  308. error = OK;
  309. return packed_scene;
  310. }
  311. }
  312. } else if (next_tag.name == "editable") {
  313. if (!next_tag.fields.has("path")) {
  314. error = ERR_FILE_CORRUPT;
  315. error_text = "missing 'path' field from editable tag";
  316. _printerr();
  317. return Ref<PackedScene>();
  318. }
  319. NodePath path = next_tag.fields["path"];
  320. packed_scene->get_state()->add_editable_instance(path.simplified());
  321. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser);
  322. if (error) {
  323. if (error != ERR_FILE_EOF) {
  324. _printerr();
  325. return Ref<PackedScene>();
  326. } else {
  327. error = OK;
  328. return packed_scene;
  329. }
  330. }
  331. } else {
  332. error = ERR_FILE_CORRUPT;
  333. _printerr();
  334. return Ref<PackedScene>();
  335. }
  336. }
  337. }
  338. Error ResourceLoaderText::load() {
  339. if (error != OK) {
  340. return error;
  341. }
  342. while (true) {
  343. if (next_tag.name != "ext_resource") {
  344. break;
  345. }
  346. if (!next_tag.fields.has("path")) {
  347. error = ERR_FILE_CORRUPT;
  348. error_text = "Missing 'path' in external resource tag";
  349. _printerr();
  350. return error;
  351. }
  352. if (!next_tag.fields.has("type")) {
  353. error = ERR_FILE_CORRUPT;
  354. error_text = "Missing 'type' in external resource tag";
  355. _printerr();
  356. return error;
  357. }
  358. if (!next_tag.fields.has("id")) {
  359. error = ERR_FILE_CORRUPT;
  360. error_text = "Missing 'id' in external resource tag";
  361. _printerr();
  362. return error;
  363. }
  364. String path = next_tag.fields["path"];
  365. String type = next_tag.fields["type"];
  366. String id = next_tag.fields["id"];
  367. if (next_tag.fields.has("uid")) {
  368. String uidt = next_tag.fields["uid"];
  369. ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
  370. if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
  371. // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
  372. path = ResourceUID::get_singleton()->get_id_path(uid);
  373. } else {
  374. #ifdef TOOLS_ENABLED
  375. // Silence a warning that can happen during the initial filesystem scan due to cache being regenerated.
  376. if (ResourceLoader::get_resource_uid(path) != uid) {
  377. WARN_PRINT(String(res_path + ":" + itos(lines) + " - ext_resource, invalid UID: " + uidt + " - using text path instead: " + path).utf8().get_data());
  378. }
  379. #else
  380. WARN_PRINT(String(res_path + ":" + itos(lines) + " - ext_resource, invalid UID: " + uidt + " - using text path instead: " + path).utf8().get_data());
  381. #endif
  382. }
  383. }
  384. if (!path.contains("://") && path.is_relative_path()) {
  385. // path is relative to file being loaded, so convert to a resource path
  386. path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().path_join(path));
  387. }
  388. if (remaps.has(path)) {
  389. path = remaps[path];
  390. }
  391. ext_resources[id].path = path;
  392. ext_resources[id].type = type;
  393. ext_resources[id].load_token = ResourceLoader::_load_start(path, type, use_sub_threads ? ResourceLoader::LOAD_THREAD_DISTRIBUTE : ResourceLoader::LOAD_THREAD_FROM_CURRENT, ResourceFormatLoader::CACHE_MODE_REUSE);
  394. if (!ext_resources[id].load_token.is_valid()) {
  395. if (ResourceLoader::get_abort_on_missing_resources()) {
  396. error = ERR_FILE_CORRUPT;
  397. error_text = "[ext_resource] referenced non-existent resource at: " + path;
  398. _printerr();
  399. return error;
  400. } else {
  401. ResourceLoader::notify_dependency_error(local_path, path, type);
  402. }
  403. }
  404. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  405. if (error) {
  406. _printerr();
  407. return error;
  408. }
  409. resource_current++;
  410. }
  411. //these are the ones that count
  412. resources_total -= resource_current;
  413. resource_current = 0;
  414. while (true) {
  415. if (next_tag.name != "sub_resource") {
  416. break;
  417. }
  418. if (!next_tag.fields.has("type")) {
  419. error = ERR_FILE_CORRUPT;
  420. error_text = "Missing 'type' in external resource tag";
  421. _printerr();
  422. return error;
  423. }
  424. if (!next_tag.fields.has("id")) {
  425. error = ERR_FILE_CORRUPT;
  426. error_text = "Missing 'id' in external resource tag";
  427. _printerr();
  428. return error;
  429. }
  430. String type = next_tag.fields["type"];
  431. String id = next_tag.fields["id"];
  432. String path = local_path + "::" + id;
  433. //bool exists=ResourceCache::has(path);
  434. Ref<Resource> res;
  435. bool do_assign = false;
  436. if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) {
  437. //reuse existing
  438. Ref<Resource> cache = ResourceCache::get_ref(path);
  439. if (cache.is_valid() && cache->get_class() == type) {
  440. res = cache;
  441. res->reset_state();
  442. do_assign = true;
  443. }
  444. }
  445. MissingResource *missing_resource = nullptr;
  446. if (res.is_null()) { //not reuse
  447. Ref<Resource> cache = ResourceCache::get_ref(path);
  448. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && cache.is_valid()) { //only if it doesn't exist
  449. //cached, do not assign
  450. res = cache;
  451. } else {
  452. //create
  453. Object *obj = ClassDB::instantiate(type);
  454. if (!obj) {
  455. if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) {
  456. missing_resource = memnew(MissingResource);
  457. missing_resource->set_original_class(type);
  458. missing_resource->set_recording_properties(true);
  459. obj = missing_resource;
  460. } else {
  461. error_text += "Can't create sub resource of type: " + type;
  462. _printerr();
  463. error = ERR_FILE_CORRUPT;
  464. return error;
  465. }
  466. }
  467. Resource *r = Object::cast_to<Resource>(obj);
  468. if (!r) {
  469. error_text += "Can't create sub resource of type, because not a resource: " + type;
  470. _printerr();
  471. error = ERR_FILE_CORRUPT;
  472. return error;
  473. }
  474. res = Ref<Resource>(r);
  475. do_assign = true;
  476. }
  477. }
  478. resource_current++;
  479. if (progress && resources_total > 0) {
  480. *progress = resource_current / float(resources_total);
  481. }
  482. int_resources[id] = res; // Always assign int resources.
  483. if (do_assign) {
  484. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
  485. res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
  486. } else if (!path.is_resource_file()) {
  487. res->set_path_cache(path);
  488. }
  489. res->set_scene_unique_id(id);
  490. }
  491. Dictionary missing_resource_properties;
  492. while (true) {
  493. String assign;
  494. Variant value;
  495. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
  496. if (error) {
  497. _printerr();
  498. return error;
  499. }
  500. if (!assign.is_empty()) {
  501. if (do_assign) {
  502. bool set_valid = true;
  503. if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) {
  504. // If the property being set is a missing resource (and the parent is not),
  505. // then setting it will most likely not work.
  506. // Instead, save it as metadata.
  507. Ref<MissingResource> mr = value;
  508. if (mr.is_valid()) {
  509. missing_resource_properties[assign] = mr;
  510. set_valid = false;
  511. }
  512. }
  513. if (value.get_type() == Variant::ARRAY) {
  514. Array set_array = value;
  515. bool is_get_valid = false;
  516. Variant get_value = res->get(assign, &is_get_valid);
  517. if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
  518. Array get_array = get_value;
  519. if (!set_array.is_same_typed(get_array)) {
  520. value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
  521. }
  522. }
  523. }
  524. if (set_valid) {
  525. res->set(assign, value);
  526. }
  527. }
  528. //it's assignment
  529. } else if (!next_tag.name.is_empty()) {
  530. error = OK;
  531. break;
  532. } else {
  533. error = ERR_FILE_CORRUPT;
  534. error_text = "Premature end of file while parsing [sub_resource]";
  535. _printerr();
  536. return error;
  537. }
  538. }
  539. if (missing_resource) {
  540. missing_resource->set_recording_properties(false);
  541. }
  542. if (!missing_resource_properties.is_empty()) {
  543. res->set_meta(META_MISSING_RESOURCES, missing_resource_properties);
  544. }
  545. }
  546. while (true) {
  547. if (next_tag.name != "resource") {
  548. break;
  549. }
  550. if (is_scene) {
  551. error_text += "found the 'resource' tag on a scene file!";
  552. _printerr();
  553. error = ERR_FILE_CORRUPT;
  554. return error;
  555. }
  556. Ref<Resource> cache = ResourceCache::get_ref(local_path);
  557. if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && cache.is_valid() && cache->get_class() == res_type) {
  558. cache->reset_state();
  559. resource = cache;
  560. }
  561. MissingResource *missing_resource = nullptr;
  562. if (!resource.is_valid()) {
  563. Object *obj = ClassDB::instantiate(res_type);
  564. if (!obj) {
  565. if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) {
  566. missing_resource = memnew(MissingResource);
  567. missing_resource->set_original_class(res_type);
  568. missing_resource->set_recording_properties(true);
  569. obj = missing_resource;
  570. } else {
  571. error_text += "Can't create sub resource of type: " + res_type;
  572. _printerr();
  573. error = ERR_FILE_CORRUPT;
  574. return error;
  575. }
  576. }
  577. Resource *r = Object::cast_to<Resource>(obj);
  578. if (!r) {
  579. error_text += "Can't create sub resource of type, because not a resource: " + res_type;
  580. _printerr();
  581. error = ERR_FILE_CORRUPT;
  582. return error;
  583. }
  584. resource = Ref<Resource>(r);
  585. }
  586. Dictionary missing_resource_properties;
  587. while (true) {
  588. String assign;
  589. Variant value;
  590. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
  591. if (error) {
  592. if (error != ERR_FILE_EOF) {
  593. _printerr();
  594. } else {
  595. error = OK;
  596. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
  597. if (!ResourceCache::has(res_path)) {
  598. resource->set_path(res_path);
  599. }
  600. resource->set_as_translation_remapped(translation_remapped);
  601. }
  602. }
  603. return error;
  604. }
  605. if (!assign.is_empty()) {
  606. bool set_valid = true;
  607. if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) {
  608. // If the property being set is a missing resource (and the parent is not),
  609. // then setting it will most likely not work.
  610. // Instead, save it as metadata.
  611. Ref<MissingResource> mr = value;
  612. if (mr.is_valid()) {
  613. missing_resource_properties[assign] = mr;
  614. set_valid = false;
  615. }
  616. }
  617. if (value.get_type() == Variant::ARRAY) {
  618. Array set_array = value;
  619. bool is_get_valid = false;
  620. Variant get_value = resource->get(assign, &is_get_valid);
  621. if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
  622. Array get_array = get_value;
  623. if (!set_array.is_same_typed(get_array)) {
  624. value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
  625. }
  626. }
  627. }
  628. if (set_valid) {
  629. resource->set(assign, value);
  630. }
  631. //it's assignment
  632. } else if (!next_tag.name.is_empty()) {
  633. error = ERR_FILE_CORRUPT;
  634. error_text = "Extra tag found when parsing main resource file";
  635. _printerr();
  636. return error;
  637. } else {
  638. break;
  639. }
  640. }
  641. resource_current++;
  642. if (progress && resources_total > 0) {
  643. *progress = resource_current / float(resources_total);
  644. }
  645. if (missing_resource) {
  646. missing_resource->set_recording_properties(false);
  647. }
  648. if (!missing_resource_properties.is_empty()) {
  649. resource->set_meta(META_MISSING_RESOURCES, missing_resource_properties);
  650. }
  651. error = OK;
  652. return error;
  653. }
  654. //for scene files
  655. if (next_tag.name == "node") {
  656. if (!is_scene) {
  657. error_text += "found the 'node' tag on a resource file!";
  658. _printerr();
  659. error = ERR_FILE_CORRUPT;
  660. return error;
  661. }
  662. Ref<PackedScene> packed_scene = _parse_node_tag(rp);
  663. if (!packed_scene.is_valid()) {
  664. return error;
  665. }
  666. error = OK;
  667. //get it here
  668. resource = packed_scene;
  669. if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && !ResourceCache::has(res_path)) {
  670. packed_scene->set_path(res_path);
  671. }
  672. resource_current++;
  673. if (progress && resources_total > 0) {
  674. *progress = resource_current / float(resources_total);
  675. }
  676. return error;
  677. } else {
  678. error_text += "Unknown tag in file: " + next_tag.name;
  679. _printerr();
  680. error = ERR_FILE_CORRUPT;
  681. return error;
  682. }
  683. }
  684. int ResourceLoaderText::get_stage() const {
  685. return resource_current;
  686. }
  687. int ResourceLoaderText::get_stage_count() const {
  688. return resources_total; //+ext_resources;
  689. }
  690. void ResourceLoaderText::set_translation_remapped(bool p_remapped) {
  691. translation_remapped = p_remapped;
  692. }
  693. ResourceLoaderText::ResourceLoaderText() :
  694. stream(false) {}
  695. void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
  696. open(p_f);
  697. ignore_resource_parsing = true;
  698. ERR_FAIL_COND(error != OK);
  699. while (next_tag.name == "ext_resource") {
  700. if (!next_tag.fields.has("type")) {
  701. error = ERR_FILE_CORRUPT;
  702. error_text = "Missing 'type' in external resource tag";
  703. _printerr();
  704. return;
  705. }
  706. if (!next_tag.fields.has("id")) {
  707. error = ERR_FILE_CORRUPT;
  708. error_text = "Missing 'id' in external resource tag";
  709. _printerr();
  710. return;
  711. }
  712. String path = next_tag.fields["path"];
  713. String type = next_tag.fields["type"];
  714. String fallback_path;
  715. bool using_uid = false;
  716. if (next_tag.fields.has("uid")) {
  717. // If uid exists, return uid in text format, not the path.
  718. String uidt = next_tag.fields["uid"];
  719. ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
  720. if (uid != ResourceUID::INVALID_ID) {
  721. fallback_path = path; // Used by Dependency Editor, in case uid path fails.
  722. path = ResourceUID::get_singleton()->id_to_text(uid);
  723. using_uid = true;
  724. }
  725. }
  726. if (!using_uid && !path.contains("://") && path.is_relative_path()) {
  727. // Path is relative to file being loaded, so convert to a resource path.
  728. path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().path_join(path));
  729. }
  730. if (p_add_types) {
  731. path += "::" + type;
  732. }
  733. if (!fallback_path.is_empty()) {
  734. if (!p_add_types) {
  735. path += "::"; // Ensure that path comes third, even if there is no type.
  736. }
  737. path += "::" + fallback_path;
  738. }
  739. p_dependencies->push_back(path);
  740. Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  741. if (err) {
  742. print_line(error_text + " - " + itos(lines));
  743. error_text = "Unexpected end of file";
  744. _printerr();
  745. error = ERR_FILE_CORRUPT;
  746. return;
  747. }
  748. }
  749. }
  750. Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const HashMap<String, String> &p_map) {
  751. open(p_f, true);
  752. ERR_FAIL_COND_V(error != OK, error);
  753. ignore_resource_parsing = true;
  754. //FileAccess
  755. Ref<FileAccess> fw;
  756. String base_path = local_path.get_base_dir();
  757. uint64_t tag_end = f->get_position();
  758. while (true) {
  759. Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  760. if (err != OK) {
  761. error = ERR_FILE_CORRUPT;
  762. ERR_FAIL_V(error);
  763. }
  764. if (next_tag.name != "ext_resource") {
  765. //nothing was done
  766. if (fw.is_null()) {
  767. return OK;
  768. }
  769. break;
  770. } else {
  771. if (fw.is_null()) {
  772. fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
  773. if (res_uid == ResourceUID::INVALID_ID) {
  774. res_uid = ResourceSaver::get_resource_id_for_path(p_path);
  775. }
  776. String uid_text = "";
  777. if (res_uid != ResourceUID::INVALID_ID) {
  778. uid_text = " uid=\"" + ResourceUID::get_singleton()->id_to_text(res_uid) + "\"";
  779. }
  780. if (is_scene) {
  781. fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_text + "]\n");
  782. } else {
  783. String script_res_text;
  784. if (!script_class.is_empty()) {
  785. script_res_text = "script_class=\"" + script_class + "\" ";
  786. }
  787. fw->store_line("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_text + "]\n");
  788. }
  789. }
  790. if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) {
  791. error = ERR_FILE_CORRUPT;
  792. ERR_FAIL_V(error);
  793. }
  794. String path = next_tag.fields["path"];
  795. String id = next_tag.fields["id"];
  796. String type = next_tag.fields["type"];
  797. if (next_tag.fields.has("uid")) {
  798. String uidt = next_tag.fields["uid"];
  799. ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
  800. if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
  801. // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
  802. path = ResourceUID::get_singleton()->get_id_path(uid);
  803. }
  804. }
  805. bool relative = false;
  806. if (!path.begins_with("res://")) {
  807. path = base_path.path_join(path).simplify_path();
  808. relative = true;
  809. }
  810. if (p_map.has(path)) {
  811. String np = p_map[path];
  812. path = np;
  813. }
  814. if (relative) {
  815. //restore relative
  816. path = base_path.path_to_file(path);
  817. }
  818. String s = "[ext_resource type=\"" + type + "\"";
  819. ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(path);
  820. if (uid != ResourceUID::INVALID_ID) {
  821. s += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
  822. }
  823. s += " path=\"" + path + "\" id=\"" + id + "\"]";
  824. fw->store_line(s); // Bundled.
  825. tag_end = f->get_position();
  826. }
  827. }
  828. f->seek(tag_end);
  829. const uint32_t buffer_size = 2048;
  830. uint8_t *buffer = (uint8_t *)alloca(buffer_size);
  831. uint32_t num_read;
  832. num_read = f->get_buffer(buffer, buffer_size);
  833. ERR_FAIL_COND_V_MSG(num_read == UINT32_MAX, ERR_CANT_CREATE, "Failed to allocate memory for buffer.");
  834. ERR_FAIL_COND_V(num_read == 0, ERR_FILE_CORRUPT);
  835. if (*buffer == '\n') {
  836. // Skip first newline character since we added one.
  837. if (num_read > 1) {
  838. fw->store_buffer(buffer + 1, num_read - 1);
  839. }
  840. } else {
  841. fw->store_buffer(buffer, num_read);
  842. }
  843. while (!f->eof_reached()) {
  844. num_read = f->get_buffer(buffer, buffer_size);
  845. fw->store_buffer(buffer, num_read);
  846. }
  847. bool all_ok = fw->get_error() == OK;
  848. if (!all_ok) {
  849. return ERR_CANT_CREATE;
  850. }
  851. return OK;
  852. }
  853. void ResourceLoaderText::open(Ref<FileAccess> p_f, bool p_skip_first_tag) {
  854. error = OK;
  855. lines = 1;
  856. f = p_f;
  857. stream.f = f;
  858. is_scene = false;
  859. ignore_resource_parsing = false;
  860. resource_current = 0;
  861. VariantParser::Tag tag;
  862. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  863. if (err) {
  864. error = err;
  865. _printerr();
  866. return;
  867. }
  868. if (tag.fields.has("format")) {
  869. int fmt = tag.fields["format"];
  870. if (fmt > FORMAT_VERSION_READABLE) {
  871. error_text = "Saved with newer format version";
  872. _printerr();
  873. error = ERR_PARSE_ERROR;
  874. return;
  875. }
  876. }
  877. if (tag.name == "gd_scene") {
  878. is_scene = true;
  879. } else if (tag.name == "gd_resource") {
  880. if (!tag.fields.has("type")) {
  881. error_text = "Missing 'type' field in 'gd_resource' tag";
  882. _printerr();
  883. error = ERR_PARSE_ERROR;
  884. return;
  885. }
  886. if (tag.fields.has("script_class")) {
  887. script_class = tag.fields["script_class"];
  888. }
  889. res_type = tag.fields["type"];
  890. } else {
  891. error_text = "Unrecognized file type: " + tag.name;
  892. _printerr();
  893. error = ERR_PARSE_ERROR;
  894. return;
  895. }
  896. if (tag.fields.has("uid")) {
  897. res_uid = ResourceUID::get_singleton()->text_to_id(tag.fields["uid"]);
  898. } else {
  899. res_uid = ResourceUID::INVALID_ID;
  900. }
  901. if (tag.fields.has("load_steps")) {
  902. resources_total = tag.fields["load_steps"];
  903. } else {
  904. resources_total = 0;
  905. }
  906. if (!p_skip_first_tag) {
  907. err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
  908. if (err) {
  909. error_text = "Unexpected end of file";
  910. _printerr();
  911. error = ERR_FILE_CORRUPT;
  912. }
  913. }
  914. rp.ext_func = _parse_ext_resources;
  915. rp.sub_func = _parse_sub_resources;
  916. rp.userdata = this;
  917. }
  918. static void bs_save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len = false) {
  919. CharString utf8 = p_string.utf8();
  920. if (p_bit_on_len) {
  921. p_f->store_32((utf8.length() + 1) | 0x80000000);
  922. } else {
  923. p_f->store_32(utf8.length() + 1);
  924. }
  925. p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
  926. }
  927. Error ResourceLoaderText::save_as_binary(const String &p_path) {
  928. if (error) {
  929. return error;
  930. }
  931. Ref<FileAccess> wf = FileAccess::open(p_path, FileAccess::WRITE);
  932. if (wf.is_null()) {
  933. return ERR_CANT_OPEN;
  934. }
  935. //save header compressed
  936. static const uint8_t header[4] = { 'R', 'S', 'R', 'C' };
  937. wf->store_buffer(header, 4);
  938. wf->store_32(0); //endianness, little endian
  939. wf->store_32(0); //64 bits file, false for now
  940. wf->store_32(VERSION_MAJOR);
  941. wf->store_32(VERSION_MINOR);
  942. static const int save_format_version = BINARY_FORMAT_VERSION;
  943. wf->store_32(save_format_version);
  944. bs_save_unicode_string(wf, is_scene ? "PackedScene" : resource_type);
  945. wf->store_64(0); //offset to import metadata, this is no longer used
  946. wf->store_32(ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS | ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS);
  947. wf->store_64(res_uid);
  948. for (int i = 0; i < ResourceFormatSaverBinaryInstance::RESERVED_FIELDS; i++) {
  949. wf->store_32(0); // reserved
  950. }
  951. wf->store_32(0); //string table size, will not be in use
  952. uint64_t ext_res_count_pos = wf->get_position();
  953. wf->store_32(0); //zero ext resources, still parsing them
  954. //go with external resources
  955. DummyReadData dummy_read;
  956. VariantParser::ResourceParser rp_new;
  957. rp_new.ext_func = _parse_ext_resource_dummys;
  958. rp_new.sub_func = _parse_sub_resource_dummys;
  959. rp_new.userdata = &dummy_read;
  960. while (next_tag.name == "ext_resource") {
  961. if (!next_tag.fields.has("path")) {
  962. error = ERR_FILE_CORRUPT;
  963. error_text = "Missing 'path' in external resource tag";
  964. _printerr();
  965. return error;
  966. }
  967. if (!next_tag.fields.has("type")) {
  968. error = ERR_FILE_CORRUPT;
  969. error_text = "Missing 'type' in external resource tag";
  970. _printerr();
  971. return error;
  972. }
  973. if (!next_tag.fields.has("id")) {
  974. error = ERR_FILE_CORRUPT;
  975. error_text = "Missing 'id' in external resource tag";
  976. _printerr();
  977. return error;
  978. }
  979. String path = next_tag.fields["path"];
  980. String type = next_tag.fields["type"];
  981. String id = next_tag.fields["id"];
  982. ResourceUID::ID uid = ResourceUID::INVALID_ID;
  983. if (next_tag.fields.has("uid")) {
  984. String uidt = next_tag.fields["uid"];
  985. uid = ResourceUID::get_singleton()->text_to_id(uidt);
  986. }
  987. bs_save_unicode_string(wf, type);
  988. bs_save_unicode_string(wf, path);
  989. wf->store_64(uid);
  990. int lindex = dummy_read.external_resources.size();
  991. Ref<DummyResource> dr;
  992. dr.instantiate();
  993. dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external
  994. dummy_read.external_resources[dr] = lindex;
  995. dummy_read.rev_external_resources[id] = dr;
  996. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp_new);
  997. if (error) {
  998. _printerr();
  999. return error;
  1000. }
  1001. }
  1002. // save external resource table
  1003. wf->seek(ext_res_count_pos);
  1004. wf->store_32(dummy_read.external_resources.size());
  1005. wf->seek_end();
  1006. //now, save resources to a separate file, for now
  1007. uint64_t sub_res_count_pos = wf->get_position();
  1008. wf->store_32(0); //zero sub resources, still parsing them
  1009. String temp_file = p_path + ".temp";
  1010. Vector<uint64_t> local_offsets;
  1011. Vector<uint64_t> local_pointers_pos;
  1012. {
  1013. Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
  1014. if (wf2.is_null()) {
  1015. return ERR_CANT_OPEN;
  1016. }
  1017. while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
  1018. String type;
  1019. String id;
  1020. bool main_res;
  1021. if (next_tag.name == "sub_resource") {
  1022. if (!next_tag.fields.has("type")) {
  1023. error = ERR_FILE_CORRUPT;
  1024. error_text = "Missing 'type' in external resource tag";
  1025. _printerr();
  1026. return error;
  1027. }
  1028. if (!next_tag.fields.has("id")) {
  1029. error = ERR_FILE_CORRUPT;
  1030. error_text = "Missing 'id' in external resource tag";
  1031. _printerr();
  1032. return error;
  1033. }
  1034. type = next_tag.fields["type"];
  1035. id = next_tag.fields["id"];
  1036. main_res = false;
  1037. if (!dummy_read.resource_map.has(id)) {
  1038. Ref<DummyResource> dr;
  1039. dr.instantiate();
  1040. dr->set_scene_unique_id(id);
  1041. dummy_read.resource_map[id] = dr;
  1042. uint32_t im_size = dummy_read.resource_index_map.size();
  1043. dummy_read.resource_index_map.insert(dr, im_size);
  1044. }
  1045. } else {
  1046. type = res_type;
  1047. String uid_text = ResourceUID::get_singleton()->id_to_text(res_uid);
  1048. id = type + "_" + uid_text.replace("uid://", "").replace("<invalid>", "0");
  1049. main_res = true;
  1050. }
  1051. local_offsets.push_back(wf2->get_position());
  1052. bs_save_unicode_string(wf, "local://" + id);
  1053. local_pointers_pos.push_back(wf->get_position());
  1054. wf->store_64(0); //temp local offset
  1055. bs_save_unicode_string(wf2, type);
  1056. uint64_t propcount_ofs = wf2->get_position();
  1057. wf2->store_32(0);
  1058. int prop_count = 0;
  1059. while (true) {
  1060. String assign;
  1061. Variant value;
  1062. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp_new);
  1063. if (error) {
  1064. if (main_res && error == ERR_FILE_EOF) {
  1065. next_tag.name = ""; //exit
  1066. break;
  1067. }
  1068. _printerr();
  1069. return error;
  1070. }
  1071. if (!assign.is_empty()) {
  1072. HashMap<StringName, int> empty_string_map; //unused
  1073. bs_save_unicode_string(wf2, assign, true);
  1074. ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
  1075. prop_count++;
  1076. } else if (!next_tag.name.is_empty()) {
  1077. error = OK;
  1078. break;
  1079. } else {
  1080. error = ERR_FILE_CORRUPT;
  1081. error_text = "Premature end of file while parsing [sub_resource]";
  1082. _printerr();
  1083. return error;
  1084. }
  1085. }
  1086. wf2->seek(propcount_ofs);
  1087. wf2->store_32(prop_count);
  1088. wf2->seek_end();
  1089. }
  1090. if (next_tag.name == "node") {
  1091. // This is a node, must save one more!
  1092. if (!is_scene) {
  1093. error_text += "found the 'node' tag on a resource file!";
  1094. _printerr();
  1095. error = ERR_FILE_CORRUPT;
  1096. return error;
  1097. }
  1098. Ref<PackedScene> packed_scene = _parse_node_tag(rp_new);
  1099. if (!packed_scene.is_valid()) {
  1100. return error;
  1101. }
  1102. error = OK;
  1103. //get it here
  1104. List<PropertyInfo> props;
  1105. packed_scene->get_property_list(&props);
  1106. String id = "PackedScene_" + ResourceUID::get_singleton()->id_to_text(res_uid).replace("uid://", "").replace("<invalid>", "0");
  1107. bs_save_unicode_string(wf, "local://" + id);
  1108. local_pointers_pos.push_back(wf->get_position());
  1109. wf->store_64(0); //temp local offset
  1110. local_offsets.push_back(wf2->get_position());
  1111. bs_save_unicode_string(wf2, "PackedScene");
  1112. uint64_t propcount_ofs = wf2->get_position();
  1113. wf2->store_32(0);
  1114. int prop_count = 0;
  1115. for (const PropertyInfo &E : props) {
  1116. if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
  1117. continue;
  1118. }
  1119. String name = E.name;
  1120. Variant value = packed_scene->get(name);
  1121. HashMap<StringName, int> empty_string_map; //unused
  1122. bs_save_unicode_string(wf2, name, true);
  1123. ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
  1124. prop_count++;
  1125. }
  1126. wf2->seek(propcount_ofs);
  1127. wf2->store_32(prop_count);
  1128. wf2->seek_end();
  1129. }
  1130. }
  1131. uint64_t offset_from = wf->get_position();
  1132. wf->seek(sub_res_count_pos); //plus one because the saved one
  1133. wf->store_32(local_offsets.size());
  1134. for (int i = 0; i < local_offsets.size(); i++) {
  1135. wf->seek(local_pointers_pos[i]);
  1136. wf->store_64(local_offsets[i] + offset_from);
  1137. }
  1138. wf->seek_end();
  1139. Vector<uint8_t> data = FileAccess::get_file_as_bytes(temp_file);
  1140. wf->store_buffer(data.ptr(), data.size());
  1141. {
  1142. Ref<DirAccess> dar = DirAccess::open(temp_file.get_base_dir());
  1143. ERR_FAIL_COND_V(dar.is_null(), FAILED);
  1144. dar->remove(temp_file);
  1145. }
  1146. wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
  1147. return OK;
  1148. }
  1149. Error ResourceLoaderText::get_classes_used(HashSet<StringName> *r_classes) {
  1150. if (error) {
  1151. return error;
  1152. }
  1153. ignore_resource_parsing = true;
  1154. DummyReadData dummy_read;
  1155. dummy_read.no_placeholders = true;
  1156. VariantParser::ResourceParser rp_new;
  1157. rp_new.ext_func = _parse_ext_resource_dummys;
  1158. rp_new.sub_func = _parse_sub_resource_dummys;
  1159. rp_new.userdata = &dummy_read;
  1160. while (next_tag.name == "ext_resource") {
  1161. error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp_new);
  1162. if (error) {
  1163. _printerr();
  1164. return error;
  1165. }
  1166. }
  1167. while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
  1168. if (next_tag.name == "sub_resource") {
  1169. if (!next_tag.fields.has("type")) {
  1170. error = ERR_FILE_CORRUPT;
  1171. error_text = "Missing 'type' in external resource tag";
  1172. _printerr();
  1173. return error;
  1174. }
  1175. r_classes->insert(next_tag.fields["type"]);
  1176. } else {
  1177. r_classes->insert(next_tag.fields["res_type"]);
  1178. }
  1179. while (true) {
  1180. String assign;
  1181. Variant value;
  1182. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp_new);
  1183. if (error) {
  1184. if (error == ERR_FILE_EOF) {
  1185. return OK;
  1186. }
  1187. _printerr();
  1188. return error;
  1189. }
  1190. if (!assign.is_empty()) {
  1191. continue;
  1192. } else if (!next_tag.name.is_empty()) {
  1193. error = OK;
  1194. break;
  1195. } else {
  1196. error = ERR_FILE_CORRUPT;
  1197. error_text = "Premature end of file while parsing [sub_resource]";
  1198. _printerr();
  1199. return error;
  1200. }
  1201. }
  1202. }
  1203. while (next_tag.name == "node") {
  1204. // This is a node, must save one more!
  1205. if (!is_scene) {
  1206. error_text += "found the 'node' tag on a resource file!";
  1207. _printerr();
  1208. error = ERR_FILE_CORRUPT;
  1209. return error;
  1210. }
  1211. if (!next_tag.fields.has("type")) {
  1212. error = ERR_FILE_CORRUPT;
  1213. error_text = "Missing 'type' in external resource tag";
  1214. _printerr();
  1215. return error;
  1216. }
  1217. r_classes->insert(next_tag.fields["type"]);
  1218. while (true) {
  1219. String assign;
  1220. Variant value;
  1221. error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp_new);
  1222. if (error) {
  1223. if (error == ERR_FILE_MISSING_DEPENDENCIES) {
  1224. // Resource loading error, just skip it.
  1225. } else if (error != ERR_FILE_EOF) {
  1226. _printerr();
  1227. return error;
  1228. } else {
  1229. return OK;
  1230. }
  1231. }
  1232. if (!assign.is_empty()) {
  1233. continue;
  1234. } else if (!next_tag.name.is_empty()) {
  1235. error = OK;
  1236. break;
  1237. } else {
  1238. error = ERR_FILE_CORRUPT;
  1239. error_text = "Premature end of file while parsing [sub_resource]";
  1240. _printerr();
  1241. return error;
  1242. }
  1243. }
  1244. }
  1245. return OK;
  1246. }
  1247. String ResourceLoaderText::recognize_script_class(Ref<FileAccess> p_f) {
  1248. error = OK;
  1249. lines = 1;
  1250. f = p_f;
  1251. stream.f = f;
  1252. ignore_resource_parsing = true;
  1253. VariantParser::Tag tag;
  1254. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  1255. if (err) {
  1256. _printerr();
  1257. return "";
  1258. }
  1259. if (tag.fields.has("format")) {
  1260. int fmt = tag.fields["format"];
  1261. if (fmt > FORMAT_VERSION_READABLE) {
  1262. error_text = "Saved with newer format version";
  1263. _printerr();
  1264. return "";
  1265. }
  1266. }
  1267. if (tag.name != "gd_resource") {
  1268. return "";
  1269. }
  1270. if (tag.fields.has("script_class")) {
  1271. return tag.fields["script_class"];
  1272. }
  1273. return "";
  1274. }
  1275. String ResourceLoaderText::recognize(Ref<FileAccess> p_f) {
  1276. error = OK;
  1277. lines = 1;
  1278. f = p_f;
  1279. stream.f = f;
  1280. ignore_resource_parsing = true;
  1281. VariantParser::Tag tag;
  1282. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  1283. if (err) {
  1284. _printerr();
  1285. return "";
  1286. }
  1287. if (tag.fields.has("format")) {
  1288. int fmt = tag.fields["format"];
  1289. if (fmt > FORMAT_VERSION_READABLE) {
  1290. error_text = "Saved with newer format version";
  1291. _printerr();
  1292. return "";
  1293. }
  1294. }
  1295. if (tag.name == "gd_scene") {
  1296. return "PackedScene";
  1297. }
  1298. if (tag.name != "gd_resource") {
  1299. return "";
  1300. }
  1301. if (!tag.fields.has("type")) {
  1302. error_text = "Missing 'type' field in 'gd_resource' tag";
  1303. _printerr();
  1304. return "";
  1305. }
  1306. return tag.fields["type"];
  1307. }
  1308. ResourceUID::ID ResourceLoaderText::get_uid(Ref<FileAccess> p_f) {
  1309. error = OK;
  1310. lines = 1;
  1311. f = p_f;
  1312. stream.f = f;
  1313. ignore_resource_parsing = true;
  1314. VariantParser::Tag tag;
  1315. Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
  1316. if (err) {
  1317. _printerr();
  1318. return ResourceUID::INVALID_ID;
  1319. }
  1320. if (tag.fields.has("uid")) { //field is optional
  1321. String uidt = tag.fields["uid"];
  1322. return ResourceUID::get_singleton()->text_to_id(uidt);
  1323. }
  1324. return ResourceUID::INVALID_ID;
  1325. }
  1326. /////////////////////
  1327. Ref<Resource> 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) {
  1328. if (r_error) {
  1329. *r_error = ERR_CANT_OPEN;
  1330. }
  1331. Error err;
  1332. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
  1333. ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot open file '" + p_path + "'.");
  1334. ResourceLoaderText loader;
  1335. String path = !p_original_path.is_empty() ? p_original_path : p_path;
  1336. loader.cache_mode = p_cache_mode;
  1337. loader.use_sub_threads = p_use_sub_threads;
  1338. loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
  1339. loader.progress = r_progress;
  1340. loader.res_path = loader.local_path;
  1341. loader.open(f);
  1342. err = loader.load();
  1343. if (r_error) {
  1344. *r_error = err;
  1345. }
  1346. if (err == OK) {
  1347. return loader.get_resource();
  1348. } else {
  1349. return Ref<Resource>();
  1350. }
  1351. }
  1352. void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
  1353. if (p_type.is_empty()) {
  1354. get_recognized_extensions(p_extensions);
  1355. return;
  1356. }
  1357. if (ClassDB::is_parent_class("PackedScene", p_type)) {
  1358. p_extensions->push_back("tscn");
  1359. }
  1360. // Don't allow .tres for PackedScenes.
  1361. if (p_type != "PackedScene") {
  1362. p_extensions->push_back("tres");
  1363. }
  1364. }
  1365. void ResourceFormatLoaderText::get_recognized_extensions(List<String> *p_extensions) const {
  1366. p_extensions->push_back("tscn");
  1367. p_extensions->push_back("tres");
  1368. }
  1369. bool ResourceFormatLoaderText::handles_type(const String &p_type) const {
  1370. return true;
  1371. }
  1372. void ResourceFormatLoaderText::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
  1373. String ext = p_path.get_extension().to_lower();
  1374. if (ext == "tscn") {
  1375. r_classes->insert("PackedScene");
  1376. }
  1377. // ...for anything else must test...
  1378. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1379. if (f.is_null()) {
  1380. return; // Could not read.
  1381. }
  1382. ResourceLoaderText loader;
  1383. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1384. loader.res_path = loader.local_path;
  1385. loader.open(f);
  1386. loader.get_classes_used(r_classes);
  1387. }
  1388. String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
  1389. String ext = p_path.get_extension().to_lower();
  1390. if (ext == "tscn") {
  1391. return "PackedScene";
  1392. } else if (ext != "tres") {
  1393. return String();
  1394. }
  1395. // ...for anything else must test...
  1396. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1397. if (f.is_null()) {
  1398. return ""; //could not read
  1399. }
  1400. ResourceLoaderText loader;
  1401. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1402. loader.res_path = loader.local_path;
  1403. String r = loader.recognize(f);
  1404. return ClassDB::get_compatibility_remapped_class(r);
  1405. }
  1406. String ResourceFormatLoaderText::get_resource_script_class(const String &p_path) const {
  1407. String ext = p_path.get_extension().to_lower();
  1408. if (ext != "tres") {
  1409. return String();
  1410. }
  1411. // ...for anything else must test...
  1412. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1413. if (f.is_null()) {
  1414. return ""; //could not read
  1415. }
  1416. ResourceLoaderText loader;
  1417. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1418. loader.res_path = loader.local_path;
  1419. return loader.recognize_script_class(f);
  1420. }
  1421. ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path) const {
  1422. String ext = p_path.get_extension().to_lower();
  1423. if (ext != "tscn" && ext != "tres") {
  1424. return ResourceUID::INVALID_ID;
  1425. }
  1426. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1427. if (f.is_null()) {
  1428. return ResourceUID::INVALID_ID; //could not read
  1429. }
  1430. ResourceLoaderText loader;
  1431. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1432. loader.res_path = loader.local_path;
  1433. return loader.get_uid(f);
  1434. }
  1435. void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
  1436. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1437. if (f.is_null()) {
  1438. ERR_FAIL();
  1439. }
  1440. ResourceLoaderText loader;
  1441. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1442. loader.res_path = loader.local_path;
  1443. loader.get_dependencies(f, p_dependencies, p_add_types);
  1444. }
  1445. Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) {
  1446. Error err = OK;
  1447. {
  1448. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
  1449. if (f.is_null()) {
  1450. ERR_FAIL_V(ERR_CANT_OPEN);
  1451. }
  1452. ResourceLoaderText loader;
  1453. loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1454. loader.res_path = loader.local_path;
  1455. err = loader.rename_dependencies(f, p_path, p_map);
  1456. }
  1457. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
  1458. if (err == OK && da->file_exists(p_path + ".depren")) {
  1459. da->remove(p_path);
  1460. da->rename(p_path + ".depren", p_path);
  1461. }
  1462. return err;
  1463. }
  1464. ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = nullptr;
  1465. Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) {
  1466. Error err;
  1467. Ref<FileAccess> f = FileAccess::open(p_src_path, FileAccess::READ, &err);
  1468. ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_src_path + "'.");
  1469. ResourceLoaderText loader;
  1470. const String &path = p_src_path;
  1471. loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
  1472. loader.res_path = loader.local_path;
  1473. loader.open(f);
  1474. return loader.save_as_binary(p_dst_path);
  1475. }
  1476. /*****************************************************************************************************/
  1477. /*****************************************************************************************************/
  1478. /*****************************************************************************************************/
  1479. /*****************************************************************************************************/
  1480. /*****************************************************************************************************/
  1481. /*****************************************************************************************************/
  1482. /*****************************************************************************************************/
  1483. /*****************************************************************************************************/
  1484. /*****************************************************************************************************/
  1485. /*****************************************************************************************************/
  1486. String ResourceFormatSaverTextInstance::_write_resources(void *ud, const Ref<Resource> &p_resource) {
  1487. ResourceFormatSaverTextInstance *rsi = static_cast<ResourceFormatSaverTextInstance *>(ud);
  1488. return rsi->_write_resource(p_resource);
  1489. }
  1490. String ResourceFormatSaverTextInstance::_write_resource(const Ref<Resource> &res) {
  1491. if (res->get_meta(SNAME("_skip_save_"), false)) {
  1492. return "null";
  1493. }
  1494. if (external_resources.has(res)) {
  1495. return "ExtResource(\"" + external_resources[res] + "\")";
  1496. } else {
  1497. if (internal_resources.has(res)) {
  1498. return "SubResource(\"" + internal_resources[res] + "\")";
  1499. } else if (!res->is_built_in()) {
  1500. if (res->get_path() == local_path) { //circular reference attempt
  1501. return "null";
  1502. }
  1503. //external resource
  1504. String path = relative_paths ? local_path.path_to_file(res->get_path()) : res->get_path();
  1505. return "Resource(\"" + path + "\")";
  1506. } else {
  1507. ERR_FAIL_V_MSG("null", "Resource was not pre cached for the resource section, bug?");
  1508. //internal resource
  1509. }
  1510. }
  1511. }
  1512. void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, bool p_main) {
  1513. switch (p_variant.get_type()) {
  1514. case Variant::OBJECT: {
  1515. Ref<Resource> res = p_variant;
  1516. if (res.is_null() || external_resources.has(res) || res->get_meta(SNAME("_skip_save_"), false)) {
  1517. return;
  1518. }
  1519. if (!p_main && (!bundle_resources) && !res->is_built_in()) {
  1520. if (res->get_path() == local_path) {
  1521. ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
  1522. return;
  1523. }
  1524. // Use a numeric ID as a base, because they are sorted in natural order before saving.
  1525. // This increases the chances of thread loading to fetch them first.
  1526. String id = itos(external_resources.size() + 1) + "_" + Resource::generate_scene_unique_id();
  1527. external_resources[res] = id;
  1528. return;
  1529. }
  1530. if (resource_set.has(res)) {
  1531. return;
  1532. }
  1533. resource_set.insert(res);
  1534. List<PropertyInfo> property_list;
  1535. res->get_property_list(&property_list);
  1536. property_list.sort();
  1537. List<PropertyInfo>::Element *I = property_list.front();
  1538. while (I) {
  1539. PropertyInfo pi = I->get();
  1540. if (pi.usage & PROPERTY_USAGE_STORAGE) {
  1541. Variant v = res->get(I->get().name);
  1542. if (pi.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
  1543. NonPersistentKey npk;
  1544. npk.base = res;
  1545. npk.property = pi.name;
  1546. non_persistent_map[npk] = v;
  1547. Ref<Resource> sres = v;
  1548. if (sres.is_valid()) {
  1549. resource_set.insert(sres);
  1550. saved_resources.push_back(sres);
  1551. } else {
  1552. _find_resources(v);
  1553. }
  1554. } else {
  1555. _find_resources(v);
  1556. }
  1557. }
  1558. I = I->next();
  1559. }
  1560. saved_resources.push_back(res); // Saved after, so the children it needs are available when loaded
  1561. } break;
  1562. case Variant::ARRAY: {
  1563. Array varray = p_variant;
  1564. int len = varray.size();
  1565. for (int i = 0; i < len; i++) {
  1566. const Variant &v = varray.get(i);
  1567. _find_resources(v);
  1568. }
  1569. } break;
  1570. case Variant::DICTIONARY: {
  1571. Dictionary d = p_variant;
  1572. List<Variant> keys;
  1573. d.get_key_list(&keys);
  1574. for (const Variant &E : keys) {
  1575. // Of course keys should also be cached, after all we can't prevent users from using resources as keys, right?
  1576. // See also ResourceFormatSaverBinaryInstance::_find_resources (when p_variant is of type Variant::DICTIONARY)
  1577. _find_resources(E);
  1578. Variant v = d[E];
  1579. _find_resources(v);
  1580. }
  1581. } break;
  1582. default: {
  1583. }
  1584. }
  1585. }
  1586. static String _resource_get_class(Ref<Resource> p_resource) {
  1587. Ref<MissingResource> missing_resource = p_resource;
  1588. if (missing_resource.is_valid()) {
  1589. return missing_resource->get_original_class();
  1590. } else {
  1591. return p_resource->get_class();
  1592. }
  1593. }
  1594. Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
  1595. if (p_path.ends_with(".tscn")) {
  1596. packed_scene = p_resource;
  1597. }
  1598. Error err;
  1599. Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
  1600. ERR_FAIL_COND_V_MSG(err, ERR_CANT_OPEN, "Cannot save file '" + p_path + "'.");
  1601. Ref<FileAccess> _fref(f);
  1602. local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1603. relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
  1604. skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
  1605. bundle_resources = p_flags & ResourceSaver::FLAG_BUNDLE_RESOURCES;
  1606. takeover_paths = p_flags & ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
  1607. if (!p_path.begins_with("res://")) {
  1608. takeover_paths = false;
  1609. }
  1610. // Save resources.
  1611. _find_resources(p_resource, true);
  1612. if (packed_scene.is_valid()) {
  1613. // Add instances to external resources if saving a packed scene.
  1614. for (int i = 0; i < packed_scene->get_state()->get_node_count(); i++) {
  1615. if (packed_scene->get_state()->is_node_instance_placeholder(i)) {
  1616. continue;
  1617. }
  1618. Ref<PackedScene> instance = packed_scene->get_state()->get_node_instance(i);
  1619. if (instance.is_valid() && !external_resources.has(instance)) {
  1620. int index = external_resources.size() + 1;
  1621. external_resources[instance] = itos(index) + "_" + Resource::generate_scene_unique_id(); // Keep the order for improved thread loading performance.
  1622. }
  1623. }
  1624. }
  1625. {
  1626. String title = packed_scene.is_valid() ? "[gd_scene " : "[gd_resource ";
  1627. if (packed_scene.is_null()) {
  1628. title += "type=\"" + _resource_get_class(p_resource) + "\" ";
  1629. Ref<Script> script = p_resource->get_script();
  1630. if (script.is_valid() && script->get_global_name()) {
  1631. title += "script_class=\"" + String(script->get_global_name()) + "\" ";
  1632. }
  1633. }
  1634. int load_steps = saved_resources.size() + external_resources.size();
  1635. if (load_steps > 1) {
  1636. title += "load_steps=" + itos(load_steps) + " ";
  1637. }
  1638. title += "format=" + itos(FORMAT_VERSION) + "";
  1639. ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(local_path, true);
  1640. if (uid != ResourceUID::INVALID_ID) {
  1641. title += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
  1642. }
  1643. f->store_string(title);
  1644. f->store_line("]\n"); // One empty line.
  1645. }
  1646. #ifdef TOOLS_ENABLED
  1647. // Keep order from cached ids.
  1648. HashSet<String> cached_ids_found;
  1649. for (KeyValue<Ref<Resource>, String> &E : external_resources) {
  1650. String cached_id = E.key->get_id_for_path(local_path);
  1651. if (cached_id.is_empty() || cached_ids_found.has(cached_id)) {
  1652. int sep_pos = E.value.find("_");
  1653. if (sep_pos != -1) {
  1654. E.value = E.value.substr(0, sep_pos + 1); // Keep the order found, for improved thread loading performance.
  1655. } else {
  1656. E.value = "";
  1657. }
  1658. } else {
  1659. E.value = cached_id;
  1660. cached_ids_found.insert(cached_id);
  1661. }
  1662. }
  1663. // Create IDs for non cached resources.
  1664. for (KeyValue<Ref<Resource>, String> &E : external_resources) {
  1665. if (cached_ids_found.has(E.value)) { // Already cached, go on.
  1666. continue;
  1667. }
  1668. String attempt;
  1669. while (true) {
  1670. attempt = E.value + Resource::generate_scene_unique_id();
  1671. if (!cached_ids_found.has(attempt)) {
  1672. break;
  1673. }
  1674. }
  1675. cached_ids_found.insert(attempt);
  1676. E.value = attempt;
  1677. // Update also in resource.
  1678. Ref<Resource> res = E.key;
  1679. res->set_id_for_path(local_path, attempt);
  1680. }
  1681. #else
  1682. // Make sure to start from one, as it makes format more readable.
  1683. int counter = 1;
  1684. for (KeyValue<Ref<Resource>, String> &E : external_resources) {
  1685. E.value = itos(counter++);
  1686. }
  1687. #endif
  1688. Vector<ResourceSort> sorted_er;
  1689. for (const KeyValue<Ref<Resource>, String> &E : external_resources) {
  1690. ResourceSort rs;
  1691. rs.resource = E.key;
  1692. rs.id = E.value;
  1693. sorted_er.push_back(rs);
  1694. }
  1695. sorted_er.sort();
  1696. for (int i = 0; i < sorted_er.size(); i++) {
  1697. String p = sorted_er[i].resource->get_path();
  1698. String s = "[ext_resource type=\"" + sorted_er[i].resource->get_save_class() + "\"";
  1699. ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p, false);
  1700. if (uid != ResourceUID::INVALID_ID) {
  1701. s += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
  1702. }
  1703. s += " path=\"" + p + "\" id=\"" + sorted_er[i].id + "\"]\n";
  1704. f->store_string(s); // Bundled.
  1705. }
  1706. if (external_resources.size()) {
  1707. f->store_line(String()); // Separate.
  1708. }
  1709. HashSet<String> used_unique_ids;
  1710. for (List<Ref<Resource>>::Element *E = saved_resources.front(); E; E = E->next()) {
  1711. Ref<Resource> res = E->get();
  1712. if (E->next() && res->is_built_in()) {
  1713. if (!res->get_scene_unique_id().is_empty()) {
  1714. if (used_unique_ids.has(res->get_scene_unique_id())) {
  1715. res->set_scene_unique_id(""); // Repeated.
  1716. } else {
  1717. used_unique_ids.insert(res->get_scene_unique_id());
  1718. }
  1719. }
  1720. }
  1721. }
  1722. for (List<Ref<Resource>>::Element *E = saved_resources.front(); E; E = E->next()) {
  1723. Ref<Resource> res = E->get();
  1724. ERR_CONTINUE(!resource_set.has(res));
  1725. bool main = (E->next() == nullptr);
  1726. if (main && packed_scene.is_valid()) {
  1727. break; // Save as a scene.
  1728. }
  1729. if (main) {
  1730. f->store_line("[resource]");
  1731. } else {
  1732. String line = "[sub_resource ";
  1733. if (res->get_scene_unique_id().is_empty()) {
  1734. String new_id;
  1735. while (true) {
  1736. new_id = _resource_get_class(res) + "_" + Resource::generate_scene_unique_id();
  1737. if (!used_unique_ids.has(new_id)) {
  1738. break;
  1739. }
  1740. }
  1741. res->set_scene_unique_id(new_id);
  1742. used_unique_ids.insert(new_id);
  1743. }
  1744. String id = res->get_scene_unique_id();
  1745. line += "type=\"" + _resource_get_class(res) + "\" id=\"" + id;
  1746. f->store_line(line + "\"]");
  1747. if (takeover_paths) {
  1748. res->set_path(p_path + "::" + id, true);
  1749. }
  1750. internal_resources[res] = id;
  1751. #ifdef TOOLS_ENABLED
  1752. res->set_edited(false);
  1753. #endif
  1754. }
  1755. Dictionary missing_resource_properties = p_resource->get_meta(META_MISSING_RESOURCES, Dictionary());
  1756. List<PropertyInfo> property_list;
  1757. res->get_property_list(&property_list);
  1758. for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) {
  1759. if (skip_editor && PE->get().name.begins_with("__editor")) {
  1760. continue;
  1761. }
  1762. if (PE->get().name == META_PROPERTY_MISSING_RESOURCES) {
  1763. continue;
  1764. }
  1765. if (PE->get().usage & PROPERTY_USAGE_STORAGE) {
  1766. String name = PE->get().name;
  1767. Variant value;
  1768. if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
  1769. NonPersistentKey npk;
  1770. npk.base = res;
  1771. npk.property = name;
  1772. if (non_persistent_map.has(npk)) {
  1773. value = non_persistent_map[npk];
  1774. }
  1775. } else {
  1776. value = res->get(name);
  1777. }
  1778. if (PE->get().type == Variant::OBJECT && missing_resource_properties.has(PE->get().name)) {
  1779. // Was this missing resource overridden? If so do not save the old value.
  1780. Ref<Resource> ures = value;
  1781. if (ures.is_null()) {
  1782. value = missing_resource_properties[PE->get().name];
  1783. }
  1784. }
  1785. Variant default_value = ClassDB::class_get_default_property_value(res->get_class(), name);
  1786. if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) {
  1787. continue;
  1788. }
  1789. if (PE->get().type == Variant::OBJECT && value.is_zero() && !(PE->get().usage & PROPERTY_USAGE_STORE_IF_NULL)) {
  1790. continue;
  1791. }
  1792. String vars;
  1793. VariantWriter::write_to_string(value, vars, _write_resources, this);
  1794. f->store_string(name.property_name_encode() + " = " + vars + "\n");
  1795. }
  1796. }
  1797. if (E->next()) {
  1798. f->store_line(String());
  1799. }
  1800. }
  1801. if (packed_scene.is_valid()) {
  1802. // If this is a scene, save nodes and connections!
  1803. Ref<SceneState> state = packed_scene->get_state();
  1804. for (int i = 0; i < state->get_node_count(); i++) {
  1805. StringName type = state->get_node_type(i);
  1806. StringName name = state->get_node_name(i);
  1807. int index = state->get_node_index(i);
  1808. NodePath path = state->get_node_path(i, true);
  1809. NodePath owner = state->get_node_owner_path(i);
  1810. Ref<PackedScene> instance = state->get_node_instance(i);
  1811. String instance_placeholder = state->get_node_instance_placeholder(i);
  1812. Vector<StringName> groups = state->get_node_groups(i);
  1813. Vector<String> deferred_node_paths = state->get_node_deferred_nodepath_properties(i);
  1814. String header = "[node";
  1815. header += " name=\"" + String(name).c_escape() + "\"";
  1816. if (type != StringName()) {
  1817. header += " type=\"" + String(type) + "\"";
  1818. }
  1819. if (path != NodePath()) {
  1820. header += " parent=\"" + String(path.simplified()).c_escape() + "\"";
  1821. }
  1822. if (owner != NodePath() && owner != NodePath(".")) {
  1823. header += " owner=\"" + String(owner.simplified()).c_escape() + "\"";
  1824. }
  1825. if (index >= 0) {
  1826. header += " index=\"" + itos(index) + "\"";
  1827. }
  1828. if (deferred_node_paths.size()) {
  1829. header += " node_paths=" + Variant(deferred_node_paths).get_construct_string();
  1830. }
  1831. if (groups.size()) {
  1832. // Write all groups on the same line as they're part of a section header.
  1833. // This improves readability while not impacting VCS friendliness too much,
  1834. // since it's rare to have more than 5 groups assigned to a single node.
  1835. groups.sort_custom<StringName::AlphCompare>();
  1836. String sgroups = " groups=[";
  1837. for (int j = 0; j < groups.size(); j++) {
  1838. sgroups += "\"" + String(groups[j]).c_escape() + "\"";
  1839. if (j < groups.size() - 1) {
  1840. sgroups += ", ";
  1841. }
  1842. }
  1843. sgroups += "]";
  1844. header += sgroups;
  1845. }
  1846. f->store_string(header);
  1847. if (!instance_placeholder.is_empty()) {
  1848. String vars;
  1849. f->store_string(" instance_placeholder=");
  1850. VariantWriter::write_to_string(instance_placeholder, vars, _write_resources, this);
  1851. f->store_string(vars);
  1852. }
  1853. if (instance.is_valid()) {
  1854. String vars;
  1855. f->store_string(" instance=");
  1856. VariantWriter::write_to_string(instance, vars, _write_resources, this);
  1857. f->store_string(vars);
  1858. }
  1859. f->store_line("]");
  1860. for (int j = 0; j < state->get_node_property_count(i); j++) {
  1861. String vars;
  1862. VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this);
  1863. f->store_string(String(state->get_node_property_name(i, j)).property_name_encode() + " = " + vars + "\n");
  1864. }
  1865. if (i < state->get_node_count() - 1) {
  1866. f->store_line(String());
  1867. }
  1868. }
  1869. for (int i = 0; i < state->get_connection_count(); i++) {
  1870. if (i == 0) {
  1871. f->store_line("");
  1872. }
  1873. String connstr = "[connection";
  1874. connstr += " signal=\"" + String(state->get_connection_signal(i)).c_escape() + "\"";
  1875. connstr += " from=\"" + String(state->get_connection_source(i).simplified()).c_escape() + "\"";
  1876. connstr += " to=\"" + String(state->get_connection_target(i).simplified()).c_escape() + "\"";
  1877. connstr += " method=\"" + String(state->get_connection_method(i)).c_escape() + "\"";
  1878. int flags = state->get_connection_flags(i);
  1879. if (flags != Object::CONNECT_PERSIST) {
  1880. connstr += " flags=" + itos(flags);
  1881. }
  1882. int unbinds = state->get_connection_unbinds(i);
  1883. if (unbinds > 0) {
  1884. connstr += " unbinds=" + itos(unbinds);
  1885. }
  1886. Array binds = state->get_connection_binds(i);
  1887. f->store_string(connstr);
  1888. if (binds.size()) {
  1889. String vars;
  1890. VariantWriter::write_to_string(binds, vars, _write_resources, this);
  1891. f->store_string(" binds= " + vars);
  1892. }
  1893. f->store_line("]");
  1894. }
  1895. Vector<NodePath> editable_instances = state->get_editable_instances();
  1896. for (int i = 0; i < editable_instances.size(); i++) {
  1897. if (i == 0) {
  1898. f->store_line("");
  1899. }
  1900. f->store_line("[editable path=\"" + editable_instances[i].operator String().c_escape() + "\"]");
  1901. }
  1902. }
  1903. if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
  1904. return ERR_CANT_CREATE;
  1905. }
  1906. return OK;
  1907. }
  1908. Error ResourceLoaderText::set_uid(Ref<FileAccess> p_f, ResourceUID::ID p_uid) {
  1909. open(p_f, true);
  1910. ERR_FAIL_COND_V(error != OK, error);
  1911. ignore_resource_parsing = true;
  1912. Ref<FileAccess> fw;
  1913. fw = FileAccess::open(local_path + ".uidren", FileAccess::WRITE);
  1914. if (is_scene) {
  1915. fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]");
  1916. } else {
  1917. String script_res_text;
  1918. if (!script_class.is_empty()) {
  1919. script_res_text = "script_class=\"" + script_class + "\" ";
  1920. }
  1921. fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]");
  1922. }
  1923. uint8_t c = f->get_8();
  1924. while (!f->eof_reached()) {
  1925. fw->store_8(c);
  1926. c = f->get_8();
  1927. }
  1928. bool all_ok = fw->get_error() == OK;
  1929. if (!all_ok) {
  1930. return ERR_CANT_CREATE;
  1931. }
  1932. return OK;
  1933. }
  1934. Error ResourceFormatSaverText::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
  1935. if (p_path.ends_with(".tscn") && !Ref<PackedScene>(p_resource).is_valid()) {
  1936. return ERR_FILE_UNRECOGNIZED;
  1937. }
  1938. ResourceFormatSaverTextInstance saver;
  1939. return saver.save(p_path, p_resource, p_flags);
  1940. }
  1941. Error ResourceFormatSaverText::set_uid(const String &p_path, ResourceUID::ID p_uid) {
  1942. String lc = p_path.to_lower();
  1943. if (!lc.ends_with(".tscn") && !lc.ends_with(".tres")) {
  1944. return ERR_FILE_UNRECOGNIZED;
  1945. }
  1946. String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
  1947. Error err = OK;
  1948. {
  1949. Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
  1950. if (file.is_null()) {
  1951. ERR_FAIL_V(ERR_CANT_OPEN);
  1952. }
  1953. ResourceLoaderText loader;
  1954. loader.local_path = local_path;
  1955. loader.res_path = loader.local_path;
  1956. err = loader.set_uid(file, p_uid);
  1957. }
  1958. if (err == OK) {
  1959. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
  1960. da->remove(local_path);
  1961. da->rename(local_path + ".uidren", local_path);
  1962. }
  1963. return err;
  1964. }
  1965. bool ResourceFormatSaverText::recognize(const Ref<Resource> &p_resource) const {
  1966. return true; // All resources recognized!
  1967. }
  1968. void ResourceFormatSaverText::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
  1969. if (Ref<PackedScene>(p_resource).is_valid()) {
  1970. p_extensions->push_back("tscn"); // Text scene.
  1971. } else {
  1972. p_extensions->push_back("tres"); // Text resource.
  1973. }
  1974. }
  1975. ResourceFormatSaverText *ResourceFormatSaverText::singleton = nullptr;
  1976. ResourceFormatSaverText::ResourceFormatSaverText() {
  1977. singleton = this;
  1978. }