project_settings_editor.cpp 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. /*************************************************************************/
  2. /* project_settings_editor.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://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_editor.h"
  31. #include "core/global_constants.h"
  32. #include "core/os/keyboard.h"
  33. #include "core/project_settings.h"
  34. #include "core/translation.h"
  35. #include "editor/editor_node.h"
  36. #include "scene/gui/margin_container.h"
  37. #include "scene/gui/tab_container.h"
  38. ProjectSettingsEditor *ProjectSettingsEditor::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 ProjectSettingsEditor::_notification(int p_what) {
  71. switch (p_what) {
  72. case NOTIFICATION_ENTER_TREE: {
  73. globals_editor->edit(ProjectSettings::get_singleton());
  74. search_button->set_icon(get_icon("Search", "EditorIcons"));
  75. clear_button->set_icon(get_icon("Close", "EditorIcons"));
  76. action_add_error->add_color_override("font_color", get_color("error_color", "Editor"));
  77. translation_list->connect("button_pressed", this, "_translation_delete");
  78. _update_actions();
  79. popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation
  80. popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON);
  81. popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION);
  82. popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON);
  83. List<String> tfn;
  84. ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn);
  85. for (List<String>::Element *E = tfn.front(); E; E = E->next()) {
  86. translation_file_open->add_filter("*." + E->get());
  87. }
  88. List<String> rfn;
  89. ResourceLoader::get_recognized_extensions_for_type("Resource", &rfn);
  90. for (List<String>::Element *E = rfn.front(); E; E = E->next()) {
  91. translation_res_file_open->add_filter("*." + E->get());
  92. translation_res_option_file_open->add_filter("*." + E->get());
  93. }
  94. } break;
  95. case NOTIFICATION_POPUP_HIDE: {
  96. EditorSettings::get_singleton()->set("interface/dialogs/project_settings_bounds", get_rect());
  97. } break;
  98. case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
  99. _update_actions();
  100. } break;
  101. }
  102. }
  103. void ProjectSettingsEditor::_action_selected() {
  104. TreeItem *ti = input_editor->get_selected();
  105. if (!ti || !ti->is_editable(0))
  106. return;
  107. add_at = "input/" + ti->get_text(0);
  108. edit_idx = -1;
  109. }
  110. void ProjectSettingsEditor::_action_edited() {
  111. TreeItem *ti = input_editor->get_selected();
  112. if (!ti)
  113. return;
  114. String new_name = ti->get_text(0);
  115. String old_name = add_at.substr(add_at.find("/") + 1, add_at.length());
  116. if (new_name == old_name)
  117. return;
  118. if (new_name.find("/") != -1 || new_name.find(":") != -1 || new_name == "") {
  119. ti->set_text(0, old_name);
  120. add_at = "input/" + old_name;
  121. message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
  122. message->popup_centered(Size2(300, 100) * EDSCALE);
  123. return;
  124. }
  125. String action_prop = "input/" + new_name;
  126. if (ProjectSettings::get_singleton()->has_setting(action_prop)) {
  127. ti->set_text(0, old_name);
  128. add_at = "input/" + old_name;
  129. message->set_text(vformat(TTR("Action '%s' already exists!"), new_name));
  130. message->popup_centered(Size2(300, 100) * EDSCALE);
  131. return;
  132. }
  133. int order = ProjectSettings::get_singleton()->get_order(add_at);
  134. Array va = ProjectSettings::get_singleton()->get(add_at);
  135. setting = true;
  136. undo_redo->create_action(TTR("Rename Input Action Event"));
  137. undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at);
  138. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, va);
  139. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order);
  140. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop);
  141. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, va);
  142. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order);
  143. undo_redo->add_do_method(this, "_update_actions");
  144. undo_redo->add_undo_method(this, "_update_actions");
  145. undo_redo->add_do_method(this, "_settings_changed");
  146. undo_redo->add_undo_method(this, "_settings_changed");
  147. undo_redo->commit_action();
  148. setting = false;
  149. add_at = action_prop;
  150. }
  151. void ProjectSettingsEditor::_device_input_add() {
  152. Ref<InputEvent> ie;
  153. String name = add_at;
  154. int idx = edit_idx;
  155. Array old_val = ProjectSettings::get_singleton()->get(name);
  156. Array arr = old_val.duplicate();
  157. switch (add_type) {
  158. case INPUT_MOUSE_BUTTON: {
  159. Ref<InputEventMouseButton> mb;
  160. mb.instance();
  161. mb->set_button_index(device_index->get_selected() + 1);
  162. mb->set_device(device_id->get_value());
  163. for (int i = 0; i < arr.size(); i++) {
  164. Ref<InputEventMouseButton> aie = arr[i];
  165. if (aie.is_null())
  166. continue;
  167. if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) {
  168. return;
  169. }
  170. }
  171. ie = mb;
  172. } break;
  173. case INPUT_JOY_MOTION: {
  174. Ref<InputEventJoypadMotion> jm;
  175. jm.instance();
  176. jm->set_axis(device_index->get_selected() >> 1);
  177. jm->set_axis_value(device_index->get_selected() & 1 ? 1 : -1);
  178. jm->set_device(device_id->get_value());
  179. for (int i = 0; i < arr.size(); i++) {
  180. Ref<InputEventJoypadMotion> aie = arr[i];
  181. if (aie.is_null())
  182. continue;
  183. if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) {
  184. return;
  185. }
  186. }
  187. ie = jm;
  188. } break;
  189. case INPUT_JOY_BUTTON: {
  190. Ref<InputEventJoypadButton> jb;
  191. jb.instance();
  192. jb->set_button_index(device_index->get_selected());
  193. jb->set_device(device_id->get_value());
  194. for (int i = 0; i < arr.size(); i++) {
  195. Ref<InputEventJoypadButton> aie = arr[i];
  196. if (aie.is_null())
  197. continue;
  198. if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) {
  199. return;
  200. }
  201. }
  202. ie = jb;
  203. } break;
  204. default: {}
  205. }
  206. if (idx < 0 || idx >= arr.size()) {
  207. arr.push_back(ie);
  208. } else {
  209. arr[idx] = ie;
  210. }
  211. undo_redo->create_action(TTR("Add Input Action Event"));
  212. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr);
  213. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
  214. undo_redo->add_do_method(this, "_update_actions");
  215. undo_redo->add_undo_method(this, "_update_actions");
  216. undo_redo->add_do_method(this, "_settings_changed");
  217. undo_redo->add_undo_method(this, "_settings_changed");
  218. undo_redo->commit_action();
  219. _show_last_added(ie, name);
  220. }
  221. void ProjectSettingsEditor::_press_a_key_confirm() {
  222. if (last_wait_for_key.is_null())
  223. return;
  224. Ref<InputEventKey> ie;
  225. ie.instance();
  226. ie->set_scancode(last_wait_for_key->get_scancode());
  227. ie->set_shift(last_wait_for_key->get_shift());
  228. ie->set_alt(last_wait_for_key->get_alt());
  229. ie->set_control(last_wait_for_key->get_control());
  230. ie->set_metakey(last_wait_for_key->get_metakey());
  231. String name = add_at;
  232. int idx = edit_idx;
  233. Array old_val = ProjectSettings::get_singleton()->get(name);
  234. Array arr = old_val.duplicate();
  235. for (int i = 0; i < arr.size(); i++) {
  236. Ref<InputEventKey> aie = arr[i];
  237. if (aie.is_null())
  238. continue;
  239. if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) {
  240. return;
  241. }
  242. }
  243. if (idx < 0 || idx >= arr.size()) {
  244. arr.push_back(ie);
  245. } else {
  246. arr[idx] = ie;
  247. }
  248. undo_redo->create_action(TTR("Add Input Action Event"));
  249. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr);
  250. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
  251. undo_redo->add_do_method(this, "_update_actions");
  252. undo_redo->add_undo_method(this, "_update_actions");
  253. undo_redo->add_do_method(this, "_settings_changed");
  254. undo_redo->add_undo_method(this, "_settings_changed");
  255. undo_redo->commit_action();
  256. _show_last_added(ie, name);
  257. }
  258. void ProjectSettingsEditor::_show_last_added(const Ref<InputEvent> &p_event, const String &p_name) {
  259. TreeItem *r = input_editor->get_root();
  260. String name = p_name;
  261. name.erase(0, 6);
  262. if (!r)
  263. return;
  264. r = r->get_children();
  265. if (!r)
  266. return;
  267. bool found = false;
  268. while (r) {
  269. if (r->get_text(0) != name) {
  270. r = r->get_next();
  271. continue;
  272. }
  273. TreeItem *child = r->get_children();
  274. while (child) {
  275. Variant input = child->get_meta("__input");
  276. if (p_event == input) {
  277. child->select(0);
  278. found = true;
  279. break;
  280. }
  281. child = child->get_next();
  282. }
  283. if (found) break;
  284. r = r->get_next();
  285. }
  286. if (found) input_editor->ensure_cursor_is_visible();
  287. }
  288. void ProjectSettingsEditor::_wait_for_key(const Ref<InputEvent> &p_event) {
  289. Ref<InputEventKey> k = p_event;
  290. if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) {
  291. last_wait_for_key = p_event;
  292. String str = keycode_get_string(k->get_scancode()).capitalize();
  293. if (k->get_metakey())
  294. str = TTR("Meta+") + str;
  295. if (k->get_shift())
  296. str = TTR("Shift+") + str;
  297. if (k->get_alt())
  298. str = TTR("Alt+") + str;
  299. if (k->get_control())
  300. str = TTR("Control+") + str;
  301. press_a_key_label->set_text(str);
  302. press_a_key->accept_event();
  303. }
  304. }
  305. void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_event) {
  306. add_type = InputType(p_item);
  307. switch (add_type) {
  308. case INPUT_KEY: {
  309. press_a_key_label->set_text(TTR("Press a Key.."));
  310. last_wait_for_key = Ref<InputEvent>();
  311. press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
  312. press_a_key->grab_focus();
  313. } break;
  314. case INPUT_MOUSE_BUTTON: {
  315. device_index_label->set_text(TTR("Mouse Button Index:"));
  316. device_index->clear();
  317. device_index->add_item(TTR("Left Button"));
  318. device_index->add_item(TTR("Right Button"));
  319. device_index->add_item(TTR("Middle Button"));
  320. device_index->add_item(TTR("Wheel Up Button"));
  321. device_index->add_item(TTR("Wheel Down Button"));
  322. device_index->add_item(TTR("Button 6"));
  323. device_index->add_item(TTR("Button 7"));
  324. device_index->add_item(TTR("Button 8"));
  325. device_index->add_item(TTR("Button 9"));
  326. device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
  327. Ref<InputEventMouseButton> mb = p_exiting_event;
  328. if (mb.is_valid()) {
  329. device_index->select(mb->get_button_index() - 1);
  330. device_id->set_value(mb->get_device());
  331. device_input->get_ok()->set_text(TTR("Change"));
  332. } else {
  333. device_id->set_value(0);
  334. device_input->get_ok()->set_text(TTR("Add"));
  335. }
  336. } break;
  337. case INPUT_JOY_MOTION: {
  338. device_index_label->set_text(TTR("Joypad Axis Index:"));
  339. device_index->clear();
  340. for (int i = 0; i < JOY_AXIS_MAX * 2; i++) {
  341. String desc = _axis_names[i];
  342. device_index->add_item(TTR("Axis") + " " + itos(i / 2) + " " + (i & 1 ? "+" : "-") + desc);
  343. }
  344. device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
  345. Ref<InputEventJoypadMotion> jm = p_exiting_event;
  346. if (jm.is_valid()) {
  347. device_index->select(jm->get_axis() * 2 + (jm->get_axis_value() > 0 ? 1 : 0));
  348. device_id->set_value(jm->get_device());
  349. device_input->get_ok()->set_text(TTR("Change"));
  350. } else {
  351. device_id->set_value(0);
  352. device_input->get_ok()->set_text(TTR("Add"));
  353. }
  354. } break;
  355. case INPUT_JOY_BUTTON: {
  356. device_index_label->set_text(TTR("Joypad Button Index:"));
  357. device_index->clear();
  358. for (int i = 0; i < JOY_BUTTON_MAX; i++) {
  359. device_index->add_item(itos(i) + ": " + String(_button_names[i]));
  360. }
  361. device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
  362. Ref<InputEventJoypadButton> jb = p_exiting_event;
  363. if (jb.is_valid()) {
  364. device_index->select(jb->get_button_index());
  365. device_id->set_value(jb->get_device());
  366. device_input->get_ok()->set_text(TTR("Change"));
  367. } else {
  368. device_id->set_value(0);
  369. device_input->get_ok()->set_text(TTR("Add"));
  370. }
  371. } break;
  372. default: {}
  373. }
  374. }
  375. void ProjectSettingsEditor::_edit_item(Ref<InputEvent> p_exiting_event) {
  376. InputType ie_type;
  377. if ((Ref<InputEventKey>(p_exiting_event)).is_valid()) {
  378. ie_type = INPUT_KEY;
  379. } else if ((Ref<InputEventJoypadButton>(p_exiting_event)).is_valid()) {
  380. ie_type = INPUT_JOY_BUTTON;
  381. } else if ((Ref<InputEventMouseButton>(p_exiting_event)).is_valid()) {
  382. ie_type = INPUT_MOUSE_BUTTON;
  383. } else if ((Ref<InputEventJoypadMotion>(p_exiting_event)).is_valid()) {
  384. ie_type = INPUT_JOY_MOTION;
  385. } else {
  386. return;
  387. }
  388. _add_item(ie_type, p_exiting_event);
  389. }
  390. void ProjectSettingsEditor::_action_activated() {
  391. TreeItem *ti = input_editor->get_selected();
  392. if (!ti || ti->get_parent() == input_editor->get_root())
  393. return;
  394. String name = "input/" + ti->get_parent()->get_text(0);
  395. int idx = ti->get_metadata(0);
  396. Array va = ProjectSettings::get_singleton()->get(name);
  397. ERR_FAIL_INDEX(idx, va.size());
  398. Ref<InputEvent> ie = va[idx];
  399. if (ie.is_null())
  400. return;
  401. add_at = name;
  402. edit_idx = idx;
  403. _edit_item(ie);
  404. }
  405. void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) {
  406. TreeItem *ti = Object::cast_to<TreeItem>(p_obj);
  407. ERR_FAIL_COND(!ti);
  408. if (p_id == 1) {
  409. Point2 ofs = input_editor->get_global_position();
  410. Rect2 ir = input_editor->get_item_rect(ti);
  411. ir.position.y -= input_editor->get_scroll().y;
  412. ofs += ir.position + ir.size;
  413. ofs.x -= 100;
  414. popup_add->set_position(ofs);
  415. popup_add->popup();
  416. add_at = "input/" + ti->get_text(0);
  417. edit_idx = -1;
  418. } else if (p_id == 2) {
  419. //remove
  420. if (ti->get_parent() == input_editor->get_root()) {
  421. //remove main thing
  422. String name = "input/" + ti->get_text(0);
  423. Variant old_val = ProjectSettings::get_singleton()->get(name);
  424. int order = ProjectSettings::get_singleton()->get_order(name);
  425. undo_redo->create_action(TTR("Add Input Action"));
  426. undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", name);
  427. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
  428. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", name, order);
  429. undo_redo->add_do_method(this, "_update_actions");
  430. undo_redo->add_undo_method(this, "_update_actions");
  431. undo_redo->add_do_method(this, "_settings_changed");
  432. undo_redo->add_undo_method(this, "_settings_changed");
  433. undo_redo->commit_action();
  434. } else {
  435. //remove action
  436. String name = "input/" + ti->get_parent()->get_text(0);
  437. Variant old_val = ProjectSettings::get_singleton()->get(name);
  438. int idx = ti->get_metadata(0);
  439. Array va = old_val;
  440. ERR_FAIL_INDEX(idx, va.size());
  441. for (int i = idx; i < va.size() - 1; i++) {
  442. va[i] = va[i + 1];
  443. }
  444. va.resize(va.size() - 1);
  445. undo_redo->create_action(TTR("Erase Input Action Event"));
  446. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
  447. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
  448. undo_redo->add_do_method(this, "_update_actions");
  449. undo_redo->add_undo_method(this, "_update_actions");
  450. undo_redo->add_do_method(this, "_settings_changed");
  451. undo_redo->add_undo_method(this, "_settings_changed");
  452. undo_redo->commit_action();
  453. }
  454. } else if (p_id == 3) {
  455. //edit
  456. if (ti->get_parent() == input_editor->get_root()) {
  457. ti->set_as_cursor(0);
  458. input_editor->edit_selected();
  459. } else {
  460. //edit action
  461. String name = "input/" + ti->get_parent()->get_text(0);
  462. int idx = ti->get_metadata(0);
  463. Array va = ProjectSettings::get_singleton()->get(name);
  464. ERR_FAIL_INDEX(idx, va.size());
  465. Ref<InputEvent> ie = va[idx];
  466. if (ie.is_null())
  467. return;
  468. ti->set_as_cursor(0);
  469. add_at = name;
  470. edit_idx = idx;
  471. _edit_item(ie);
  472. }
  473. }
  474. }
  475. void ProjectSettingsEditor::_update_actions() {
  476. if (setting)
  477. return;
  478. input_editor->clear();
  479. TreeItem *root = input_editor->create_item();
  480. input_editor->set_hide_root(true);
  481. List<PropertyInfo> props;
  482. ProjectSettings::get_singleton()->get_property_list(&props);
  483. for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
  484. const PropertyInfo &pi = E->get();
  485. if (!pi.name.begins_with("input/"))
  486. continue;
  487. String name = pi.name.get_slice("/", 1);
  488. if (name == "")
  489. continue;
  490. TreeItem *item = input_editor->create_item(root);
  491. item->set_text(0, name);
  492. item->add_button(0, get_icon("Add", "EditorIcons"), 1, false, TTR("Add Event"));
  493. if (!ProjectSettings::get_singleton()->get_input_presets().find(pi.name)) {
  494. item->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
  495. item->set_editable(0, true);
  496. }
  497. item->set_custom_bg_color(0, get_color("prop_subsection", "Editor"));
  498. Array actions = ProjectSettings::get_singleton()->get(pi.name);
  499. for (int i = 0; i < actions.size(); i++) {
  500. Ref<InputEvent> ie = actions[i];
  501. if (ie.is_null())
  502. continue;
  503. TreeItem *action = input_editor->create_item(item);
  504. Ref<InputEventKey> k = ie;
  505. if (k.is_valid()) {
  506. String str = keycode_get_string(k->get_scancode()).capitalize();
  507. if (k->get_metakey())
  508. str = TTR("Meta+") + str;
  509. if (k->get_shift())
  510. str = TTR("Shift+") + str;
  511. if (k->get_alt())
  512. str = TTR("Alt+") + str;
  513. if (k->get_control())
  514. str = TTR("Control+") + str;
  515. action->set_text(0, str);
  516. action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
  517. }
  518. Ref<InputEventJoypadButton> jb = ie;
  519. if (jb.is_valid()) {
  520. String str = TTR("Device") + " " + itos(jb->get_device()) + ", " + TTR("Button") + " " + itos(jb->get_button_index());
  521. if (jb->get_button_index() >= 0 && jb->get_button_index() < JOY_BUTTON_MAX)
  522. str += String() + " (" + _button_names[jb->get_button_index()] + ").";
  523. else
  524. str += ".";
  525. action->set_text(0, str);
  526. action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
  527. }
  528. Ref<InputEventMouseButton> mb = ie;
  529. if (mb.is_valid()) {
  530. String str = TTR("Device") + " " + itos(mb->get_device()) + ", ";
  531. switch (mb->get_button_index()) {
  532. case BUTTON_LEFT: str += TTR("Left Button."); break;
  533. case BUTTON_RIGHT: str += TTR("Right Button."); break;
  534. case BUTTON_MIDDLE: str += TTR("Middle Button."); break;
  535. case BUTTON_WHEEL_UP: str += TTR("Wheel Up."); break;
  536. case BUTTON_WHEEL_DOWN: str += TTR("Wheel Down."); break;
  537. default: str += TTR("Button") + " " + itos(mb->get_button_index()) + ".";
  538. }
  539. action->set_text(0, str);
  540. action->set_icon(0, get_icon("Mouse", "EditorIcons"));
  541. }
  542. Ref<InputEventJoypadMotion> jm = ie;
  543. if (jm.is_valid()) {
  544. int ax = jm->get_axis();
  545. int n = 2 * ax + (jm->get_axis_value() < 0 ? 0 : 1);
  546. String desc = _axis_names[n];
  547. String str = TTR("Device") + " " + itos(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc + ".";
  548. action->set_text(0, str);
  549. action->set_icon(0, get_icon("JoyAxis", "EditorIcons"));
  550. }
  551. action->add_button(0, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit"));
  552. action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
  553. action->set_metadata(0, i);
  554. action->set_meta("__input", ie);
  555. }
  556. }
  557. _action_check(action_name->get_text());
  558. }
  559. void ProjectSettingsEditor::popup_project_settings() {
  560. // Restore valid window bounds or pop up at default size.
  561. if (EditorSettings::get_singleton()->has_setting("interface/dialogs/project_settings_bounds")) {
  562. popup(EditorSettings::get_singleton()->get("interface/dialogs/project_settings_bounds"));
  563. } else {
  564. popup_centered_ratio();
  565. }
  566. globals_editor->update_category_list();
  567. _update_translations();
  568. autoload_settings->update_autoload();
  569. plugin_settings->update_plugins();
  570. }
  571. void ProjectSettingsEditor::_item_selected() {
  572. TreeItem *ti = globals_editor->get_property_editor()->get_scene_tree()->get_selected();
  573. if (!ti)
  574. return;
  575. if (!ti->get_parent())
  576. return;
  577. category->set_text(globals_editor->get_current_section());
  578. property->set_text(ti->get_text(0));
  579. popup_copy_to_feature->set_disabled(false);
  580. }
  581. void ProjectSettingsEditor::_item_adds(String) {
  582. _item_add();
  583. }
  584. void ProjectSettingsEditor::_item_add() {
  585. Variant value;
  586. switch (type->get_selected()) {
  587. case 0: value = false; break;
  588. case 1: value = 0; break;
  589. case 2: value = 0.0; break;
  590. case 3: value = ""; break;
  591. }
  592. String catname = category->get_text().strip_edges();
  593. String propname = property->get_text().strip_edges();
  594. String name = catname != "" ? catname + "/" + propname : propname;
  595. undo_redo->create_action(TTR("Add Global Property"));
  596. undo_redo->add_do_property(ProjectSettings::get_singleton(), name, value);
  597. if (ProjectSettings::get_singleton()->has_setting(name)) {
  598. undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, ProjectSettings::get_singleton()->get(name));
  599. } else {
  600. undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, Variant());
  601. }
  602. undo_redo->add_do_method(globals_editor, "update_category_list");
  603. undo_redo->add_undo_method(globals_editor, "update_category_list");
  604. undo_redo->add_do_method(this, "_settings_changed");
  605. undo_redo->add_undo_method(this, "_settings_changed");
  606. undo_redo->commit_action();
  607. globals_editor->set_current_section(catname);
  608. _settings_changed();
  609. }
  610. void ProjectSettingsEditor::_item_del() {
  611. String path = globals_editor->get_property_editor()->get_selected_path();
  612. if (path == String()) {
  613. EditorNode::get_singleton()->show_warning(TTR("Select a setting item first!"));
  614. return;
  615. }
  616. String property = globals_editor->get_current_section().plus_file(path);
  617. if (!ProjectSettings::get_singleton()->has_setting(property)) {
  618. EditorNode::get_singleton()->show_warning(TTR("No property '" + property + "' exists."));
  619. return;
  620. }
  621. if (ProjectSettings::get_singleton()->get_order(property) < ProjectSettings::NO_BUILTIN_ORDER_BASE) {
  622. EditorNode::get_singleton()->show_warning(TTR("Setting '" + property + "' is internal, and it can't be deleted."));
  623. return;
  624. }
  625. print_line("to delete.. " + property);
  626. undo_redo->create_action(TTR("Delete Item"));
  627. Variant value = ProjectSettings::get_singleton()->get(property);
  628. int order = ProjectSettings::get_singleton()->get_order(property);
  629. undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property);
  630. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property, value);
  631. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", property, order);
  632. undo_redo->add_do_method(globals_editor, "update_category_list");
  633. undo_redo->add_undo_method(globals_editor, "update_category_list");
  634. undo_redo->add_do_method(this, "_settings_changed");
  635. undo_redo->add_undo_method(this, "_settings_changed");
  636. undo_redo->commit_action();
  637. }
  638. void ProjectSettingsEditor::_action_check(String p_action) {
  639. if (p_action == "") {
  640. action_add->set_disabled(true);
  641. } else {
  642. if (p_action.find("/") != -1 || p_action.find(":") != -1) {
  643. action_add_error->set_text(TTR("Can't contain '/' or ':'"));
  644. action_add_error->show();
  645. action_add->set_disabled(true);
  646. return;
  647. }
  648. if (ProjectSettings::get_singleton()->has_setting("input/" + p_action)) {
  649. action_add_error->set_text(TTR("Already existing"));
  650. action_add_error->show();
  651. action_add->set_disabled(true);
  652. return;
  653. }
  654. action_add->set_disabled(false);
  655. }
  656. action_add_error->hide();
  657. }
  658. void ProjectSettingsEditor::_action_adds(String) {
  659. if (!action_add->is_disabled()) {
  660. _action_add();
  661. }
  662. }
  663. void ProjectSettingsEditor::_action_add() {
  664. Array va;
  665. String name = "input/" + action_name->get_text();
  666. undo_redo->create_action(TTR("Add Input Action Event"));
  667. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
  668. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
  669. undo_redo->add_do_method(this, "_update_actions");
  670. undo_redo->add_undo_method(this, "_update_actions");
  671. undo_redo->add_do_method(this, "_settings_changed");
  672. undo_redo->add_undo_method(this, "_settings_changed");
  673. undo_redo->commit_action();
  674. TreeItem *r = input_editor->get_root();
  675. if (!r)
  676. return;
  677. r = r->get_children();
  678. if (!r)
  679. return;
  680. while (r->get_next())
  681. r = r->get_next();
  682. if (!r)
  683. return;
  684. r->select(0);
  685. input_editor->ensure_cursor_is_visible();
  686. action_add_error->hide();
  687. action_name->clear();
  688. }
  689. void ProjectSettingsEditor::_item_checked(const String &p_item, bool p_check) {
  690. }
  691. void ProjectSettingsEditor::_save() {
  692. Error err = ProjectSettings::get_singleton()->save();
  693. message->set_text(err != OK ? TTR("Error saving settings.") : TTR("Settings saved OK."));
  694. message->popup_centered(Size2(300, 100) * EDSCALE);
  695. }
  696. void ProjectSettingsEditor::_settings_prop_edited(const String &p_name) {
  697. // Method needed to discard the mandatory argument of the property_edited signal
  698. _settings_changed();
  699. }
  700. void ProjectSettingsEditor::_settings_changed() {
  701. timer->start();
  702. }
  703. void ProjectSettingsEditor::queue_save() {
  704. _settings_changed();
  705. }
  706. void ProjectSettingsEditor::_copy_to_platform_about_to_show() {
  707. Set<String> presets;
  708. presets.insert("s3tc");
  709. presets.insert("etc");
  710. presets.insert("etc2");
  711. presets.insert("pvrtc");
  712. presets.insert("debug");
  713. presets.insert("release");
  714. presets.insert("32");
  715. presets.insert("64");
  716. for (int i = 0; i < EditorExport::get_singleton()->get_export_platform_count(); i++) {
  717. List<String> p;
  718. EditorExport::get_singleton()->get_export_platform(i)->get_platform_features(&p);
  719. for (List<String>::Element *E = p.front(); E; E = E->next()) {
  720. presets.insert(E->get());
  721. }
  722. }
  723. for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
  724. List<String> p;
  725. EditorExport::get_singleton()->get_export_preset(i)->get_platform()->get_preset_features(EditorExport::get_singleton()->get_export_preset(i), &p);
  726. for (List<String>::Element *E = p.front(); E; E = E->next()) {
  727. presets.insert(E->get());
  728. }
  729. String custom = EditorExport::get_singleton()->get_export_preset(i)->get_custom_features();
  730. Vector<String> custom_list = custom.split(",");
  731. for (int i = 0; i < custom_list.size(); i++) {
  732. String f = custom_list[i].strip_edges();
  733. if (f != String()) {
  734. presets.insert(f);
  735. }
  736. }
  737. }
  738. popup_copy_to_feature->get_popup()->clear();
  739. int id = 0;
  740. for (Set<String>::Element *E = presets.front(); E; E = E->next()) {
  741. popup_copy_to_feature->get_popup()->add_item(E->get(), id++);
  742. }
  743. }
  744. void ProjectSettingsEditor::_copy_to_platform(int p_which) {
  745. String path = globals_editor->get_property_editor()->get_selected_path();
  746. if (path == String()) {
  747. EditorNode::get_singleton()->show_warning(TTR("Select a setting item first!"));
  748. return;
  749. }
  750. String property = globals_editor->get_current_section().plus_file(path);
  751. undo_redo->create_action(TTR("Override for Feature"));
  752. Variant value = ProjectSettings::get_singleton()->get(property);
  753. if (property.find(".") != -1) { //overwriting overwrite, keep overwrite
  754. undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property);
  755. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property, value);
  756. }
  757. String feature = popup_copy_to_feature->get_popup()->get_item_text(p_which);
  758. String new_path = property + "." + feature;
  759. undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", new_path, value);
  760. if (ProjectSettings::get_singleton()->has_setting(new_path)) {
  761. undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", new_path, ProjectSettings::get_singleton()->get(new_path));
  762. }
  763. undo_redo->add_do_method(globals_editor, "update_category_list");
  764. undo_redo->add_undo_method(globals_editor, "update_category_list");
  765. undo_redo->add_do_method(this, "_settings_changed");
  766. undo_redo->add_undo_method(this, "_settings_changed");
  767. undo_redo->commit_action();
  768. }
  769. void ProjectSettingsEditor::add_translation(const String &p_translation) {
  770. _translation_add(p_translation);
  771. }
  772. void ProjectSettingsEditor::_translation_add(const String &p_path) {
  773. PoolStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
  774. for (int i = 0; i < translations.size(); i++) {
  775. if (translations[i] == p_path)
  776. return; //exists
  777. }
  778. translations.push_back(p_path);
  779. undo_redo->create_action(TTR("Add Translation"));
  780. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations", translations);
  781. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations", ProjectSettings::get_singleton()->get("locale/translations"));
  782. undo_redo->add_do_method(this, "_update_translations");
  783. undo_redo->add_undo_method(this, "_update_translations");
  784. undo_redo->add_do_method(this, "_settings_changed");
  785. undo_redo->add_undo_method(this, "_settings_changed");
  786. undo_redo->commit_action();
  787. }
  788. void ProjectSettingsEditor::_translation_file_open() {
  789. translation_file_open->popup_centered_ratio();
  790. }
  791. void ProjectSettingsEditor::_translation_delete(Object *p_item, int p_column, int p_button) {
  792. TreeItem *ti = Object::cast_to<TreeItem>(p_item);
  793. ERR_FAIL_COND(!ti);
  794. int idx = ti->get_metadata(0);
  795. PoolStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
  796. ERR_FAIL_INDEX(idx, translations.size());
  797. translations.remove(idx);
  798. undo_redo->create_action(TTR("Remove Translation"));
  799. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations", translations);
  800. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations", ProjectSettings::get_singleton()->get("locale/translations"));
  801. undo_redo->add_do_method(this, "_update_translations");
  802. undo_redo->add_undo_method(this, "_update_translations");
  803. undo_redo->add_do_method(this, "_settings_changed");
  804. undo_redo->add_undo_method(this, "_settings_changed");
  805. undo_redo->commit_action();
  806. }
  807. void ProjectSettingsEditor::_translation_res_file_open() {
  808. translation_res_file_open->popup_centered_ratio();
  809. }
  810. void ProjectSettingsEditor::_translation_res_add(const String &p_path) {
  811. Variant prev;
  812. Dictionary remaps;
  813. if (ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
  814. remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  815. prev = remaps;
  816. }
  817. if (remaps.has(p_path))
  818. return; //pointless already has it
  819. remaps[p_path] = PoolStringArray();
  820. undo_redo->create_action(TTR("Add Remapped Path"));
  821. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
  822. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", prev);
  823. undo_redo->add_do_method(this, "_update_translations");
  824. undo_redo->add_undo_method(this, "_update_translations");
  825. undo_redo->add_do_method(this, "_settings_changed");
  826. undo_redo->add_undo_method(this, "_settings_changed");
  827. undo_redo->commit_action();
  828. }
  829. void ProjectSettingsEditor::_translation_res_option_file_open() {
  830. translation_res_option_file_open->popup_centered_ratio();
  831. }
  832. void ProjectSettingsEditor::_translation_res_option_add(const String &p_path) {
  833. ERR_FAIL_COND(!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"));
  834. Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  835. TreeItem *k = translation_remap->get_selected();
  836. ERR_FAIL_COND(!k);
  837. String key = k->get_metadata(0);
  838. ERR_FAIL_COND(!remaps.has(key));
  839. PoolStringArray r = remaps[key];
  840. r.push_back(p_path + ":" + "en");
  841. remaps[key] = r;
  842. undo_redo->create_action(TTR("Resource Remap Add Remap"));
  843. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
  844. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
  845. undo_redo->add_do_method(this, "_update_translations");
  846. undo_redo->add_undo_method(this, "_update_translations");
  847. undo_redo->add_do_method(this, "_settings_changed");
  848. undo_redo->add_undo_method(this, "_settings_changed");
  849. undo_redo->commit_action();
  850. }
  851. void ProjectSettingsEditor::_translation_res_select() {
  852. if (updating_translations)
  853. return;
  854. call_deferred("_update_translations");
  855. }
  856. void ProjectSettingsEditor::_translation_res_option_changed() {
  857. if (updating_translations)
  858. return;
  859. if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"))
  860. return;
  861. Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  862. TreeItem *k = translation_remap->get_selected();
  863. ERR_FAIL_COND(!k);
  864. TreeItem *ed = translation_remap_options->get_edited();
  865. ERR_FAIL_COND(!ed);
  866. String key = k->get_metadata(0);
  867. int idx = ed->get_metadata(0);
  868. String path = ed->get_metadata(1);
  869. int which = ed->get_range(1);
  870. Vector<String> langs = TranslationServer::get_all_locales();
  871. ERR_FAIL_INDEX(which, langs.size());
  872. ERR_FAIL_COND(!remaps.has(key));
  873. PoolStringArray r = remaps[key];
  874. ERR_FAIL_INDEX(idx, r.size());
  875. if (translation_locales_idxs_remap.size() > 0) {
  876. r.set(idx, path + ":" + langs[translation_locales_idxs_remap[which]]);
  877. } else {
  878. r.set(idx, path + ":" + langs[which]);
  879. }
  880. remaps[key] = r;
  881. updating_translations = true;
  882. undo_redo->create_action(TTR("Change Resource Remap Language"));
  883. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
  884. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
  885. undo_redo->add_do_method(this, "_update_translations");
  886. undo_redo->add_undo_method(this, "_update_translations");
  887. undo_redo->add_do_method(this, "_settings_changed");
  888. undo_redo->add_undo_method(this, "_settings_changed");
  889. undo_redo->commit_action();
  890. updating_translations = false;
  891. }
  892. void ProjectSettingsEditor::_translation_res_delete(Object *p_item, int p_column, int p_button) {
  893. if (updating_translations)
  894. return;
  895. if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"))
  896. return;
  897. Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  898. TreeItem *k = Object::cast_to<TreeItem>(p_item);
  899. String key = k->get_metadata(0);
  900. ERR_FAIL_COND(!remaps.has(key));
  901. remaps.erase(key);
  902. undo_redo->create_action(TTR("Remove Resource Remap"));
  903. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
  904. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
  905. undo_redo->add_do_method(this, "_update_translations");
  906. undo_redo->add_undo_method(this, "_update_translations");
  907. undo_redo->add_do_method(this, "_settings_changed");
  908. undo_redo->add_undo_method(this, "_settings_changed");
  909. undo_redo->commit_action();
  910. }
  911. void ProjectSettingsEditor::_translation_res_option_delete(Object *p_item, int p_column, int p_button) {
  912. if (updating_translations)
  913. return;
  914. if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"))
  915. return;
  916. Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  917. TreeItem *k = translation_remap->get_selected();
  918. ERR_FAIL_COND(!k);
  919. TreeItem *ed = Object::cast_to<TreeItem>(p_item);
  920. ERR_FAIL_COND(!ed);
  921. String key = k->get_metadata(0);
  922. int idx = ed->get_metadata(0);
  923. ERR_FAIL_COND(!remaps.has(key));
  924. PoolStringArray r = remaps[key];
  925. ERR_FAIL_INDEX(idx, r.size());
  926. r.remove(idx);
  927. remaps[key] = r;
  928. undo_redo->create_action(TTR("Remove Resource Remap Option"));
  929. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translation_remaps", remaps);
  930. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translation_remaps", ProjectSettings::get_singleton()->get("locale/translation_remaps"));
  931. undo_redo->add_do_method(this, "_update_translations");
  932. undo_redo->add_undo_method(this, "_update_translations");
  933. undo_redo->add_do_method(this, "_settings_changed");
  934. undo_redo->add_undo_method(this, "_settings_changed");
  935. undo_redo->commit_action();
  936. }
  937. void ProjectSettingsEditor::_translation_filter_option_changed() {
  938. int sel_id = translation_locale_filter_mode->get_selected_id();
  939. TreeItem *t = translation_filter->get_selected();
  940. String locale = t->get_tooltip(0);
  941. bool checked = t->is_checked(0);
  942. Variant prev;
  943. Array f_locales_all;
  944. if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
  945. f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
  946. prev = f_locales_all;
  947. if (f_locales_all.size() != 2) {
  948. f_locales_all.clear();
  949. f_locales_all.append(sel_id);
  950. f_locales_all.append(Array());
  951. }
  952. } else {
  953. f_locales_all.append(sel_id);
  954. f_locales_all.append(Array());
  955. }
  956. Array f_locales = f_locales_all[1];
  957. int l_idx = f_locales.find(locale);
  958. if (checked) {
  959. if (l_idx == -1) {
  960. f_locales.append(locale);
  961. }
  962. } else {
  963. if (l_idx != -1) {
  964. f_locales.remove(l_idx);
  965. }
  966. }
  967. f_locales = f_locales.sort();
  968. undo_redo->create_action(TTR("Changed Locale Filter"));
  969. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
  970. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
  971. undo_redo->add_do_method(this, "_update_translations");
  972. undo_redo->add_undo_method(this, "_update_translations");
  973. undo_redo->add_do_method(this, "_settings_changed");
  974. undo_redo->add_undo_method(this, "_settings_changed");
  975. undo_redo->commit_action();
  976. }
  977. void ProjectSettingsEditor::_translation_filter_mode_changed(int p_mode) {
  978. int sel_id = translation_locale_filter_mode->get_selected_id();
  979. Variant prev;
  980. Array f_locales_all;
  981. if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
  982. f_locales_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
  983. prev = f_locales_all;
  984. if (f_locales_all.size() != 2) {
  985. f_locales_all.clear();
  986. f_locales_all.append(sel_id);
  987. f_locales_all.append(Array());
  988. } else {
  989. f_locales_all[0] = sel_id;
  990. }
  991. } else {
  992. f_locales_all.append(sel_id);
  993. f_locales_all.append(Array());
  994. }
  995. undo_redo->create_action(TTR("Changed Locale Filter Mode"));
  996. undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/locale_filter", f_locales_all);
  997. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/locale_filter", prev);
  998. undo_redo->add_do_method(this, "_update_translations");
  999. undo_redo->add_undo_method(this, "_update_translations");
  1000. undo_redo->add_do_method(this, "_settings_changed");
  1001. undo_redo->add_undo_method(this, "_settings_changed");
  1002. undo_redo->commit_action();
  1003. }
  1004. void ProjectSettingsEditor::_update_translations() {
  1005. //update translations
  1006. if (updating_translations)
  1007. return;
  1008. updating_translations = true;
  1009. translation_list->clear();
  1010. TreeItem *root = translation_list->create_item(NULL);
  1011. translation_list->set_hide_root(true);
  1012. if (ProjectSettings::get_singleton()->has_setting("locale/translations")) {
  1013. PoolStringArray translations = ProjectSettings::get_singleton()->get("locale/translations");
  1014. for (int i = 0; i < translations.size(); i++) {
  1015. TreeItem *t = translation_list->create_item(root);
  1016. t->set_editable(0, false);
  1017. t->set_text(0, translations[i].replace_first("res://", ""));
  1018. t->set_tooltip(0, translations[i]);
  1019. t->set_metadata(0, i);
  1020. t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  1021. }
  1022. }
  1023. Vector<String> langs = TranslationServer::get_all_locales();
  1024. Vector<String> names = TranslationServer::get_all_locale_names();
  1025. //update filter tab
  1026. Array l_filter_all;
  1027. bool is_arr_empty = true;
  1028. if (ProjectSettings::get_singleton()->has_setting("locale/locale_filter")) {
  1029. l_filter_all = ProjectSettings::get_singleton()->get("locale/locale_filter");
  1030. if (l_filter_all.size() == 2) {
  1031. translation_locale_filter_mode->select(l_filter_all[0]);
  1032. is_arr_empty = false;
  1033. }
  1034. }
  1035. if (is_arr_empty) {
  1036. l_filter_all.append(0);
  1037. l_filter_all.append(Array());
  1038. translation_locale_filter_mode->select(0);
  1039. }
  1040. int filter_mode = l_filter_all[0];
  1041. Array l_filter = l_filter_all[1];
  1042. int s = names.size();
  1043. if (!translation_locales_list_created) {
  1044. translation_locales_list_created = true;
  1045. translation_filter->clear();
  1046. root = translation_filter->create_item(NULL);
  1047. translation_filter->set_hide_root(true);
  1048. translation_filter_treeitems.resize(s);
  1049. for (int i = 0; i < s; i++) {
  1050. String n = names[i];
  1051. String l = langs[i];
  1052. TreeItem *t = translation_filter->create_item(root);
  1053. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  1054. t->set_text(0, n);
  1055. t->set_editable(0, true);
  1056. t->set_tooltip(0, l);
  1057. t->set_checked(0, l_filter.has(l));
  1058. translation_filter_treeitems[i] = t;
  1059. }
  1060. } else {
  1061. for (int i = 0; i < s; i++) {
  1062. TreeItem *t = translation_filter_treeitems[i];
  1063. t->set_checked(0, l_filter.has(t->get_tooltip(0)));
  1064. }
  1065. }
  1066. //update translation remaps
  1067. String remap_selected;
  1068. if (translation_remap->get_selected()) {
  1069. remap_selected = translation_remap->get_selected()->get_metadata(0);
  1070. }
  1071. translation_remap->clear();
  1072. translation_remap_options->clear();
  1073. root = translation_remap->create_item(NULL);
  1074. TreeItem *root2 = translation_remap_options->create_item(NULL);
  1075. translation_remap->set_hide_root(true);
  1076. translation_remap_options->set_hide_root(true);
  1077. translation_res_option_add_button->set_disabled(true);
  1078. translation_locales_idxs_remap.clear();
  1079. translation_locales_idxs_remap.resize(l_filter.size());
  1080. int fl_idx_count = translation_locales_idxs_remap.size();
  1081. String langnames = "";
  1082. int l_idx = 0;
  1083. for (int i = 0; i < names.size(); i++) {
  1084. if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && fl_idx_count != 0) {
  1085. if (l_filter.size() > 0) {
  1086. if (l_filter.find(langs[i]) != -1) {
  1087. if (langnames.length() > 0)
  1088. langnames += ",";
  1089. langnames += names[i];
  1090. translation_locales_idxs_remap[l_idx] = i;
  1091. l_idx++;
  1092. }
  1093. }
  1094. } else {
  1095. if (i > 0)
  1096. langnames += ",";
  1097. langnames += names[i];
  1098. }
  1099. }
  1100. if (ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) {
  1101. Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
  1102. List<Variant> rk;
  1103. remaps.get_key_list(&rk);
  1104. Vector<String> keys;
  1105. for (List<Variant>::Element *E = rk.front(); E; E = E->next()) {
  1106. keys.push_back(E->get());
  1107. }
  1108. keys.sort();
  1109. for (int i = 0; i < keys.size(); i++) {
  1110. TreeItem *t = translation_remap->create_item(root);
  1111. t->set_editable(0, false);
  1112. t->set_text(0, keys[i].replace_first("res://", ""));
  1113. t->set_tooltip(0, keys[i]);
  1114. t->set_metadata(0, keys[i]);
  1115. t->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  1116. if (keys[i] == remap_selected) {
  1117. t->select(0);
  1118. translation_res_option_add_button->set_disabled(false);
  1119. PoolStringArray selected = remaps[keys[i]];
  1120. for (int j = 0; j < selected.size(); j++) {
  1121. String s = selected[j];
  1122. int qp = s.find_last(":");
  1123. String path = s.substr(0, qp);
  1124. String locale = s.substr(qp + 1, s.length());
  1125. TreeItem *t2 = translation_remap_options->create_item(root2);
  1126. t2->set_editable(0, false);
  1127. t2->set_text(0, path.replace_first("res://", ""));
  1128. t2->set_tooltip(0, path);
  1129. t2->set_metadata(0, j);
  1130. t2->add_button(0, get_icon("Del", "EditorIcons"), 0, false, TTR("Remove"));
  1131. t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
  1132. t2->set_text(1, langnames);
  1133. t2->set_editable(1, true);
  1134. t2->set_metadata(1, path);
  1135. int idx = langs.find(locale);
  1136. //print_line("find " + locale + " at " + itos(idx));
  1137. if (idx < 0)
  1138. idx = 0;
  1139. int f_idx = translation_locales_idxs_remap.find(idx);
  1140. if (f_idx != -1 && fl_idx_count > 0 && filter_mode == SHOW_ONLY_SELECTED_LOCALES) {
  1141. t2->set_range(1, f_idx);
  1142. } else {
  1143. t2->set_range(1, idx);
  1144. }
  1145. }
  1146. }
  1147. }
  1148. }
  1149. updating_translations = false;
  1150. }
  1151. void ProjectSettingsEditor::_toggle_search_bar(bool p_pressed) {
  1152. globals_editor->get_property_editor()->set_use_filter(p_pressed);
  1153. if (p_pressed) {
  1154. search_bar->show();
  1155. add_prop_bar->hide();
  1156. search_box->grab_focus();
  1157. search_box->select_all();
  1158. } else {
  1159. search_bar->hide();
  1160. add_prop_bar->show();
  1161. }
  1162. }
  1163. void ProjectSettingsEditor::_clear_search_box() {
  1164. if (search_box->get_text() == "")
  1165. return;
  1166. search_box->clear();
  1167. globals_editor->get_property_editor()->update_tree();
  1168. }
  1169. void ProjectSettingsEditor::set_plugins_page() {
  1170. tab_container->set_current_tab(plugin_settings->get_index());
  1171. }
  1172. TabContainer *ProjectSettingsEditor::get_tabs() {
  1173. return tab_container;
  1174. }
  1175. void ProjectSettingsEditor::_bind_methods() {
  1176. ClassDB::bind_method(D_METHOD("_item_selected"), &ProjectSettingsEditor::_item_selected);
  1177. ClassDB::bind_method(D_METHOD("_item_add"), &ProjectSettingsEditor::_item_add);
  1178. ClassDB::bind_method(D_METHOD("_item_adds"), &ProjectSettingsEditor::_item_adds);
  1179. ClassDB::bind_method(D_METHOD("_item_del"), &ProjectSettingsEditor::_item_del);
  1180. ClassDB::bind_method(D_METHOD("_item_checked"), &ProjectSettingsEditor::_item_checked);
  1181. ClassDB::bind_method(D_METHOD("_save"), &ProjectSettingsEditor::_save);
  1182. ClassDB::bind_method(D_METHOD("_action_add"), &ProjectSettingsEditor::_action_add);
  1183. ClassDB::bind_method(D_METHOD("_action_adds"), &ProjectSettingsEditor::_action_adds);
  1184. ClassDB::bind_method(D_METHOD("_action_check"), &ProjectSettingsEditor::_action_check);
  1185. ClassDB::bind_method(D_METHOD("_action_selected"), &ProjectSettingsEditor::_action_selected);
  1186. ClassDB::bind_method(D_METHOD("_action_edited"), &ProjectSettingsEditor::_action_edited);
  1187. ClassDB::bind_method(D_METHOD("_action_activated"), &ProjectSettingsEditor::_action_activated);
  1188. ClassDB::bind_method(D_METHOD("_action_button_pressed"), &ProjectSettingsEditor::_action_button_pressed);
  1189. ClassDB::bind_method(D_METHOD("_update_actions"), &ProjectSettingsEditor::_update_actions);
  1190. ClassDB::bind_method(D_METHOD("_wait_for_key"), &ProjectSettingsEditor::_wait_for_key);
  1191. ClassDB::bind_method(D_METHOD("_add_item"), &ProjectSettingsEditor::_add_item, DEFVAL(Variant()));
  1192. ClassDB::bind_method(D_METHOD("_device_input_add"), &ProjectSettingsEditor::_device_input_add);
  1193. ClassDB::bind_method(D_METHOD("_press_a_key_confirm"), &ProjectSettingsEditor::_press_a_key_confirm);
  1194. ClassDB::bind_method(D_METHOD("_settings_prop_edited"), &ProjectSettingsEditor::_settings_prop_edited);
  1195. ClassDB::bind_method(D_METHOD("_copy_to_platform"), &ProjectSettingsEditor::_copy_to_platform);
  1196. ClassDB::bind_method(D_METHOD("_update_translations"), &ProjectSettingsEditor::_update_translations);
  1197. ClassDB::bind_method(D_METHOD("_translation_delete"), &ProjectSettingsEditor::_translation_delete);
  1198. ClassDB::bind_method(D_METHOD("_settings_changed"), &ProjectSettingsEditor::_settings_changed);
  1199. ClassDB::bind_method(D_METHOD("_translation_add"), &ProjectSettingsEditor::_translation_add);
  1200. ClassDB::bind_method(D_METHOD("_translation_file_open"), &ProjectSettingsEditor::_translation_file_open);
  1201. ClassDB::bind_method(D_METHOD("_translation_res_add"), &ProjectSettingsEditor::_translation_res_add);
  1202. ClassDB::bind_method(D_METHOD("_translation_res_file_open"), &ProjectSettingsEditor::_translation_res_file_open);
  1203. ClassDB::bind_method(D_METHOD("_translation_res_option_add"), &ProjectSettingsEditor::_translation_res_option_add);
  1204. ClassDB::bind_method(D_METHOD("_translation_res_option_file_open"), &ProjectSettingsEditor::_translation_res_option_file_open);
  1205. ClassDB::bind_method(D_METHOD("_translation_res_select"), &ProjectSettingsEditor::_translation_res_select);
  1206. ClassDB::bind_method(D_METHOD("_translation_res_option_changed"), &ProjectSettingsEditor::_translation_res_option_changed);
  1207. ClassDB::bind_method(D_METHOD("_translation_res_delete"), &ProjectSettingsEditor::_translation_res_delete);
  1208. ClassDB::bind_method(D_METHOD("_translation_res_option_delete"), &ProjectSettingsEditor::_translation_res_option_delete);
  1209. ClassDB::bind_method(D_METHOD("_translation_filter_option_changed"), &ProjectSettingsEditor::_translation_filter_option_changed);
  1210. ClassDB::bind_method(D_METHOD("_translation_filter_mode_changed"), &ProjectSettingsEditor::_translation_filter_mode_changed);
  1211. ClassDB::bind_method(D_METHOD("_clear_search_box"), &ProjectSettingsEditor::_clear_search_box);
  1212. ClassDB::bind_method(D_METHOD("_toggle_search_bar"), &ProjectSettingsEditor::_toggle_search_bar);
  1213. ClassDB::bind_method(D_METHOD("_copy_to_platform_about_to_show"), &ProjectSettingsEditor::_copy_to_platform_about_to_show);
  1214. ClassDB::bind_method(D_METHOD("get_tabs"), &ProjectSettingsEditor::get_tabs);
  1215. }
  1216. ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
  1217. singleton = this;
  1218. set_title(TTR("Project Settings (project.godot)"));
  1219. set_resizable(true);
  1220. undo_redo = &p_data->get_undo_redo();
  1221. data = p_data;
  1222. tab_container = memnew(TabContainer);
  1223. tab_container->set_tab_align(TabContainer::ALIGN_LEFT);
  1224. add_child(tab_container);
  1225. VBoxContainer *props_base = memnew(VBoxContainer);
  1226. props_base->set_alignment(BoxContainer::ALIGN_BEGIN);
  1227. props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1228. tab_container->add_child(props_base);
  1229. props_base->set_name(TTR("General"));
  1230. HBoxContainer *hbc = memnew(HBoxContainer);
  1231. hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1232. props_base->add_child(hbc);
  1233. search_button = memnew(ToolButton);
  1234. search_button->set_toggle_mode(true);
  1235. search_button->set_pressed(false);
  1236. search_button->set_text(TTR("Search"));
  1237. hbc->add_child(search_button);
  1238. search_button->connect("toggled", this, "_toggle_search_bar");
  1239. hbc->add_child(memnew(VSeparator));
  1240. add_prop_bar = memnew(HBoxContainer);
  1241. add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1242. hbc->add_child(add_prop_bar);
  1243. Label *l = memnew(Label);
  1244. add_prop_bar->add_child(l);
  1245. l->set_text(TTR("Category:"));
  1246. category = memnew(LineEdit);
  1247. category->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1248. add_prop_bar->add_child(category);
  1249. category->connect("text_entered", this, "_item_adds");
  1250. l = memnew(Label);
  1251. add_prop_bar->add_child(l);
  1252. l->set_text(TTR("Property:"));
  1253. property = memnew(LineEdit);
  1254. property->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1255. add_prop_bar->add_child(property);
  1256. property->connect("text_entered", this, "_item_adds");
  1257. l = memnew(Label);
  1258. add_prop_bar->add_child(l);
  1259. l->set_text(TTR("Type:"));
  1260. type = memnew(OptionButton);
  1261. type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1262. add_prop_bar->add_child(type);
  1263. type->add_item("bool");
  1264. type->add_item("int");
  1265. type->add_item("float");
  1266. type->add_item("string");
  1267. Button *add = memnew(Button);
  1268. add_prop_bar->add_child(add);
  1269. add->set_text(TTR("Add"));
  1270. add->connect("pressed", this, "_item_add");
  1271. search_bar = memnew(HBoxContainer);
  1272. search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1273. hbc->add_child(search_bar);
  1274. search_bar->hide();
  1275. search_box = memnew(LineEdit);
  1276. search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1277. search_bar->add_child(search_box);
  1278. clear_button = memnew(ToolButton);
  1279. search_bar->add_child(clear_button);
  1280. clear_button->connect("pressed", this, "_clear_search_box");
  1281. globals_editor = memnew(SectionedPropertyEditor);
  1282. props_base->add_child(globals_editor);
  1283. globals_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
  1284. globals_editor->get_property_editor()->set_property_selectable(true);
  1285. //globals_editor->hide_top_label();
  1286. globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1287. globals_editor->register_search_box(search_box);
  1288. globals_editor->get_property_editor()->get_scene_tree()->connect("cell_selected", this, "_item_selected");
  1289. globals_editor->get_property_editor()->connect("property_toggled", this, "_item_checked", varray(), CONNECT_DEFERRED);
  1290. globals_editor->get_property_editor()->connect("property_edited", this, "_settings_prop_edited");
  1291. Button *del = memnew(Button);
  1292. hbc->add_child(del);
  1293. del->set_text(TTR("Delete"));
  1294. del->connect("pressed", this, "_item_del");
  1295. add_prop_bar->add_child(memnew(VSeparator));
  1296. popup_copy_to_feature = memnew(MenuButton);
  1297. popup_copy_to_feature->set_text(TTR("Override For.."));
  1298. popup_copy_to_feature->set_disabled(true);
  1299. add_prop_bar->add_child(popup_copy_to_feature);
  1300. popup_copy_to_feature->get_popup()->connect("id_pressed", this, "_copy_to_platform");
  1301. popup_copy_to_feature->get_popup()->connect("about_to_show", this, "_copy_to_platform_about_to_show");
  1302. get_ok()->set_text(TTR("Close"));
  1303. set_hide_on_ok(true);
  1304. message = memnew(AcceptDialog);
  1305. add_child(message);
  1306. Control *input_base = memnew(Control);
  1307. input_base->set_name(TTR("Input Map"));
  1308. tab_container->add_child(input_base);
  1309. VBoxContainer *vbc = memnew(VBoxContainer);
  1310. input_base->add_child(vbc);
  1311. vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
  1312. vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
  1313. vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0);
  1314. vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
  1315. l = memnew(Label);
  1316. vbc->add_child(l);
  1317. l->set_text(TTR("Action:"));
  1318. hbc = memnew(HBoxContainer);
  1319. vbc->add_child(hbc);
  1320. action_name = memnew(LineEdit);
  1321. action_name->set_h_size_flags(SIZE_EXPAND_FILL);
  1322. hbc->add_child(action_name);
  1323. action_name->connect("text_entered", this, "_action_adds");
  1324. action_name->connect("text_changed", this, "_action_check");
  1325. action_add_error = memnew(Label);
  1326. hbc->add_child(action_add_error);
  1327. action_add_error->hide();
  1328. add = memnew(Button);
  1329. hbc->add_child(add);
  1330. add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
  1331. add->set_text(TTR("Add"));
  1332. add->set_disabled(true);
  1333. add->connect("pressed", this, "_action_add");
  1334. action_add = add;
  1335. input_editor = memnew(Tree);
  1336. vbc->add_child(input_editor);
  1337. input_editor->set_v_size_flags(SIZE_EXPAND_FILL);
  1338. input_editor->connect("item_edited", this, "_action_edited");
  1339. input_editor->connect("item_activated", this, "_action_activated");
  1340. input_editor->connect("cell_selected", this, "_action_selected");
  1341. input_editor->connect("button_pressed", this, "_action_button_pressed");
  1342. popup_add = memnew(PopupMenu);
  1343. add_child(popup_add);
  1344. popup_add->connect("id_pressed", this, "_add_item");
  1345. press_a_key = memnew(ConfirmationDialog);
  1346. press_a_key->set_focus_mode(FOCUS_ALL);
  1347. add_child(press_a_key);
  1348. l = memnew(Label);
  1349. l->set_text(TTR("Press a Key.."));
  1350. l->set_anchors_and_margins_preset(Control::PRESET_WIDE);
  1351. l->set_align(Label::ALIGN_CENTER);
  1352. l->set_margin(MARGIN_TOP, 20);
  1353. l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30);
  1354. press_a_key_label = l;
  1355. press_a_key->add_child(l);
  1356. press_a_key->connect("gui_input", this, "_wait_for_key");
  1357. press_a_key->connect("confirmed", this, "_press_a_key_confirm");
  1358. device_input = memnew(ConfirmationDialog);
  1359. add_child(device_input);
  1360. device_input->get_ok()->set_text(TTR("Add"));
  1361. device_input->connect("confirmed", this, "_device_input_add");
  1362. hbc = memnew(HBoxContainer);
  1363. device_input->add_child(hbc);
  1364. VBoxContainer *vbc_left = memnew(VBoxContainer);
  1365. hbc->add_child(vbc_left);
  1366. l = memnew(Label);
  1367. l->set_text(TTR("Device:"));
  1368. vbc_left->add_child(l);
  1369. device_id = memnew(SpinBox);
  1370. device_id->set_value(0);
  1371. vbc_left->add_child(device_id);
  1372. VBoxContainer *vbc_right = memnew(VBoxContainer);
  1373. hbc->add_child(vbc_right);
  1374. vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
  1375. l = memnew(Label);
  1376. l->set_text(TTR("Index:"));
  1377. vbc_right->add_child(l);
  1378. device_index_label = l;
  1379. device_index = memnew(OptionButton);
  1380. vbc_right->add_child(device_index);
  1381. setting = false;
  1382. //translations
  1383. TabContainer *translations = memnew(TabContainer);
  1384. translations->add_style_override("panel", memnew(StyleBoxEmpty));
  1385. translations->set_tab_align(TabContainer::ALIGN_LEFT);
  1386. translations->set_name(TTR("Localization"));
  1387. tab_container->add_child(translations);
  1388. //remap for properly select language in popup
  1389. translation_locales_idxs_remap = Vector<int>();
  1390. {
  1391. VBoxContainer *tvb = memnew(VBoxContainer);
  1392. translations->add_child(tvb);
  1393. tvb->set_name(TTR("Translations"));
  1394. HBoxContainer *thb = memnew(HBoxContainer);
  1395. tvb->add_child(thb);
  1396. thb->add_child(memnew(Label(TTR("Translations:"))));
  1397. thb->add_spacer();
  1398. Button *addtr = memnew(Button(TTR("Add..")));
  1399. addtr->connect("pressed", this, "_translation_file_open");
  1400. thb->add_child(addtr);
  1401. VBoxContainer *tmc = memnew(VBoxContainer);
  1402. tvb->add_child(tmc);
  1403. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1404. translation_list = memnew(Tree);
  1405. translation_list->set_v_size_flags(SIZE_EXPAND_FILL);
  1406. tmc->add_child(translation_list);
  1407. translation_file_open = memnew(EditorFileDialog);
  1408. add_child(translation_file_open);
  1409. translation_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1410. translation_file_open->connect("file_selected", this, "_translation_add");
  1411. }
  1412. {
  1413. VBoxContainer *tvb = memnew(VBoxContainer);
  1414. translations->add_child(tvb);
  1415. tvb->set_name(TTR("Remaps"));
  1416. HBoxContainer *thb = memnew(HBoxContainer);
  1417. tvb->add_child(thb);
  1418. thb->add_child(memnew(Label(TTR("Resources:"))));
  1419. thb->add_spacer();
  1420. Button *addtr = memnew(Button(TTR("Add..")));
  1421. addtr->connect("pressed", this, "_translation_res_file_open");
  1422. thb->add_child(addtr);
  1423. VBoxContainer *tmc = memnew(VBoxContainer);
  1424. tvb->add_child(tmc);
  1425. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1426. translation_remap = memnew(Tree);
  1427. translation_remap->set_v_size_flags(SIZE_EXPAND_FILL);
  1428. translation_remap->connect("cell_selected", this, "_translation_res_select");
  1429. tmc->add_child(translation_remap);
  1430. translation_remap->connect("button_pressed", this, "_translation_res_delete");
  1431. translation_res_file_open = memnew(EditorFileDialog);
  1432. add_child(translation_res_file_open);
  1433. translation_res_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1434. translation_res_file_open->connect("file_selected", this, "_translation_res_add");
  1435. thb = memnew(HBoxContainer);
  1436. tvb->add_child(thb);
  1437. thb->add_child(memnew(Label(TTR("Remaps by Locale:"))));
  1438. thb->add_spacer();
  1439. addtr = memnew(Button(TTR("Add..")));
  1440. addtr->connect("pressed", this, "_translation_res_option_file_open");
  1441. translation_res_option_add_button = addtr;
  1442. thb->add_child(addtr);
  1443. tmc = memnew(VBoxContainer);
  1444. tvb->add_child(tmc);
  1445. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1446. translation_remap_options = memnew(Tree);
  1447. translation_remap_options->set_v_size_flags(SIZE_EXPAND_FILL);
  1448. tmc->add_child(translation_remap_options);
  1449. translation_remap_options->set_columns(2);
  1450. translation_remap_options->set_column_title(0, TTR("Path"));
  1451. translation_remap_options->set_column_title(1, TTR("Locale"));
  1452. translation_remap_options->set_column_titles_visible(true);
  1453. translation_remap_options->set_column_expand(0, true);
  1454. translation_remap_options->set_column_expand(1, false);
  1455. translation_remap_options->set_column_min_width(1, 200);
  1456. translation_remap_options->connect("item_edited", this, "_translation_res_option_changed");
  1457. translation_remap_options->connect("button_pressed", this, "_translation_res_option_delete");
  1458. translation_res_option_file_open = memnew(EditorFileDialog);
  1459. add_child(translation_res_option_file_open);
  1460. translation_res_option_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
  1461. translation_res_option_file_open->connect("file_selected", this, "_translation_res_option_add");
  1462. }
  1463. {
  1464. VBoxContainer *tvb = memnew(VBoxContainer);
  1465. translations->add_child(tvb);
  1466. tvb->set_name(TTR("Locales Filter"));
  1467. VBoxContainer *tmc = memnew(VBoxContainer);
  1468. tmc->set_v_size_flags(SIZE_EXPAND_FILL);
  1469. tvb->add_child(tmc);
  1470. translation_locale_filter_mode = memnew(OptionButton);
  1471. translation_locale_filter_mode->add_item(TTR("Show all locales"), SHOW_ALL_LOCALES);
  1472. translation_locale_filter_mode->add_item(TTR("Show only selected locales"), SHOW_ONLY_SELECTED_LOCALES);
  1473. translation_locale_filter_mode->select(0);
  1474. tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode);
  1475. translation_locale_filter_mode->connect("item_selected", this, "_translation_filter_mode_changed");
  1476. translation_filter = memnew(Tree);
  1477. translation_filter->set_v_size_flags(SIZE_EXPAND_FILL);
  1478. translation_filter->set_columns(1);
  1479. tmc->add_child(memnew(Label(TTR("Locales:"))));
  1480. tmc->add_child(translation_filter);
  1481. translation_filter->connect("item_edited", this, "_translation_filter_option_changed");
  1482. }
  1483. {
  1484. autoload_settings = memnew(EditorAutoloadSettings);
  1485. autoload_settings->set_name(TTR("AutoLoad"));
  1486. tab_container->add_child(autoload_settings);
  1487. autoload_settings->connect("autoload_changed", this, "_settings_changed");
  1488. }
  1489. {
  1490. plugin_settings = memnew(EditorPluginSettings);
  1491. plugin_settings->set_name(TTR("Plugins"));
  1492. tab_container->add_child(plugin_settings);
  1493. }
  1494. timer = memnew(Timer);
  1495. timer->set_wait_time(1.5);
  1496. timer->connect("timeout", ProjectSettings::get_singleton(), "save");
  1497. timer->set_one_shot(true);
  1498. add_child(timer);
  1499. updating_translations = false;
  1500. }