resource_format_xml.cpp 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947
  1. /*************************************************************************/
  2. /* resource_format_xml.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2017 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_xml.h"
  31. #include "globals.h"
  32. #include "os/dir_access.h"
  33. #include "version.h"
  34. ResourceInteractiveLoaderXML::Tag *ResourceInteractiveLoaderXML::parse_tag(bool *r_exit, bool p_printerr, List<String> *r_order) {
  35. while (get_char() != '<' && !f->eof_reached()) {
  36. }
  37. if (f->eof_reached()) {
  38. return NULL;
  39. }
  40. Tag tag;
  41. bool exit = false;
  42. if (r_exit)
  43. *r_exit = false;
  44. bool complete = false;
  45. while (!f->eof_reached()) {
  46. CharType c = get_char();
  47. if (c < 33 && tag.name.length() && !exit) {
  48. break;
  49. } else if (c == '>') {
  50. complete = true;
  51. break;
  52. } else if (c == '/') {
  53. exit = true;
  54. } else {
  55. tag.name += c;
  56. }
  57. }
  58. if (f->eof_reached()) {
  59. return NULL;
  60. }
  61. if (exit) {
  62. if (!tag_stack.size()) {
  63. if (!p_printerr)
  64. return NULL;
  65. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Unmatched exit tag </" + tag.name + ">");
  66. ERR_FAIL_COND_V(!tag_stack.size(), NULL);
  67. }
  68. if (tag_stack.back()->get().name != tag.name) {
  69. if (!p_printerr)
  70. return NULL;
  71. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Mismatched exit tag. Got </" + tag.name + ">, expected </" + tag_stack.back()->get().name + ">");
  72. ERR_FAIL_COND_V(tag_stack.back()->get().name != tag.name, NULL);
  73. }
  74. if (!complete) {
  75. while (get_char() != '>' && !f->eof_reached()) {
  76. }
  77. if (f->eof_reached())
  78. return NULL;
  79. }
  80. if (r_exit)
  81. *r_exit = true;
  82. tag_stack.pop_back();
  83. return NULL;
  84. }
  85. if (!complete) {
  86. String name;
  87. CharString r_value;
  88. bool reading_value = false;
  89. while (!f->eof_reached()) {
  90. CharType c = get_char();
  91. if (c == '>') {
  92. if (r_value.size()) {
  93. r_value.push_back(0);
  94. String str;
  95. str.parse_utf8(r_value.get_data());
  96. tag.args[name] = str;
  97. if (r_order)
  98. r_order->push_back(name);
  99. }
  100. break;
  101. } else if (((!reading_value && (c < 33)) || c == '=' || c == '"' || c == '\'') && tag.name.length()) {
  102. if (!reading_value && name.length()) {
  103. reading_value = true;
  104. } else if (reading_value && r_value.size()) {
  105. r_value.push_back(0);
  106. String str;
  107. str.parse_utf8(r_value.get_data());
  108. tag.args[name] = str;
  109. if (r_order)
  110. r_order->push_back(name);
  111. name = "";
  112. r_value.clear();
  113. reading_value = false;
  114. }
  115. } else if (reading_value) {
  116. r_value.push_back(c);
  117. } else {
  118. name += c;
  119. }
  120. }
  121. if (f->eof_reached())
  122. return NULL;
  123. }
  124. tag_stack.push_back(tag);
  125. return &tag_stack.back()->get();
  126. }
  127. Error ResourceInteractiveLoaderXML::close_tag(const String &p_name) {
  128. int level = 0;
  129. bool inside_tag = false;
  130. while (true) {
  131. if (f->eof_reached()) {
  132. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": EOF found while attempting to find </" + p_name + ">");
  133. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  134. }
  135. uint8_t c = get_char();
  136. if (c == '<') {
  137. if (inside_tag) {
  138. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Malformed XML. Already inside Tag.");
  139. ERR_FAIL_COND_V(inside_tag, ERR_FILE_CORRUPT);
  140. }
  141. inside_tag = true;
  142. c = get_char();
  143. if (c == '/') {
  144. --level;
  145. } else {
  146. ++level;
  147. };
  148. } else if (c == '>') {
  149. if (!inside_tag) {
  150. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Malformed XML. Already outside Tag");
  151. ERR_FAIL_COND_V(!inside_tag, ERR_FILE_CORRUPT);
  152. }
  153. inside_tag = false;
  154. if (level == -1) {
  155. tag_stack.pop_back();
  156. return OK;
  157. };
  158. };
  159. }
  160. return OK;
  161. }
  162. void ResourceInteractiveLoaderXML::unquote(String &p_str) {
  163. p_str = p_str.strip_edges().replace("\"", "").xml_unescape();
  164. /*p_str=p_str.strip_edges();
  165. p_str=p_str.replace("\"","");
  166. p_str=p_str.replace("&gt;","<");
  167. p_str=p_str.replace("&lt;",">");
  168. p_str=p_str.replace("&apos;","'");
  169. p_str=p_str.replace("&quot;","\"");
  170. for (int i=1;i<32;i++) {
  171. char chr[2]={i,0};
  172. p_str=p_str.replace("&#"+String::num(i)+";",chr);
  173. }
  174. p_str=p_str.replace("&amp;","&");
  175. */
  176. //p_str.parse_utf8( p_str.ascii(true).get_data() );
  177. }
  178. Error ResourceInteractiveLoaderXML::goto_end_of_tag() {
  179. uint8_t c;
  180. while (true) {
  181. c = get_char();
  182. if (c == '>') //closetag
  183. break;
  184. if (f->eof_reached()) {
  185. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": EOF found while attempting to find close tag.");
  186. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  187. }
  188. }
  189. tag_stack.pop_back();
  190. return OK;
  191. }
  192. Error ResourceInteractiveLoaderXML::parse_property_data(String &r_data) {
  193. r_data = "";
  194. CharString cs;
  195. while (true) {
  196. CharType c = get_char();
  197. if (c == '<')
  198. break;
  199. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  200. cs.push_back(c);
  201. }
  202. cs.push_back(0);
  203. r_data.parse_utf8(cs.get_data());
  204. while (get_char() != '>' && !f->eof_reached()) {
  205. }
  206. if (f->eof_reached()) {
  207. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Malformed XML.");
  208. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  209. }
  210. r_data = r_data.strip_edges();
  211. tag_stack.pop_back();
  212. return OK;
  213. }
  214. Error ResourceInteractiveLoaderXML::_parse_array_element(Vector<char> &buff, bool p_number_only, FileAccess *f, bool *end) {
  215. if (buff.empty())
  216. buff.resize(32); // optimi
  217. int buff_max = buff.size();
  218. int buff_size = 0;
  219. *end = false;
  220. char *buffptr = &buff[0];
  221. bool found = false;
  222. bool quoted = false;
  223. while (true) {
  224. char c = get_char();
  225. if (c == 0) {
  226. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": File corrupt (zero found).");
  227. ERR_FAIL_V(ERR_FILE_CORRUPT);
  228. } else if (c == '"') {
  229. quoted = !quoted;
  230. } else if ((!quoted && ((p_number_only && c < 33) || c == ',')) || c == '<') {
  231. if (c == '<') {
  232. *end = true;
  233. break;
  234. }
  235. if (c < 32 && f->eof_reached()) {
  236. *end = true;
  237. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": File corrupt (unexpected EOF).");
  238. ERR_FAIL_V(ERR_FILE_CORRUPT);
  239. }
  240. if (found)
  241. break;
  242. } else {
  243. found = true;
  244. if (buff_size >= buff_max) {
  245. buff_max++;
  246. buff.resize(buff_max);
  247. buffptr = buff.ptr();
  248. }
  249. buffptr[buff_size] = c;
  250. buff_size++;
  251. }
  252. }
  253. if (buff_size >= buff_max) {
  254. buff_max++;
  255. buff.resize(buff_max);
  256. }
  257. buff[buff_size] = 0;
  258. buff_size++;
  259. return OK;
  260. }
  261. Error ResourceInteractiveLoaderXML::parse_property(Variant &r_v, String &r_name, bool p_for_export_data) {
  262. bool exit;
  263. Tag *tag = parse_tag(&exit);
  264. if (!tag) {
  265. if (exit) // shouldn't have exited
  266. return ERR_FILE_EOF;
  267. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": File corrupt (No Property Tag).");
  268. ERR_FAIL_V(ERR_FILE_CORRUPT);
  269. }
  270. r_v = Variant();
  271. r_name = "";
  272. //ERR_FAIL_COND_V(tag->name!="property",ERR_FILE_CORRUPT);
  273. //ERR_FAIL_COND_V(!tag->args.has("name"),ERR_FILE_CORRUPT);
  274. // ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
  275. //String name=tag->args["name"];
  276. //ERR_FAIL_COND_V(name=="",ERR_FILE_CORRUPT);
  277. String type = tag->name;
  278. String name = tag->args["name"];
  279. if (type == "") {
  280. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": 'type' field is empty.");
  281. ERR_FAIL_COND_V(type == "", ERR_FILE_CORRUPT);
  282. }
  283. if (type == "dictionary") {
  284. Dictionary d(tag->args.has("shared") && (String(tag->args["shared"]) == "true" || String(tag->args["shared"]) == "1"));
  285. while (true) {
  286. Error err;
  287. String tagname;
  288. Variant key;
  289. int dictline = get_current_line();
  290. err = parse_property(key, tagname, p_for_export_data);
  291. if (err && err != ERR_FILE_EOF) {
  292. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error parsing dictionary: " + name + " (from line " + itos(dictline) + ")");
  293. ERR_FAIL_COND_V(err && err != ERR_FILE_EOF, err);
  294. }
  295. //ERR_FAIL_COND_V(tagname!="key",ERR_FILE_CORRUPT);
  296. if (err)
  297. break;
  298. Variant value;
  299. err = parse_property(value, tagname, p_for_export_data);
  300. if (err) {
  301. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error parsing dictionary: " + name + " (from line " + itos(dictline) + ")");
  302. }
  303. ERR_FAIL_COND_V(err, err);
  304. //ERR_FAIL_COND_V(tagname!="value",ERR_FILE_CORRUPT);
  305. d[key] = value;
  306. }
  307. //err=parse_property_data(name); // skip the rest
  308. //ERR_FAIL_COND_V(err,err);
  309. r_name = name;
  310. r_v = d;
  311. return OK;
  312. } else if (type == "array") {
  313. if (!tag->args.has("len")) {
  314. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  315. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  316. }
  317. int len = tag->args["len"].to_int();
  318. bool shared = tag->args.has("shared") && (String(tag->args["shared"]) == "true" || String(tag->args["shared"]) == "1");
  319. Array array(shared);
  320. array.resize(len);
  321. Error err;
  322. Variant v;
  323. String tagname;
  324. int idx = 0;
  325. while ((err = parse_property(v, tagname, p_for_export_data)) == OK) {
  326. ERR_CONTINUE(idx < 0 || idx >= len);
  327. array.set(idx, v);
  328. idx++;
  329. }
  330. if (idx != len) {
  331. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error loading array (size mismatch): " + name);
  332. ERR_FAIL_COND_V(idx != len, err);
  333. }
  334. if (err != ERR_FILE_EOF) {
  335. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error loading array: " + name);
  336. ERR_FAIL_COND_V(err != ERR_FILE_EOF, err);
  337. }
  338. //err=parse_property_data(name); // skip the rest
  339. //ERR_FAIL_COND_V(err,err);
  340. r_name = name;
  341. r_v = array;
  342. return OK;
  343. } else if (type == "resource") {
  344. if (tag->args.has("path")) {
  345. String path = tag->args["path"];
  346. String hint;
  347. if (tag->args.has("resource_type"))
  348. hint = tag->args["resource_type"];
  349. if (p_for_export_data) {
  350. String prop;
  351. if (path.begins_with("local://")) {
  352. prop = "@RESLOCAL:" + itos(path.replace("local://", "").to_int());
  353. }
  354. r_v = prop;
  355. return OK;
  356. }
  357. if (path.begins_with("local://"))
  358. path = path.replace("local://", local_path + "::");
  359. else if (path.find("://") == -1 && path.is_rel_path()) {
  360. // path is relative to file being loaded, so convert to a resource path
  361. path = Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
  362. }
  363. if (remaps.has(path)) {
  364. path = remaps[path];
  365. }
  366. //take advantage of the resource loader cache. The resource is cached on it, even if
  367. RES res = ResourceLoader::load(path, hint);
  368. if (res.is_null()) {
  369. WARN_PRINT(String("Couldn't load resource: " + path).ascii().get_data());
  370. }
  371. r_v = res.get_ref_ptr();
  372. } else if (tag->args.has("external")) {
  373. int index = tag->args["external"].to_int();
  374. if (p_for_export_data) {
  375. String prop;
  376. prop = "@RESEXTERNAL:" + itos(index);
  377. r_v = prop;
  378. return OK;
  379. }
  380. if (ext_resources.has(index)) {
  381. String path = ext_resources[index].path;
  382. String type = ext_resources[index].type;
  383. //take advantage of the resource loader cache. The resource is cached on it, even if
  384. RES res = ResourceLoader::load(path, type);
  385. if (res.is_null()) {
  386. WARN_PRINT(String("Couldn't load externalresource: " + path).ascii().get_data());
  387. }
  388. r_v = res.get_ref_ptr();
  389. } else {
  390. WARN_PRINT(String("Invalid external resource index: " + itos(index)).ascii().get_data());
  391. }
  392. }
  393. Error err = goto_end_of_tag();
  394. if (err) {
  395. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error closing <resource> tag.");
  396. ERR_FAIL_COND_V(err, err);
  397. }
  398. r_name = name;
  399. return OK;
  400. } else if (type == "image") {
  401. if (!tag->args.has("encoding")) {
  402. //empty image
  403. r_v = Image();
  404. String sdfsdfg;
  405. Error err = parse_property_data(sdfsdfg);
  406. return OK;
  407. }
  408. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Image missing 'encoding' field.");
  409. ERR_FAIL_COND_V(!tag->args.has("encoding"), ERR_FILE_CORRUPT);
  410. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Image missing 'width' field.");
  411. ERR_FAIL_COND_V(!tag->args.has("width"), ERR_FILE_CORRUPT);
  412. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Image missing 'height' field.");
  413. ERR_FAIL_COND_V(!tag->args.has("height"), ERR_FILE_CORRUPT);
  414. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Image missing 'format' field.");
  415. ERR_FAIL_COND_V(!tag->args.has("format"), ERR_FILE_CORRUPT);
  416. String encoding = tag->args["encoding"];
  417. if (encoding == "raw") {
  418. String width = tag->args["width"];
  419. String height = tag->args["height"];
  420. String format = tag->args["format"];
  421. int mipmaps = tag->args.has("mipmaps") ? int(tag->args["mipmaps"].to_int()) : int(0);
  422. int custom_size = tag->args.has("custom_size") ? int(tag->args["custom_size"].to_int()) : int(0);
  423. r_name = name;
  424. Image::Format imgformat;
  425. if (format == "grayscale") {
  426. imgformat = Image::FORMAT_GRAYSCALE;
  427. } else if (format == "intensity") {
  428. imgformat = Image::FORMAT_INTENSITY;
  429. } else if (format == "grayscale_alpha") {
  430. imgformat = Image::FORMAT_GRAYSCALE_ALPHA;
  431. } else if (format == "rgb") {
  432. imgformat = Image::FORMAT_RGB;
  433. } else if (format == "rgba") {
  434. imgformat = Image::FORMAT_RGBA;
  435. } else if (format == "indexed") {
  436. imgformat = Image::FORMAT_INDEXED;
  437. } else if (format == "indexed_alpha") {
  438. imgformat = Image::FORMAT_INDEXED_ALPHA;
  439. } else if (format == "bc1") {
  440. imgformat = Image::FORMAT_BC1;
  441. } else if (format == "bc2") {
  442. imgformat = Image::FORMAT_BC2;
  443. } else if (format == "bc3") {
  444. imgformat = Image::FORMAT_BC3;
  445. } else if (format == "bc4") {
  446. imgformat = Image::FORMAT_BC4;
  447. } else if (format == "bc5") {
  448. imgformat = Image::FORMAT_BC5;
  449. } else if (format == "pvrtc2") {
  450. imgformat = Image::FORMAT_PVRTC2;
  451. } else if (format == "pvrtc2a") {
  452. imgformat = Image::FORMAT_PVRTC2_ALPHA;
  453. } else if (format == "pvrtc4") {
  454. imgformat = Image::FORMAT_PVRTC4;
  455. } else if (format == "pvrtc4a") {
  456. imgformat = Image::FORMAT_PVRTC4_ALPHA;
  457. } else if (format == "etc") {
  458. imgformat = Image::FORMAT_ETC;
  459. } else if (format == "atc") {
  460. imgformat = Image::FORMAT_ATC;
  461. } else if (format == "atcai") {
  462. imgformat = Image::FORMAT_ATC_ALPHA_INTERPOLATED;
  463. } else if (format == "atcae") {
  464. imgformat = Image::FORMAT_ATC_ALPHA_EXPLICIT;
  465. } else if (format == "custom") {
  466. imgformat = Image::FORMAT_CUSTOM;
  467. } else {
  468. ERR_FAIL_V(ERR_FILE_CORRUPT);
  469. }
  470. int datasize;
  471. int w = width.to_int();
  472. int h = height.to_int();
  473. if (w == 0 && h == 0) {
  474. //r_v = Image(w, h, imgformat);
  475. r_v = Image();
  476. String sdfsdfg;
  477. Error err = parse_property_data(sdfsdfg);
  478. return OK;
  479. };
  480. if (imgformat == Image::FORMAT_CUSTOM) {
  481. datasize = custom_size;
  482. } else {
  483. datasize = Image::get_image_data_size(h, w, imgformat, mipmaps);
  484. }
  485. if (datasize == 0) {
  486. //r_v = Image(w, h, imgformat);
  487. r_v = Image();
  488. String sdfsdfg;
  489. Error err = parse_property_data(sdfsdfg);
  490. return OK;
  491. };
  492. DVector<uint8_t> pixels;
  493. pixels.resize(datasize);
  494. DVector<uint8_t>::Write wb = pixels.write();
  495. int idx = 0;
  496. uint8_t byte;
  497. while (idx < datasize * 2) {
  498. CharType c = get_char();
  499. ERR_FAIL_COND_V(c == '<', ERR_FILE_CORRUPT);
  500. if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
  501. if (idx & 1) {
  502. byte |= HEX2CHR(c);
  503. wb[idx >> 1] = byte;
  504. } else {
  505. byte = HEX2CHR(c) << 4;
  506. }
  507. idx++;
  508. }
  509. }
  510. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  511. wb = DVector<uint8_t>::Write();
  512. r_v = Image(w, h, mipmaps, imgformat, pixels);
  513. String sdfsdfg;
  514. Error err = parse_property_data(sdfsdfg);
  515. ERR_FAIL_COND_V(err, err);
  516. return OK;
  517. }
  518. ERR_FAIL_V(ERR_FILE_CORRUPT);
  519. } else if (type == "raw_array") {
  520. if (!tag->args.has("len")) {
  521. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": RawArray missing 'len' field: " + name);
  522. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  523. }
  524. int len = tag->args["len"].to_int();
  525. DVector<uint8_t> bytes;
  526. bytes.resize(len);
  527. DVector<uint8_t>::Write w = bytes.write();
  528. uint8_t *bytesptr = w.ptr();
  529. int idx = 0;
  530. uint8_t byte;
  531. while (idx < len * 2) {
  532. CharType c = get_char();
  533. if (c <= 32)
  534. continue;
  535. if (idx & 1) {
  536. byte |= HEX2CHR(c);
  537. bytesptr[idx >> 1] = byte;
  538. //printf("%x\n",int(byte));
  539. } else {
  540. byte = HEX2CHR(c) << 4;
  541. }
  542. idx++;
  543. }
  544. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  545. w = DVector<uint8_t>::Write();
  546. r_v = bytes;
  547. String sdfsdfg;
  548. Error err = parse_property_data(sdfsdfg);
  549. ERR_FAIL_COND_V(err, err);
  550. r_name = name;
  551. return OK;
  552. } else if (type == "int_array") {
  553. if (!tag->args.has("len")) {
  554. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  555. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  556. }
  557. int len = tag->args["len"].to_int();
  558. DVector<int> ints;
  559. ints.resize(len);
  560. DVector<int>::Write w = ints.write();
  561. int *intsptr = w.ptr();
  562. int idx = 0;
  563. String str;
  564. #if 0
  565. while( idx<len ) {
  566. CharType c=get_char();
  567. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  568. if (c<33 || c==',' || c=='<') {
  569. if (str.length()) {
  570. intsptr[idx]=str.to_int();
  571. str="";
  572. idx++;
  573. }
  574. if (c=='<') {
  575. while(get_char()!='>' && !f->eof_reached()) {}
  576. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  577. break;
  578. }
  579. } else {
  580. str+=c;
  581. }
  582. }
  583. #else
  584. Vector<char> tmpdata;
  585. while (idx < len) {
  586. bool end = false;
  587. Error err = _parse_array_element(tmpdata, true, f, &end);
  588. ERR_FAIL_COND_V(err, err);
  589. intsptr[idx] = String::to_int(&tmpdata[0]);
  590. idx++;
  591. if (end)
  592. break;
  593. }
  594. #endif
  595. w = DVector<int>::Write();
  596. r_v = ints;
  597. Error err = goto_end_of_tag();
  598. ERR_FAIL_COND_V(err, err);
  599. r_name = name;
  600. return OK;
  601. } else if (type == "real_array") {
  602. if (!tag->args.has("len")) {
  603. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  604. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  605. }
  606. int len = tag->args["len"].to_int();
  607. ;
  608. DVector<real_t> reals;
  609. reals.resize(len);
  610. DVector<real_t>::Write w = reals.write();
  611. real_t *realsptr = w.ptr();
  612. int idx = 0;
  613. String str;
  614. #if 0
  615. while( idx<len ) {
  616. CharType c=get_char();
  617. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  618. if (c<33 || c==',' || c=='<') {
  619. if (str.length()) {
  620. realsptr[idx]=str.to_double();
  621. str="";
  622. idx++;
  623. }
  624. if (c=='<') {
  625. while(get_char()!='>' && !f->eof_reached()) {}
  626. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  627. break;
  628. }
  629. } else {
  630. str+=c;
  631. }
  632. }
  633. #else
  634. Vector<char> tmpdata;
  635. while (idx < len) {
  636. bool end = false;
  637. Error err = _parse_array_element(tmpdata, true, f, &end);
  638. ERR_FAIL_COND_V(err, err);
  639. realsptr[idx] = String::to_double(&tmpdata[0]);
  640. idx++;
  641. if (end)
  642. break;
  643. }
  644. #endif
  645. w = DVector<real_t>::Write();
  646. r_v = reals;
  647. Error err = goto_end_of_tag();
  648. ERR_FAIL_COND_V(err, err);
  649. r_name = name;
  650. return OK;
  651. } else if (type == "string_array") {
  652. #if 0
  653. if (!tag->args.has("len")) {
  654. ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Array missing 'len' field: "+name);
  655. ERR_FAIL_COND_V(!tag->args.has("len"),ERR_FILE_CORRUPT);
  656. }
  657. int len=tag->args["len"].to_int();
  658. DVector<String> strings;
  659. strings.resize(len);
  660. DVector<String>::Write w=strings.write();
  661. String *stringsptr=w.ptr();
  662. int idx=0;
  663. String str;
  664. bool inside_str=false;
  665. CharString cs;
  666. while( idx<len ) {
  667. CharType c=get_char();
  668. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  669. if (c=='"') {
  670. if (inside_str) {
  671. cs.push_back(0);
  672. String str;
  673. str.parse_utf8(cs.get_data());
  674. unquote(str);
  675. stringsptr[idx]=str;
  676. cs.clear();
  677. idx++;
  678. inside_str=false;
  679. } else {
  680. inside_str=true;
  681. }
  682. } else if (c=='<') {
  683. while(get_char()!='>' && !f->eof_reached()) {}
  684. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  685. break;
  686. } else if (inside_str){
  687. cs.push_back(c);
  688. }
  689. }
  690. w=DVector<String>::Write();
  691. r_v=strings;
  692. String sdfsdfg;
  693. Error err=parse_property_data(sdfsdfg);
  694. ERR_FAIL_COND_V(err,err);
  695. r_name=name;
  696. return OK;
  697. #endif
  698. if (!tag->args.has("len")) {
  699. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": String Array missing 'len' field: " + name);
  700. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  701. }
  702. int len = tag->args["len"].to_int();
  703. StringArray array;
  704. array.resize(len);
  705. DVector<String>::Write w = array.write();
  706. Error err;
  707. Variant v;
  708. String tagname;
  709. int idx = 0;
  710. while ((err = parse_property(v, tagname)) == OK) {
  711. ERR_CONTINUE(idx < 0 || idx >= len);
  712. String str = v; //convert back to string
  713. w[idx] = str;
  714. idx++;
  715. }
  716. if (idx != len) {
  717. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error loading array (size mismatch): " + name);
  718. ERR_FAIL_COND_V(idx != len, err);
  719. }
  720. if (err != ERR_FILE_EOF) {
  721. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Error loading array: " + name);
  722. ERR_FAIL_COND_V(err != ERR_FILE_EOF, err);
  723. }
  724. //err=parse_property_data(name); // skip the rest
  725. //ERR_FAIL_COND_V(err,err);
  726. r_name = name;
  727. r_v = array;
  728. return OK;
  729. } else if (type == "vector3_array") {
  730. if (!tag->args.has("len")) {
  731. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  732. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  733. }
  734. int len = tag->args["len"].to_int();
  735. ;
  736. DVector<Vector3> vectors;
  737. vectors.resize(len);
  738. DVector<Vector3>::Write w = vectors.write();
  739. Vector3 *vectorsptr = w.ptr();
  740. int idx = 0;
  741. int subidx = 0;
  742. Vector3 auxvec;
  743. String str;
  744. // uint64_t tbegin = OS::get_singleton()->get_ticks_usec();
  745. #if 0
  746. while( idx<len ) {
  747. CharType c=get_char();
  748. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  749. if (c<33 || c==',' || c=='<') {
  750. if (str.length()) {
  751. auxvec[subidx]=str.to_double();
  752. subidx++;
  753. str="";
  754. if (subidx==3) {
  755. vectorsptr[idx]=auxvec;
  756. idx++;
  757. subidx=0;
  758. }
  759. }
  760. if (c=='<') {
  761. while(get_char()!='>' && !f->eof_reached()) {}
  762. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  763. break;
  764. }
  765. } else {
  766. str+=c;
  767. }
  768. }
  769. #else
  770. Vector<char> tmpdata;
  771. while (idx < len) {
  772. bool end = false;
  773. Error err = _parse_array_element(tmpdata, true, f, &end);
  774. ERR_FAIL_COND_V(err, err);
  775. auxvec[subidx] = String::to_double(&tmpdata[0]);
  776. subidx++;
  777. if (subidx == 3) {
  778. vectorsptr[idx] = auxvec;
  779. idx++;
  780. subidx = 0;
  781. }
  782. if (end)
  783. break;
  784. }
  785. #endif
  786. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Premature end of vector3 array");
  787. ERR_FAIL_COND_V(idx < len, ERR_FILE_CORRUPT);
  788. // double time_taken = (OS::get_singleton()->get_ticks_usec() - tbegin)/1000000.0;
  789. w = DVector<Vector3>::Write();
  790. r_v = vectors;
  791. String sdfsdfg;
  792. Error err = goto_end_of_tag();
  793. ERR_FAIL_COND_V(err, err);
  794. r_name = name;
  795. return OK;
  796. } else if (type == "vector2_array") {
  797. if (!tag->args.has("len")) {
  798. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  799. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  800. }
  801. int len = tag->args["len"].to_int();
  802. ;
  803. DVector<Vector2> vectors;
  804. vectors.resize(len);
  805. DVector<Vector2>::Write w = vectors.write();
  806. Vector2 *vectorsptr = w.ptr();
  807. int idx = 0;
  808. int subidx = 0;
  809. Vector2 auxvec;
  810. String str;
  811. // uint64_t tbegin = OS::get_singleton()->get_ticks_usec();
  812. #if 0
  813. while( idx<len ) {
  814. CharType c=get_char();
  815. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  816. if (c<22 || c==',' || c=='<') {
  817. if (str.length()) {
  818. auxvec[subidx]=str.to_double();
  819. subidx++;
  820. str="";
  821. if (subidx==2) {
  822. vectorsptr[idx]=auxvec;
  823. idx++;
  824. subidx=0;
  825. }
  826. }
  827. if (c=='<') {
  828. while(get_char()!='>' && !f->eof_reached()) {}
  829. ERR_FAIL_COND_V(f->eof_reached(),ERR_FILE_CORRUPT);
  830. break;
  831. }
  832. } else {
  833. str+=c;
  834. }
  835. }
  836. #else
  837. Vector<char> tmpdata;
  838. while (idx < len) {
  839. bool end = false;
  840. Error err = _parse_array_element(tmpdata, true, f, &end);
  841. ERR_FAIL_COND_V(err, err);
  842. auxvec[subidx] = String::to_double(&tmpdata[0]);
  843. subidx++;
  844. if (subidx == 2) {
  845. vectorsptr[idx] = auxvec;
  846. idx++;
  847. subidx = 0;
  848. }
  849. if (end)
  850. break;
  851. }
  852. #endif
  853. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Premature end of vector2 array");
  854. ERR_FAIL_COND_V(idx < len, ERR_FILE_CORRUPT);
  855. // double time_taken = (OS::get_singleton()->get_ticks_usec() - tbegin)/1000000.0;
  856. w = DVector<Vector2>::Write();
  857. r_v = vectors;
  858. String sdfsdfg;
  859. Error err = goto_end_of_tag();
  860. ERR_FAIL_COND_V(err, err);
  861. r_name = name;
  862. return OK;
  863. } else if (type == "color_array") {
  864. if (!tag->args.has("len")) {
  865. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Array missing 'len' field: " + name);
  866. ERR_FAIL_COND_V(!tag->args.has("len"), ERR_FILE_CORRUPT);
  867. }
  868. int len = tag->args["len"].to_int();
  869. ;
  870. DVector<Color> colors;
  871. colors.resize(len);
  872. DVector<Color>::Write w = colors.write();
  873. Color *colorsptr = w.ptr();
  874. int idx = 0;
  875. int subidx = 0;
  876. Color auxcol;
  877. String str;
  878. while (idx < len) {
  879. CharType c = get_char();
  880. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  881. if (c < 33 || c == ',' || c == '<') {
  882. if (str.length()) {
  883. auxcol[subidx] = str.to_double();
  884. subidx++;
  885. str = "";
  886. if (subidx == 4) {
  887. colorsptr[idx] = auxcol;
  888. idx++;
  889. subidx = 0;
  890. }
  891. }
  892. if (c == '<') {
  893. while (get_char() != '>' && !f->eof_reached()) {
  894. }
  895. ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_CORRUPT);
  896. break;
  897. }
  898. } else {
  899. str += c;
  900. }
  901. }
  902. w = DVector<Color>::Write();
  903. r_v = colors;
  904. String sdfsdfg;
  905. Error err = parse_property_data(sdfsdfg);
  906. ERR_FAIL_COND_V(err, err);
  907. r_name = name;
  908. return OK;
  909. }
  910. String data;
  911. Error err = parse_property_data(data);
  912. ERR_FAIL_COND_V(err != OK, err);
  913. if (type == "nil") {
  914. // uh do nothing
  915. } else if (type == "bool") {
  916. // uh do nothing
  917. if (data.nocasecmp_to("true") == 0 || data.to_int() != 0)
  918. r_v = true;
  919. else
  920. r_v = false;
  921. } else if (type == "int") {
  922. r_v = data.to_int();
  923. } else if (type == "real") {
  924. r_v = data.to_double();
  925. } else if (type == "string") {
  926. String str = data;
  927. unquote(str);
  928. r_v = str;
  929. } else if (type == "vector3") {
  930. r_v = Vector3(
  931. data.get_slicec(',', 0).to_double(),
  932. data.get_slicec(',', 1).to_double(),
  933. data.get_slicec(',', 2).to_double());
  934. } else if (type == "vector2") {
  935. r_v = Vector2(
  936. data.get_slicec(',', 0).to_double(),
  937. data.get_slicec(',', 1).to_double());
  938. } else if (type == "plane") {
  939. r_v = Plane(
  940. data.get_slicec(',', 0).to_double(),
  941. data.get_slicec(',', 1).to_double(),
  942. data.get_slicec(',', 2).to_double(),
  943. data.get_slicec(',', 3).to_double());
  944. } else if (type == "quaternion") {
  945. r_v = Quat(
  946. data.get_slicec(',', 0).to_double(),
  947. data.get_slicec(',', 1).to_double(),
  948. data.get_slicec(',', 2).to_double(),
  949. data.get_slicec(',', 3).to_double());
  950. } else if (type == "rect2") {
  951. r_v = Rect2(
  952. Vector2(
  953. data.get_slicec(',', 0).to_double(),
  954. data.get_slicec(',', 1).to_double()),
  955. Vector2(
  956. data.get_slicec(',', 2).to_double(),
  957. data.get_slicec(',', 3).to_double()));
  958. } else if (type == "aabb") {
  959. r_v = AABB(
  960. Vector3(
  961. data.get_slicec(',', 0).to_double(),
  962. data.get_slicec(',', 1).to_double(),
  963. data.get_slicec(',', 2).to_double()),
  964. Vector3(
  965. data.get_slicec(',', 3).to_double(),
  966. data.get_slicec(',', 4).to_double(),
  967. data.get_slicec(',', 5).to_double()));
  968. } else if (type == "matrix32") {
  969. Matrix32 m3;
  970. for (int i = 0; i < 3; i++) {
  971. for (int j = 0; j < 2; j++) {
  972. m3.elements[i][j] = data.get_slicec(',', i * 2 + j).to_double();
  973. }
  974. }
  975. r_v = m3;
  976. } else if (type == "matrix3") {
  977. Matrix3 m3;
  978. for (int i = 0; i < 3; i++) {
  979. for (int j = 0; j < 3; j++) {
  980. m3.elements[i][j] = data.get_slicec(',', i * 3 + j).to_double();
  981. }
  982. }
  983. r_v = m3;
  984. } else if (type == "transform") {
  985. Transform tr;
  986. for (int i = 0; i < 3; i++) {
  987. for (int j = 0; j < 3; j++) {
  988. tr.basis.elements[i][j] = data.get_slicec(',', i * 3 + j).to_double();
  989. }
  990. }
  991. tr.origin = Vector3(
  992. data.get_slicec(',', 9).to_double(),
  993. data.get_slicec(',', 10).to_double(),
  994. data.get_slicec(',', 11).to_double());
  995. r_v = tr;
  996. } else if (type == "color") {
  997. r_v = Color(
  998. data.get_slicec(',', 0).to_double(),
  999. data.get_slicec(',', 1).to_double(),
  1000. data.get_slicec(',', 2).to_double(),
  1001. data.get_slicec(',', 3).to_double());
  1002. } else if (type == "node_path") {
  1003. String str = data;
  1004. unquote(str);
  1005. r_v = NodePath(str);
  1006. } else if (type == "input_event") {
  1007. // ?
  1008. } else {
  1009. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Unrecognized tag in file: " + type);
  1010. ERR_FAIL_V(ERR_FILE_CORRUPT);
  1011. }
  1012. r_name = name;
  1013. return OK;
  1014. }
  1015. int ResourceInteractiveLoaderXML::get_current_line() const {
  1016. return lines;
  1017. }
  1018. uint8_t ResourceInteractiveLoaderXML::get_char() const {
  1019. uint8_t c = f->get_8();
  1020. if (c == '\n')
  1021. lines++;
  1022. return c;
  1023. }
  1024. ///
  1025. void ResourceInteractiveLoaderXML::set_local_path(const String &p_local_path) {
  1026. res_path = p_local_path;
  1027. }
  1028. Ref<Resource> ResourceInteractiveLoaderXML::get_resource() {
  1029. return resource;
  1030. }
  1031. Error ResourceInteractiveLoaderXML::poll() {
  1032. if (error != OK)
  1033. return error;
  1034. bool exit;
  1035. Tag *tag = parse_tag(&exit);
  1036. if (!tag) {
  1037. error = ERR_FILE_CORRUPT;
  1038. if (!exit) // shouldn't have exited
  1039. ERR_FAIL_V(error);
  1040. error = ERR_FILE_EOF;
  1041. return error;
  1042. }
  1043. RES res;
  1044. //Object *obj=NULL;
  1045. bool main;
  1046. if (tag->name == "ext_resource") {
  1047. error = ERR_FILE_CORRUPT;
  1048. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> missing 'path' field.");
  1049. ERR_FAIL_COND_V(!tag->args.has("path"), ERR_FILE_CORRUPT);
  1050. String type = "Resource";
  1051. if (tag->args.has("type"))
  1052. type = tag->args["type"];
  1053. String path = tag->args["path"];
  1054. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> can't use a local path, this is a bug?.");
  1055. ERR_FAIL_COND_V(path.begins_with("local://"), ERR_FILE_CORRUPT);
  1056. if (path.find("://") == -1 && path.is_rel_path()) {
  1057. // path is relative to file being loaded, so convert to a resource path
  1058. path = Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
  1059. }
  1060. if (remaps.has(path)) {
  1061. path = remaps[path];
  1062. }
  1063. RES res = ResourceLoader::load(path, type);
  1064. if (res.is_null()) {
  1065. if (ResourceLoader::get_abort_on_missing_resources()) {
  1066. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> referenced nonexistent resource at: " + path);
  1067. ERR_FAIL_V(error);
  1068. } else {
  1069. ResourceLoader::notify_dependency_error(local_path, path, type);
  1070. }
  1071. } else {
  1072. resource_cache.push_back(res);
  1073. }
  1074. if (tag->args.has("index")) {
  1075. ExtResource er;
  1076. er.path = path;
  1077. er.type = type;
  1078. ext_resources[tag->args["index"].to_int()] = er;
  1079. }
  1080. Error err = close_tag("ext_resource");
  1081. if (err)
  1082. return error;
  1083. error = OK;
  1084. resource_current++;
  1085. return error;
  1086. } else if (tag->name == "resource") {
  1087. main = false;
  1088. } else if (tag->name == "main_resource") {
  1089. main = true;
  1090. } else {
  1091. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": unexpected main tag: " + tag->name);
  1092. error = ERR_FILE_CORRUPT;
  1093. ERR_FAIL_V(error);
  1094. }
  1095. String type;
  1096. String path;
  1097. int subres = 0;
  1098. if (!main) {
  1099. //loading resource
  1100. error = ERR_FILE_CORRUPT;
  1101. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <resource> missing 'len' field.");
  1102. ERR_FAIL_COND_V(!tag->args.has("path"), ERR_FILE_CORRUPT);
  1103. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <resource> missing 'type' field.");
  1104. ERR_FAIL_COND_V(!tag->args.has("type"), ERR_FILE_CORRUPT);
  1105. path = tag->args["path"];
  1106. error = OK;
  1107. if (path.begins_with("local://")) {
  1108. //built-in resource (but really external)
  1109. path = path.replace("local://", "");
  1110. subres = path.to_int();
  1111. path = local_path + "::" + path;
  1112. }
  1113. if (ResourceCache::has(path)) {
  1114. Error err = close_tag(tag->name);
  1115. if (err) {
  1116. error = ERR_FILE_CORRUPT;
  1117. }
  1118. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Unable to close <resource> tag.");
  1119. ERR_FAIL_COND_V(err, err);
  1120. resource_current++;
  1121. error = OK;
  1122. return OK;
  1123. }
  1124. type = tag->args["type"];
  1125. } else {
  1126. type = resource_type;
  1127. }
  1128. Object *obj = ObjectTypeDB::instance(type);
  1129. if (!obj) {
  1130. error = ERR_FILE_CORRUPT;
  1131. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Object of unrecognized type in file: " + type);
  1132. }
  1133. ERR_FAIL_COND_V(!obj, ERR_FILE_CORRUPT);
  1134. Resource *r = obj->cast_to<Resource>();
  1135. if (!r) {
  1136. error = ERR_FILE_CORRUPT;
  1137. memdelete(obj); //bye
  1138. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": Object type in resource field not a resource, type is: " + obj->get_type());
  1139. ERR_FAIL_COND_V(!r, ERR_FILE_CORRUPT);
  1140. }
  1141. res = RES(r);
  1142. if (path != "")
  1143. r->set_path(path);
  1144. r->set_subindex(subres);
  1145. //load properties
  1146. while (true) {
  1147. String name;
  1148. Variant v;
  1149. Error err;
  1150. err = parse_property(v, name);
  1151. if (err == ERR_FILE_EOF) //tag closed
  1152. break;
  1153. if (err != OK) {
  1154. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": XML Parsing aborted.");
  1155. ERR_FAIL_COND_V(err != OK, ERR_FILE_CORRUPT);
  1156. }
  1157. obj->set(name, v);
  1158. }
  1159. #ifdef TOOLS_ENABLED
  1160. res->set_edited(false);
  1161. #endif
  1162. resource_cache.push_back(res); //keep it in mem until finished loading
  1163. resource_current++;
  1164. if (main) {
  1165. f->close();
  1166. resource = res;
  1167. if (!ResourceCache::has(res_path)) {
  1168. resource->set_path(res_path);
  1169. }
  1170. error = ERR_FILE_EOF;
  1171. return error;
  1172. }
  1173. error = OK;
  1174. return OK;
  1175. }
  1176. int ResourceInteractiveLoaderXML::get_stage() const {
  1177. return resource_current;
  1178. }
  1179. int ResourceInteractiveLoaderXML::get_stage_count() const {
  1180. return resources_total; //+ext_resources;
  1181. }
  1182. ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
  1183. memdelete(f);
  1184. }
  1185. void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f, List<String> *p_dependencies, bool p_add_types) {
  1186. open(f);
  1187. ERR_FAIL_COND(error != OK);
  1188. while (true) {
  1189. bool exit;
  1190. Tag *tag = parse_tag(&exit);
  1191. if (!tag) {
  1192. error = ERR_FILE_CORRUPT;
  1193. ERR_FAIL_COND(!exit);
  1194. error = ERR_FILE_EOF;
  1195. return;
  1196. }
  1197. if (tag->name != "ext_resource") {
  1198. return;
  1199. }
  1200. error = ERR_FILE_CORRUPT;
  1201. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> missing 'path' field.");
  1202. ERR_FAIL_COND(!tag->args.has("path"));
  1203. String path = tag->args["path"];
  1204. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> can't use a local path, this is a bug?.");
  1205. ERR_FAIL_COND(path.begins_with("local://"));
  1206. if (path.find("://") == -1 && path.is_rel_path()) {
  1207. // path is relative to file being loaded, so convert to a resource path
  1208. path = Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
  1209. }
  1210. if (path.ends_with("*")) {
  1211. ERR_FAIL_COND(!tag->args.has("type"));
  1212. String type = tag->args["type"];
  1213. path = ResourceLoader::guess_full_filename(path, type);
  1214. }
  1215. if (p_add_types && tag->args.has("type")) {
  1216. path += "::" + tag->args["type"];
  1217. }
  1218. p_dependencies->push_back(path);
  1219. Error err = close_tag("ext_resource");
  1220. if (err)
  1221. return;
  1222. error = OK;
  1223. }
  1224. }
  1225. Error ResourceInteractiveLoaderXML::get_export_data(FileAccess *p_f, ExportData &r_export_data) {
  1226. open(p_f);
  1227. ERR_FAIL_COND_V(error != OK, error);
  1228. while (true) {
  1229. bool exit;
  1230. Tag *tag = parse_tag(&exit);
  1231. if (!tag) {
  1232. error = ERR_FILE_CORRUPT;
  1233. if (!exit) // shouldn't have exited
  1234. ERR_FAIL_V(error);
  1235. error = ERR_FILE_EOF;
  1236. return error;
  1237. }
  1238. bool main;
  1239. if (tag->name == "ext_resource") {
  1240. ExportData::Dependency dep;
  1241. error = ERR_FILE_CORRUPT;
  1242. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": <ext_resource> missing 'path' field.");
  1243. ERR_FAIL_COND_V(!tag->args.has("path"), ERR_FILE_CORRUPT);
  1244. String type = "Resource";
  1245. if (tag->args.has("type"))
  1246. type = tag->args["type"];
  1247. String path = tag->args["path"];
  1248. dep.path = path;
  1249. dep.type = type;
  1250. if (tag->args.has("index")) {
  1251. ExtResource er;
  1252. er.path = path;
  1253. er.type = type;
  1254. r_export_data.dependencies[tag->args["index"].to_int()] = dep;
  1255. } else {
  1256. int index = r_export_data.dependencies.size();
  1257. r_export_data.dependencies[index] = dep;
  1258. }
  1259. Error err = close_tag("ext_resource");
  1260. if (err)
  1261. return error;
  1262. continue;
  1263. } else if (tag->name == "resource") {
  1264. main = false;
  1265. } else if (tag->name == "main_resource") {
  1266. main = true;
  1267. } else {
  1268. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": unexpected main tag: " + tag->name);
  1269. error = ERR_FILE_CORRUPT;
  1270. ERR_FAIL_V(error);
  1271. }
  1272. r_export_data.resources.resize(r_export_data.resources.size() + 1);
  1273. ExportData::ResourceData &res_data = r_export_data.resources[r_export_data.resources.size() - 1];
  1274. res_data.index = -1;
  1275. if (!main) {
  1276. //loading resource
  1277. String path = tag->args["path"];
  1278. error = OK;
  1279. if (path.begins_with("local://")) {
  1280. //built-in resource (but really external)
  1281. path = path.replace("local://", "");
  1282. res_data.index = path.to_int();
  1283. }
  1284. res_data.type = tag->args["type"];
  1285. } else {
  1286. res_data.type = resource_type;
  1287. }
  1288. //load properties
  1289. while (true) {
  1290. String name;
  1291. Variant v;
  1292. Error err;
  1293. err = parse_property(v, name);
  1294. if (err == ERR_FILE_EOF) //tag closed
  1295. break;
  1296. if (err != OK) {
  1297. ERR_EXPLAIN(local_path + ":" + itos(get_current_line()) + ": XML Parsing aborted.");
  1298. ERR_FAIL_COND_V(err != OK, ERR_FILE_CORRUPT);
  1299. }
  1300. ExportData::PropertyData prop;
  1301. prop.name = name;
  1302. prop.value = v;
  1303. res_data.properties.push_back(prop);
  1304. }
  1305. if (main) {
  1306. return OK;
  1307. }
  1308. }
  1309. return OK;
  1310. }
  1311. Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map) {
  1312. open(p_f);
  1313. ERR_FAIL_COND_V(error != OK, error);
  1314. //FileAccess
  1315. bool old_format = false;
  1316. FileAccess *fw = NULL;
  1317. String base_path = local_path.get_base_dir();
  1318. while (true) {
  1319. bool exit;
  1320. List<String> order;
  1321. Tag *tag = parse_tag(&exit, true, &order);
  1322. bool done = false;
  1323. if (!tag) {
  1324. if (fw) {
  1325. memdelete(fw);
  1326. }
  1327. error = ERR_FILE_CORRUPT;
  1328. ERR_FAIL_COND_V(!exit, error);
  1329. error = ERR_FILE_EOF;
  1330. return error;
  1331. }
  1332. if (tag->name == "ext_resource") {
  1333. if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
  1334. old_format = true;
  1335. break;
  1336. }
  1337. if (!fw) {
  1338. fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
  1339. fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
  1340. fw->store_line("<resource_file type=\"" + resource_type + "\" subresource_count=\"" + itos(resources_total) + "\" version=\"" + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "\" version_name=\"" + VERSION_FULL_NAME + "\">");
  1341. }
  1342. String path = tag->args["path"];
  1343. String index = tag->args["index"];
  1344. String type = tag->args["type"];
  1345. bool relative = false;
  1346. if (!path.begins_with("res://")) {
  1347. path = base_path.plus_file(path).simplify_path();
  1348. relative = true;
  1349. }
  1350. if (p_map.has(path)) {
  1351. String np = p_map[path];
  1352. path = np;
  1353. }
  1354. if (relative) {
  1355. //restore relative
  1356. path = base_path.path_to_file(path);
  1357. }
  1358. tag->args["path"] = path;
  1359. tag->args["index"] = index;
  1360. tag->args["type"] = type;
  1361. } else {
  1362. done = true;
  1363. }
  1364. String tagt = "\t<";
  1365. if (exit)
  1366. tagt += "/";
  1367. tagt += tag->name;
  1368. for (List<String>::Element *E = order.front(); E; E = E->next()) {
  1369. tagt += " " + E->get() + "=\"" + tag->args[E->get()] + "\"";
  1370. }
  1371. tagt += ">";
  1372. fw->store_line(tagt);
  1373. if (done)
  1374. break;
  1375. close_tag("ext_resource");
  1376. fw->store_line("\t</ext_resource>");
  1377. }
  1378. if (old_format) {
  1379. if (fw)
  1380. memdelete(fw);
  1381. DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
  1382. da->remove(p_path + ".depren");
  1383. memdelete(da);
  1384. //fuck it, use the old approach;
  1385. WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: " + p_path).utf8().get_data());
  1386. Error err;
  1387. FileAccess *f2 = FileAccess::open(p_path, FileAccess::READ, &err);
  1388. if (err != OK) {
  1389. ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
  1390. }
  1391. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1392. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1393. ria->res_path = ria->local_path;
  1394. ria->remaps = p_map;
  1395. // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
  1396. ria->open(f2);
  1397. err = ria->poll();
  1398. while (err == OK) {
  1399. err = ria->poll();
  1400. }
  1401. ERR_FAIL_COND_V(err != ERR_FILE_EOF, ERR_FILE_CORRUPT);
  1402. RES res = ria->get_resource();
  1403. ERR_FAIL_COND_V(!res.is_valid(), ERR_FILE_CORRUPT);
  1404. return ResourceFormatSaverXML::singleton->save(p_path, res);
  1405. }
  1406. if (!fw) {
  1407. return OK; //nothing to rename, do nothing
  1408. }
  1409. uint8_t c = f->get_8();
  1410. while (!f->eof_reached()) {
  1411. fw->store_8(c);
  1412. c = f->get_8();
  1413. }
  1414. f->close();
  1415. bool all_ok = fw->get_error() == OK;
  1416. memdelete(fw);
  1417. if (!all_ok) {
  1418. return ERR_CANT_CREATE;
  1419. }
  1420. DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
  1421. da->remove(p_path);
  1422. da->rename(p_path + ".depren", p_path);
  1423. memdelete(da);
  1424. return OK;
  1425. }
  1426. void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
  1427. error = OK;
  1428. lines = 1;
  1429. f = p_f;
  1430. ResourceInteractiveLoaderXML::Tag *tag = parse_tag();
  1431. if (!tag || tag->name != "?xml" || !tag->args.has("version") || !tag->args.has("encoding") || tag->args["encoding"] != "UTF-8") {
  1432. error = ERR_FILE_CORRUPT;
  1433. ResourceLoader::notify_load_error("XML is invalid (missing header tags)");
  1434. ERR_EXPLAIN("Not a XML:UTF-8 File: " + local_path);
  1435. ERR_FAIL();
  1436. }
  1437. tag_stack.clear();
  1438. tag = parse_tag();
  1439. if (!tag || tag->name != "resource_file" || !tag->args.has("type") || !tag->args.has("version")) {
  1440. ResourceLoader::notify_load_error(local_path + ": XML is not a valid resource file.");
  1441. error = ERR_FILE_CORRUPT;
  1442. ERR_EXPLAIN("Unrecognized XML File: " + local_path);
  1443. ERR_FAIL();
  1444. }
  1445. if (tag->args.has("subresource_count"))
  1446. resources_total = tag->args["subresource_count"].to_int();
  1447. resource_current = 0;
  1448. resource_type = tag->args["type"];
  1449. String version = tag->args["version"];
  1450. if (version.get_slice_count(".") != 2) {
  1451. error = ERR_FILE_CORRUPT;
  1452. ResourceLoader::notify_load_error(local_path + ":XML version string is invalid: " + version);
  1453. ERR_EXPLAIN("Invalid Version String '" + version + "'' in file: " + local_path);
  1454. ERR_FAIL();
  1455. }
  1456. int major = version.get_slicec('.', 0).to_int();
  1457. if (major > VERSION_MAJOR) {
  1458. error = ERR_FILE_UNRECOGNIZED;
  1459. ResourceLoader::notify_load_error(local_path + ": File Format '" + version + "' is too new. Please upgrade to a newer engine version.");
  1460. ERR_EXPLAIN("File Format '" + version + "' is too new! Please upgrade to a a new engine version: " + local_path);
  1461. ERR_FAIL();
  1462. }
  1463. /*
  1464. String preload_depts = "deps/"+local_path.md5_text();
  1465. if (Globals::get_singleton()->has(preload_depts)) {
  1466. ext_resources.clear();
  1467. //ignore external resources and use these
  1468. NodePath depts=Globals::get_singleton()->get(preload_depts);
  1469. for(int i=0;i<depts.get_name_count();i++) {
  1470. ext_resources.push_back(depts.get_name(i));
  1471. }
  1472. print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size()));
  1473. }
  1474. */
  1475. }
  1476. String ResourceInteractiveLoaderXML::recognize(FileAccess *p_f) {
  1477. error = OK;
  1478. lines = 1;
  1479. f = p_f;
  1480. ResourceInteractiveLoaderXML::Tag *tag = parse_tag();
  1481. if (!tag || tag->name != "?xml" || !tag->args.has("version") || !tag->args.has("encoding") || tag->args["encoding"] != "UTF-8") {
  1482. return ""; //unrecognized
  1483. }
  1484. tag_stack.clear();
  1485. tag = parse_tag();
  1486. if (!tag || tag->name != "resource_file" || !tag->args.has("type") || !tag->args.has("version")) {
  1487. return ""; //unrecognized
  1488. }
  1489. return tag->args["type"];
  1490. }
  1491. /////////////////////
  1492. Ref<ResourceInteractiveLoader> ResourceFormatLoaderXML::load_interactive(const String &p_path, Error *r_error) {
  1493. if (r_error)
  1494. *r_error = ERR_CANT_OPEN;
  1495. Error err;
  1496. FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
  1497. if (err != OK) {
  1498. ERR_FAIL_COND_V(err != OK, Ref<ResourceInteractiveLoader>());
  1499. }
  1500. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1501. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1502. ria->res_path = ria->local_path;
  1503. // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
  1504. ria->open(f);
  1505. return ria;
  1506. }
  1507. void ResourceFormatLoaderXML::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
  1508. if (p_type == "") {
  1509. get_recognized_extensions(p_extensions);
  1510. return;
  1511. }
  1512. List<String> extensions;
  1513. ObjectTypeDB::get_extensions_for_type(p_type, &extensions);
  1514. extensions.sort();
  1515. for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
  1516. String ext = E->get().to_lower();
  1517. if (ext == "res")
  1518. continue;
  1519. p_extensions->push_back("x" + ext);
  1520. }
  1521. p_extensions->push_back("xml");
  1522. }
  1523. void ResourceFormatLoaderXML::get_recognized_extensions(List<String> *p_extensions) const {
  1524. List<String> extensions;
  1525. ObjectTypeDB::get_resource_base_extensions(&extensions);
  1526. extensions.sort();
  1527. for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
  1528. String ext = E->get().to_lower();
  1529. if (ext == "res")
  1530. continue;
  1531. p_extensions->push_back("x" + ext);
  1532. }
  1533. p_extensions->push_back("xml");
  1534. }
  1535. bool ResourceFormatLoaderXML::handles_type(const String &p_type) const {
  1536. return true;
  1537. }
  1538. String ResourceFormatLoaderXML::get_resource_type(const String &p_path) const {
  1539. String ext = p_path.extension().to_lower();
  1540. if (!ext.begins_with("x")) //a lie but..
  1541. return "";
  1542. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1543. if (!f) {
  1544. return ""; //could not rwead
  1545. }
  1546. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1547. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1548. ria->res_path = ria->local_path;
  1549. // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
  1550. String r = ria->recognize(f);
  1551. return r;
  1552. }
  1553. void ResourceFormatLoaderXML::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
  1554. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1555. if (!f) {
  1556. ERR_FAIL();
  1557. }
  1558. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1559. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1560. ria->res_path = ria->local_path;
  1561. // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
  1562. ria->get_dependencies(f, p_dependencies, p_add_types);
  1563. }
  1564. Error ResourceFormatLoaderXML::get_export_data(const String &p_path, ExportData &r_export_data) {
  1565. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1566. if (!f) {
  1567. ERR_FAIL_V(ERR_CANT_OPEN);
  1568. }
  1569. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1570. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1571. ria->res_path = ria->local_path;
  1572. return ria->get_export_data(f, r_export_data);
  1573. }
  1574. Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
  1575. FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
  1576. if (!f) {
  1577. ERR_FAIL_V(ERR_CANT_OPEN);
  1578. }
  1579. Ref<ResourceInteractiveLoaderXML> ria = memnew(ResourceInteractiveLoaderXML);
  1580. ria->local_path = Globals::get_singleton()->localize_path(p_path);
  1581. ria->res_path = ria->local_path;
  1582. // ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
  1583. return ria->rename_dependencies(f, p_path, p_map);
  1584. }
  1585. ResourceFormatLoaderXML *ResourceFormatLoaderXML::singleton = NULL;
  1586. /****************************************************************************************/
  1587. /****************************************************************************************/
  1588. /****************************************************************************************/
  1589. /****************************************************************************************/
  1590. /****************************************************************************************/
  1591. /****************************************************************************************/
  1592. /****************************************************************************************/
  1593. /****************************************************************************************/
  1594. /****************************************************************************************/
  1595. /****************************************************************************************/
  1596. /****************************************************************************************/
  1597. /****************************************************************************************/
  1598. /****************************************************************************************/
  1599. void ResourceFormatSaverXMLInstance::escape(String &p_str) {
  1600. p_str = p_str.replace("&", "&amp;");
  1601. p_str = p_str.replace("<", "&lt;");
  1602. p_str = p_str.replace(">", "&gt;");
  1603. p_str = p_str.replace("'", "&apos;");
  1604. p_str = p_str.replace("\"", "&quot;");
  1605. for (char i = 1; i < 32; i++) {
  1606. char chr[2] = { i, 0 };
  1607. const char hexn[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  1608. const char hex[8] = { '&', '#', '0', '0', hexn[i >> 4], hexn[i & 0xf], ';', 0 };
  1609. p_str = p_str.replace(chr, hex);
  1610. }
  1611. }
  1612. void ResourceFormatSaverXMLInstance::write_tabs(int p_diff) {
  1613. for (int i = 0; i < depth + p_diff; i++) {
  1614. f->store_8('\t');
  1615. }
  1616. }
  1617. void ResourceFormatSaverXMLInstance::write_string(String p_str, bool p_escape) {
  1618. /* write an UTF8 string */
  1619. if (p_escape)
  1620. escape(p_str);
  1621. f->store_string(p_str);
  1622. ;
  1623. /*
  1624. CharString cs=p_str.utf8();
  1625. const char *data=cs.get_data();
  1626. while (*data) {
  1627. f->store_8(*data);
  1628. data++;
  1629. }*/
  1630. }
  1631. void ResourceFormatSaverXMLInstance::enter_tag(const char *p_tag, const String &p_args) {
  1632. f->store_8('<');
  1633. int cc = 0;
  1634. const char *c = p_tag;
  1635. while (*c) {
  1636. cc++;
  1637. c++;
  1638. }
  1639. f->store_buffer((const uint8_t *)p_tag, cc);
  1640. if (p_args.length()) {
  1641. f->store_8(' ');
  1642. f->store_string(p_args);
  1643. }
  1644. f->store_8('>');
  1645. depth++;
  1646. }
  1647. void ResourceFormatSaverXMLInstance::exit_tag(const char *p_tag) {
  1648. depth--;
  1649. f->store_8('<');
  1650. f->store_8('/');
  1651. int cc = 0;
  1652. const char *c = p_tag;
  1653. while (*c) {
  1654. cc++;
  1655. c++;
  1656. }
  1657. f->store_buffer((const uint8_t *)p_tag, cc);
  1658. f->store_8('>');
  1659. }
  1660. /*
  1661. static bool _check_type(const Variant& p_property) {
  1662. if (p_property.get_type()==Variant::_RID)
  1663. return false;
  1664. if (p_property.get_type()==Variant::OBJECT) {
  1665. RES res = p_property;
  1666. if (res.is_null())
  1667. return false;
  1668. }
  1669. return true;
  1670. }*/
  1671. void ResourceFormatSaverXMLInstance::write_property(const String &p_name, const Variant &p_property, bool *r_ok) {
  1672. if (r_ok)
  1673. *r_ok = false;
  1674. const char *type;
  1675. String params;
  1676. bool oneliner = true;
  1677. switch (p_property.get_type()) {
  1678. case Variant::NIL: type = "nil"; break;
  1679. case Variant::BOOL: type = "bool"; break;
  1680. case Variant::INT: type = "int"; break;
  1681. case Variant::REAL: type = "real"; break;
  1682. case Variant::STRING: type = "string"; break;
  1683. case Variant::VECTOR2: type = "vector2"; break;
  1684. case Variant::RECT2: type = "rect2"; break;
  1685. case Variant::VECTOR3: type = "vector3"; break;
  1686. case Variant::PLANE: type = "plane"; break;
  1687. case Variant::_AABB: type = "aabb"; break;
  1688. case Variant::QUAT: type = "quaternion"; break;
  1689. case Variant::MATRIX32: type = "matrix32"; break;
  1690. case Variant::MATRIX3: type = "matrix3"; break;
  1691. case Variant::TRANSFORM: type = "transform"; break;
  1692. case Variant::COLOR: type = "color"; break;
  1693. case Variant::IMAGE: {
  1694. type = "image";
  1695. Image img = p_property;
  1696. if (img.empty()) {
  1697. write_tabs();
  1698. enter_tag(type, "name=\"" + p_name + "\"");
  1699. exit_tag(type);
  1700. if (r_ok)
  1701. *r_ok = true;
  1702. return;
  1703. }
  1704. params += "encoding=\"raw\"";
  1705. params += " width=\"" + itos(img.get_width()) + "\"";
  1706. params += " height=\"" + itos(img.get_height()) + "\"";
  1707. params += " mipmaps=\"" + itos(img.get_mipmaps()) + "\"";
  1708. switch (img.get_format()) {
  1709. case Image::FORMAT_GRAYSCALE: params += " format=\"grayscale\""; break;
  1710. case Image::FORMAT_INTENSITY: params += " format=\"intensity\""; break;
  1711. case Image::FORMAT_GRAYSCALE_ALPHA: params += " format=\"grayscale_alpha\""; break;
  1712. case Image::FORMAT_RGB: params += " format=\"rgb\""; break;
  1713. case Image::FORMAT_RGBA: params += " format=\"rgba\""; break;
  1714. case Image::FORMAT_INDEXED: params += " format=\"indexed\""; break;
  1715. case Image::FORMAT_INDEXED_ALPHA: params += " format=\"indexed_alpha\""; break;
  1716. case Image::FORMAT_BC1: params += " format=\"bc1\""; break;
  1717. case Image::FORMAT_BC2: params += " format=\"bc2\""; break;
  1718. case Image::FORMAT_BC3: params += " format=\"bc3\""; break;
  1719. case Image::FORMAT_BC4: params += " format=\"bc4\""; break;
  1720. case Image::FORMAT_BC5: params += " format=\"bc5\""; break;
  1721. case Image::FORMAT_PVRTC2: params += " format=\"pvrtc2\""; break;
  1722. case Image::FORMAT_PVRTC2_ALPHA: params += " format=\"pvrtc2a\""; break;
  1723. case Image::FORMAT_PVRTC4: params += " format=\"pvrtc4\""; break;
  1724. case Image::FORMAT_PVRTC4_ALPHA: params += " format=\"pvrtc4a\""; break;
  1725. case Image::FORMAT_ETC: params += " format=\"etc\""; break;
  1726. case Image::FORMAT_ATC: params += " format=\"atc\""; break;
  1727. case Image::FORMAT_ATC_ALPHA_EXPLICIT: params += " format=\"atcae\""; break;
  1728. case Image::FORMAT_ATC_ALPHA_INTERPOLATED: params += " format=\"atcai\""; break;
  1729. case Image::FORMAT_CUSTOM: params += " format=\"custom\" custom_size=\"" + itos(img.get_data().size()) + "\""; break;
  1730. default: {}
  1731. }
  1732. } break;
  1733. case Variant::NODE_PATH: type = "node_path"; break;
  1734. case Variant::OBJECT: {
  1735. type = "resource";
  1736. RES res = p_property;
  1737. if (res.is_null()) {
  1738. write_tabs();
  1739. enter_tag(type, "name=\"" + p_name + "\"");
  1740. exit_tag(type);
  1741. if (r_ok)
  1742. *r_ok = true;
  1743. return; // don't save it
  1744. }
  1745. if (external_resources.has(res)) {
  1746. params = "external=\"" + itos(external_resources[res]) + "\"";
  1747. } else {
  1748. params = "resource_type=\"" + res->get_save_type() + "\"";
  1749. if (res->get_path().length() && res->get_path().find("::") == -1) {
  1750. //external resource
  1751. String path = relative_paths ? local_path.path_to_file(res->get_path()) : res->get_path();
  1752. escape(path);
  1753. params += " path=\"" + path + "\"";
  1754. } else {
  1755. //internal resource
  1756. ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
  1757. ERR_FAIL_COND(!resource_set.has(res));
  1758. params += " path=\"local://" + itos(res->get_subindex()) + "\"";
  1759. }
  1760. }
  1761. } break;
  1762. case Variant::INPUT_EVENT: type = "input_event"; break;
  1763. case Variant::DICTIONARY:
  1764. type = "dictionary";
  1765. params = "shared=\"" + String(p_property.is_shared() ? "true" : "false") + "\"";
  1766. oneliner = false;
  1767. break;
  1768. case Variant::ARRAY:
  1769. type = "array";
  1770. params = "len=\"" + itos(p_property.operator Array().size()) + "\" shared=\"" + String(p_property.is_shared() ? "true" : "false") + "\"";
  1771. oneliner = false;
  1772. break;
  1773. case Variant::RAW_ARRAY:
  1774. type = "raw_array";
  1775. params = "len=\"" + itos(p_property.operator DVector<uint8_t>().size()) + "\"";
  1776. break;
  1777. case Variant::INT_ARRAY:
  1778. type = "int_array";
  1779. params = "len=\"" + itos(p_property.operator DVector<int>().size()) + "\"";
  1780. break;
  1781. case Variant::REAL_ARRAY:
  1782. type = "real_array";
  1783. params = "len=\"" + itos(p_property.operator DVector<real_t>().size()) + "\"";
  1784. break;
  1785. case Variant::STRING_ARRAY:
  1786. oneliner = false;
  1787. type = "string_array";
  1788. params = "len=\"" + itos(p_property.operator DVector<String>().size()) + "\"";
  1789. break;
  1790. case Variant::VECTOR2_ARRAY:
  1791. type = "vector2_array";
  1792. params = "len=\"" + itos(p_property.operator DVector<Vector2>().size()) + "\"";
  1793. break;
  1794. case Variant::VECTOR3_ARRAY:
  1795. type = "vector3_array";
  1796. params = "len=\"" + itos(p_property.operator DVector<Vector3>().size()) + "\"";
  1797. break;
  1798. case Variant::COLOR_ARRAY:
  1799. type = "color_array";
  1800. params = "len=\"" + itos(p_property.operator DVector<Color>().size()) + "\"";
  1801. break;
  1802. default: {
  1803. ERR_PRINT("Unknown Variant type.");
  1804. ERR_FAIL();
  1805. }
  1806. }
  1807. write_tabs();
  1808. if (p_name != "") {
  1809. if (params.length())
  1810. enter_tag(type, "name=\"" + p_name + "\" " + params);
  1811. else
  1812. enter_tag(type, "name=\"" + p_name + "\"");
  1813. } else {
  1814. if (params.length())
  1815. enter_tag(type, " " + params);
  1816. else
  1817. enter_tag(type, String());
  1818. }
  1819. if (!oneliner)
  1820. f->store_8('\n');
  1821. else
  1822. f->store_8(' ');
  1823. switch (p_property.get_type()) {
  1824. case Variant::NIL: {
  1825. } break;
  1826. case Variant::BOOL: {
  1827. write_string(p_property.operator bool() ? "True" : "False");
  1828. } break;
  1829. case Variant::INT: {
  1830. write_string(itos(p_property.operator int()));
  1831. } break;
  1832. case Variant::REAL: {
  1833. write_string(rtos(p_property.operator real_t()));
  1834. } break;
  1835. case Variant::STRING: {
  1836. String str = p_property;
  1837. escape(str);
  1838. str = "\"" + str + "\"";
  1839. write_string(str, false);
  1840. } break;
  1841. case Variant::VECTOR2: {
  1842. Vector2 v = p_property;
  1843. write_string(rtoss(v.x) + ", " + rtoss(v.y));
  1844. } break;
  1845. case Variant::RECT2: {
  1846. Rect2 aabb = p_property;
  1847. write_string(rtoss(aabb.pos.x) + ", " + rtoss(aabb.pos.y) + ", " + rtoss(aabb.size.x) + ", " + rtoss(aabb.size.y));
  1848. } break;
  1849. case Variant::VECTOR3: {
  1850. Vector3 v = p_property;
  1851. write_string(rtoss(v.x) + ", " + rtoss(v.y) + ", " + rtoss(v.z));
  1852. } break;
  1853. case Variant::PLANE: {
  1854. Plane p = p_property;
  1855. write_string(rtoss(p.normal.x) + ", " + rtoss(p.normal.y) + ", " + rtoss(p.normal.z) + ", " + rtoss(p.d));
  1856. } break;
  1857. case Variant::_AABB: {
  1858. AABB aabb = p_property;
  1859. write_string(rtoss(aabb.pos.x) + ", " + rtoss(aabb.pos.y) + ", " + rtoss(aabb.pos.z) + ", " + rtoss(aabb.size.x) + ", " + rtoss(aabb.size.y) + ", " + rtoss(aabb.size.z));
  1860. } break;
  1861. case Variant::QUAT: {
  1862. Quat quat = p_property;
  1863. write_string(rtoss(quat.x) + ", " + rtoss(quat.y) + ", " + rtoss(quat.z) + ", " + rtoss(quat.w) + ", ");
  1864. } break;
  1865. case Variant::MATRIX32: {
  1866. String s;
  1867. Matrix32 m3 = p_property;
  1868. for (int i = 0; i < 3; i++) {
  1869. for (int j = 0; j < 2; j++) {
  1870. if (i != 0 || j != 0)
  1871. s += ", ";
  1872. s += rtoss(m3.elements[i][j]);
  1873. }
  1874. }
  1875. write_string(s);
  1876. } break;
  1877. case Variant::MATRIX3: {
  1878. String s;
  1879. Matrix3 m3 = p_property;
  1880. for (int i = 0; i < 3; i++) {
  1881. for (int j = 0; j < 3; j++) {
  1882. if (i != 0 || j != 0)
  1883. s += ", ";
  1884. s += rtoss(m3.elements[i][j]);
  1885. }
  1886. }
  1887. write_string(s);
  1888. } break;
  1889. case Variant::TRANSFORM: {
  1890. String s;
  1891. Transform t = p_property;
  1892. Matrix3 &m3 = t.basis;
  1893. for (int i = 0; i < 3; i++) {
  1894. for (int j = 0; j < 3; j++) {
  1895. if (i != 0 || j != 0)
  1896. s += ", ";
  1897. s += rtoss(m3.elements[i][j]);
  1898. }
  1899. }
  1900. s = s + ", " + rtoss(t.origin.x) + ", " + rtoss(t.origin.y) + ", " + rtoss(t.origin.z);
  1901. write_string(s);
  1902. } break;
  1903. // misc types
  1904. case Variant::COLOR: {
  1905. Color c = p_property;
  1906. write_string(rtoss(c.r) + ", " + rtoss(c.g) + ", " + rtoss(c.b) + ", " + rtoss(c.a));
  1907. } break;
  1908. case Variant::IMAGE: {
  1909. String s;
  1910. Image img = p_property;
  1911. DVector<uint8_t> data = img.get_data();
  1912. int len = data.size();
  1913. DVector<uint8_t>::Read r = data.read();
  1914. const uint8_t *ptr = r.ptr();
  1915. ;
  1916. for (int i = 0; i < len; i++) {
  1917. uint8_t byte = ptr[i];
  1918. const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  1919. char str[3] = { hex[byte >> 4], hex[byte & 0xF], 0 };
  1920. s += str;
  1921. }
  1922. write_string(s);
  1923. } break;
  1924. case Variant::NODE_PATH: {
  1925. String str = p_property;
  1926. escape(str);
  1927. str = "\"" + str + "\"";
  1928. write_string(str, false);
  1929. } break;
  1930. case Variant::OBJECT: {
  1931. /* this saver does not save resources in here
  1932. RES res = p_property;
  1933. if (!res.is_null()) {
  1934. String path=res->get_path();
  1935. if (!res->is_shared() || !path.length()) {
  1936. // if no path, or path is from inside a scene
  1937. write_object( *res );
  1938. }
  1939. }
  1940. */
  1941. } break;
  1942. case Variant::INPUT_EVENT: {
  1943. write_string(p_property.operator String());
  1944. } break;
  1945. case Variant::DICTIONARY: {
  1946. Dictionary dict = p_property;
  1947. List<Variant> keys;
  1948. dict.get_key_list(&keys);
  1949. keys.sort();
  1950. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  1951. //if (!_check_type(dict[E->get()]))
  1952. // continue;
  1953. bool ok;
  1954. write_property("", E->get(), &ok);
  1955. ERR_CONTINUE(!ok);
  1956. write_property("", dict[E->get()], &ok);
  1957. if (!ok)
  1958. write_property("", Variant()); //at least make the file consistent..
  1959. }
  1960. } break;
  1961. case Variant::ARRAY: {
  1962. Array array = p_property;
  1963. int len = array.size();
  1964. for (int i = 0; i < len; i++) {
  1965. write_property("", array[i]);
  1966. }
  1967. } break;
  1968. case Variant::RAW_ARRAY: {
  1969. String s;
  1970. DVector<uint8_t> data = p_property;
  1971. int len = data.size();
  1972. DVector<uint8_t>::Read r = data.read();
  1973. const uint8_t *ptr = r.ptr();
  1974. ;
  1975. for (int i = 0; i < len; i++) {
  1976. uint8_t byte = ptr[i];
  1977. const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  1978. char str[3] = { hex[byte >> 4], hex[byte & 0xF], 0 };
  1979. s += str;
  1980. }
  1981. write_string(s, false);
  1982. } break;
  1983. case Variant::INT_ARRAY: {
  1984. DVector<int> data = p_property;
  1985. int len = data.size();
  1986. DVector<int>::Read r = data.read();
  1987. const int *ptr = r.ptr();
  1988. ;
  1989. write_tabs();
  1990. for (int i = 0; i < len; i++) {
  1991. if (i > 0)
  1992. write_string(", ", false);
  1993. write_string(itos(ptr[i]), false);
  1994. }
  1995. } break;
  1996. case Variant::REAL_ARRAY: {
  1997. DVector<real_t> data = p_property;
  1998. int len = data.size();
  1999. DVector<real_t>::Read r = data.read();
  2000. const real_t *ptr = r.ptr();
  2001. ;
  2002. write_tabs();
  2003. String cm = ", ";
  2004. for (int i = 0; i < len; i++) {
  2005. if (i > 0)
  2006. write_string(cm, false);
  2007. write_string(rtoss(ptr[i]), false);
  2008. }
  2009. } break;
  2010. case Variant::STRING_ARRAY: {
  2011. DVector<String> data = p_property;
  2012. int len = data.size();
  2013. DVector<String>::Read r = data.read();
  2014. const String *ptr = r.ptr();
  2015. ;
  2016. String s;
  2017. //write_string("\n");
  2018. for (int i = 0; i < len; i++) {
  2019. write_tabs(0);
  2020. String str = ptr[i];
  2021. escape(str);
  2022. write_string("<string> \"" + str + "\" </string>\n", false);
  2023. }
  2024. } break;
  2025. case Variant::VECTOR2_ARRAY: {
  2026. DVector<Vector2> data = p_property;
  2027. int len = data.size();
  2028. DVector<Vector2>::Read r = data.read();
  2029. const Vector2 *ptr = r.ptr();
  2030. ;
  2031. write_tabs();
  2032. for (int i = 0; i < len; i++) {
  2033. if (i > 0)
  2034. write_string(", ", false);
  2035. write_string(rtoss(ptr[i].x), false);
  2036. write_string(", " + rtoss(ptr[i].y), false);
  2037. }
  2038. } break;
  2039. case Variant::VECTOR3_ARRAY: {
  2040. DVector<Vector3> data = p_property;
  2041. int len = data.size();
  2042. DVector<Vector3>::Read r = data.read();
  2043. const Vector3 *ptr = r.ptr();
  2044. ;
  2045. write_tabs();
  2046. for (int i = 0; i < len; i++) {
  2047. if (i > 0)
  2048. write_string(", ", false);
  2049. write_string(rtoss(ptr[i].x), false);
  2050. write_string(", " + rtoss(ptr[i].y), false);
  2051. write_string(", " + rtoss(ptr[i].z), false);
  2052. }
  2053. } break;
  2054. case Variant::COLOR_ARRAY: {
  2055. DVector<Color> data = p_property;
  2056. int len = data.size();
  2057. DVector<Color>::Read r = data.read();
  2058. const Color *ptr = r.ptr();
  2059. ;
  2060. write_tabs();
  2061. for (int i = 0; i < len; i++) {
  2062. if (i > 0)
  2063. write_string(", ", false);
  2064. write_string(rtoss(ptr[i].r), false);
  2065. write_string(", " + rtoss(ptr[i].g), false);
  2066. write_string(", " + rtoss(ptr[i].b), false);
  2067. write_string(", " + rtoss(ptr[i].a), false);
  2068. }
  2069. } break;
  2070. default: {}
  2071. }
  2072. if (oneliner)
  2073. f->store_8(' ');
  2074. else
  2075. write_tabs(-1);
  2076. exit_tag(type);
  2077. f->store_8('\n');
  2078. if (r_ok)
  2079. *r_ok = true;
  2080. }
  2081. void ResourceFormatSaverXMLInstance::_find_resources(const Variant &p_variant, bool p_main) {
  2082. switch (p_variant.get_type()) {
  2083. case Variant::OBJECT: {
  2084. RES res = p_variant.operator RefPtr();
  2085. if (res.is_null() || external_resources.has(res))
  2086. return;
  2087. if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
  2088. int index = external_resources.size();
  2089. external_resources[res] = index;
  2090. return;
  2091. }
  2092. if (resource_set.has(res))
  2093. return;
  2094. List<PropertyInfo> property_list;
  2095. res->get_property_list(&property_list);
  2096. property_list.sort();
  2097. List<PropertyInfo>::Element *I = property_list.front();
  2098. while (I) {
  2099. PropertyInfo pi = I->get();
  2100. if (pi.usage & PROPERTY_USAGE_STORAGE || (bundle_resources && pi.usage & PROPERTY_USAGE_BUNDLE)) {
  2101. Variant v = res->get(I->get().name);
  2102. _find_resources(v);
  2103. }
  2104. I = I->next();
  2105. }
  2106. resource_set.insert(res); //saved after, so the childs it needs are available when loaded
  2107. saved_resources.push_back(res);
  2108. } break;
  2109. case Variant::ARRAY: {
  2110. Array varray = p_variant;
  2111. int len = varray.size();
  2112. for (int i = 0; i < len; i++) {
  2113. Variant v = varray.get(i);
  2114. _find_resources(v);
  2115. }
  2116. } break;
  2117. case Variant::DICTIONARY: {
  2118. Dictionary d = p_variant;
  2119. List<Variant> keys;
  2120. d.get_key_list(&keys);
  2121. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  2122. Variant v = d[E->get()];
  2123. _find_resources(v);
  2124. }
  2125. } break;
  2126. default: {}
  2127. }
  2128. }
  2129. Error ResourceFormatSaverXMLInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  2130. Error err;
  2131. f = FileAccess::open(p_path, FileAccess::WRITE, &err);
  2132. ERR_FAIL_COND_V(err, ERR_CANT_OPEN);
  2133. FileAccessRef _fref(f);
  2134. local_path = Globals::get_singleton()->localize_path(p_path);
  2135. relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
  2136. skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
  2137. bundle_resources = p_flags & ResourceSaver::FLAG_BUNDLE_RESOURCES;
  2138. takeover_paths = p_flags & ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
  2139. if (!p_path.begins_with("res://")) {
  2140. takeover_paths = false;
  2141. }
  2142. depth = 0;
  2143. // save resources
  2144. _find_resources(p_resource, true);
  2145. ERR_FAIL_COND_V(err != OK, err);
  2146. write_string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", false); //no escape
  2147. write_string("\n", false);
  2148. enter_tag("resource_file", "type=\"" + p_resource->get_type() + "\" subresource_count=\"" + itos(saved_resources.size() + external_resources.size()) + "\" version=\"" + itos(VERSION_MAJOR) + "." + itos(VERSION_MINOR) + "\" version_name=\"" + VERSION_FULL_NAME + "\"");
  2149. write_string("\n", false);
  2150. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  2151. write_tabs();
  2152. String p = E->key()->get_path();
  2153. enter_tag("ext_resource", "path=\"" + p + "\" type=\"" + E->key()->get_save_type() + "\" index=\"" + itos(E->get()) + "\""); //bundled
  2154. exit_tag("ext_resource"); //bundled
  2155. write_string("\n", false);
  2156. }
  2157. Set<int> used_indices;
  2158. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  2159. RES res = E->get();
  2160. if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) {
  2161. if (res->get_subindex() != 0) {
  2162. if (used_indices.has(res->get_subindex())) {
  2163. res->set_subindex(0); //repeated
  2164. } else {
  2165. used_indices.insert(res->get_subindex());
  2166. }
  2167. }
  2168. }
  2169. }
  2170. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  2171. RES res = E->get();
  2172. ERR_CONTINUE(!resource_set.has(res));
  2173. bool main = (E->next() == NULL);
  2174. write_tabs();
  2175. if (main)
  2176. enter_tag("main_resource", ""); //bundled
  2177. else if (res->get_path().length() && res->get_path().find("::") == -1)
  2178. enter_tag("resource", "type=\"" + res->get_type() + "\" path=\"" + res->get_path() + "\""); //bundled
  2179. else {
  2180. if (res->get_subindex() == 0) {
  2181. int new_subindex = 1;
  2182. if (used_indices.size()) {
  2183. new_subindex = used_indices.back()->get() + 1;
  2184. }
  2185. res->set_subindex(new_subindex);
  2186. used_indices.insert(new_subindex);
  2187. }
  2188. int idx = res->get_subindex();
  2189. enter_tag("resource", "type=\"" + res->get_type() + "\" path=\"local://" + itos(idx) + "\"");
  2190. if (takeover_paths) {
  2191. res->set_path(p_path + "::" + itos(idx), true);
  2192. }
  2193. }
  2194. write_string("\n", false);
  2195. List<PropertyInfo> property_list;
  2196. res->get_property_list(&property_list);
  2197. // property_list.sort();
  2198. for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) {
  2199. if (skip_editor && PE->get().name.begins_with("__editor"))
  2200. continue;
  2201. if (PE->get().usage & PROPERTY_USAGE_STORAGE || (bundle_resources && PE->get().usage & PROPERTY_USAGE_BUNDLE)) {
  2202. String name = PE->get().name;
  2203. Variant value = res->get(name);
  2204. if ((PE->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) || (PE->get().usage & PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()))
  2205. continue;
  2206. write_property(name, value);
  2207. }
  2208. }
  2209. write_string("\n", false);
  2210. write_tabs(-1);
  2211. if (main)
  2212. exit_tag("main_resource");
  2213. else
  2214. exit_tag("resource");
  2215. write_string("\n", false);
  2216. }
  2217. exit_tag("resource_file");
  2218. if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
  2219. f->close();
  2220. return ERR_CANT_CREATE;
  2221. }
  2222. f->close();
  2223. //memdelete(f);
  2224. return OK;
  2225. }
  2226. Error ResourceFormatSaverXML::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  2227. ResourceFormatSaverXMLInstance saver;
  2228. return saver.save(p_path, p_resource, p_flags);
  2229. }
  2230. bool ResourceFormatSaverXML::recognize(const RES &p_resource) const {
  2231. return true; // all recognized!
  2232. }
  2233. void ResourceFormatSaverXML::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
  2234. //here comes the sun, lalalala
  2235. String base = p_resource->get_base_extension().to_lower();
  2236. p_extensions->push_back("xml");
  2237. if (base != "res") {
  2238. p_extensions->push_back("x" + base);
  2239. }
  2240. }
  2241. ResourceFormatSaverXML *ResourceFormatSaverXML::singleton = NULL;
  2242. ResourceFormatSaverXML::ResourceFormatSaverXML() {
  2243. singleton = this;
  2244. }