2
0

globals.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500
  1. /*************************************************************************/
  2. /* globals.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 "globals.h"
  31. #include "os/dir_access.h"
  32. #include "os/file_access.h"
  33. #include "bind/core_bind.h"
  34. #include "io/file_access_network.h"
  35. #include "io/file_access_pack.h"
  36. #include "io/marshalls.h"
  37. #include "os/keyboard.h"
  38. #include "os/os.h"
  39. Globals *Globals::singleton = NULL;
  40. Globals *Globals::get_singleton() {
  41. return singleton;
  42. }
  43. String Globals::get_resource_path() const {
  44. return resource_path;
  45. };
  46. String Globals::localize_path(const String &p_path) const {
  47. if (resource_path == "")
  48. return p_path; //not initialied yet
  49. if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
  50. (p_path.is_abs_path() && !p_path.begins_with(resource_path)))
  51. return p_path.simplify_path();
  52. DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
  53. String path = p_path.replace("\\", "/").simplify_path();
  54. if (dir->change_dir(path) == OK) {
  55. String cwd = dir->get_current_dir();
  56. cwd = cwd.replace("\\", "/");
  57. memdelete(dir);
  58. if (!cwd.begins_with(resource_path)) {
  59. return p_path;
  60. };
  61. return cwd.replace_first(resource_path, "res:/");
  62. } else {
  63. memdelete(dir);
  64. int sep = path.find_last("/");
  65. if (sep == -1) {
  66. return "res://" + path;
  67. };
  68. String parent = path.substr(0, sep);
  69. String plocal = localize_path(parent);
  70. if (plocal == "") {
  71. return "";
  72. };
  73. return plocal + path.substr(sep, path.size() - sep);
  74. };
  75. }
  76. void Globals::set_persisting(const String &p_name, bool p_persist) {
  77. ERR_FAIL_COND(!props.has(p_name));
  78. props[p_name].persist = p_persist;
  79. }
  80. bool Globals::is_persisting(const String &p_name) const {
  81. ERR_FAIL_COND_V(!props.has(p_name), false);
  82. return props[p_name].persist;
  83. }
  84. String Globals::globalize_path(const String &p_path) const {
  85. if (p_path.begins_with("res://")) {
  86. if (resource_path != "") {
  87. return p_path.replace("res:/", resource_path);
  88. };
  89. return p_path.replace("res://", "");
  90. };
  91. return p_path;
  92. }
  93. bool Globals::_set(const StringName &p_name, const Variant &p_value) {
  94. _THREAD_SAFE_METHOD_
  95. if (p_value.get_type() == Variant::NIL)
  96. props.erase(p_name);
  97. else {
  98. if (props.has(p_name)) {
  99. if (!props[p_name].overrided)
  100. props[p_name].variant = p_value;
  101. if (props[p_name].order >= NO_ORDER_BASE && registering_order) {
  102. props[p_name].order = last_order++;
  103. }
  104. } else {
  105. props[p_name] = VariantContainer(p_value, last_order++ + (registering_order ? 0 : NO_ORDER_BASE));
  106. }
  107. }
  108. if (!disable_platform_override) {
  109. String s = String(p_name);
  110. int sl = s.find("/");
  111. int p = s.find(".");
  112. if (p != -1 && sl != -1 && p < sl) {
  113. Vector<String> ps = s.substr(0, sl).split(".");
  114. String prop = s.substr(sl, s.length() - sl);
  115. for (int i = 1; i < ps.size(); i++) {
  116. if (ps[i] == OS::get_singleton()->get_name()) {
  117. String fullprop = ps[0] + prop;
  118. set(fullprop, p_value);
  119. props[fullprop].overrided = true;
  120. }
  121. }
  122. }
  123. }
  124. return true;
  125. }
  126. bool Globals::_get(const StringName &p_name, Variant &r_ret) const {
  127. _THREAD_SAFE_METHOD_
  128. if (!props.has(p_name))
  129. return false;
  130. r_ret = props[p_name].variant;
  131. return true;
  132. }
  133. struct _VCSort {
  134. String name;
  135. Variant::Type type;
  136. int order;
  137. int flags;
  138. bool operator<(const _VCSort &p_vcs) const { return order == p_vcs.order ? name < p_vcs.name : order < p_vcs.order; }
  139. };
  140. void Globals::_get_property_list(List<PropertyInfo> *p_list) const {
  141. _THREAD_SAFE_METHOD_
  142. Set<_VCSort> vclist;
  143. for (Map<StringName, VariantContainer>::Element *E = props.front(); E; E = E->next()) {
  144. const VariantContainer *v = &E->get();
  145. if (v->hide_from_editor)
  146. continue;
  147. _VCSort vc;
  148. vc.name = E->key();
  149. vc.order = v->order;
  150. vc.type = v->variant.get_type();
  151. if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload"))
  152. vc.flags = PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_STORAGE;
  153. else
  154. vc.flags = PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
  155. if (v->persist) {
  156. vc.flags |= PROPERTY_USAGE_CHECKED;
  157. }
  158. vclist.insert(vc);
  159. }
  160. for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) {
  161. if (custom_prop_info.has(E->get().name)) {
  162. PropertyInfo pi = custom_prop_info[E->get().name];
  163. pi.name = E->get().name;
  164. pi.usage = E->get().flags;
  165. p_list->push_back(pi);
  166. } else
  167. p_list->push_back(PropertyInfo(E->get().type, E->get().name, PROPERTY_HINT_NONE, "", E->get().flags));
  168. }
  169. }
  170. bool Globals::_load_resource_pack(const String &p_pack) {
  171. if (PackedData::get_singleton()->is_disabled())
  172. return false;
  173. bool ok = PackedData::get_singleton()->add_pack(p_pack) == OK;
  174. if (!ok)
  175. return false;
  176. //if data.pck is found, all directory access will be from here
  177. DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
  178. using_datapack = true;
  179. return true;
  180. }
  181. Error Globals::setup(const String &p_path, const String &p_main_pack) {
  182. //an absolute mess of a function, must be cleaned up and reorganized somehow at some point
  183. //_load_settings(p_path+"/override.cfg");
  184. if (p_main_pack != "") {
  185. bool ok = _load_resource_pack(p_main_pack);
  186. ERR_FAIL_COND_V(!ok, ERR_CANT_OPEN);
  187. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  188. _load_settings("res://override.cfg");
  189. }
  190. return OK;
  191. }
  192. if (OS::get_singleton()->get_executable_path() != "") {
  193. if (_load_resource_pack(OS::get_singleton()->get_executable_path())) {
  194. if (p_path != "") {
  195. resource_path = p_path;
  196. } else {
  197. DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
  198. resource_path = d->get_current_dir();
  199. memdelete(d);
  200. }
  201. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  202. _load_settings("res://override.cfg");
  203. }
  204. return OK;
  205. }
  206. }
  207. if (FileAccessNetworkClient::get_singleton()) {
  208. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  209. _load_settings("res://override.cfg");
  210. }
  211. return OK;
  212. }
  213. if (OS::get_singleton()->get_resource_dir() != "") {
  214. //OS will call Globals->get_resource_path which will be empty if not overriden!
  215. //if the OS would rather use somewhere else, then it will not be empty.
  216. resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/");
  217. if (resource_path.length() && resource_path[resource_path.length() - 1] == '/')
  218. resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end
  219. print_line("has res dir: " + resource_path);
  220. if (!_load_resource_pack("res://data.pck"))
  221. _load_resource_pack("res://data.zip");
  222. // make sure this is load from the resource path
  223. print_line("exists engine cfg? " + itos(FileAccess::exists("/engine.cfg")));
  224. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  225. print_line("loaded engine.cfg");
  226. _load_settings("res://override.cfg");
  227. }
  228. return OK;
  229. }
  230. DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
  231. if (!d) {
  232. resource_path = p_path;
  233. } else {
  234. d->change_dir(p_path);
  235. String candidate = d->get_current_dir();
  236. String current_dir = d->get_current_dir();
  237. String exec_name = OS::get_singleton()->get_executable_path().get_file().basename();
  238. bool found = false;
  239. bool first_time = true;
  240. while (true) {
  241. //try to load settings in ascending through dirs shape!
  242. //tries to open pack, but only first time
  243. if (first_time && (_load_resource_pack(current_dir + "/" + exec_name + ".pck") || _load_resource_pack(current_dir + "/" + exec_name + ".zip"))) {
  244. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  245. _load_settings("res://override.cfg");
  246. found = true;
  247. }
  248. break;
  249. } else if (first_time && (_load_resource_pack(current_dir + "/data.pck") || _load_resource_pack(current_dir + "/data.zip"))) {
  250. if (_load_settings("res://engine.cfg") == OK || _load_settings_binary("res://engine.cfb") == OK) {
  251. _load_settings("res://override.cfg");
  252. found = true;
  253. }
  254. break;
  255. } else if (_load_settings(current_dir + "/engine.cfg") == OK || _load_settings_binary(current_dir + "/engine.cfb") == OK) {
  256. _load_settings(current_dir + "/override.cfg");
  257. candidate = current_dir;
  258. found = true;
  259. break;
  260. }
  261. d->change_dir("..");
  262. if (d->get_current_dir() == current_dir)
  263. break; //not doing anything useful
  264. current_dir = d->get_current_dir();
  265. first_time = false;
  266. }
  267. resource_path = candidate;
  268. resource_path = resource_path.replace("\\", "/"); // windows path to unix path just in case
  269. memdelete(d);
  270. if (!found)
  271. return ERR_FILE_NOT_FOUND;
  272. };
  273. if (resource_path.length() && resource_path[resource_path.length() - 1] == '/')
  274. resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end
  275. return OK;
  276. }
  277. bool Globals::has(String p_var) const {
  278. _THREAD_SAFE_METHOD_
  279. return props.has(p_var);
  280. }
  281. static Vector<String> _decode_params(const String &p_string) {
  282. int begin = p_string.find("(");
  283. ERR_FAIL_COND_V(begin == -1, Vector<String>());
  284. begin++;
  285. int end = p_string.find(")");
  286. ERR_FAIL_COND_V(end < begin, Vector<String>());
  287. return p_string.substr(begin, end - begin).split(",");
  288. }
  289. static String _get_chunk(const String &str, int &pos, int close_pos) {
  290. enum {
  291. MIN_COMMA,
  292. MIN_COLON,
  293. MIN_CLOSE,
  294. MIN_QUOTE,
  295. MIN_PARENTHESIS,
  296. MIN_CURLY_OPEN,
  297. MIN_OPEN
  298. };
  299. int min_pos = close_pos;
  300. int min_what = MIN_CLOSE;
  301. #define TEST_MIN(m_how, m_what) \
  302. { \
  303. int res = str.find(m_how, pos); \
  304. if (res != -1 && res < min_pos) { \
  305. min_pos = res; \
  306. min_what = m_what; \
  307. } \
  308. }
  309. TEST_MIN(",", MIN_COMMA);
  310. TEST_MIN("[", MIN_OPEN);
  311. TEST_MIN("{", MIN_CURLY_OPEN);
  312. TEST_MIN("(", MIN_PARENTHESIS);
  313. TEST_MIN("\"", MIN_QUOTE);
  314. int end = min_pos;
  315. switch (min_what) {
  316. case MIN_COMMA: {
  317. } break;
  318. case MIN_CLOSE: {
  319. //end because it's done
  320. } break;
  321. case MIN_QUOTE: {
  322. end = str.find("\"", min_pos + 1) + 1;
  323. ERR_FAIL_COND_V(end == -1, Variant());
  324. } break;
  325. case MIN_PARENTHESIS: {
  326. end = str.find(")", min_pos + 1) + 1;
  327. ERR_FAIL_COND_V(end == -1, Variant());
  328. } break;
  329. case MIN_OPEN: {
  330. int level = 1;
  331. end++;
  332. while (end < close_pos) {
  333. if (str[end] == '[')
  334. level++;
  335. if (str[end] == ']') {
  336. level--;
  337. if (level == 0)
  338. break;
  339. }
  340. end++;
  341. }
  342. ERR_FAIL_COND_V(level != 0, Variant());
  343. end++;
  344. } break;
  345. case MIN_CURLY_OPEN: {
  346. int level = 1;
  347. end++;
  348. while (end < close_pos) {
  349. if (str[end] == '{')
  350. level++;
  351. if (str[end] == '}') {
  352. level--;
  353. if (level == 0)
  354. break;
  355. }
  356. end++;
  357. }
  358. ERR_FAIL_COND_V(level != 0, Variant());
  359. end++;
  360. } break;
  361. }
  362. String ret = str.substr(pos, end - pos);
  363. pos = end;
  364. while (pos < close_pos) {
  365. if (str[pos] != ',' && str[pos] != ' ' && str[pos] != ':')
  366. break;
  367. pos++;
  368. }
  369. return ret;
  370. }
  371. static Variant _decode_variant(const String &p_string) {
  372. String str = p_string.strip_edges();
  373. if (str.nocasecmp_to("true") == 0)
  374. return Variant(true);
  375. if (str.nocasecmp_to("false") == 0)
  376. return Variant(false);
  377. if (str.nocasecmp_to("nil") == 0)
  378. return Variant();
  379. if (str.is_valid_float()) {
  380. if (str.find(".") == -1)
  381. return str.to_int();
  382. else
  383. return str.to_double();
  384. }
  385. if (str.begins_with("#")) { //string
  386. return Color::html(str);
  387. }
  388. if (str.begins_with("\"")) { //string
  389. int end = str.find_last("\"");
  390. ERR_FAIL_COND_V(end == 0, Variant());
  391. return str.substr(1, end - 1).xml_unescape();
  392. }
  393. if (str.begins_with("[")) { //array
  394. int close_pos = str.find_last("]");
  395. ERR_FAIL_COND_V(close_pos == -1, Variant());
  396. Array array;
  397. int pos = 1;
  398. while (pos < close_pos) {
  399. String s = _get_chunk(str, pos, close_pos);
  400. array.push_back(_decode_variant(s));
  401. }
  402. return array;
  403. }
  404. if (str.begins_with("{")) { //array
  405. int close_pos = str.find_last("}");
  406. ERR_FAIL_COND_V(close_pos == -1, Variant());
  407. Dictionary d;
  408. int pos = 1;
  409. while (pos < close_pos) {
  410. String key = _get_chunk(str, pos, close_pos);
  411. String data = _get_chunk(str, pos, close_pos);
  412. d[_decode_variant(key)] = _decode_variant(data);
  413. }
  414. return d;
  415. }
  416. if (str.begins_with("key")) {
  417. Vector<String> params = _decode_params(p_string);
  418. ERR_FAIL_COND_V(params.size() != 1 && params.size() != 2, Variant());
  419. int scode = 0;
  420. if (params[0].is_numeric()) {
  421. scode = params[0].to_int();
  422. if (scode < 10)
  423. scode += KEY_0;
  424. } else
  425. scode = find_keycode(params[0]);
  426. InputEvent ie;
  427. ie.type = InputEvent::KEY;
  428. ie.key.scancode = scode;
  429. if (params.size() == 2) {
  430. String mods = params[1];
  431. if (mods.findn("C") != -1)
  432. ie.key.mod.control = true;
  433. if (mods.findn("A") != -1)
  434. ie.key.mod.alt = true;
  435. if (mods.findn("S") != -1)
  436. ie.key.mod.shift = true;
  437. if (mods.findn("M") != -1)
  438. ie.key.mod.meta = true;
  439. }
  440. return ie;
  441. }
  442. if (str.begins_with("mbutton")) {
  443. Vector<String> params = _decode_params(p_string);
  444. ERR_FAIL_COND_V(params.size() != 2, Variant());
  445. InputEvent ie;
  446. ie.type = InputEvent::MOUSE_BUTTON;
  447. ie.device = params[0].to_int();
  448. ie.mouse_button.button_index = params[1].to_int();
  449. return ie;
  450. }
  451. if (str.begins_with("jbutton")) {
  452. Vector<String> params = _decode_params(p_string);
  453. ERR_FAIL_COND_V(params.size() != 2, Variant());
  454. InputEvent ie;
  455. ie.type = InputEvent::JOYSTICK_BUTTON;
  456. ie.device = params[0].to_int();
  457. ie.joy_button.button_index = params[1].to_int();
  458. return ie;
  459. }
  460. if (str.begins_with("jaxis")) {
  461. Vector<String> params = _decode_params(p_string);
  462. ERR_FAIL_COND_V(params.size() != 2, Variant());
  463. InputEvent ie;
  464. ie.type = InputEvent::JOYSTICK_MOTION;
  465. ie.device = params[0].to_int();
  466. int axis = params[1].to_int();
  467. ;
  468. ie.joy_motion.axis = axis >> 1;
  469. ie.joy_motion.axis_value = axis & 1 ? 1 : -1;
  470. return ie;
  471. }
  472. if (str.begins_with("img")) {
  473. Vector<String> params = _decode_params(p_string);
  474. if (params.size() == 0) {
  475. return Image();
  476. }
  477. ERR_FAIL_COND_V(params.size() != 5, Image());
  478. String format = params[0].strip_edges();
  479. Image::Format imgformat;
  480. if (format == "grayscale") {
  481. imgformat = Image::FORMAT_GRAYSCALE;
  482. } else if (format == "intensity") {
  483. imgformat = Image::FORMAT_INTENSITY;
  484. } else if (format == "grayscale_alpha") {
  485. imgformat = Image::FORMAT_GRAYSCALE_ALPHA;
  486. } else if (format == "rgb") {
  487. imgformat = Image::FORMAT_RGB;
  488. } else if (format == "rgba") {
  489. imgformat = Image::FORMAT_RGBA;
  490. } else if (format == "indexed") {
  491. imgformat = Image::FORMAT_INDEXED;
  492. } else if (format == "indexed_alpha") {
  493. imgformat = Image::FORMAT_INDEXED_ALPHA;
  494. } else if (format == "bc1") {
  495. imgformat = Image::FORMAT_BC1;
  496. } else if (format == "bc2") {
  497. imgformat = Image::FORMAT_BC2;
  498. } else if (format == "bc3") {
  499. imgformat = Image::FORMAT_BC3;
  500. } else if (format == "bc4") {
  501. imgformat = Image::FORMAT_BC4;
  502. } else if (format == "bc5") {
  503. imgformat = Image::FORMAT_BC5;
  504. } else if (format == "custom") {
  505. imgformat = Image::FORMAT_CUSTOM;
  506. } else {
  507. ERR_FAIL_V(Image());
  508. }
  509. int mipmaps = params[1].to_int();
  510. int w = params[2].to_int();
  511. int h = params[3].to_int();
  512. if (w == 0 && h == 0) {
  513. //r_v = Image(w, h, imgformat);
  514. return Image();
  515. };
  516. String data = params[4];
  517. int datasize = data.length() / 2;
  518. DVector<uint8_t> pixels;
  519. pixels.resize(datasize);
  520. DVector<uint8_t>::Write wb = pixels.write();
  521. const CharType *cptr = data.c_str();
  522. int idx = 0;
  523. uint8_t byte;
  524. while (idx < datasize * 2) {
  525. CharType c = *(cptr++);
  526. ERR_FAIL_COND_V(c == '<', ERR_FILE_CORRUPT);
  527. if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
  528. if (idx & 1) {
  529. byte |= HEX2CHR(c);
  530. wb[idx >> 1] = byte;
  531. } else {
  532. byte = HEX2CHR(c) << 4;
  533. }
  534. idx++;
  535. }
  536. }
  537. wb = DVector<uint8_t>::Write();
  538. return Image(w, h, mipmaps, imgformat, pixels);
  539. }
  540. if (str.find(",") != -1) { //vector2 or vector3
  541. // Since the data could be stored as Vector2(0, 0)
  542. // We need to first remove any string from the data.
  543. // To do that, we split the data using '(' as delimiter
  544. // and keep the last element only.
  545. // Then using the "split_floats" function should work like a charm
  546. Vector<String> sarr = str.split("(", true);
  547. Vector<float> farr = sarr[sarr.size() - 1].split_floats(",", true);
  548. if (farr.size() == 2) {
  549. return Vector2(farr[0], farr[1]);
  550. }
  551. if (farr.size() == 3) {
  552. return Vector3(farr[0], farr[1], farr[2]);
  553. }
  554. ERR_FAIL_V(Variant());
  555. }
  556. return Variant();
  557. }
  558. void Globals::set_registering_order(bool p_enable) {
  559. registering_order = p_enable;
  560. }
  561. Error Globals::_load_settings_binary(const String p_path) {
  562. Error err;
  563. FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
  564. if (err != OK) {
  565. return err;
  566. }
  567. uint8_t hdr[4];
  568. f->get_buffer(hdr, 4);
  569. if (hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G') {
  570. memdelete(f);
  571. ERR_EXPLAIN("Corrupted header in binary engine.cfb (not ECFG)");
  572. ERR_FAIL_V(ERR_FILE_CORRUPT;)
  573. }
  574. set_registering_order(false);
  575. uint32_t count = f->get_32();
  576. for (int i = 0; i < count; i++) {
  577. uint32_t slen = f->get_32();
  578. CharString cs;
  579. cs.resize(slen + 1);
  580. cs[slen] = 0;
  581. f->get_buffer((uint8_t *)cs.ptr(), slen);
  582. String key;
  583. key.parse_utf8(cs.ptr());
  584. uint32_t vlen = f->get_32();
  585. Vector<uint8_t> d;
  586. d.resize(vlen);
  587. f->get_buffer(d.ptr(), vlen);
  588. Variant value;
  589. Error err = decode_variant(value, d.ptr(), d.size());
  590. ERR_EXPLAIN("Error decoding property: " + key);
  591. ERR_CONTINUE(err != OK);
  592. set(key, value);
  593. set_persisting(key, true);
  594. }
  595. set_registering_order(true);
  596. return OK;
  597. }
  598. Error Globals::_load_settings(const String p_path) {
  599. Error err;
  600. FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
  601. if (err != OK) {
  602. return err;
  603. }
  604. String line;
  605. String section;
  606. String subpath;
  607. set_registering_order(false);
  608. int line_count = 0;
  609. while (!f->eof_reached()) {
  610. String line = f->get_line().strip_edges();
  611. line_count++;
  612. if (line == "")
  613. continue;
  614. // find comments
  615. {
  616. int pos = 0;
  617. while (true) {
  618. int ret = line.find(";", pos);
  619. if (ret == -1)
  620. break;
  621. int qc = 0;
  622. for (int i = 0; i < ret; i++) {
  623. if (line[i] == '"')
  624. qc++;
  625. }
  626. if (!(qc & 1)) {
  627. //not inside string, real comment
  628. line = line.substr(0, ret);
  629. break;
  630. }
  631. pos = ret + 1;
  632. }
  633. }
  634. if (line.begins_with("[")) {
  635. int end = line.find_last("]");
  636. ERR_CONTINUE(end != line.length() - 1);
  637. String section = line.substr(1, line.length() - 2);
  638. if (section == "global" || section == "")
  639. subpath = "";
  640. else
  641. subpath = section + "/";
  642. } else if (line.find("=") != -1) {
  643. int eqpos = line.find("=");
  644. String var = line.substr(0, eqpos).strip_edges();
  645. String value = line.substr(eqpos + 1, line.length()).strip_edges();
  646. Variant val = _decode_variant(value);
  647. set(subpath + var, val);
  648. set_persisting(subpath + var, true);
  649. //props[subpath+var]=VariantContainer(val,last_order++,true);
  650. } else {
  651. if (line.length() > 0) {
  652. ERR_PRINT(String("Syntax error on line " + itos(line_count) + " of file " + p_path).ascii().get_data());
  653. };
  654. };
  655. }
  656. memdelete(f);
  657. set_registering_order(true);
  658. return OK;
  659. }
  660. static String _encode_variant(const Variant &p_variant) {
  661. switch (p_variant.get_type()) {
  662. case Variant::BOOL: {
  663. bool val = p_variant;
  664. return (val ? "true" : "false");
  665. } break;
  666. case Variant::INT: {
  667. int val = p_variant;
  668. return itos(val);
  669. } break;
  670. case Variant::REAL: {
  671. float val = p_variant;
  672. return rtos(val) + (val == int(val) ? ".0" : "");
  673. } break;
  674. case Variant::VECTOR2: {
  675. Vector2 val = p_variant;
  676. return String("Vector2(") + rtos(val.x) + String(", ") + rtos(val.y) + String(")");
  677. } break;
  678. case Variant::VECTOR3: {
  679. Vector3 val = p_variant;
  680. return String("Vector3(") + rtos(val.x) + String(", ") + rtos(val.y) + String(", ") + rtos(val.z) + String(")");
  681. } break;
  682. case Variant::STRING: {
  683. String val = p_variant;
  684. return "\"" + val.xml_escape() + "\"";
  685. } break;
  686. case Variant::COLOR: {
  687. Color val = p_variant;
  688. return "#" + val.to_html();
  689. } break;
  690. case Variant::STRING_ARRAY:
  691. case Variant::INT_ARRAY:
  692. case Variant::REAL_ARRAY:
  693. case Variant::ARRAY: {
  694. Array arr = p_variant;
  695. String str = "[";
  696. for (int i = 0; i < arr.size(); i++) {
  697. if (i > 0)
  698. str += ", ";
  699. str += _encode_variant(arr[i]);
  700. }
  701. str += "]";
  702. return str;
  703. } break;
  704. case Variant::DICTIONARY: {
  705. Dictionary d = p_variant;
  706. String str = "{";
  707. List<Variant> keys;
  708. d.get_key_list(&keys);
  709. for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
  710. if (E != keys.front())
  711. str += ", ";
  712. str += _encode_variant(E->get());
  713. str += ":";
  714. str += _encode_variant(d[E->get()]);
  715. }
  716. str += "}";
  717. return str;
  718. } break;
  719. case Variant::IMAGE: {
  720. String str = "img(";
  721. Image img = p_variant;
  722. if (!img.empty()) {
  723. String format;
  724. switch (img.get_format()) {
  725. case Image::FORMAT_GRAYSCALE: format = "grayscale"; break;
  726. case Image::FORMAT_INTENSITY: format = "intensity"; break;
  727. case Image::FORMAT_GRAYSCALE_ALPHA: format = "grayscale_alpha"; break;
  728. case Image::FORMAT_RGB: format = "rgb"; break;
  729. case Image::FORMAT_RGBA: format = "rgba"; break;
  730. case Image::FORMAT_INDEXED: format = "indexed"; break;
  731. case Image::FORMAT_INDEXED_ALPHA: format = "indexed_alpha"; break;
  732. case Image::FORMAT_BC1: format = "bc1"; break;
  733. case Image::FORMAT_BC2: format = "bc2"; break;
  734. case Image::FORMAT_BC3: format = "bc3"; break;
  735. case Image::FORMAT_BC4: format = "bc4"; break;
  736. case Image::FORMAT_BC5: format = "bc5"; break;
  737. case Image::FORMAT_CUSTOM: format = "custom custom_size=" + itos(img.get_data().size()) + ""; break;
  738. default: {
  739. }
  740. }
  741. str += format + ", ";
  742. str += itos(img.get_mipmaps()) + ", ";
  743. str += itos(img.get_width()) + ", ";
  744. str += itos(img.get_height()) + ", ";
  745. DVector<uint8_t> data = img.get_data();
  746. int ds = data.size();
  747. DVector<uint8_t>::Read r = data.read();
  748. for (int i = 0; i < ds; i++) {
  749. uint8_t byte = r[i];
  750. const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  751. char bstr[3] = { hex[byte >> 4], hex[byte & 0xF], 0 };
  752. str += bstr;
  753. }
  754. }
  755. str += ")";
  756. return str;
  757. } break;
  758. case Variant::INPUT_EVENT: {
  759. InputEvent ev = p_variant;
  760. switch (ev.type) {
  761. case InputEvent::KEY: {
  762. String mods;
  763. if (ev.key.mod.control)
  764. mods += "C";
  765. if (ev.key.mod.shift)
  766. mods += "S";
  767. if (ev.key.mod.alt)
  768. mods += "A";
  769. if (ev.key.mod.meta)
  770. mods += "M";
  771. if (mods != "")
  772. mods = ", " + mods;
  773. return "key(" + keycode_get_string(ev.key.scancode) + mods + ")";
  774. } break;
  775. case InputEvent::MOUSE_BUTTON: {
  776. return "mbutton(" + itos(ev.device) + ", " + itos(ev.mouse_button.button_index) + ")";
  777. } break;
  778. case InputEvent::JOYSTICK_BUTTON: {
  779. return "jbutton(" + itos(ev.device) + ", " + itos(ev.joy_button.button_index) + ")";
  780. } break;
  781. case InputEvent::JOYSTICK_MOTION: {
  782. return "jaxis(" + itos(ev.device) + ", " + itos(ev.joy_motion.axis * 2 + (ev.joy_motion.axis_value < 0 ? 0 : 1)) + ")";
  783. } break;
  784. default: {
  785. return "nil";
  786. } break;
  787. }
  788. } break;
  789. default: {
  790. }
  791. }
  792. return "nil"; //don't know wha to do with this
  793. }
  794. int Globals::get_order(const String &p_name) const {
  795. ERR_FAIL_COND_V(!props.has(p_name), -1);
  796. return props[p_name].order;
  797. }
  798. void Globals::set_order(const String &p_name, int p_order) {
  799. ERR_FAIL_COND(!props.has(p_name));
  800. props[p_name].order = p_order;
  801. }
  802. void Globals::clear(const String &p_name) {
  803. ERR_FAIL_COND(!props.has(p_name));
  804. props.erase(p_name);
  805. }
  806. Error Globals::save() {
  807. return save_custom(get_resource_path() + "/engine.cfg");
  808. }
  809. Error Globals::_save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom) {
  810. Error err;
  811. FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
  812. if (err != OK) {
  813. ERR_EXPLAIN("Coudln't save engine.cfb at " + p_file);
  814. ERR_FAIL_COND_V(err, err)
  815. }
  816. uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
  817. file->store_buffer(hdr, 4);
  818. int count = 0;
  819. for (Map<String, List<String> >::Element *E = props.front(); E; E = E->next()) {
  820. for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
  821. count++;
  822. }
  823. }
  824. file->store_32(count); //store how many properties are saved
  825. for (Map<String, List<String> >::Element *E = props.front(); E; E = E->next()) {
  826. for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
  827. String key = F->get();
  828. if (E->key() != "")
  829. key = E->key() + "/" + key;
  830. Variant value;
  831. if (p_custom.has(key))
  832. value = p_custom[key];
  833. else
  834. value = get(key);
  835. file->store_32(key.length());
  836. file->store_string(key);
  837. int len;
  838. Error err = encode_variant(value, NULL, len);
  839. if (err != OK)
  840. memdelete(file);
  841. ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA);
  842. Vector<uint8_t> buff;
  843. buff.resize(len);
  844. err = encode_variant(value, &buff[0], len);
  845. if (err != OK)
  846. memdelete(file);
  847. ERR_FAIL_COND_V(err != OK, ERR_INVALID_DATA);
  848. file->store_32(len);
  849. file->store_buffer(buff.ptr(), buff.size());
  850. }
  851. }
  852. file->close();
  853. memdelete(file);
  854. return OK;
  855. }
  856. Error Globals::_save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom) {
  857. Error err;
  858. FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
  859. if (err) {
  860. ERR_EXPLAIN("Coudln't save engine.cfg - " + p_file);
  861. ERR_FAIL_COND_V(err, err)
  862. }
  863. for (Map<String, List<String> >::Element *E = props.front(); E; E = E->next()) {
  864. if (E != props.front())
  865. file->store_string("\n");
  866. if (E->key() != "")
  867. file->store_string("[" + E->key() + "]\n\n");
  868. for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
  869. String key = F->get();
  870. if (E->key() != "")
  871. key = E->key() + "/" + key;
  872. Variant value;
  873. if (p_custom.has(key))
  874. value = p_custom[key];
  875. else
  876. value = get(key);
  877. file->store_string(F->get() + "=" + _encode_variant(value) + "\n");
  878. }
  879. }
  880. file->close();
  881. memdelete(file);
  882. return OK;
  883. }
  884. Error Globals::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
  885. return save_custom(p_file);
  886. };
  887. Error Globals::save_custom(const String &p_path, const CustomMap &p_custom, const Set<String> &p_ignore_masks) {
  888. ERR_FAIL_COND_V(p_path == "", ERR_INVALID_PARAMETER);
  889. Set<_VCSort> vclist;
  890. for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) {
  891. const VariantContainer *v = &G->get();
  892. if (v->hide_from_editor)
  893. continue;
  894. if (p_custom.has(G->key()))
  895. continue;
  896. bool discard = false;
  897. for (const Set<String>::Element *E = p_ignore_masks.front(); E; E = E->next()) {
  898. if (String(G->key()).match(E->get())) {
  899. discard = true;
  900. break;
  901. }
  902. }
  903. if (discard)
  904. continue;
  905. _VCSort vc;
  906. vc.name = G->key(); //*k;
  907. vc.order = v->order;
  908. vc.type = v->variant.get_type();
  909. vc.flags = PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
  910. if (!v->persist)
  911. continue;
  912. vclist.insert(vc);
  913. }
  914. for (const Map<String, Variant>::Element *E = p_custom.front(); E; E = E->next()) {
  915. _VCSort vc;
  916. vc.name = E->key();
  917. vc.order = 0xFFFFFFF;
  918. vc.type = E->get().get_type();
  919. vc.flags = PROPERTY_USAGE_STORAGE;
  920. vclist.insert(vc);
  921. }
  922. Map<String, List<String> > props;
  923. for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) {
  924. String category = E->get().name;
  925. String name = E->get().name;
  926. int div = category.find("/");
  927. if (div < 0)
  928. category = "";
  929. else {
  930. category = category.substr(0, div);
  931. name = name.substr(div + 1, name.size());
  932. }
  933. props[category].push_back(name);
  934. }
  935. if (p_path.ends_with(".cfg"))
  936. return _save_settings_text(p_path, props, p_custom);
  937. else if (p_path.ends_with(".cfb"))
  938. return _save_settings_binary(p_path, props, p_custom);
  939. else {
  940. ERR_EXPLAIN("Unknown config file format: " + p_path);
  941. ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
  942. }
  943. return OK;
  944. #if 0
  945. Error err = file->open(dst_file,FileAccess::WRITE);
  946. if (err) {
  947. memdelete(file);
  948. ERR_EXPLAIN("Coudln't save engine.cfg");
  949. ERR_FAIL_COND_V(err,err)
  950. }
  951. for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
  952. if (E!=props.front())
  953. file->store_string("\n");
  954. if (E->key()!="")
  955. file->store_string("["+E->key()+"]\n\n");
  956. for(List<String>::Element *F=E->get().front();F;F=F->next()) {
  957. String key = F->get();
  958. if (E->key()!="")
  959. key=E->key()+"/"+key;
  960. Variant value;
  961. if (p_custom.has(key))
  962. value=p_custom[key];
  963. else
  964. value = get(key);
  965. file->store_string(F->get()+"="+_encode_variant(value)+"\n");
  966. }
  967. }
  968. file->close();
  969. memdelete(file);
  970. return OK;
  971. #endif
  972. }
  973. Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) {
  974. if (Globals::get_singleton()->has(p_var))
  975. return Globals::get_singleton()->get(p_var);
  976. Globals::get_singleton()->set(p_var, p_default);
  977. return p_default;
  978. }
  979. void Globals::add_singleton(const Singleton &p_singleton) {
  980. singletons.push_back(p_singleton);
  981. }
  982. Object *Globals::get_singleton_object(const String &p_name) const {
  983. for (const List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
  984. if (E->get().name == p_name) {
  985. return E->get().ptr;
  986. };
  987. };
  988. return NULL;
  989. };
  990. bool Globals::has_singleton(const String &p_name) const {
  991. return get_singleton_object(p_name) != NULL;
  992. };
  993. void Globals::get_singletons(List<Singleton> *p_singletons) {
  994. for (List<Singleton>::Element *E = singletons.front(); E; E = E->next())
  995. p_singletons->push_back(E->get());
  996. }
  997. Vector<String> Globals::get_optimizer_presets() const {
  998. List<PropertyInfo> pi;
  999. Globals::get_singleton()->get_property_list(&pi);
  1000. Vector<String> names;
  1001. for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
  1002. if (!E->get().name.begins_with("optimizer_presets/"))
  1003. continue;
  1004. names.push_back(E->get().name.get_slicec('/', 1));
  1005. }
  1006. names.sort();
  1007. return names;
  1008. }
  1009. void Globals::_add_property_info_bind(const Dictionary &p_info) {
  1010. ERR_FAIL_COND(!p_info.has("name"));
  1011. ERR_FAIL_COND(!p_info.has("type"));
  1012. PropertyInfo pinfo;
  1013. pinfo.name = p_info["name"];
  1014. ERR_FAIL_COND(!props.has(pinfo.name));
  1015. pinfo.type = Variant::Type(p_info["type"].operator int());
  1016. ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
  1017. if (p_info.has("hint"))
  1018. pinfo.hint = PropertyHint(p_info["hint"].operator int());
  1019. if (p_info.has("hint_string"))
  1020. pinfo.hint_string = p_info["hint_string"];
  1021. set_custom_property_info(pinfo.name, pinfo);
  1022. }
  1023. void Globals::set_custom_property_info(const String &p_prop, const PropertyInfo &p_info) {
  1024. ERR_FAIL_COND(!props.has(p_prop));
  1025. custom_prop_info[p_prop] = p_info;
  1026. }
  1027. void Globals::set_disable_platform_override(bool p_disable) {
  1028. disable_platform_override = p_disable;
  1029. }
  1030. bool Globals::is_using_datapack() const {
  1031. return using_datapack;
  1032. }
  1033. void Globals::_bind_methods() {
  1034. ObjectTypeDB::bind_method(_MD("has", "name"), &Globals::has);
  1035. ObjectTypeDB::bind_method(_MD("set_order", "name", "pos"), &Globals::set_order);
  1036. ObjectTypeDB::bind_method(_MD("get_order", "name"), &Globals::get_order);
  1037. ObjectTypeDB::bind_method(_MD("set_persisting", "name", "enable"), &Globals::set_persisting);
  1038. ObjectTypeDB::bind_method(_MD("is_persisting", "name"), &Globals::is_persisting);
  1039. ObjectTypeDB::bind_method(_MD("add_property_info", "hint"), &Globals::_add_property_info_bind);
  1040. ObjectTypeDB::bind_method(_MD("clear", "name"), &Globals::clear);
  1041. ObjectTypeDB::bind_method(_MD("localize_path", "path"), &Globals::localize_path);
  1042. ObjectTypeDB::bind_method(_MD("globalize_path", "path"), &Globals::globalize_path);
  1043. ObjectTypeDB::bind_method(_MD("save"), &Globals::save);
  1044. ObjectTypeDB::bind_method(_MD("has_singleton", "name"), &Globals::has_singleton);
  1045. ObjectTypeDB::bind_method(_MD("get_singleton", "name"), &Globals::get_singleton_object);
  1046. ObjectTypeDB::bind_method(_MD("load_resource_pack", "pack"), &Globals::_load_resource_pack);
  1047. ObjectTypeDB::bind_method(_MD("save_custom", "file"), &Globals::_save_custom_bnd);
  1048. }
  1049. Globals::Globals() {
  1050. singleton = this;
  1051. last_order = 0;
  1052. disable_platform_override = false;
  1053. registering_order = true;
  1054. Array va;
  1055. InputEvent key;
  1056. key.type = InputEvent::KEY;
  1057. InputEvent joyb;
  1058. joyb.type = InputEvent::JOYSTICK_BUTTON;
  1059. set("application/name", "");
  1060. set("application/main_scene", "");
  1061. custom_prop_info["application/main_scene"] = PropertyInfo(Variant::STRING, "application/main_scene", PROPERTY_HINT_FILE, "tscn,scn,xscn,xml,res");
  1062. set("application/disable_stdout", false);
  1063. set("application/use_shared_user_dir", true);
  1064. key.key.scancode = KEY_RETURN;
  1065. va.push_back(key);
  1066. key.key.scancode = KEY_ENTER;
  1067. va.push_back(key);
  1068. key.key.scancode = KEY_SPACE;
  1069. va.push_back(key);
  1070. joyb.joy_button.button_index = JOY_BUTTON_0;
  1071. va.push_back(joyb);
  1072. set("input/ui_accept", va);
  1073. input_presets.push_back("input/ui_accept");
  1074. va = Array();
  1075. key.key.scancode = KEY_SPACE;
  1076. va.push_back(key);
  1077. joyb.joy_button.button_index = JOY_BUTTON_3;
  1078. va.push_back(joyb);
  1079. set("input/ui_select", va);
  1080. input_presets.push_back("input/ui_select");
  1081. va = Array();
  1082. key.key.scancode = KEY_ESCAPE;
  1083. va.push_back(key);
  1084. joyb.joy_button.button_index = JOY_BUTTON_1;
  1085. va.push_back(joyb);
  1086. set("input/ui_cancel", va);
  1087. input_presets.push_back("input/ui_cancel");
  1088. va = Array();
  1089. key.key.scancode = KEY_TAB;
  1090. va.push_back(key);
  1091. set("input/ui_focus_next", va);
  1092. input_presets.push_back("input/ui_focus_next");
  1093. va = Array();
  1094. key.key.scancode = KEY_TAB;
  1095. key.key.mod.shift = true;
  1096. va.push_back(key);
  1097. set("input/ui_focus_prev", va);
  1098. input_presets.push_back("input/ui_focus_prev");
  1099. key.key.mod.shift = false;
  1100. va = Array();
  1101. key.key.scancode = KEY_LEFT;
  1102. va.push_back(key);
  1103. joyb.joy_button.button_index = JOY_DPAD_LEFT;
  1104. va.push_back(joyb);
  1105. set("input/ui_left", va);
  1106. input_presets.push_back("input/ui_left");
  1107. va = Array();
  1108. key.key.scancode = KEY_RIGHT;
  1109. va.push_back(key);
  1110. joyb.joy_button.button_index = JOY_DPAD_RIGHT;
  1111. va.push_back(joyb);
  1112. set("input/ui_right", va);
  1113. input_presets.push_back("input/ui_right");
  1114. va = Array();
  1115. key.key.scancode = KEY_UP;
  1116. va.push_back(key);
  1117. joyb.joy_button.button_index = JOY_DPAD_UP;
  1118. va.push_back(joyb);
  1119. set("input/ui_up", va);
  1120. input_presets.push_back("input/ui_up");
  1121. va = Array();
  1122. key.key.scancode = KEY_DOWN;
  1123. va.push_back(key);
  1124. joyb.joy_button.button_index = JOY_DPAD_DOWN;
  1125. va.push_back(joyb);
  1126. set("input/ui_down", va);
  1127. input_presets.push_back("input/ui_down");
  1128. va = Array();
  1129. key.key.scancode = KEY_PAGEUP;
  1130. va.push_back(key);
  1131. set("input/ui_page_up", va);
  1132. input_presets.push_back("input/ui_page_up");
  1133. va = Array();
  1134. key.key.scancode = KEY_PAGEDOWN;
  1135. va.push_back(key);
  1136. set("input/ui_page_down", va);
  1137. input_presets.push_back("input/ui_page_down");
  1138. // set("display/orientation", "landscape");
  1139. custom_prop_info["display/orientation"] = PropertyInfo(Variant::STRING, "display/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
  1140. custom_prop_info["render/mipmap_policy"] = PropertyInfo(Variant::INT, "render/mipmap_policy", PROPERTY_HINT_ENUM, "Allow,Allow For Po2,Disallow");
  1141. custom_prop_info["render/thread_model"] = PropertyInfo(Variant::INT, "render/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
  1142. custom_prop_info["physics_2d/thread_model"] = PropertyInfo(Variant::INT, "physics_2d/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
  1143. set("debug/profiler_max_functions", 16384);
  1144. using_datapack = false;
  1145. }
  1146. Globals::~Globals() {
  1147. singleton = NULL;
  1148. }