project_settings.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  1. /*************************************************************************/
  2. /* project_settings.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "project_settings.h"
  31. #include "editor_node.h"
  32. #include "global_config.h"
  33. #include "global_constants.h"
  34. #include "os/keyboard.h"
  35. #include "scene/gui/margin_container.h"
  36. #include "scene/gui/tab_container.h"
  37. #include "translation.h"
  38. ProjectSettings *ProjectSettings::singleton = NULL;
  39. static const char *_button_names[JOY_BUTTON_MAX] = {
  40. "PS Cross, XBox A, Nintendo B",
  41. "PS Circle, XBox B, Nintendo A",
  42. "PS Square, XBox X, Nintendo Y",
  43. "PS Triangle, XBox Y, Nintendo X",
  44. "L, L1",
  45. "R, R1",
  46. "L2",
  47. "R2",
  48. "L3",
  49. "R3",
  50. "Select, Nintendo -",
  51. "Start, Nintendo +",
  52. "D-Pad Up",
  53. "D-Pad Down",
  54. "D-Pad Left",
  55. "D-Pad Right"
  56. };
  57. static const char *_axis_names[JOY_AXIS_MAX * 2] = {
  58. " (Left Stick Left)",
  59. " (Left Stick Right)",
  60. " (Left Stick Up)",
  61. " (Left Stick Down)",
  62. " (Right Stick Left)",
  63. " (Right Stick Right)",
  64. " (Right Stick Up)",
  65. " (Right Stick Down)",
  66. "", "", "", "",
  67. "", " (L2)",
  68. "", " (R2)"
  69. };
  70. void ProjectSettings::_notification(int p_what) {
  71. switch (p_what) {
  72. case NOTIFICATION_ENTER_TREE: {
  73. globals_editor->edit(GlobalConfig::get_singleton());
  74. search_button->set_icon(get_icon("Search", "EditorIcons"));
  75. clear_button->set_icon(get_icon("Close", "EditorIcons"));
  76. translation_list->connect("button_pressed", this, "_translation_delete");
  77. _update_actions();
  78. popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), InputEvent::KEY); //"Key " - because the word 'key' has already been used as a key animation
  79. popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), InputEvent::JOYPAD_BUTTON);
  80. popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), InputEvent::JOYPAD_MOTION);
  81. popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), InputEvent::MOUSE_BUTTON);
  82. List<String> tfn;
  83. ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn);
  84. for (List<String>::Element *E = tfn.front(); E; E = E->next()) {
  85. translation_file_open->add_filter("*." + E->get());
  86. }
  87. List<String> rfn;
  88. ResourceLoader::get_recognized_extensions_for_type("Resource", &rfn);
  89. for (List<String>::Element *E = rfn.front(); E; E = E->next()) {
  90. translation_res_file_open->add_filter("*." + E->get());
  91. translation_res_option_file_open->add_filter("*." + E->get());
  92. }
  93. } break;
  94. case NOTIFICATION_POPUP_HIDE: {
  95. EditorSettings::get_singleton()->set("interface/dialogs/project_settings_bounds", get_rect());
  96. } break;
  97. }
  98. }
  99. void ProjectSettings::_action_selected() {
  100. TreeItem *ti = input_editor->get_selected();
  101. if (!ti || !ti->is_editable(0))
  102. return;
  103. add_at = "input/" + ti->get_text(0);
  104. }
  105. void ProjectSettings::_action_edited() {
  106. TreeItem *ti = input_editor->get_selected();
  107. if (!ti)
  108. return;
  109. String new_name = ti->get_text(0);
  110. String old_name = add_at.substr(add_at.find("/") + 1, add_at.length());
  111. if (new_name == old_name)
  112. return;
  113. if (new_name.find("/") != -1 || new_name.find(":") != -1 || new_name == "") {
  114. ti->set_text(0, old_name);
  115. add_at = "input/" + old_name;
  116. message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
  117. message->popup_centered(Size2(300, 100));
  118. return;
  119. }
  120. String action_prop = "input/" + new_name;
  121. if (GlobalConfig::get_singleton()->has(action_prop)) {
  122. ti->set_text(0, old_name);
  123. add_at = "input/" + old_name;
  124. message->set_text(vformat(TTR("Action '%s' already exists!"), new_name));
  125. message->popup_centered(Size2(300, 100));
  126. return;
  127. }
  128. int order = GlobalConfig::get_singleton()->get_order(add_at);
  129. Array va = GlobalConfig::get_singleton()->get(add_at);
  130. setting = true;
  131. undo_redo->create_action(TTR("Rename Input Action Event"));
  132. undo_redo->add_do_method(GlobalConfig::get_singleton(), "clear", add_at);
  133. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set", action_prop, va);
  134. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", action_prop, order);
  135. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "clear", action_prop);
  136. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set", add_at, va);
  137. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", add_at, order);
  138. undo_redo->add_do_method(this, "_update_actions");
  139. undo_redo->add_undo_method(this, "_update_actions");
  140. undo_redo->add_do_method(this, "_settings_changed");
  141. undo_redo->add_undo_method(this, "_settings_changed");
  142. undo_redo->commit_action();
  143. setting = false;
  144. add_at = action_prop;
  145. }
  146. void ProjectSettings::_device_input_add() {
  147. InputEvent ie;
  148. String name = add_at;
  149. Variant old_val = GlobalConfig::get_singleton()->get(name);
  150. Array arr = old_val;
  151. ie.device = device_id->get_value();
  152. ie.type = add_type;
  153. switch (add_type) {
  154. case InputEvent::MOUSE_BUTTON: {
  155. ie.mouse_button.button_index = device_index->get_selected() + 1;
  156. for (int i = 0; i < arr.size(); i++) {
  157. InputEvent aie = arr[i];
  158. if (aie.device == ie.device && aie.type == InputEvent::MOUSE_BUTTON && aie.mouse_button.button_index == ie.mouse_button.button_index) {
  159. return;
  160. }
  161. }
  162. } break;
  163. case InputEvent::JOYPAD_MOTION: {
  164. ie.joy_motion.axis = device_index->get_selected() >> 1;
  165. ie.joy_motion.axis_value = device_index->get_selected() & 1 ? 1 : -1;
  166. for (int i = 0; i < arr.size(); i++) {
  167. InputEvent aie = arr[i];
  168. if (aie.device == ie.device && aie.type == InputEvent::JOYPAD_MOTION && aie.joy_motion.axis == ie.joy_motion.axis && aie.joy_motion.axis_value == ie.joy_motion.axis_value) {
  169. return;
  170. }
  171. }
  172. } break;
  173. case InputEvent::JOYPAD_BUTTON: {
  174. ie.joy_button.button_index = device_index->get_selected();
  175. for (int i = 0; i < arr.size(); i++) {
  176. InputEvent aie = arr[i];
  177. if (aie.device == ie.device && aie.type == InputEvent::JOYPAD_BUTTON && aie.joy_button.button_index == ie.joy_button.button_index) {
  178. return;
  179. }
  180. }
  181. } break;
  182. default: {}
  183. }
  184. arr.push_back(ie);
  185. undo_redo->create_action(TTR("Add Input Action Event"));
  186. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set", name, arr);
  187. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set", name, old_val);
  188. undo_redo->add_do_method(this, "_update_actions");
  189. undo_redo->add_undo_method(this, "_update_actions");
  190. undo_redo->add_do_method(this, "_settings_changed");
  191. undo_redo->add_undo_method(this, "_settings_changed");
  192. undo_redo->commit_action();
  193. _show_last_added(ie, name);
  194. }
  195. void ProjectSettings::_press_a_key_confirm() {
  196. if (last_wait_for_key.type != InputEvent::KEY)
  197. return;
  198. InputEvent ie;
  199. ie.type = InputEvent::KEY;
  200. ie.key.scancode = last_wait_for_key.key.scancode;
  201. ie.key.mod = last_wait_for_key.key.mod;
  202. String name = add_at;
  203. Variant old_val = GlobalConfig::get_singleton()->get(name);
  204. Array arr = old_val;
  205. for (int i = 0; i < arr.size(); i++) {
  206. InputEvent aie = arr[i];
  207. if (aie.type == InputEvent::KEY && aie.key.scancode == ie.key.scancode && aie.key.mod == ie.key.mod) {
  208. return;
  209. }
  210. }
  211. arr.push_back(ie);
  212. undo_redo->create_action(TTR("Add Input Action Event"));
  213. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set", name, arr);
  214. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set", name, old_val);
  215. undo_redo->add_do_method(this, "_update_actions");
  216. undo_redo->add_undo_method(this, "_update_actions");
  217. undo_redo->add_do_method(this, "_settings_changed");
  218. undo_redo->add_undo_method(this, "_settings_changed");
  219. undo_redo->commit_action();
  220. _show_last_added(ie, name);
  221. }
  222. void ProjectSettings::_show_last_added(const InputEvent &p_event, const String &p_name) {
  223. TreeItem *r = input_editor->get_root();
  224. String name = p_name;
  225. name.erase(0, 6);
  226. if (!r)
  227. return;
  228. r = r->get_children();
  229. if (!r)
  230. return;
  231. bool found = false;
  232. while (r) {
  233. if (r->get_text(0) != name) {
  234. r = r->get_next();
  235. continue;
  236. }
  237. TreeItem *child = r->get_children();
  238. while (child) {
  239. Variant input = child->get_meta("__input");
  240. if (p_event == input) {
  241. child->select(0);
  242. found = true;
  243. break;
  244. }
  245. child = child->get_next();
  246. }
  247. if (found) break;
  248. r = r->get_next();
  249. }
  250. if (found) input_editor->ensure_cursor_is_visible();
  251. }
  252. void ProjectSettings::_wait_for_key(const InputEvent &p_event) {
  253. if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode != 0) {
  254. last_wait_for_key = p_event;
  255. String str = keycode_get_string(p_event.key.scancode).capitalize();
  256. if (p_event.key.mod.meta)
  257. str = TTR("Meta+") + str;
  258. if (p_event.key.mod.shift)
  259. str = TTR("Shift+") + str;
  260. if (p_event.key.mod.alt)
  261. str = TTR("Alt+") + str;
  262. if (p_event.key.mod.control)
  263. str = TTR("Control+") + str;
  264. press_a_key_label->set_text(str);
  265. press_a_key->accept_event();
  266. }
  267. }
  268. void ProjectSettings::_add_item(int p_item) {
  269. add_type = InputEvent::Type(p_item);
  270. switch (add_type) {
  271. case InputEvent::KEY: {
  272. press_a_key_label->set_text(TTR("Press a Key.."));
  273. last_wait_for_key = InputEvent();
  274. press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
  275. press_a_key->grab_focus();
  276. } break;
  277. case InputEvent::MOUSE_BUTTON: {
  278. device_id->set_value(0);
  279. device_index_label->set_text(TTR("Mouse Button Index:"));
  280. device_index->clear();
  281. device_index->add_item(TTR("Left Button"));
  282. device_index->add_item(TTR("Right Button"));
  283. device_index->add_item(TTR("Middle Button"));
  284. device_index->add_item(TTR("Wheel Up Button"));
  285. device_index->add_item(TTR("Wheel Down Button"));
  286. device_index->add_item(TTR("Button 6"));
  287. device_index->add_item(TTR("Button 7"));
  288. device_index->add_item(TTR("Button 8"));
  289. device_index->add_item(TTR("Button 9"));
  290. device_input->popup_centered_minsize(Size2(350, 95));
  291. } break;
  292. case InputEvent::JOYPAD_MOTION: {
  293. device_id->set_value(0);
  294. device_index_label->set_text(TTR("Joypad Axis Index:"));
  295. device_index->clear();
  296. for (int i = 0; i < JOY_AXIS_MAX * 2; i++) {
  297. String desc = _axis_names[i];
  298. device_index->add_item(TTR("Axis") + " " + itos(i / 2) + " " + (i & 1 ? "+" : "-") + desc);
  299. }
  300. device_input->popup_centered_minsize(Size2(350, 95));
  301. } break;
  302. case InputEvent::JOYPAD_BUTTON: {
  303. device_id->set_value(0);
  304. device_index_label->set_text(TTR("Joypad Button Index:"));
  305. device_index->clear();
  306. for (int i = 0; i < JOY_BUTTON_MAX; i++) {
  307. device_index->add_item(itos(i) + ": " + String(_button_names[i]));
  308. }
  309. device_input->popup_centered_minsize(Size2(350, 95));
  310. } break;
  311. default: {}
  312. }
  313. }
  314. void ProjectSettings::_action_button_pressed(Object *p_obj, int p_column, int p_id) {
  315. TreeItem *ti = p_obj->cast_to<TreeItem>();
  316. ERR_FAIL_COND(!ti);
  317. if (p_id == 1) {
  318. Point2 ofs = input_editor->get_global_position();
  319. Rect2 ir = input_editor->get_item_rect(ti);
  320. ir.pos.y -= input_editor->get_scroll().y;
  321. ofs += ir.pos + ir.size;
  322. ofs.x -= 100;
  323. popup_add->set_position(ofs);
  324. popup_add->popup();
  325. add_at = "input/" + ti->get_text(0);
  326. } else if (p_id == 2) {
  327. //remove
  328. if (ti->get_parent() == input_editor->get_root()) {
  329. //remove main thing
  330. String name = "input/" + ti->get_text(0);
  331. Variant old_val = GlobalConfig::get_singleton()->get(name);
  332. int order = GlobalConfig::get_singleton()->get_order(name);
  333. undo_redo->create_action(TTR("Add Input Action"));
  334. undo_redo->add_do_method(GlobalConfig::get_singleton(), "clear", name);
  335. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set", name, old_val);
  336. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", name, order);
  337. undo_redo->add_do_method(this, "_update_actions");
  338. undo_redo->add_undo_method(this, "_update_actions");
  339. undo_redo->add_do_method(this, "_settings_changed");
  340. undo_redo->add_undo_method(this, "_settings_changed");
  341. undo_redo->commit_action();
  342. } else {
  343. //remove action
  344. String name = "input/" + ti->get_parent()->get_text(0);
  345. Variant old_val = GlobalConfig::get_singleton()->get(name);
  346. int idx = ti->get_metadata(0);
  347. Array va = old_val;
  348. ERR_FAIL_INDEX(idx, va.size());
  349. for (int i = idx; i < va.size() - 1; i++) {
  350. va[i] = va[i + 1];
  351. }
  352. va.resize(va.size() - 1);
  353. undo_redo->create_action(TTR("Erase Input Action Event"));
  354. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set", name, va);
  355. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set", name, old_val);
  356. undo_redo->add_do_method(this, "_update_actions");
  357. undo_redo->add_undo_method(this, "_update_actions");
  358. undo_redo->add_do_method(this, "_settings_changed");
  359. undo_redo->add_undo_method(this, "_settings_changed");
  360. undo_redo->commit_action();
  361. }
  362. }
  363. }
  364. void ProjectSettings::_update_actions() {
  365. if (setting)
  366. return;
  367. input_editor->clear();
  368. TreeItem *root = input_editor->create_item();
  369. input_editor->set_hide_root(true);
  370. List<PropertyInfo> props;
  371. GlobalConfig::get_singleton()->get_property_list(&props);
  372. for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
  373. const PropertyInfo &pi = E->get();
  374. if (!pi.name.begins_with("input/"))
  375. continue;
  376. String name = pi.name.get_slice("/", 1);
  377. if (name == "")
  378. continue;
  379. TreeItem *item = input_editor->create_item(root);
  380. //item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
  381. item->set_text(0, name);
  382. item->add_button(0, get_icon("Add", "EditorIcons"), 1, false, TTR("Add Event"));
  383. if (!GlobalConfig::get_singleton()->get_input_presets().find(pi.name)) {
  384. item->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
  385. item->set_editable(0, true);
  386. }
  387. item->set_custom_bg_color(0, get_color("prop_subsection", "Editor"));
  388. //item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
  389. Array actions = GlobalConfig::get_singleton()->get(pi.name);
  390. for (int i = 0; i < actions.size(); i++) {
  391. if (actions[i].get_type() != Variant::INPUT_EVENT)
  392. continue;
  393. InputEvent ie = actions[i];
  394. TreeItem *action = input_editor->create_item(item);
  395. switch (ie.type) {
  396. case InputEvent::KEY: {
  397. String str = keycode_get_string(ie.key.scancode).capitalize();
  398. if (ie.key.mod.meta)
  399. str = TTR("Meta+") + str;
  400. if (ie.key.mod.shift)
  401. str = TTR("Shift+") + str;
  402. if (ie.key.mod.alt)
  403. str = TTR("Alt+") + str;
  404. if (ie.key.mod.control)
  405. str = TTR("Control+") + str;
  406. action->set_text(0, str);
  407. action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
  408. } break;
  409. case InputEvent::JOYPAD_BUTTON: {
  410. String str = TTR("Device") + " " + itos(ie.device) + ", " + TTR("Button") + " " + itos(ie.joy_button.button_index);
  411. if (ie.joy_button.button_index >= 0 && ie.joy_button.button_index < JOY_BUTTON_MAX)
  412. str += String() + " (" + _button_names[ie.joy_button.button_index] + ").";
  413. else
  414. str += ".";
  415. action->set_text(0, str);
  416. action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
  417. } break;
  418. case InputEvent::MOUSE_BUTTON: {
  419. String str = TTR("Device") + " " + itos(ie.device) + ", ";
  420. switch (ie.mouse_button.button_index) {
  421. case BUTTON_LEFT: str += TTR("Left Button."); break;
  422. case BUTTON_RIGHT: str += TTR("Right Button."); break;
  423. case BUTTON_MIDDLE: str += TTR("Middle Button."); break;
  424. case BUTTON_WHEEL_UP: str += TTR("Wheel Up."); break;
  425. case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down."); break;
  426. default: str += TTR("Button") + " " + itos(ie.mouse_button.button_index) + ".";
  427. }
  428. action->set_text(0, str);
  429. action->set_icon(0, get_icon("Mouse", "EditorIcons"));
  430. } break;
  431. case InputEvent::JOYPAD_MOTION: {
  432. int ax = ie.joy_motion.axis;
  433. int n = 2 * ax + (ie.joy_motion.axis_value < 0 ? 0 : 1);
  434. String desc = _axis_names[n];
  435. String str = TTR("Device") + " " + itos(ie.device) + ", " + TTR("Axis") + " " + itos(ax) + " " + (ie.joy_motion.axis_value < 0 ? "-" : "+") + desc + ".";
  436. action->set_text(0, str);
  437. action->set_icon(0, get_icon("JoyAxis", "EditorIcons"));
  438. } break;
  439. }
  440. action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
  441. action->set_metadata(0, i);
  442. action->set_meta("__input", ie);
  443. }
  444. }
  445. }
  446. void ProjectSettings::popup_project_settings() {
  447. // Restore valid window bounds or pop up at default size.
  448. if (EditorSettings::get_singleton()->has("interface/dialogs/project_settings_bounds")) {
  449. popup(EditorSettings::get_singleton()->get("interface/dialogs/project_settings_bounds"));
  450. } else {
  451. popup_centered_ratio();
  452. }
  453. globals_editor->update_category_list();
  454. _update_translations();
  455. autoload_settings->update_autoload();
  456. plugin_settings->update_plugins();
  457. }
  458. void ProjectSettings::_item_selected() {
  459. TreeItem *ti = globals_editor->get_property_editor()->get_scene_tree()->get_selected();
  460. if (!ti)
  461. return;
  462. if (!ti->get_parent())
  463. return;
  464. category->set_text(globals_editor->get_current_section());
  465. property->set_text(ti->get_text(0));
  466. popup_platform->set_disabled(false);
  467. }
  468. void ProjectSettings::_item_adds(String) {
  469. _item_add();
  470. }
  471. void ProjectSettings::_item_add() {
  472. Variant value;
  473. switch (type->get_selected()) {
  474. case 0: value = false; break;
  475. case 1: value = 0; break;
  476. case 2: value = 0.0; break;
  477. case 3: value = ""; break;
  478. }
  479. String catname = category->get_text().strip_edges();
  480. /*if (!catname.is_valid_identifier()) {
  481. message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
  482. message->popup_centered(Size2(300,100));
  483. return;
  484. }*/
  485. String propname = property->get_text().strip_edges();
  486. /*if (!propname.is_valid_identifier()) {
  487. message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
  488. message->popup_centered(Size2(300,100));
  489. return;
  490. }*/
  491. String name = catname != "" ? catname + "/" + propname : propname;
  492. undo_redo->create_action("Add Global Property");
  493. undo_redo->add_do_property(GlobalConfig::get_singleton(), name, value);
  494. if (GlobalConfig::get_singleton()->has(name)) {
  495. undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
  496. } else {
  497. undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, Variant());
  498. }
  499. undo_redo->add_do_method(globals_editor, "update_category_list");
  500. undo_redo->add_undo_method(globals_editor, "update_category_list");
  501. undo_redo->add_do_method(this, "_settings_changed");
  502. undo_redo->add_undo_method(this, "_settings_changed");
  503. undo_redo->commit_action();
  504. globals_editor->set_current_section(catname);
  505. _settings_changed();
  506. }
  507. void ProjectSettings::_item_del() {
  508. String catname = category->get_text().strip_edges();
  509. //ERR_FAIL_COND(!catname.is_valid_identifier());
  510. String propname = property->get_text().strip_edges();
  511. //ERR_FAIL_COND(!propname.is_valid_identifier());
  512. String name = catname != "" ? catname + "/" + propname : propname;
  513. undo_redo->create_action("Delete Global Property");
  514. undo_redo->add_do_property(GlobalConfig::get_singleton(), name, Variant());
  515. undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
  516. undo_redo->add_do_method(globals_editor, "update_category_list");
  517. undo_redo->add_undo_method(globals_editor, "update_category_list");
  518. undo_redo->add_do_method(this, "_settings_changed");
  519. undo_redo->add_undo_method(this, "_settings_changed");
  520. undo_redo->commit_action();
  521. _settings_changed();
  522. }
  523. void ProjectSettings::_action_adds(String) {
  524. _action_add();
  525. }
  526. void ProjectSettings::_action_add() {
  527. String action = action_name->get_text();
  528. if (action.find("/") != -1 || action.find(":") != -1 || action == "") {
  529. message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
  530. message->popup_centered(Size2(300, 100));
  531. return;
  532. }
  533. if (GlobalConfig::get_singleton()->has("input/" + action)) {
  534. message->set_text(vformat(TTR("Action '%s' already exists!"), action));
  535. message->popup_centered(Size2(300, 100));
  536. return;
  537. }
  538. Array va;
  539. String name = "input/" + action;
  540. undo_redo->create_action(TTR("Add Input Action Event"));
  541. undo_redo->add_do_method(GlobalConfig::get_singleton(), "set", name, va);
  542. undo_redo->add_undo_method(GlobalConfig::get_singleton(), "clear", name);
  543. undo_redo->add_do_method(this, "_update_actions");
  544. undo_redo->add_undo_method(this, "_update_actions");
  545. undo_redo->add_do_method(this, "_settings_changed");
  546. undo_redo->add_undo_method(this, "_settings_changed");
  547. undo_redo->commit_action();
  548. TreeItem *r = input_editor->get_root();
  549. if (!r)
  550. return;
  551. r = r->get_children();
  552. if (!r)
  553. return;
  554. while (r->get_next())
  555. r = r->get_next();
  556. if (!r)
  557. return;
  558. r->select(0);
  559. input_editor->ensure_cursor_is_visible();
  560. }
  561. void ProjectSettings::_item_checked(const String &p_item, bool p_check) {
  562. }
  563. void ProjectSettings::_save() {
  564. Error err = GlobalConfig::get_singleton()->save();
  565. message->set_text(err != OK ? TTR("Error saving settings.") : TTR("Settings saved OK."));
  566. message->popup_centered(Size2(300, 100));
  567. }
  568. void ProjectSettings::_settings_prop_edited(const String &p_name) {
  569. String full_item = globals_editor->get_full_item_path(p_name);
  570. _settings_changed();
  571. }
  572. void ProjectSettings::_settings_changed() {
  573. timer->start();
  574. }
  575. void ProjectSettings::queue_save() {
  576. _settings_changed();
  577. }
  578. void ProjectSettings::_copy_to_platform(int p_which) {
  579. String catname = category->get_text();
  580. if (!catname.is_valid_identifier()) {
  581. message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
  582. message->popup_centered(Size2(300, 100));
  583. return;
  584. }
  585. String propname = property->get_text();
  586. if (!propname.is_valid_identifier()) {
  587. message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
  588. message->popup_centered(Size2(300, 100));
  589. return;
  590. }
  591. String name = catname + "/" + propname;
  592. Variant value = GlobalConfig::get_singleton()->get(name);
  593. catname += "." + popup_platform->get_popup()->get_item_text(p_which);
  594. name = catname + "/" + propname;
  595. GlobalConfig::get_singleton()->set(name, value);
  596. globals_editor->get_property_editor()->update_tree();
  597. }
  598. void ProjectSettings::add_translation(const String &p_translation) {
  599. _translation_add(p_translation);
  600. }
  601. void ProjectSettings::_translation_add(const String &p_path) {
  602. PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
  603. for (int i = 0; i < translations.size(); i++) {
  604. if (translations[i] == p_path)
  605. return; //exists
  606. }
  607. translations.push_back(p_path);
  608. undo_redo->create_action(TTR("Add Translation"));
  609. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translations", translations);
  610. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translations", GlobalConfig::get_singleton()->get("locale/translations"));
  611. undo_redo->add_do_method(this, "_update_translations");
  612. undo_redo->add_undo_method(this, "_update_translations");
  613. undo_redo->add_do_method(this, "_settings_changed");
  614. undo_redo->add_undo_method(this, "_settings_changed");
  615. undo_redo->commit_action();
  616. }
  617. void ProjectSettings::_translation_file_open() {
  618. translation_file_open->popup_centered_ratio();
  619. }
  620. void ProjectSettings::_translation_delete(Object *p_item, int p_column, int p_button) {
  621. TreeItem *ti = p_item->cast_to<TreeItem>();
  622. ERR_FAIL_COND(!ti);
  623. int idx = ti->get_metadata(0);
  624. PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
  625. ERR_FAIL_INDEX(idx, translations.size());
  626. translations.remove(idx);
  627. undo_redo->create_action(TTR("Remove Translation"));
  628. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translations", translations);
  629. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translations", GlobalConfig::get_singleton()->get("locale/translations"));
  630. undo_redo->add_do_method(this, "_update_translations");
  631. undo_redo->add_undo_method(this, "_update_translations");
  632. undo_redo->add_do_method(this, "_settings_changed");
  633. undo_redo->add_undo_method(this, "_settings_changed");
  634. undo_redo->commit_action();
  635. }
  636. void ProjectSettings::_translation_res_file_open() {
  637. translation_res_file_open->popup_centered_ratio();
  638. }
  639. void ProjectSettings::_translation_res_add(const String &p_path) {
  640. Variant prev;
  641. Dictionary remaps;
  642. if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
  643. remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  644. prev = remaps;
  645. }
  646. if (remaps.has(p_path))
  647. return; //pointless already has it
  648. remaps[p_path] = PoolStringArray();
  649. undo_redo->create_action(TTR("Add Remapped Path"));
  650. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translation_remaps", remaps);
  651. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translation_remaps", prev);
  652. undo_redo->add_do_method(this, "_update_translations");
  653. undo_redo->add_undo_method(this, "_update_translations");
  654. undo_redo->add_do_method(this, "_settings_changed");
  655. undo_redo->add_undo_method(this, "_settings_changed");
  656. undo_redo->commit_action();
  657. }
  658. void ProjectSettings::_translation_res_option_file_open() {
  659. translation_res_option_file_open->popup_centered_ratio();
  660. }
  661. void ProjectSettings::_translation_res_option_add(const String &p_path) {
  662. ERR_FAIL_COND(!GlobalConfig::get_singleton()->has("locale/translation_remaps"));
  663. Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  664. TreeItem *k = translation_remap->get_selected();
  665. ERR_FAIL_COND(!k);
  666. String key = k->get_metadata(0);
  667. ERR_FAIL_COND(!remaps.has(key));
  668. PoolStringArray r = remaps[key];
  669. r.push_back(p_path + ":" + "en");
  670. remaps[key] = r;
  671. undo_redo->create_action(TTR("Resource Remap Add Remap"));
  672. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translation_remaps", remaps);
  673. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translation_remaps", GlobalConfig::get_singleton()->get("locale/translation_remaps"));
  674. undo_redo->add_do_method(this, "_update_translations");
  675. undo_redo->add_undo_method(this, "_update_translations");
  676. undo_redo->add_do_method(this, "_settings_changed");
  677. undo_redo->add_undo_method(this, "_settings_changed");
  678. undo_redo->commit_action();
  679. }
  680. void ProjectSettings::_translation_res_select() {
  681. if (updating_translations)
  682. return;
  683. call_deferred("_update_translations");
  684. }
  685. void ProjectSettings::_translation_res_option_changed() {
  686. if (updating_translations)
  687. return;
  688. if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
  689. return;
  690. Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  691. TreeItem *k = translation_remap->get_selected();
  692. ERR_FAIL_COND(!k);
  693. TreeItem *ed = translation_remap_options->get_edited();
  694. ERR_FAIL_COND(!ed);
  695. String key = k->get_metadata(0);
  696. int idx = ed->get_metadata(0);
  697. String path = ed->get_metadata(1);
  698. int which = ed->get_range(1);
  699. Vector<String> langs = TranslationServer::get_all_locales();
  700. ERR_FAIL_INDEX(which, langs.size());
  701. ERR_FAIL_COND(!remaps.has(key));
  702. PoolStringArray r = remaps[key];
  703. ERR_FAIL_INDEX(idx, r.size());
  704. r.set(idx, path + ":" + langs[which]);
  705. remaps[key] = r;
  706. updating_translations = true;
  707. undo_redo->create_action(TTR("Change Resource Remap Language"));
  708. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translation_remaps", remaps);
  709. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translation_remaps", GlobalConfig::get_singleton()->get("locale/translation_remaps"));
  710. undo_redo->add_do_method(this, "_update_translations");
  711. undo_redo->add_undo_method(this, "_update_translations");
  712. undo_redo->add_do_method(this, "_settings_changed");
  713. undo_redo->add_undo_method(this, "_settings_changed");
  714. undo_redo->commit_action();
  715. updating_translations = false;
  716. }
  717. void ProjectSettings::_translation_res_delete(Object *p_item, int p_column, int p_button) {
  718. if (updating_translations)
  719. return;
  720. if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
  721. return;
  722. Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  723. TreeItem *k = p_item->cast_to<TreeItem>();
  724. String key = k->get_metadata(0);
  725. ERR_FAIL_COND(!remaps.has(key));
  726. remaps.erase(key);
  727. undo_redo->create_action(TTR("Remove Resource Remap"));
  728. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translation_remaps", remaps);
  729. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translation_remaps", GlobalConfig::get_singleton()->get("locale/translation_remaps"));
  730. undo_redo->add_do_method(this, "_update_translations");
  731. undo_redo->add_undo_method(this, "_update_translations");
  732. undo_redo->add_do_method(this, "_settings_changed");
  733. undo_redo->add_undo_method(this, "_settings_changed");
  734. undo_redo->commit_action();
  735. }
  736. void ProjectSettings::_translation_res_option_delete(Object *p_item, int p_column, int p_button) {
  737. if (updating_translations)
  738. return;
  739. if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
  740. return;
  741. Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  742. TreeItem *k = translation_remap->get_selected();
  743. ERR_FAIL_COND(!k);
  744. TreeItem *ed = p_item->cast_to<TreeItem>();
  745. ERR_FAIL_COND(!ed);
  746. String key = k->get_metadata(0);
  747. int idx = ed->get_metadata(0);
  748. ERR_FAIL_COND(!remaps.has(key));
  749. PoolStringArray r = remaps[key];
  750. ERR_FAIL_INDEX(idx, remaps.size());
  751. r.remove(idx);
  752. remaps[key] = r;
  753. undo_redo->create_action(TTR("Remove Resource Remap Option"));
  754. undo_redo->add_do_property(GlobalConfig::get_singleton(), "locale/translation_remaps", remaps);
  755. undo_redo->add_undo_property(GlobalConfig::get_singleton(), "locale/translation_remaps", GlobalConfig::get_singleton()->get("locale/translation_remaps"));
  756. undo_redo->add_do_method(this, "_update_translations");
  757. undo_redo->add_undo_method(this, "_update_translations");
  758. undo_redo->add_do_method(this, "_settings_changed");
  759. undo_redo->add_undo_method(this, "_settings_changed");
  760. undo_redo->commit_action();
  761. }
  762. void ProjectSettings::_update_translations() {
  763. //update translations
  764. if (updating_translations)
  765. return;
  766. updating_translations = true;
  767. translation_list->clear();
  768. TreeItem *root = translation_list->create_item(NULL);
  769. translation_list->set_hide_root(true);
  770. if (GlobalConfig::get_singleton()->has("locale/translations")) {
  771. PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
  772. for (int i = 0; i < translations.size(); i++) {
  773. TreeItem *t = translation_list->create_item(root);
  774. t->set_editable(0, false);
  775. t->set_text(0, translations[i].replace_first("res://", ""));
  776. t->set_tooltip(0, translations[i]);
  777. t->set_metadata(0, i);
  778. t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  779. }
  780. }
  781. //update translation remaps
  782. String remap_selected;
  783. if (translation_remap->get_selected()) {
  784. remap_selected = translation_remap->get_selected()->get_metadata(0);
  785. }
  786. translation_remap->clear();
  787. translation_remap_options->clear();
  788. root = translation_remap->create_item(NULL);
  789. TreeItem *root2 = translation_remap_options->create_item(NULL);
  790. translation_remap->set_hide_root(true);
  791. translation_remap_options->set_hide_root(true);
  792. translation_res_option_add_button->set_disabled(true);
  793. Vector<String> langs = TranslationServer::get_all_locales();
  794. Vector<String> names = TranslationServer::get_all_locale_names();
  795. String langnames;
  796. for (int i = 0; i < names.size(); i++) {
  797. if (i > 0)
  798. langnames += ",";
  799. langnames += names[i];
  800. }
  801. if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
  802. Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
  803. List<Variant> rk;
  804. remaps.get_key_list(&rk);
  805. Vector<String> keys;
  806. for (List<Variant>::Element *E = rk.front(); E; E = E->next()) {
  807. keys.push_back(E->get());
  808. }
  809. keys.sort();
  810. for (int i = 0; i < keys.size(); i++) {
  811. TreeItem *t = translation_remap->create_item(root);
  812. t->set_editable(0, false);
  813. t->set_text(0, keys[i].replace_first("res://", ""));
  814. t->set_tooltip(0, keys[i]);
  815. t->set_metadata(0, keys[i]);
  816. t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  817. if (keys[i] == remap_selected) {
  818. t->select(0);
  819. translation_res_option_add_button->set_disabled(false);
  820. PoolStringArray selected = remaps[keys[i]];
  821. for (int j = 0; j < selected.size(); j++) {
  822. String s = selected[j];
  823. int qp = s.find_last(":");
  824. String path = s.substr(0, qp);
  825. String locale = s.substr(qp + 1, s.length());
  826. TreeItem *t2 = translation_remap_options->create_item(root2);
  827. t2->set_editable(0, false);
  828. t2->set_text(0, path.replace_first("res://", ""));
  829. t2->set_tooltip(0, path);
  830. t2->set_metadata(0, j);
  831. t2->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  832. t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
  833. t2->set_text(1, langnames);
  834. t2->set_editable(1, true);
  835. t2->set_metadata(1, path);
  836. int idx = langs.find(locale);
  837. print_line("find " + locale + " at " + itos(idx));
  838. if (idx < 0)
  839. idx = 0;
  840. t2->set_range(1, idx);
  841. }
  842. }
  843. }
  844. }
  845. updating_translations = false;
  846. }
  847. void ProjectSettings::_toggle_search_bar(bool p_pressed) {
  848. globals_editor->get_property_editor()->set_use_filter(p_pressed);
  849. if (p_pressed) {
  850. search_bar->show();
  851. add_prop_bar->hide();
  852. search_box->grab_focus();
  853. search_box->select_all();
  854. } else {
  855. search_bar->hide();
  856. add_prop_bar->show();
  857. }
  858. }
  859. void ProjectSettings::_clear_search_box() {
  860. if (search_box->get_text() == "")
  861. return;
  862. search_box->clear();
  863. globals_editor->get_property_editor()->update_tree();
  864. }
  865. void ProjectSettings::set_plugins_page() {
  866. tab_container->set_current_tab(plugin_settings->get_index());
  867. }
  868. void ProjectSettings::_bind_methods() {
  869. ClassDB::bind_method(D_METHOD("_item_selected"), &ProjectSettings::_item_selected);
  870. ClassDB::bind_method(D_METHOD("_item_add"), &ProjectSettings::_item_add);
  871. ClassDB::bind_method(D_METHOD("_item_adds"), &ProjectSettings::_item_adds);
  872. ClassDB::bind_method(D_METHOD("_item_del"), &ProjectSettings::_item_del);
  873. ClassDB::bind_method(D_METHOD("_item_checked"), &ProjectSettings::_item_checked);
  874. ClassDB::bind_method(D_METHOD("_save"), &ProjectSettings::_save);
  875. ClassDB::bind_method(D_METHOD("_action_add"), &ProjectSettings::_action_add);
  876. ClassDB::bind_method(D_METHOD("_action_adds"), &ProjectSettings::_action_adds);
  877. ClassDB::bind_method(D_METHOD("_action_selected"), &ProjectSettings::_action_selected);
  878. ClassDB::bind_method(D_METHOD("_action_edited"), &ProjectSettings::_action_edited);
  879. ClassDB::bind_method(D_METHOD("_action_button_pressed"), &ProjectSettings::_action_button_pressed);
  880. ClassDB::bind_method(D_METHOD("_update_actions"), &ProjectSettings::_update_actions);
  881. ClassDB::bind_method(D_METHOD("_wait_for_key"), &ProjectSettings::_wait_for_key);
  882. ClassDB::bind_method(D_METHOD("_add_item"), &ProjectSettings::_add_item);
  883. ClassDB::bind_method(D_METHOD("_device_input_add"), &ProjectSettings::_device_input_add);
  884. ClassDB::bind_method(D_METHOD("_press_a_key_confirm"), &ProjectSettings::_press_a_key_confirm);
  885. ClassDB::bind_method(D_METHOD("_settings_prop_edited"), &ProjectSettings::_settings_prop_edited);
  886. ClassDB::bind_method(D_METHOD("_copy_to_platform"), &ProjectSettings::_copy_to_platform);
  887. ClassDB::bind_method(D_METHOD("_update_translations"), &ProjectSettings::_update_translations);
  888. ClassDB::bind_method(D_METHOD("_translation_delete"), &ProjectSettings::_translation_delete);
  889. ClassDB::bind_method(D_METHOD("_settings_changed"), &ProjectSettings::_settings_changed);
  890. ClassDB::bind_method(D_METHOD("_translation_add"), &ProjectSettings::_translation_add);
  891. ClassDB::bind_method(D_METHOD("_translation_file_open"), &ProjectSettings::_translation_file_open);
  892. ClassDB::bind_method(D_METHOD("_translation_res_add"), &ProjectSettings::_translation_res_add);
  893. ClassDB::bind_method(D_METHOD("_translation_res_file_open"), &ProjectSettings::_translation_res_file_open);
  894. ClassDB::bind_method(D_METHOD("_translation_res_option_add"), &ProjectSettings::_translation_res_option_add);
  895. ClassDB::bind_method(D_METHOD("_translation_res_option_file_open"), &ProjectSettings::_translation_res_option_file_open);
  896. ClassDB::bind_method(D_METHOD("_translation_res_select"), &ProjectSettings::_translation_res_select);
  897. ClassDB::bind_method(D_METHOD("_translation_res_option_changed"), &ProjectSettings::_translation_res_option_changed);
  898. ClassDB::bind_method(D_METHOD("_translation_res_delete"), &ProjectSettings::_translation_res_delete);
  899. ClassDB::bind_method(D_METHOD("_translation_res_option_delete"), &ProjectSettings::_translation_res_option_delete);
  900. ClassDB::bind_method(D_METHOD("_clear_search_box"), &ProjectSettings::_clear_search_box);
  901. ClassDB::bind_method(D_METHOD("_toggle_search_bar"), &ProjectSettings::_toggle_search_bar);
  902. }
  903. ProjectSettings::ProjectSettings(EditorData *p_data) {
  904. singleton = this;
  905. String project_file = "(" + GlobalConfig::get_singleton()->get_project_file_name() + ")";
  906. set_title(TTR("Project Settings " + project_file));
  907. set_resizable(true);
  908. undo_redo = &p_data->get_undo_redo();
  909. data = p_data;
  910. tab_container = memnew(TabContainer);
  911. tab_container->add_constant_override("side_margin", 0);
  912. add_child(tab_container);
  913. //set_child_rect(tab_container);
  914. //tab_container->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 15 );
  915. //tab_container->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 15 );
  916. //tab_container->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 15 );
  917. //tab_container->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
  918. VBoxContainer *props_base = memnew(VBoxContainer);
  919. props_base->set_alignment(BoxContainer::ALIGN_BEGIN);
  920. props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  921. tab_container->add_child(props_base);
  922. props_base->set_name(TTR("General"));
  923. HBoxContainer *hbc = memnew(HBoxContainer);
  924. hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  925. props_base->add_child(hbc);
  926. search_button = memnew(ToolButton);
  927. search_button->set_toggle_mode(true);
  928. search_button->set_pressed(false);
  929. search_button->set_text(TTR("Search"));
  930. hbc->add_child(search_button);
  931. search_button->connect("toggled", this, "_toggle_search_bar");
  932. hbc->add_child(memnew(VSeparator));
  933. add_prop_bar = memnew(HBoxContainer);
  934. add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  935. hbc->add_child(add_prop_bar);
  936. Label *l = memnew(Label);
  937. add_prop_bar->add_child(l);
  938. l->set_text(TTR("Category:"));
  939. category = memnew(LineEdit);
  940. category->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  941. add_prop_bar->add_child(category);
  942. category->connect("text_entered", this, "_item_adds");
  943. l = memnew(Label);
  944. add_prop_bar->add_child(l);
  945. l->set_text(TTR("Property:"));
  946. property = memnew(LineEdit);
  947. property->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  948. add_prop_bar->add_child(property);
  949. property->connect("text_entered", this, "_item_adds");
  950. l = memnew(Label);
  951. add_prop_bar->add_child(l);
  952. l->set_text(TTR("Type:"));
  953. type = memnew(OptionButton);
  954. type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  955. add_prop_bar->add_child(type);
  956. type->add_item("bool");
  957. type->add_item("int");
  958. type->add_item("float");
  959. type->add_item("string");
  960. Button *add = memnew(Button);
  961. add_prop_bar->add_child(add);
  962. add->set_text(TTR("Add"));
  963. add->connect("pressed", this, "_item_add");
  964. Button *del = memnew(Button);
  965. add_prop_bar->add_child(del);
  966. del->set_text(TTR("Del"));
  967. del->connect("pressed", this, "_item_del");
  968. search_bar = memnew(HBoxContainer);
  969. search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  970. hbc->add_child(search_bar);
  971. search_bar->hide();
  972. search_box = memnew(LineEdit);
  973. search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  974. search_bar->add_child(search_box);
  975. clear_button = memnew(ToolButton);
  976. search_bar->add_child(clear_button);
  977. clear_button->connect("pressed", this, "_clear_search_box");
  978. globals_editor = memnew(SectionedPropertyEditor);
  979. props_base->add_child(globals_editor);
  980. globals_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
  981. //globals_editor->hide_top_label();
  982. globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  983. globals_editor->get_property_editor()->register_text_enter(search_box);
  984. globals_editor->get_property_editor()->set_capitalize_paths(false);
  985. globals_editor->get_property_editor()->get_scene_tree()->connect("cell_selected", this, "_item_selected");
  986. globals_editor->get_property_editor()->connect("property_toggled", this, "_item_checked", varray(), CONNECT_DEFERRED);
  987. globals_editor->get_property_editor()->connect("property_edited", this, "_settings_prop_edited");
  988. /*
  989. Button *save = memnew( Button );
  990. props_base->add_child(save);
  991. save->set_anchor(MARGIN_LEFT,ANCHOR_END);
  992. save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
  993. save->set_anchor(MARGIN_TOP,ANCHOR_END);
  994. save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
  995. save->set_begin( Point2(80,28) );
  996. save->set_end( Point2(10,20) );
  997. save->set_text("Save");
  998. save->connect("pressed",this,"_save");
  999. */
  1000. hbc = memnew(HBoxContainer);
  1001. props_base->add_child(hbc);
  1002. popup_platform = memnew(MenuButton);
  1003. popup_platform->set_text(TTR("Copy To Platform.."));
  1004. popup_platform->set_disabled(true);
  1005. hbc->add_child(popup_platform);
  1006. hbc->add_spacer();
  1007. /*List<StringName> ep;
  1008. EditorImportExport::get_singleton()->get_export_platforms(&ep);
  1009. ep.sort_custom<StringName::AlphCompare>();
  1010. for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
  1011. popup_platform->get_popup()->add_item( E->get() );
  1012. }*/
  1013. popup_platform->get_popup()->connect("id_pressed", this, "_copy_to_platform");
  1014. get_ok()->set_text(TTR("Close"));
  1015. set_hide_on_ok(true);
  1016. message = memnew(ConfirmationDialog);
  1017. add_child(message);
  1018. //message->get_cancel()->hide();
  1019. message->set_hide_on_ok(true);
  1020. Control *input_base = memnew(Control);
  1021. input_base->set_name(TTR("Input Map"));
  1022. input_base->set_area_as_parent_rect();
  1023. tab_container->add_child(input_base);
  1024. VBoxContainer *vbc = memnew(VBoxContainer);
  1025. input_base->add_child(vbc);
  1026. vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 5);
  1027. vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 5);
  1028. vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5);
  1029. vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 5);
  1030. l = memnew(Label);
  1031. vbc->add_child(l);
  1032. l->set_position(Point2(6, 5));
  1033. l->set_text(TTR("Action:"));
  1034. hbc = memnew(HBoxContainer);
  1035. vbc->add_child(hbc);
  1036. action_name = memnew(LineEdit);
  1037. action_name->set_h_size_flags(SIZE_EXPAND_FILL);
  1038. hbc->add_child(action_name);
  1039. action_name->connect("text_entered", this, "_action_adds");
  1040. add = memnew(Button);
  1041. hbc->add_child(add);
  1042. add->set_custom_minimum_size(Size2(150, 0));
  1043. add->set_text(TTR("Add"));
  1044. add->connect("pressed", this, "_action_add");
  1045. input_editor = memnew(Tree);
  1046. vbc->add_child(input_editor);
  1047. input_editor->set_v_size_flags(SIZE_EXPAND_FILL);
  1048. input_editor->connect("item_edited", this, "_action_edited");
  1049. input_editor->connect("cell_selected", this, "_action_selected");
  1050. input_editor->connect("button_pressed", this, "_action_button_pressed");
  1051. popup_add = memnew(PopupMenu);
  1052. add_child(popup_add);
  1053. popup_add->connect("id_pressed", this, "_add_item");
  1054. press_a_key = memnew(ConfirmationDialog);
  1055. press_a_key->set_focus_mode(FOCUS_ALL);
  1056. add_child(press_a_key);
  1057. l = memnew(Label);
  1058. l->set_text(TTR("Press a Key.."));
  1059. l->set_area_as_parent_rect();
  1060. l->set_align(Label::ALIGN_CENTER);
  1061. l->set_margin(MARGIN_TOP, 20);
  1062. l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30);
  1063. press_a_key_label = l;
  1064. press_a_key->add_child(l);
  1065. press_a_key->connect("gui_input", this, "_wait_for_key");
  1066. press_a_key->connect("confirmed", this, "_press_a_key_confirm");
  1067. device_input = memnew(ConfirmationDialog);
  1068. add_child(device_input);
  1069. device_input->get_ok()->set_text(TTR("Add"));
  1070. device_input->connect("confirmed", this, "_device_input_add");
  1071. hbc = memnew(HBoxContainer);
  1072. device_input->add_child(hbc);
  1073. //device_input->set_child_rect(hbc);
  1074. VBoxContainer *vbc_left = memnew(VBoxContainer);
  1075. hbc->add_child(vbc_left);
  1076. l = memnew(Label);
  1077. l->set_text(TTR("Device:"));
  1078. vbc_left->add_child(l);
  1079. device_id = memnew(SpinBox);
  1080. device_id->set_value(0);
  1081. vbc_left->add_child(device_id);
  1082. VBoxContainer *vbc_right = memnew(VBoxContainer);
  1083. hbc->add_child(vbc_right);
  1084. vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
  1085. l = memnew(Label);
  1086. l->set_text(TTR("Index:"));
  1087. vbc_right->add_child(l);
  1088. device_index_label = l;
  1089. device_index = memnew(OptionButton);
  1090. vbc_right->add_child(device_index);
  1091. /*
  1092. save = memnew( Button );
  1093. input_base->add_child(save);
  1094. save->set_anchor(MARGIN_LEFT,ANCHOR_END);
  1095. save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
  1096. save->set_anchor(MARGIN_TOP,ANCHOR_END);
  1097. save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
  1098. save->set_begin( Point2(80,28) );
  1099. save->set_end( Point2(10,20) );
  1100. save->set_text("Save");
  1101. save->connect("pressed",this,"_save");
  1102. */
  1103. setting = false;
  1104. //translations
  1105. TabContainer *translations = memnew(TabContainer);
  1106. translations->set_name(TTR("Localization"));
  1107. tab_container->add_child(translations);
  1108. {
  1109. VBoxContainer *tvb = memnew(VBoxContainer);
  1110. translations->add_child(tvb);
  1111. tvb->set_name(TTR("Translations"));
  1112. HBoxContainer *thb = memnew(HBoxContainer);
  1113. tvb->add_child(thb);
  1114. thb->add_child(memnew(Label(TTR("Translations:"))));
  1115. thb->add_spacer();
  1116. Button *addtr = memnew(Button(TTR("Add..")));
  1117. addtr->connect("pressed", this, "_translation_file_open");
  1118. thb->add_child(addtr);
  1119. MarginContainer *tmc = memnew(MarginContainer);
  1120. tvb->add_child(tmc);
  1121. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1122. translation_list = memnew(Tree);
  1123. translation_list->set_v_size_flags(SIZE_EXPAND_FILL);
  1124. tmc->add_child(translation_list);
  1125. translation_file_open = memnew(EditorFileDialog);
  1126. add_child(translation_file_open);
  1127. translation_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1128. translation_file_open->connect("file_selected", this, "_translation_add");
  1129. }
  1130. {
  1131. VBoxContainer *tvb = memnew(VBoxContainer);
  1132. translations->add_child(tvb);
  1133. tvb->set_name(TTR("Remaps"));
  1134. HBoxContainer *thb = memnew(HBoxContainer);
  1135. tvb->add_child(thb);
  1136. thb->add_child(memnew(Label(TTR("Resources:"))));
  1137. thb->add_spacer();
  1138. Button *addtr = memnew(Button(TTR("Add..")));
  1139. addtr->connect("pressed", this, "_translation_res_file_open");
  1140. thb->add_child(addtr);
  1141. MarginContainer *tmc = memnew(MarginContainer);
  1142. tvb->add_child(tmc);
  1143. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1144. translation_remap = memnew(Tree);
  1145. translation_remap->set_v_size_flags(SIZE_EXPAND_FILL);
  1146. translation_remap->connect("cell_selected", this, "_translation_res_select");
  1147. tmc->add_child(translation_remap);
  1148. translation_remap->connect("button_pressed", this, "_translation_res_delete");
  1149. translation_res_file_open = memnew(EditorFileDialog);
  1150. add_child(translation_res_file_open);
  1151. translation_res_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1152. translation_res_file_open->connect("file_selected", this, "_translation_res_add");
  1153. thb = memnew(HBoxContainer);
  1154. tvb->add_child(thb);
  1155. thb->add_child(memnew(Label(TTR("Remaps by Locale:"))));
  1156. thb->add_spacer();
  1157. addtr = memnew(Button(TTR("Add..")));
  1158. addtr->connect("pressed", this, "_translation_res_option_file_open");
  1159. translation_res_option_add_button = addtr;
  1160. thb->add_child(addtr);
  1161. tmc = memnew(MarginContainer);
  1162. tvb->add_child(tmc);
  1163. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1164. translation_remap_options = memnew(Tree);
  1165. translation_remap_options->set_v_size_flags(SIZE_EXPAND_FILL);
  1166. tmc->add_child(translation_remap_options);
  1167. translation_remap_options->set_columns(2);
  1168. translation_remap_options->set_column_title(0, TTR("Path"));
  1169. translation_remap_options->set_column_title(1, TTR("Locale"));
  1170. translation_remap_options->set_column_titles_visible(true);
  1171. translation_remap_options->set_column_expand(0, true);
  1172. translation_remap_options->set_column_expand(1, false);
  1173. translation_remap_options->set_column_min_width(1, 200);
  1174. translation_remap_options->connect("item_edited", this, "_translation_res_option_changed");
  1175. translation_remap_options->connect("button_pressed", this, "_translation_res_option_delete");
  1176. translation_res_option_file_open = memnew(EditorFileDialog);
  1177. add_child(translation_res_option_file_open);
  1178. translation_res_option_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1179. translation_res_option_file_open->connect("file_selected", this, "_translation_res_option_add");
  1180. }
  1181. {
  1182. autoload_settings = memnew(EditorAutoloadSettings);
  1183. autoload_settings->set_name(TTR("AutoLoad"));
  1184. tab_container->add_child(autoload_settings);
  1185. autoload_settings->connect("autoload_changed", this, "_settings_changed");
  1186. }
  1187. {
  1188. plugin_settings = memnew(EditorPluginSettings);
  1189. plugin_settings->set_name(TTR("Plugins"));
  1190. tab_container->add_child(plugin_settings);
  1191. }
  1192. timer = memnew(Timer);
  1193. timer->set_wait_time(1.5);
  1194. timer->connect("timeout", GlobalConfig::get_singleton(), "save");
  1195. timer->set_one_shot(true);
  1196. add_child(timer);
  1197. updating_translations = false;
  1198. /*
  1199. Control * es = memnew( Control );
  1200. es->set_name("Export");
  1201. tab_container->add_child(es);
  1202. export_settings = memnew( ProjectExportSettings );
  1203. es->add_child(export_settings);
  1204. export_settings->set_area_as_parent_rect();
  1205. export_settings->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
  1206. */
  1207. }