resource_format_xml.cpp 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952
  1. /*************************************************************************/
  2. /* resource_format_xml.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 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. }
  1733. } break;
  1734. case Variant::NODE_PATH: type = "node_path"; break;
  1735. case Variant::OBJECT: {
  1736. type = "resource";
  1737. RES res = p_property;
  1738. if (res.is_null()) {
  1739. write_tabs();
  1740. enter_tag(type, "name=\"" + p_name + "\"");
  1741. exit_tag(type);
  1742. if (r_ok)
  1743. *r_ok = true;
  1744. return; // don't save it
  1745. }
  1746. if (external_resources.has(res)) {
  1747. params = "external=\"" + itos(external_resources[res]) + "\"";
  1748. } else {
  1749. params = "resource_type=\"" + res->get_save_type() + "\"";
  1750. if (res->get_path().length() && res->get_path().find("::") == -1) {
  1751. //external resource
  1752. String path = relative_paths ? local_path.path_to_file(res->get_path()) : res->get_path();
  1753. escape(path);
  1754. params += " path=\"" + path + "\"";
  1755. } else {
  1756. //internal resource
  1757. ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
  1758. ERR_FAIL_COND(!resource_set.has(res));
  1759. params += " path=\"local://" + itos(res->get_subindex()) + "\"";
  1760. }
  1761. }
  1762. } break;
  1763. case Variant::INPUT_EVENT: type = "input_event"; break;
  1764. case Variant::DICTIONARY:
  1765. type = "dictionary";
  1766. params = "shared=\"" + String(p_property.is_shared() ? "true" : "false") + "\"";
  1767. oneliner = false;
  1768. break;
  1769. case Variant::ARRAY:
  1770. type = "array";
  1771. params = "len=\"" + itos(p_property.operator Array().size()) + "\" shared=\"" + String(p_property.is_shared() ? "true" : "false") + "\"";
  1772. oneliner = false;
  1773. break;
  1774. case Variant::RAW_ARRAY:
  1775. type = "raw_array";
  1776. params = "len=\"" + itos(p_property.operator DVector<uint8_t>().size()) + "\"";
  1777. break;
  1778. case Variant::INT_ARRAY:
  1779. type = "int_array";
  1780. params = "len=\"" + itos(p_property.operator DVector<int>().size()) + "\"";
  1781. break;
  1782. case Variant::REAL_ARRAY:
  1783. type = "real_array";
  1784. params = "len=\"" + itos(p_property.operator DVector<real_t>().size()) + "\"";
  1785. break;
  1786. case Variant::STRING_ARRAY:
  1787. oneliner = false;
  1788. type = "string_array";
  1789. params = "len=\"" + itos(p_property.operator DVector<String>().size()) + "\"";
  1790. break;
  1791. case Variant::VECTOR2_ARRAY:
  1792. type = "vector2_array";
  1793. params = "len=\"" + itos(p_property.operator DVector<Vector2>().size()) + "\"";
  1794. break;
  1795. case Variant::VECTOR3_ARRAY:
  1796. type = "vector3_array";
  1797. params = "len=\"" + itos(p_property.operator DVector<Vector3>().size()) + "\"";
  1798. break;
  1799. case Variant::COLOR_ARRAY:
  1800. type = "color_array";
  1801. params = "len=\"" + itos(p_property.operator DVector<Color>().size()) + "\"";
  1802. break;
  1803. default: {
  1804. ERR_PRINT("Unknown Variant type.");
  1805. ERR_FAIL();
  1806. }
  1807. }
  1808. write_tabs();
  1809. if (p_name != "") {
  1810. if (params.length())
  1811. enter_tag(type, "name=\"" + p_name + "\" " + params);
  1812. else
  1813. enter_tag(type, "name=\"" + p_name + "\"");
  1814. } else {
  1815. if (params.length())
  1816. enter_tag(type, " " + params);
  1817. else
  1818. enter_tag(type, String());
  1819. }
  1820. if (!oneliner)
  1821. f->store_8('\n');
  1822. else
  1823. f->store_8(' ');
  1824. switch (p_property.get_type()) {
  1825. case Variant::NIL: {
  1826. } break;
  1827. case Variant::BOOL: {
  1828. write_string(p_property.operator bool() ? "True" : "False");
  1829. } break;
  1830. case Variant::INT: {
  1831. write_string(itos(p_property.operator int()));
  1832. } break;
  1833. case Variant::REAL: {
  1834. write_string(rtos(p_property.operator real_t()));
  1835. } break;
  1836. case Variant::STRING: {
  1837. String str = p_property;
  1838. escape(str);
  1839. str = "\"" + str + "\"";
  1840. write_string(str, false);
  1841. } break;
  1842. case Variant::VECTOR2: {
  1843. Vector2 v = p_property;
  1844. write_string(rtoss(v.x) + ", " + rtoss(v.y));
  1845. } break;
  1846. case Variant::RECT2: {
  1847. Rect2 aabb = p_property;
  1848. write_string(rtoss(aabb.pos.x) + ", " + rtoss(aabb.pos.y) + ", " + rtoss(aabb.size.x) + ", " + rtoss(aabb.size.y));
  1849. } break;
  1850. case Variant::VECTOR3: {
  1851. Vector3 v = p_property;
  1852. write_string(rtoss(v.x) + ", " + rtoss(v.y) + ", " + rtoss(v.z));
  1853. } break;
  1854. case Variant::PLANE: {
  1855. Plane p = p_property;
  1856. write_string(rtoss(p.normal.x) + ", " + rtoss(p.normal.y) + ", " + rtoss(p.normal.z) + ", " + rtoss(p.d));
  1857. } break;
  1858. case Variant::_AABB: {
  1859. AABB aabb = p_property;
  1860. 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));
  1861. } break;
  1862. case Variant::QUAT: {
  1863. Quat quat = p_property;
  1864. write_string(rtoss(quat.x) + ", " + rtoss(quat.y) + ", " + rtoss(quat.z) + ", " + rtoss(quat.w) + ", ");
  1865. } break;
  1866. case Variant::MATRIX32: {
  1867. String s;
  1868. Matrix32 m3 = p_property;
  1869. for (int i = 0; i < 3; i++) {
  1870. for (int j = 0; j < 2; j++) {
  1871. if (i != 0 || j != 0)
  1872. s += ", ";
  1873. s += rtoss(m3.elements[i][j]);
  1874. }
  1875. }
  1876. write_string(s);
  1877. } break;
  1878. case Variant::MATRIX3: {
  1879. String s;
  1880. Matrix3 m3 = p_property;
  1881. for (int i = 0; i < 3; i++) {
  1882. for (int j = 0; j < 3; j++) {
  1883. if (i != 0 || j != 0)
  1884. s += ", ";
  1885. s += rtoss(m3.elements[i][j]);
  1886. }
  1887. }
  1888. write_string(s);
  1889. } break;
  1890. case Variant::TRANSFORM: {
  1891. String s;
  1892. Transform t = p_property;
  1893. Matrix3 &m3 = t.basis;
  1894. for (int i = 0; i < 3; i++) {
  1895. for (int j = 0; j < 3; j++) {
  1896. if (i != 0 || j != 0)
  1897. s += ", ";
  1898. s += rtoss(m3.elements[i][j]);
  1899. }
  1900. }
  1901. s = s + ", " + rtoss(t.origin.x) + ", " + rtoss(t.origin.y) + ", " + rtoss(t.origin.z);
  1902. write_string(s);
  1903. } break;
  1904. // misc types
  1905. case Variant::COLOR: {
  1906. Color c = p_property;
  1907. write_string(rtoss(c.r) + ", " + rtoss(c.g) + ", " + rtoss(c.b) + ", " + rtoss(c.a));
  1908. } break;
  1909. case Variant::IMAGE: {
  1910. String s;
  1911. Image img = p_property;
  1912. DVector<uint8_t> data = img.get_data();
  1913. int len = data.size();
  1914. DVector<uint8_t>::Read r = data.read();
  1915. const uint8_t *ptr = r.ptr();
  1916. ;
  1917. for (int i = 0; i < len; i++) {
  1918. uint8_t byte = ptr[i];
  1919. const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  1920. char str[3] = { hex[byte >> 4], hex[byte & 0xF], 0 };
  1921. s += str;
  1922. }
  1923. write_string(s);
  1924. } break;
  1925. case Variant::NODE_PATH: {
  1926. String str = p_property;
  1927. escape(str);
  1928. str = "\"" + str + "\"";
  1929. write_string(str, false);
  1930. } break;
  1931. case Variant::OBJECT: {
  1932. /* this saver does not save resources in here
  1933. RES res = p_property;
  1934. if (!res.is_null()) {
  1935. String path=res->get_path();
  1936. if (!res->is_shared() || !path.length()) {
  1937. // if no path, or path is from inside a scene
  1938. write_object( *res );
  1939. }
  1940. }
  1941. */
  1942. } break;
  1943. case Variant::INPUT_EVENT: {
  1944. write_string(p_property.operator String());
  1945. } break;
  1946. case Variant::DICTIONARY: {
  1947. Dictionary dict = p_property;
  1948. List<Variant> keys;
  1949. dict.get_key_list(&keys);
  1950. keys.sort();
  1951. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  1952. //if (!_check_type(dict[E->get()]))
  1953. // continue;
  1954. bool ok;
  1955. write_property("", E->get(), &ok);
  1956. ERR_CONTINUE(!ok);
  1957. write_property("", dict[E->get()], &ok);
  1958. if (!ok)
  1959. write_property("", Variant()); //at least make the file consistent..
  1960. }
  1961. } break;
  1962. case Variant::ARRAY: {
  1963. Array array = p_property;
  1964. int len = array.size();
  1965. for (int i = 0; i < len; i++) {
  1966. write_property("", array[i]);
  1967. }
  1968. } break;
  1969. case Variant::RAW_ARRAY: {
  1970. String s;
  1971. DVector<uint8_t> data = p_property;
  1972. int len = data.size();
  1973. DVector<uint8_t>::Read r = data.read();
  1974. const uint8_t *ptr = r.ptr();
  1975. ;
  1976. for (int i = 0; i < len; i++) {
  1977. uint8_t byte = ptr[i];
  1978. const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  1979. char str[3] = { hex[byte >> 4], hex[byte & 0xF], 0 };
  1980. s += str;
  1981. }
  1982. write_string(s, false);
  1983. } break;
  1984. case Variant::INT_ARRAY: {
  1985. DVector<int> data = p_property;
  1986. int len = data.size();
  1987. DVector<int>::Read r = data.read();
  1988. const int *ptr = r.ptr();
  1989. ;
  1990. write_tabs();
  1991. for (int i = 0; i < len; i++) {
  1992. if (i > 0)
  1993. write_string(", ", false);
  1994. write_string(itos(ptr[i]), false);
  1995. }
  1996. } break;
  1997. case Variant::REAL_ARRAY: {
  1998. DVector<real_t> data = p_property;
  1999. int len = data.size();
  2000. DVector<real_t>::Read r = data.read();
  2001. const real_t *ptr = r.ptr();
  2002. ;
  2003. write_tabs();
  2004. String cm = ", ";
  2005. for (int i = 0; i < len; i++) {
  2006. if (i > 0)
  2007. write_string(cm, false);
  2008. write_string(rtoss(ptr[i]), false);
  2009. }
  2010. } break;
  2011. case Variant::STRING_ARRAY: {
  2012. DVector<String> data = p_property;
  2013. int len = data.size();
  2014. DVector<String>::Read r = data.read();
  2015. const String *ptr = r.ptr();
  2016. ;
  2017. String s;
  2018. //write_string("\n");
  2019. for (int i = 0; i < len; i++) {
  2020. write_tabs(0);
  2021. String str = ptr[i];
  2022. escape(str);
  2023. write_string("<string> \"" + str + "\" </string>\n", false);
  2024. }
  2025. } break;
  2026. case Variant::VECTOR2_ARRAY: {
  2027. DVector<Vector2> data = p_property;
  2028. int len = data.size();
  2029. DVector<Vector2>::Read r = data.read();
  2030. const Vector2 *ptr = r.ptr();
  2031. ;
  2032. write_tabs();
  2033. for (int i = 0; i < len; i++) {
  2034. if (i > 0)
  2035. write_string(", ", false);
  2036. write_string(rtoss(ptr[i].x), false);
  2037. write_string(", " + rtoss(ptr[i].y), false);
  2038. }
  2039. } break;
  2040. case Variant::VECTOR3_ARRAY: {
  2041. DVector<Vector3> data = p_property;
  2042. int len = data.size();
  2043. DVector<Vector3>::Read r = data.read();
  2044. const Vector3 *ptr = r.ptr();
  2045. ;
  2046. write_tabs();
  2047. for (int i = 0; i < len; i++) {
  2048. if (i > 0)
  2049. write_string(", ", false);
  2050. write_string(rtoss(ptr[i].x), false);
  2051. write_string(", " + rtoss(ptr[i].y), false);
  2052. write_string(", " + rtoss(ptr[i].z), false);
  2053. }
  2054. } break;
  2055. case Variant::COLOR_ARRAY: {
  2056. DVector<Color> data = p_property;
  2057. int len = data.size();
  2058. DVector<Color>::Read r = data.read();
  2059. const Color *ptr = r.ptr();
  2060. ;
  2061. write_tabs();
  2062. for (int i = 0; i < len; i++) {
  2063. if (i > 0)
  2064. write_string(", ", false);
  2065. write_string(rtoss(ptr[i].r), false);
  2066. write_string(", " + rtoss(ptr[i].g), false);
  2067. write_string(", " + rtoss(ptr[i].b), false);
  2068. write_string(", " + rtoss(ptr[i].a), false);
  2069. }
  2070. } break;
  2071. default: {
  2072. }
  2073. }
  2074. if (oneliner)
  2075. f->store_8(' ');
  2076. else
  2077. write_tabs(-1);
  2078. exit_tag(type);
  2079. f->store_8('\n');
  2080. if (r_ok)
  2081. *r_ok = true;
  2082. }
  2083. void ResourceFormatSaverXMLInstance::_find_resources(const Variant &p_variant, bool p_main) {
  2084. switch (p_variant.get_type()) {
  2085. case Variant::OBJECT: {
  2086. RES res = p_variant.operator RefPtr();
  2087. if (res.is_null() || external_resources.has(res))
  2088. return;
  2089. if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
  2090. int index = external_resources.size();
  2091. external_resources[res] = index;
  2092. return;
  2093. }
  2094. if (resource_set.has(res))
  2095. return;
  2096. List<PropertyInfo> property_list;
  2097. res->get_property_list(&property_list);
  2098. property_list.sort();
  2099. List<PropertyInfo>::Element *I = property_list.front();
  2100. while (I) {
  2101. PropertyInfo pi = I->get();
  2102. if (pi.usage & PROPERTY_USAGE_STORAGE || (bundle_resources && pi.usage & PROPERTY_USAGE_BUNDLE)) {
  2103. Variant v = res->get(I->get().name);
  2104. _find_resources(v);
  2105. }
  2106. I = I->next();
  2107. }
  2108. resource_set.insert(res); //saved after, so the childs it needs are available when loaded
  2109. saved_resources.push_back(res);
  2110. } break;
  2111. case Variant::ARRAY: {
  2112. Array varray = p_variant;
  2113. int len = varray.size();
  2114. for (int i = 0; i < len; i++) {
  2115. Variant v = varray.get(i);
  2116. _find_resources(v);
  2117. }
  2118. } break;
  2119. case Variant::DICTIONARY: {
  2120. Dictionary d = p_variant;
  2121. List<Variant> keys;
  2122. d.get_key_list(&keys);
  2123. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  2124. Variant v = d[E->get()];
  2125. _find_resources(v);
  2126. }
  2127. } break;
  2128. default: {
  2129. }
  2130. }
  2131. }
  2132. Error ResourceFormatSaverXMLInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  2133. Error err;
  2134. f = FileAccess::open(p_path, FileAccess::WRITE, &err);
  2135. ERR_FAIL_COND_V(err, ERR_CANT_OPEN);
  2136. FileAccessRef _fref(f);
  2137. local_path = Globals::get_singleton()->localize_path(p_path);
  2138. relative_paths = p_flags & ResourceSaver::FLAG_RELATIVE_PATHS;
  2139. skip_editor = p_flags & ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
  2140. bundle_resources = p_flags & ResourceSaver::FLAG_BUNDLE_RESOURCES;
  2141. takeover_paths = p_flags & ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
  2142. if (!p_path.begins_with("res://")) {
  2143. takeover_paths = false;
  2144. }
  2145. depth = 0;
  2146. // save resources
  2147. _find_resources(p_resource, true);
  2148. ERR_FAIL_COND_V(err != OK, err);
  2149. write_string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", false); //no escape
  2150. write_string("\n", false);
  2151. 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 + "\"");
  2152. write_string("\n", false);
  2153. for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
  2154. write_tabs();
  2155. String p = E->key()->get_path();
  2156. enter_tag("ext_resource", "path=\"" + p + "\" type=\"" + E->key()->get_save_type() + "\" index=\"" + itos(E->get()) + "\""); //bundled
  2157. exit_tag("ext_resource"); //bundled
  2158. write_string("\n", false);
  2159. }
  2160. Set<int> used_indices;
  2161. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  2162. RES res = E->get();
  2163. if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) {
  2164. if (res->get_subindex() != 0) {
  2165. if (used_indices.has(res->get_subindex())) {
  2166. res->set_subindex(0); //repeated
  2167. } else {
  2168. used_indices.insert(res->get_subindex());
  2169. }
  2170. }
  2171. }
  2172. }
  2173. for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
  2174. RES res = E->get();
  2175. ERR_CONTINUE(!resource_set.has(res));
  2176. bool main = (E->next() == NULL);
  2177. write_tabs();
  2178. if (main)
  2179. enter_tag("main_resource", ""); //bundled
  2180. else if (res->get_path().length() && res->get_path().find("::") == -1)
  2181. enter_tag("resource", "type=\"" + res->get_type() + "\" path=\"" + res->get_path() + "\""); //bundled
  2182. else {
  2183. if (res->get_subindex() == 0) {
  2184. int new_subindex = 1;
  2185. if (used_indices.size()) {
  2186. new_subindex = used_indices.back()->get() + 1;
  2187. }
  2188. res->set_subindex(new_subindex);
  2189. used_indices.insert(new_subindex);
  2190. }
  2191. int idx = res->get_subindex();
  2192. enter_tag("resource", "type=\"" + res->get_type() + "\" path=\"local://" + itos(idx) + "\"");
  2193. if (takeover_paths) {
  2194. res->set_path(p_path + "::" + itos(idx), true);
  2195. }
  2196. }
  2197. write_string("\n", false);
  2198. List<PropertyInfo> property_list;
  2199. res->get_property_list(&property_list);
  2200. // property_list.sort();
  2201. for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) {
  2202. if (skip_editor && PE->get().name.begins_with("__editor"))
  2203. continue;
  2204. if (PE->get().usage & PROPERTY_USAGE_STORAGE || (bundle_resources && PE->get().usage & PROPERTY_USAGE_BUNDLE)) {
  2205. String name = PE->get().name;
  2206. Variant value = res->get(name);
  2207. if ((PE->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) || (PE->get().usage & PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()))
  2208. continue;
  2209. write_property(name, value);
  2210. }
  2211. }
  2212. write_string("\n", false);
  2213. write_tabs(-1);
  2214. if (main)
  2215. exit_tag("main_resource");
  2216. else
  2217. exit_tag("resource");
  2218. write_string("\n", false);
  2219. }
  2220. exit_tag("resource_file");
  2221. if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
  2222. f->close();
  2223. return ERR_CANT_CREATE;
  2224. }
  2225. f->close();
  2226. //memdelete(f);
  2227. return OK;
  2228. }
  2229. Error ResourceFormatSaverXML::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  2230. ResourceFormatSaverXMLInstance saver;
  2231. return saver.save(p_path, p_resource, p_flags);
  2232. }
  2233. bool ResourceFormatSaverXML::recognize(const RES &p_resource) const {
  2234. return true; // all recognized!
  2235. }
  2236. void ResourceFormatSaverXML::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
  2237. //here comes the sun, lalalala
  2238. String base = p_resource->get_base_extension().to_lower();
  2239. p_extensions->push_back("xml");
  2240. if (base != "res") {
  2241. p_extensions->push_back("x" + base);
  2242. }
  2243. }
  2244. ResourceFormatSaverXML *ResourceFormatSaverXML::singleton = NULL;
  2245. ResourceFormatSaverXML::ResourceFormatSaverXML() {
  2246. singleton = this;
  2247. }