tile_map_editor_plugin.cpp 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302
  1. /**************************************************************************/
  2. /* tile_map_editor_plugin.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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 "tile_map_editor_plugin.h"
  31. #include "canvas_item_editor_plugin.h"
  32. #include "core/math/math_funcs.h"
  33. #include "core/os/input.h"
  34. #include "core/os/keyboard.h"
  35. #include "editor/editor_scale.h"
  36. #include "editor/editor_settings.h"
  37. #include "scene/gui/split_container.h"
  38. static float _lerp_fade(int total, int fade, float position) {
  39. if (position < fade) {
  40. return Math::inverse_lerp(0, fade, position);
  41. } else if (position > (total - fade)) {
  42. return Math::inverse_lerp(total, total - fade, position);
  43. }
  44. return 1.0;
  45. }
  46. void TileMapEditor::_node_removed(Node *p_node) {
  47. if (p_node == node) {
  48. node = nullptr;
  49. }
  50. }
  51. void TileMapEditor::_notification(int p_what) {
  52. switch (p_what) {
  53. case NOTIFICATION_PROCESS: {
  54. if (bucket_queue.size()) {
  55. CanvasItemEditor::get_singleton()->update_viewport();
  56. }
  57. } break;
  58. case NOTIFICATION_ENTER_TREE: {
  59. get_tree()->connect("node_removed", this, "_node_removed");
  60. FALLTHROUGH;
  61. }
  62. case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
  63. if (is_visible_in_tree()) {
  64. _update_palette();
  65. }
  66. paint_button->set_icon(get_icon("Edit", "EditorIcons"));
  67. bucket_fill_button->set_icon(get_icon("Bucket", "EditorIcons"));
  68. picker_button->set_icon(get_icon("ColorPick", "EditorIcons"));
  69. select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
  70. rotate_left_button->set_icon(get_icon("RotateLeft", "EditorIcons"));
  71. rotate_right_button->set_icon(get_icon("RotateRight", "EditorIcons"));
  72. flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons"));
  73. flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons"));
  74. clear_transform_button->set_icon(get_icon("Clear", "EditorIcons"));
  75. search_box->set_right_icon(get_icon("Search", "EditorIcons"));
  76. search_box->set_clear_button_enabled(true);
  77. PopupMenu *p = options->get_popup();
  78. p->set_item_icon(p->get_item_index(OPTION_CUT), get_icon("ActionCut", "EditorIcons"));
  79. p->set_item_icon(p->get_item_index(OPTION_COPY), get_icon("Duplicate", "EditorIcons"));
  80. p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_icon("Remove", "EditorIcons"));
  81. } break;
  82. case NOTIFICATION_EXIT_TREE: {
  83. get_tree()->disconnect("node_removed", this, "_node_removed");
  84. } break;
  85. case NOTIFICATION_WM_FOCUS_OUT: {
  86. if (tool == TOOL_PAINTING) {
  87. Vector<int> ids = get_selected_tiles();
  88. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  89. _set_cell(over_tile, ids, flip_h, flip_v, transpose);
  90. _finish_undo();
  91. paint_undo.clear();
  92. }
  93. tool = TOOL_NONE;
  94. _update_button_tool();
  95. }
  96. // set flag to ignore over_tile on refocus
  97. refocus_over_tile = true;
  98. } break;
  99. }
  100. }
  101. void TileMapEditor::_update_button_tool() {
  102. ToolButton *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button };
  103. // Unpress all buttons
  104. for (int i = 0; i < 4; i++) {
  105. tb[i]->set_pressed(false);
  106. }
  107. // Press the good button
  108. switch (tool) {
  109. case TOOL_NONE:
  110. case TOOL_PAINTING: {
  111. paint_button->set_pressed(true);
  112. } break;
  113. case TOOL_BUCKET: {
  114. bucket_fill_button->set_pressed(true);
  115. } break;
  116. case TOOL_PICKING: {
  117. picker_button->set_pressed(true);
  118. } break;
  119. case TOOL_SELECTING: {
  120. select_button->set_pressed(true);
  121. } break;
  122. default:
  123. break;
  124. }
  125. if (tool != TOOL_PICKING) {
  126. last_tool = tool;
  127. }
  128. }
  129. void TileMapEditor::_button_tool_select(int p_tool) {
  130. if (_mouse_buttons_pressed) {
  131. // Disallow changing tool when drawing,
  132. // to prevent undo actions getting messed up
  133. // and out of sync.
  134. return;
  135. }
  136. tool = (Tool)p_tool;
  137. _update_button_tool();
  138. switch (tool) {
  139. case TOOL_SELECTING: {
  140. selection_active = false;
  141. } break;
  142. default:
  143. break;
  144. }
  145. CanvasItemEditor::get_singleton()->update_viewport();
  146. }
  147. void TileMapEditor::_menu_option(int p_option) {
  148. switch (p_option) {
  149. case OPTION_COPY: {
  150. _update_copydata();
  151. if (selection_active) {
  152. tool = TOOL_PASTING;
  153. CanvasItemEditor::get_singleton()->update_viewport();
  154. }
  155. } break;
  156. case OPTION_ERASE_SELECTION: {
  157. if (!selection_active) {
  158. return;
  159. }
  160. _start_undo(TTR("Erase Selection"));
  161. _erase_selection();
  162. _finish_undo();
  163. selection_active = false;
  164. copydata.clear();
  165. CanvasItemEditor::get_singleton()->update_viewport();
  166. } break;
  167. case OPTION_FIX_INVALID: {
  168. undo_redo->create_action(TTR("Fix Invalid Tiles"));
  169. undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
  170. node->fix_invalid_tiles();
  171. undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
  172. undo_redo->commit_action();
  173. } break;
  174. case OPTION_CUT: {
  175. if (selection_active) {
  176. _update_copydata();
  177. _start_undo(TTR("Cut Selection"));
  178. _erase_selection();
  179. _finish_undo();
  180. selection_active = false;
  181. tool = TOOL_PASTING;
  182. CanvasItemEditor::get_singleton()->update_viewport();
  183. }
  184. } break;
  185. }
  186. _update_button_tool();
  187. }
  188. void TileMapEditor::_palette_selected(int index) {
  189. _update_palette();
  190. }
  191. void TileMapEditor::_palette_multi_selected(int index, bool selected) {
  192. _update_palette();
  193. }
  194. void TileMapEditor::_palette_input(const Ref<InputEvent> &p_event) {
  195. const Ref<InputEventMouseButton> mb = p_event;
  196. // Zoom in/out using Ctrl + mouse wheel.
  197. if (mb.is_valid() && mb->is_pressed() && mb->get_command()) {
  198. if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
  199. size_slider->set_value(size_slider->get_value() + 0.2);
  200. }
  201. if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
  202. size_slider->set_value(size_slider->get_value() - 0.2);
  203. }
  204. }
  205. }
  206. void TileMapEditor::_canvas_mouse_enter() {
  207. mouse_over = true;
  208. CanvasItemEditor::get_singleton()->update_viewport();
  209. }
  210. void TileMapEditor::_canvas_mouse_exit() {
  211. mouse_over = false;
  212. CanvasItemEditor::get_singleton()->update_viewport();
  213. }
  214. Vector<int> TileMapEditor::get_selected_tiles() const {
  215. Vector<int> items = palette->get_selected_items();
  216. if (items.size() == 0) {
  217. items.push_back(TileMap::INVALID_CELL);
  218. return items;
  219. }
  220. for (int i = items.size() - 1; i >= 0; i--) {
  221. items.write[i] = palette->get_item_metadata(items[i]);
  222. }
  223. return items;
  224. }
  225. void TileMapEditor::set_selected_tiles(Vector<int> p_tiles) {
  226. palette->unselect_all();
  227. for (int i = p_tiles.size() - 1; i >= 0; i--) {
  228. int idx = palette->find_metadata(p_tiles[i]);
  229. if (idx >= 0) {
  230. palette->select(idx, false);
  231. }
  232. }
  233. palette->ensure_current_is_visible();
  234. }
  235. Dictionary TileMapEditor::_create_cell_dictionary(int tile, bool flip_x, bool flip_y, bool transpose, Vector2 autotile_coord) {
  236. Dictionary cell;
  237. cell["id"] = tile;
  238. cell["flip_h"] = flip_x;
  239. cell["flip_y"] = flip_y;
  240. cell["transpose"] = transpose;
  241. cell["auto_coord"] = autotile_coord;
  242. return cell;
  243. }
  244. void TileMapEditor::_create_set_cell_undo_redo(const Vector2 &p_vec, const CellOp &p_cell_old, const CellOp &p_cell_new) {
  245. Dictionary cell_old = _create_cell_dictionary(p_cell_old.idx, p_cell_old.xf, p_cell_old.yf, p_cell_old.tr, p_cell_old.ac);
  246. Dictionary cell_new = _create_cell_dictionary(p_cell_new.idx, p_cell_new.xf, p_cell_new.yf, p_cell_new.tr, p_cell_new.ac);
  247. undo_redo->add_undo_method(node, "_set_celld", p_vec, cell_old);
  248. undo_redo->add_do_method(node, "_set_celld", p_vec, cell_new);
  249. }
  250. void TileMapEditor::_start_undo(const String &p_action) {
  251. undo_data.clear();
  252. undo_redo->create_action(p_action);
  253. }
  254. void TileMapEditor::_finish_undo() {
  255. if (undo_data.size()) {
  256. for (Map<Point2i, CellOp>::Element *E = undo_data.front(); E; E = E->next()) {
  257. _create_set_cell_undo_redo(E->key(), E->get(), _get_op_from_cell(E->key()));
  258. }
  259. undo_data.clear();
  260. }
  261. undo_redo->commit_action();
  262. }
  263. void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord) {
  264. ERR_FAIL_COND(!node);
  265. if (p_values.size() == 0) {
  266. return;
  267. }
  268. int p_value = p_values[Math::rand() % p_values.size()];
  269. int prev_val = node->get_cell(p_pos.x, p_pos.y);
  270. bool prev_flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y);
  271. bool prev_flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y);
  272. bool prev_transpose = node->is_cell_transposed(p_pos.x, p_pos.y);
  273. Vector2 prev_position = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
  274. Vector2 position;
  275. int current = manual_palette->get_current();
  276. if (current != -1) {
  277. if (tool != TOOL_PASTING) {
  278. position = manual_palette->get_item_metadata(current);
  279. } else {
  280. position = p_autotile_coord;
  281. }
  282. } else {
  283. // If there is no manual tile selected, that either means that
  284. // autotiling is enabled, or the given tile is not autotiling. Either
  285. // way, the coordinate of the tile does not matter, so assigning it to
  286. // the coordinate of the existing tile works fine.
  287. position = prev_position;
  288. }
  289. if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose && prev_position == position) {
  290. return; // Check that it's actually different.
  291. }
  292. for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
  293. for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
  294. Point2i p = Point2i(x, y);
  295. if (!undo_data.has(p)) {
  296. undo_data[p] = _get_op_from_cell(p);
  297. }
  298. }
  299. }
  300. node->_set_celld(p_pos, _create_cell_dictionary(p_value, p_flip_h, p_flip_v, p_transpose, p_autotile_coord));
  301. if (tool == TOOL_PASTING) {
  302. return;
  303. }
  304. if (manual_autotile || (p_value != -1 && node->get_tileset()->has_tile(p_value) && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE)) {
  305. if (current != -1) {
  306. node->set_cell_autotile_coord(p_pos.x, p_pos.y, position);
  307. } else if (node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE && priority_atlastile) {
  308. // BIND_CENTER is used to indicate that bitmask should not update for this tile cell.
  309. node->get_tileset()->autotile_set_bitmask(p_value, Vector2(p_pos.x, p_pos.y), TileSet::BIND_CENTER);
  310. node->update_cell_bitmask(p_pos.x, p_pos.y);
  311. }
  312. } else {
  313. node->update_bitmask_area(Point2(p_pos));
  314. }
  315. }
  316. void TileMapEditor::_manual_toggled(bool p_enabled) {
  317. manual_autotile = p_enabled;
  318. _update_palette();
  319. }
  320. void TileMapEditor::_priority_toggled(bool p_enabled) {
  321. priority_atlastile = p_enabled;
  322. _update_palette();
  323. }
  324. void TileMapEditor::_text_entered(const String &p_text) {
  325. canvas_item_editor_viewport->grab_focus();
  326. }
  327. void TileMapEditor::_text_changed(const String &p_text) {
  328. _update_palette();
  329. }
  330. void TileMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
  331. Ref<InputEventKey> k = p_ie;
  332. if (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_PAGEUP || k->get_scancode() == KEY_PAGEDOWN)) {
  333. palette->call("_gui_input", k);
  334. search_box->accept_event();
  335. }
  336. }
  337. void TileMapEditor::_update_palette() {
  338. if (!node) {
  339. return;
  340. }
  341. // Update the clear button.
  342. clear_transform_button->set_disabled(!flip_h && !flip_v && !transpose);
  343. // Update the palette.
  344. Vector<int> selected = get_selected_tiles();
  345. int selected_single = palette->get_current();
  346. int selected_manual = manual_palette->get_current();
  347. palette->clear();
  348. manual_palette->clear();
  349. manual_palette->hide();
  350. Ref<TileSet> tileset = node->get_tileset();
  351. if (tileset.is_null()) {
  352. search_box->set_text("");
  353. search_box->set_editable(false);
  354. info_message->show();
  355. return;
  356. }
  357. search_box->set_editable(true);
  358. info_message->hide();
  359. List<int> tiles;
  360. tileset->get_tile_list(&tiles);
  361. if (tiles.empty()) {
  362. return;
  363. }
  364. float min_size = EDITOR_GET("editors/tile_map/preview_size");
  365. min_size *= EDSCALE;
  366. int hseparation = EDITOR_GET("editors/tile_map/palette_item_hseparation");
  367. bool show_tile_names = bool(EDITOR_GET("editors/tile_map/show_tile_names"));
  368. bool show_tile_ids = bool(EDITOR_GET("editors/tile_map/show_tile_ids"));
  369. bool sort_by_name = bool(EDITOR_GET("editors/tile_map/sort_tiles_by_name"));
  370. palette->add_constant_override("hseparation", hseparation * EDSCALE);
  371. palette->set_fixed_icon_size(Size2(min_size, min_size));
  372. palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1));
  373. palette->set_same_column_width(true);
  374. manual_palette->set_fixed_icon_size(Size2(min_size, min_size));
  375. manual_palette->set_same_column_width(true);
  376. String filter = search_box->get_text().strip_edges();
  377. struct _PaletteEntry {
  378. int id;
  379. String item_name;
  380. bool operator<(const _PaletteEntry &p_rhs) const {
  381. // Natural no case comparison will compare strings based on CharType
  382. // order (except digits) and on numbers that start on the same position.
  383. return item_name.naturalnocasecmp_to(p_rhs.item_name) < 0;
  384. }
  385. };
  386. Vector<_PaletteEntry> entries;
  387. for (List<int>::Element *E = tiles.front(); E; E = E->next()) {
  388. int id = E->get();
  389. String item_name;
  390. if (show_tile_ids) {
  391. item_name += "#" + itos(id);
  392. }
  393. if (show_tile_names) {
  394. String tile_name = tileset->tile_get_name(id);
  395. if (tile_name != "") {
  396. if (item_name != "") {
  397. item_name += " ";
  398. }
  399. item_name += tile_name;
  400. }
  401. }
  402. if (filter != "" && !filter.is_subsequence_ofi(item_name)) {
  403. continue;
  404. }
  405. const _PaletteEntry entry = { id, item_name };
  406. entries.push_back(entry);
  407. }
  408. if (sort_by_name) {
  409. entries.sort();
  410. }
  411. for (int i = 0; i < entries.size(); i++) {
  412. palette->add_item(entries[i].item_name);
  413. palette->set_item_tooltip(palette->get_item_count() - 1, "ID = " + itos(entries[i].id) + "\nName = " + tileset->tile_get_name(entries[i].id));
  414. Ref<Texture> tex = tileset->tile_get_texture(entries[i].id);
  415. if (tex.is_valid()) {
  416. Rect2 region = tileset->tile_get_region(entries[i].id);
  417. if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(entries[i].id) == TileSet::ATLAS_TILE) {
  418. int spacing = tileset->autotile_get_spacing(entries[i].id);
  419. region.size = tileset->autotile_get_size(entries[i].id);
  420. region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id);
  421. }
  422. // Transpose and flip.
  423. palette->set_item_icon_transposed(palette->get_item_count() - 1, transpose);
  424. if (flip_h) {
  425. region.size.x = -region.size.x;
  426. }
  427. if (flip_v) {
  428. region.size.y = -region.size.y;
  429. }
  430. // Set region.
  431. if (region.size != Size2()) {
  432. palette->set_item_icon_region(palette->get_item_count() - 1, region);
  433. }
  434. // Set icon.
  435. palette->set_item_icon(palette->get_item_count() - 1, tex);
  436. // Modulation.
  437. Color color = tileset->tile_get_modulate(entries[i].id);
  438. palette->set_item_icon_modulate(palette->get_item_count() - 1, color);
  439. }
  440. palette->set_item_metadata(palette->get_item_count() - 1, entries[i].id);
  441. }
  442. int sel_tile = selected.get(0);
  443. if (selected.get(0) != TileMap::INVALID_CELL) {
  444. set_selected_tiles(selected);
  445. sel_tile = selected.get(Math::rand() % selected.size());
  446. } else if (palette->get_item_count() > 0) {
  447. palette->select(0);
  448. sel_tile = palette->get_selected_items().get(0);
  449. }
  450. if (sel_tile != TileMap::INVALID_CELL && tileset->has_tile(sel_tile) && ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || (!priority_atlastile && tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE))) {
  451. const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile);
  452. Vector<Vector2> entries2;
  453. for (const Map<Vector2, uint32_t>::Element *E = tiles2.front(); E; E = E->next()) {
  454. entries2.push_back(E->key());
  455. }
  456. // Sort tiles in row-major order.
  457. struct SwapComparator {
  458. _FORCE_INLINE_ bool operator()(const Vector2 &v_l, const Vector2 &v_r) const {
  459. return v_l.y != v_r.y ? v_l.y < v_r.y : v_l.x < v_r.x;
  460. }
  461. };
  462. entries2.sort_custom<SwapComparator>();
  463. Ref<Texture> tex = tileset->tile_get_texture(sel_tile);
  464. Color modulate = tileset->tile_get_modulate(sel_tile);
  465. for (int i = 0; i < entries2.size(); i++) {
  466. manual_palette->add_item(String());
  467. manual_palette->set_item_tooltip(manual_palette->get_item_count() - 1, "Autotile Coords = (" + entries2[i].operator String() + ")");
  468. if (tex.is_valid()) {
  469. Rect2 region = tileset->tile_get_region(sel_tile);
  470. int spacing = tileset->autotile_get_spacing(sel_tile);
  471. region.size = tileset->autotile_get_size(sel_tile); // !!
  472. region.position += (region.size + Vector2(spacing, spacing)) * entries2[i];
  473. if (!region.has_no_area()) {
  474. manual_palette->set_item_icon_region(manual_palette->get_item_count() - 1, region);
  475. }
  476. manual_palette->set_item_icon(manual_palette->get_item_count() - 1, tex);
  477. manual_palette->set_item_icon_modulate(manual_palette->get_item_count() - 1, modulate);
  478. }
  479. manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries2[i]);
  480. }
  481. }
  482. if (manual_palette->get_item_count() > 0) {
  483. // Only show the manual palette if at least tile exists in it.
  484. if (selected_manual == -1 || selected_single != palette->get_current()) {
  485. selected_manual = 0;
  486. }
  487. if (selected_manual < manual_palette->get_item_count()) {
  488. manual_palette->set_current(selected_manual);
  489. }
  490. manual_palette->show();
  491. }
  492. if (sel_tile != TileMap::INVALID_CELL && tileset->has_tile(sel_tile) && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) {
  493. manual_button->show();
  494. priority_button->hide();
  495. } else {
  496. manual_button->hide();
  497. priority_button->show();
  498. }
  499. }
  500. void TileMapEditor::_pick_tile(const Point2 &p_pos) {
  501. int id = node->get_cell(p_pos.x, p_pos.y);
  502. if (id == TileMap::INVALID_CELL || !node->get_tileset()->has_tile(id)) {
  503. return;
  504. }
  505. if (search_box->get_text() != "") {
  506. search_box->set_text("");
  507. _update_palette();
  508. }
  509. flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y);
  510. flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y);
  511. transpose = node->is_cell_transposed(p_pos.x, p_pos.y);
  512. autotile_coord = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
  513. Vector<int> selected;
  514. selected.push_back(id);
  515. set_selected_tiles(selected);
  516. _update_palette();
  517. if ((manual_autotile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::AUTO_TILE) || (!priority_atlastile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::ATLAS_TILE)) {
  518. manual_palette->select(manual_palette->find_metadata((Point2)autotile_coord));
  519. }
  520. CanvasItemEditor::get_singleton()->update_viewport();
  521. }
  522. PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool erase, bool preview) {
  523. int prev_id = node->get_cell(p_start.x, p_start.y);
  524. Vector<int> ids;
  525. ids.push_back(TileMap::INVALID_CELL);
  526. if (!erase) {
  527. ids = get_selected_tiles();
  528. if (ids.size() == 0 || ids[0] == TileMap::INVALID_CELL) {
  529. return PoolVector<Vector2>();
  530. }
  531. } else if (prev_id == TileMap::INVALID_CELL) {
  532. return PoolVector<Vector2>();
  533. }
  534. // Check if the tile variation is the same
  535. if (ids.size() == 1 && ids[0] == prev_id) {
  536. int current = manual_palette->get_current();
  537. if (current == -1) {
  538. // Same ID, no variation selected, nothing to change
  539. return PoolVector<Vector2>();
  540. }
  541. Vector2 prev_autotile_coord = node->get_cell_autotile_coord(p_start.x, p_start.y);
  542. Vector2 autotile_coord = manual_palette->get_item_metadata(current);
  543. if (autotile_coord == prev_autotile_coord) {
  544. // Same ID and variation, nothing to change
  545. return PoolVector<Vector2>();
  546. }
  547. }
  548. Rect2i r = node->get_used_rect();
  549. int area = r.get_area();
  550. if (preview) {
  551. // Test if we can re-use the result from preview bucket fill
  552. bool invalidate_cache = false;
  553. // Area changed
  554. if (r != bucket_cache_rect) {
  555. _clear_bucket_cache();
  556. }
  557. // Cache grid is not initialized
  558. if (bucket_cache_visited == nullptr) {
  559. bucket_cache_visited = new bool[area];
  560. invalidate_cache = true;
  561. }
  562. // Tile ID changed or position wasn't visited by the previous fill
  563. const int loc = (p_start.x - r.position.x) + (p_start.y - r.position.y) * r.get_size().x;
  564. const bool in_range = 0 <= loc && loc < area;
  565. if (prev_id != bucket_cache_tile || (in_range && !bucket_cache_visited[loc])) {
  566. invalidate_cache = true;
  567. }
  568. if (invalidate_cache) {
  569. for (int i = 0; i < area; ++i) {
  570. bucket_cache_visited[i] = false;
  571. }
  572. bucket_cache = PoolVector<Vector2>();
  573. bucket_cache_tile = prev_id;
  574. bucket_cache_rect = r;
  575. bucket_queue.clear();
  576. }
  577. }
  578. PoolVector<Vector2> points;
  579. Vector<Vector2> non_preview_cache;
  580. int count = 0;
  581. int limit = 0;
  582. if (preview) {
  583. limit = 1024;
  584. } else {
  585. bucket_queue.clear();
  586. }
  587. bucket_queue.push_back(p_start);
  588. while (bucket_queue.size()) {
  589. Point2i n = bucket_queue.front()->get();
  590. bucket_queue.pop_front();
  591. if (!r.has_point(n)) {
  592. continue;
  593. }
  594. if (node->get_cell(n.x, n.y) == prev_id) {
  595. if (preview) {
  596. int loc = (n.x - r.position.x) + (n.y - r.position.y) * r.get_size().x;
  597. if (bucket_cache_visited[loc]) {
  598. continue;
  599. }
  600. bucket_cache_visited[loc] = true;
  601. bucket_cache.push_back(n);
  602. } else {
  603. if (non_preview_cache.find(n) >= 0) {
  604. continue;
  605. }
  606. points.push_back(n);
  607. non_preview_cache.push_back(n);
  608. }
  609. bucket_queue.push_back(Point2i(n.x, n.y + 1));
  610. bucket_queue.push_back(Point2i(n.x, n.y - 1));
  611. bucket_queue.push_back(Point2i(n.x + 1, n.y));
  612. bucket_queue.push_back(Point2i(n.x - 1, n.y));
  613. count++;
  614. }
  615. if (limit > 0 && count >= limit) {
  616. break;
  617. }
  618. }
  619. return preview ? bucket_cache : points;
  620. }
  621. void TileMapEditor::_fill_points(const PoolVector<Vector2> &p_points, const Dictionary &p_op) {
  622. int len = p_points.size();
  623. PoolVector<Vector2>::Read pr = p_points.read();
  624. Vector<int> ids = p_op["id"];
  625. bool xf = p_op["flip_h"];
  626. bool yf = p_op["flip_v"];
  627. bool tr = p_op["transpose"];
  628. for (int i = 0; i < len; i++) {
  629. _set_cell(pr[i], ids, xf, yf, tr);
  630. node->make_bitmask_area_dirty(pr[i]);
  631. }
  632. if (!manual_autotile) {
  633. node->update_dirty_bitmask();
  634. }
  635. }
  636. void TileMapEditor::_erase_points(const PoolVector<Vector2> &p_points) {
  637. int len = p_points.size();
  638. PoolVector<Vector2>::Read pr = p_points.read();
  639. for (int i = 0; i < len; i++) {
  640. _set_cell(pr[i], invalid_cell);
  641. }
  642. }
  643. void TileMapEditor::_select(const Point2i &p_from, const Point2i &p_to) {
  644. Point2i begin = p_from;
  645. Point2i end = p_to;
  646. if (begin.x > end.x) {
  647. SWAP(begin.x, end.x);
  648. }
  649. if (begin.y > end.y) {
  650. SWAP(begin.y, end.y);
  651. }
  652. rectangle.position = begin;
  653. rectangle.size = end - begin;
  654. CanvasItemEditor::get_singleton()->update_viewport();
  655. }
  656. void TileMapEditor::_erase_selection() {
  657. if (!selection_active) {
  658. return;
  659. }
  660. for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
  661. for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
  662. _set_cell(Point2i(j, i), invalid_cell, false, false, false);
  663. }
  664. }
  665. }
  666. void TileMapEditor::_draw_grid(Control *p_viewport, const Rect2 &p_rect) const {
  667. if (!EDITOR_GET("editors/tile_map/display_grid")) {
  668. return;
  669. }
  670. const Transform2D cell_xf = node->get_cell_transform();
  671. const Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
  672. // Fade the grid when the rendered cell size is relatively small.
  673. const float cell_area = xform.xform(Rect2(Point2(), node->get_cell_size())).get_area();
  674. const float distance_fade = MIN(Math::inverse_lerp(4.0f, 64.0f, cell_area), 1.0f);
  675. if (distance_fade <= 0) {
  676. return;
  677. }
  678. const Color grid_color = Color(EDITOR_GET("editors/tile_map/grid_color")) * Color(1, 1, 1, distance_fade);
  679. const Color axis_color = Color(EDITOR_GET("editors/tile_map/axis_color")) * Color(1, 1, 1, distance_fade);
  680. const int fade = 5;
  681. const Rect2i si = p_rect.grow(fade);
  682. // When zoomed in, it's useful to clip the rendering.
  683. Rect2i clipped;
  684. {
  685. const Transform2D xform_inv = xform.affine_inverse();
  686. const Size2 screen_size = p_viewport->get_size();
  687. Rect2 rect;
  688. rect.position = node->world_to_map(xform_inv.xform(Vector2()));
  689. rect.expand_to(node->world_to_map(xform_inv.xform(Vector2(0, screen_size.height))) + Vector2(0, 1));
  690. rect.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width, 0))) + Vector2(1, 0));
  691. rect.expand_to(node->world_to_map(xform_inv.xform(screen_size)) + Vector2(1, 1));
  692. if (node->get_half_offset() != TileMap::HALF_OFFSET_DISABLED) {
  693. rect.grow_by(1); // So it won't matter whether corners are on an odd or even row/column.
  694. }
  695. clipped = rect.clip(si);
  696. }
  697. clipped.position -= si.position; // Relative to the fade rect, in grid unit.
  698. const Point2i clipped_end = clipped.position + clipped.size;
  699. if (clipped.has_no_area()) {
  700. return;
  701. }
  702. Vector<Point2> points;
  703. Vector<Color> colors;
  704. // Vertical lines.
  705. if (node->get_half_offset() != TileMap::HALF_OFFSET_X && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_X) {
  706. points.resize(4);
  707. colors.resize(4);
  708. for (int x = clipped.position.x; x <= clipped_end.x; x++) {
  709. points.write[0] = xform.xform(node->map_to_world(si.position + Vector2(x, 0)));
  710. points.write[1] = xform.xform(node->map_to_world(si.position + Vector2(x, fade)));
  711. points.write[2] = xform.xform(node->map_to_world(si.position + Vector2(x, si.size.y - fade)));
  712. points.write[3] = xform.xform(node->map_to_world(si.position + Vector2(x, si.size.y)));
  713. const Color color = (x + si.position.x == 0) ? axis_color : grid_color;
  714. const float line_opacity = _lerp_fade(si.size.x, fade, x);
  715. colors.write[0] = Color(color.r, color.g, color.b, 0.0);
  716. colors.write[1] = Color(color.r, color.g, color.b, color.a * line_opacity);
  717. colors.write[2] = Color(color.r, color.g, color.b, color.a * line_opacity);
  718. colors.write[3] = Color(color.r, color.g, color.b, 0.0);
  719. p_viewport->draw_polyline_colors(points, colors, 1);
  720. }
  721. } else {
  722. const float half_offset = node->get_half_offset() == TileMap::HALF_OFFSET_X ? 0.5 : -0.5;
  723. const int cell_count = clipped.size.y;
  724. points.resize(cell_count * 2);
  725. colors.resize(cell_count * 2);
  726. for (int x = clipped.position.x; x <= clipped_end.x; x++) {
  727. const Color color = (x + si.position.x == 0) ? axis_color : grid_color;
  728. const float line_opacity = _lerp_fade(si.size.x, fade, x);
  729. for (int y = clipped.position.y; y < clipped_end.y; y++) {
  730. Vector2 ofs;
  731. if (ABS(si.position.y + y) & 1) {
  732. ofs = cell_xf[0] * half_offset;
  733. }
  734. const int index = (y - clipped.position.y) * 2;
  735. points.write[index + 0] = xform.xform(ofs + node->map_to_world(si.position + Vector2(x, y), true));
  736. points.write[index + 1] = xform.xform(ofs + node->map_to_world(si.position + Vector2(x, y + 1), true));
  737. colors.write[index + 0] = Color(color.r, color.g, color.b, color.a * line_opacity * _lerp_fade(si.size.y, fade, y));
  738. colors.write[index + 1] = Color(color.r, color.g, color.b, color.a * line_opacity * _lerp_fade(si.size.y, fade, y + 1));
  739. }
  740. p_viewport->draw_multiline_colors(points, colors, 1);
  741. }
  742. }
  743. // Horizontal lines.
  744. if (node->get_half_offset() != TileMap::HALF_OFFSET_Y && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_Y) {
  745. points.resize(4);
  746. colors.resize(4);
  747. for (int y = clipped.position.y; y <= clipped_end.y; y++) {
  748. points.write[0] = xform.xform(node->map_to_world(si.position + Vector2(0, y)));
  749. points.write[1] = xform.xform(node->map_to_world(si.position + Vector2(fade, y)));
  750. points.write[2] = xform.xform(node->map_to_world(si.position + Vector2(si.size.x - fade, y)));
  751. points.write[3] = xform.xform(node->map_to_world(si.position + Vector2(si.size.x, y)));
  752. const Color color = (y + si.position.y == 0) ? axis_color : grid_color;
  753. const float line_opacity = _lerp_fade(si.size.y, fade, y);
  754. colors.write[0] = Color(color.r, color.g, color.b, 0.0);
  755. colors.write[1] = Color(color.r, color.g, color.b, color.a * line_opacity);
  756. colors.write[2] = Color(color.r, color.g, color.b, color.a * line_opacity);
  757. colors.write[3] = Color(color.r, color.g, color.b, 0.0);
  758. p_viewport->draw_polyline_colors(points, colors, 1);
  759. }
  760. } else {
  761. const float half_offset = node->get_half_offset() == TileMap::HALF_OFFSET_Y ? 0.5 : -0.5;
  762. const int cell_count = clipped.size.x;
  763. points.resize(cell_count * 2);
  764. colors.resize(cell_count * 2);
  765. for (int y = clipped.position.y; y <= clipped_end.y; y++) {
  766. const Color color = (y + si.position.y == 0) ? axis_color : grid_color;
  767. const float line_opacity = _lerp_fade(si.size.y, fade, y);
  768. for (int x = clipped.position.x; x < clipped_end.x; x++) {
  769. Vector2 ofs;
  770. if (ABS(si.position.x + x) & 1) {
  771. ofs = cell_xf[1] * half_offset;
  772. }
  773. const int index = (x - clipped.position.x) * 2;
  774. points.write[index + 0] = xform.xform(ofs + node->map_to_world(si.position + Vector2(x, y), true));
  775. points.write[index + 1] = xform.xform(ofs + node->map_to_world(si.position + Vector2(x + 1, y), true));
  776. colors.write[index + 0] = Color(color.r, color.g, color.b, color.a * line_opacity * _lerp_fade(si.size.x, fade, x));
  777. colors.write[index + 1] = Color(color.r, color.g, color.b, color.a * line_opacity * _lerp_fade(si.size.x, fade, x + 1));
  778. }
  779. p_viewport->draw_multiline_colors(points, colors, 1);
  780. }
  781. }
  782. }
  783. void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord, const Transform2D &p_xform) {
  784. if (!node->get_tileset()->has_tile(p_cell)) {
  785. return;
  786. }
  787. Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell);
  788. if (t.is_null()) {
  789. return;
  790. }
  791. Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell);
  792. Rect2 r = node->get_tileset()->tile_get_region(p_cell);
  793. if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) {
  794. Vector2 offset;
  795. if (tool != TOOL_PASTING) {
  796. int selected = manual_palette->get_current();
  797. if ((manual_autotile || (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE && !priority_atlastile)) && selected != -1) {
  798. offset = manual_palette->get_item_metadata(selected);
  799. } else {
  800. offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell);
  801. }
  802. } else {
  803. offset = p_autotile_coord;
  804. }
  805. int spacing = node->get_tileset()->autotile_get_spacing(p_cell);
  806. r.size = node->get_tileset()->autotile_get_size(p_cell);
  807. r.position += (r.size + Vector2(spacing, spacing)) * offset;
  808. }
  809. Size2 cell_size = node->get_cell_size();
  810. bool centered_texture = node->is_centered_textures_enabled();
  811. bool compatibility_mode_enabled = node->is_compatibility_mode_enabled();
  812. Rect2 rect = Rect2();
  813. rect.position = node->map_to_world(p_point) + node->get_cell_draw_offset();
  814. if (r.has_no_area()) {
  815. rect.size = t->get_size();
  816. } else {
  817. rect.size = r.size;
  818. }
  819. if (compatibility_mode_enabled && !centered_texture) {
  820. if (rect.size.y > rect.size.x) {
  821. if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose)) {
  822. tile_ofs.y += rect.size.y - rect.size.x;
  823. }
  824. } else if (rect.size.y < rect.size.x) {
  825. if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose)) {
  826. tile_ofs.x += rect.size.x - rect.size.y;
  827. }
  828. }
  829. }
  830. if (p_transpose) {
  831. SWAP(tile_ofs.x, tile_ofs.y);
  832. if (centered_texture) {
  833. rect.position.x += cell_size.x / 2 - rect.size.y / 2;
  834. rect.position.y += cell_size.y / 2 - rect.size.x / 2;
  835. }
  836. } else if (centered_texture) {
  837. rect.position += cell_size / 2 - rect.size / 2;
  838. }
  839. if (p_flip_h) {
  840. rect.size.x *= -1.0;
  841. tile_ofs.x *= -1.0;
  842. }
  843. if (p_flip_v) {
  844. rect.size.y *= -1.0;
  845. tile_ofs.y *= -1.0;
  846. }
  847. if (compatibility_mode_enabled && !centered_texture) {
  848. if (node->get_tile_origin() == TileMap::TILE_ORIGIN_TOP_LEFT) {
  849. rect.position += tile_ofs;
  850. } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_BOTTOM_LEFT) {
  851. rect.position += tile_ofs;
  852. if (p_transpose) {
  853. if (p_flip_h) {
  854. rect.position.x -= cell_size.x;
  855. } else {
  856. rect.position.x += cell_size.x;
  857. }
  858. } else {
  859. if (p_flip_v) {
  860. rect.position.y -= cell_size.y;
  861. } else {
  862. rect.position.y += cell_size.y;
  863. }
  864. }
  865. } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_CENTER) {
  866. rect.position += tile_ofs;
  867. if (p_flip_h) {
  868. rect.position.x -= cell_size.x / 2;
  869. } else {
  870. rect.position.x += cell_size.x / 2;
  871. }
  872. if (p_flip_v) {
  873. rect.position.y -= cell_size.y / 2;
  874. } else {
  875. rect.position.y += cell_size.y / 2;
  876. }
  877. }
  878. } else {
  879. rect.position += tile_ofs;
  880. }
  881. Color modulate = node->get_tileset()->tile_get_modulate(p_cell);
  882. modulate.a = 0.5;
  883. Transform2D old_transform = p_viewport->get_viewport_transform();
  884. p_viewport->draw_set_transform_matrix(p_xform); // Take into account TileMap transformation when displaying cell
  885. if (r.has_no_area()) {
  886. p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose);
  887. } else {
  888. p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose);
  889. }
  890. p_viewport->draw_set_transform_matrix(old_transform);
  891. }
  892. void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord, const Transform2D &p_xform) {
  893. PoolVector<Vector2> points = _bucket_fill(p_point, false, true);
  894. PoolVector<Vector2>::Read pr = points.read();
  895. int len = points.size();
  896. for (int i = 0; i < len; ++i) {
  897. _draw_cell(p_viewport, p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_autotile_coord, p_xform);
  898. }
  899. }
  900. void TileMapEditor::_clear_bucket_cache() {
  901. if (bucket_cache_visited) {
  902. delete[] bucket_cache_visited;
  903. bucket_cache_visited = nullptr;
  904. }
  905. }
  906. void TileMapEditor::_update_copydata() {
  907. copydata.clear();
  908. if (!selection_active) {
  909. return;
  910. }
  911. for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
  912. for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
  913. TileData tcd;
  914. tcd.cell = node->get_cell(j, i);
  915. if (tcd.cell != TileMap::INVALID_CELL) {
  916. tcd.pos = Point2i(j, i);
  917. tcd.flip_h = node->is_cell_x_flipped(j, i);
  918. tcd.flip_v = node->is_cell_y_flipped(j, i);
  919. tcd.transpose = node->is_cell_transposed(j, i);
  920. tcd.autotile_coord = node->get_cell_autotile_coord(j, i);
  921. copydata.push_back(tcd);
  922. }
  923. }
  924. }
  925. }
  926. static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
  927. Vector<Point2i> points;
  928. float dx = ABS(x1 - x0);
  929. float dy = ABS(y1 - y0);
  930. int x = x0;
  931. int y = y0;
  932. int sx = x0 > x1 ? -1 : 1;
  933. int sy = y0 > y1 ? -1 : 1;
  934. if (dx > dy) {
  935. float err = dx / 2;
  936. for (; x != x1; x += sx) {
  937. points.push_back(Vector2(x, y));
  938. err -= dy;
  939. if (err < 0) {
  940. y += sy;
  941. err += dx;
  942. }
  943. }
  944. } else {
  945. float err = dy / 2;
  946. for (; y != y1; y += sy) {
  947. points.push_back(Vector2(x, y));
  948. err -= dx;
  949. if (err < 0) {
  950. x += sx;
  951. err += dy;
  952. }
  953. }
  954. }
  955. points.push_back(Vector2(x, y));
  956. return points;
  957. }
  958. bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
  959. if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree() || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT) {
  960. return false;
  961. }
  962. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
  963. Transform2D xform_inv = xform.affine_inverse();
  964. Ref<InputEventMouseButton> mb = p_event;
  965. if (mb.is_valid()) {
  966. // Keep track internally of which mouse buttons are pressed
  967. // so we can disallow changing tool.
  968. if (mb->is_pressed()) {
  969. _mouse_buttons_pressed |= mb->get_button_index();
  970. } else {
  971. _mouse_buttons_pressed &= ~mb->get_button_index();
  972. }
  973. if (mb->get_button_index() == BUTTON_LEFT) {
  974. if (mb->is_pressed()) {
  975. if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
  976. return false; // Drag.
  977. }
  978. // Finish ongoing erasing.
  979. if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
  980. _finish_undo();
  981. if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
  982. CanvasItemEditor::get_singleton()->update_viewport();
  983. }
  984. tool = TOOL_NONE;
  985. }
  986. if (tool == TOOL_NONE) {
  987. if (mb->get_shift()) {
  988. if (mb->get_command()) {
  989. tool = TOOL_RECTANGLE_PAINT;
  990. } else {
  991. tool = TOOL_LINE_PAINT;
  992. }
  993. selection_active = false;
  994. rectangle_begin = over_tile;
  995. _update_button_tool();
  996. return true;
  997. }
  998. if (mb->get_command()) {
  999. tool = TOOL_PICKING;
  1000. _pick_tile(over_tile);
  1001. _update_button_tool();
  1002. return true;
  1003. }
  1004. tool = TOOL_PAINTING;
  1005. _update_button_tool();
  1006. }
  1007. if (tool == TOOL_PAINTING) {
  1008. Vector<int> ids = get_selected_tiles();
  1009. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  1010. tool = TOOL_PAINTING;
  1011. _start_undo(TTR("Paint TileMap"));
  1012. }
  1013. } else if (tool == TOOL_PICKING) {
  1014. _pick_tile(over_tile);
  1015. } else if (tool == TOOL_SELECTING) {
  1016. selection_active = true;
  1017. rectangle_begin = over_tile;
  1018. }
  1019. _update_button_tool();
  1020. return true;
  1021. } else {
  1022. // Mousebutton was released.
  1023. if (tool != TOOL_NONE) {
  1024. if (tool == TOOL_PAINTING) {
  1025. Vector<int> ids = get_selected_tiles();
  1026. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  1027. _set_cell(over_tile, ids, flip_h, flip_v, transpose);
  1028. _finish_undo();
  1029. paint_undo.clear();
  1030. }
  1031. } else if (tool == TOOL_LINE_PAINT) {
  1032. Vector<int> ids = get_selected_tiles();
  1033. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  1034. _start_undo(TTR("Line Draw"));
  1035. for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
  1036. _set_cell(E->key(), ids, flip_h, flip_v, transpose);
  1037. }
  1038. _finish_undo();
  1039. paint_undo.clear();
  1040. CanvasItemEditor::get_singleton()->update_viewport();
  1041. }
  1042. } else if (tool == TOOL_RECTANGLE_PAINT) {
  1043. Vector<int> ids = get_selected_tiles();
  1044. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  1045. _start_undo(TTR("Rectangle Paint"));
  1046. for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
  1047. for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
  1048. _set_cell(Point2i(j, i), ids, flip_h, flip_v, transpose);
  1049. }
  1050. }
  1051. _finish_undo();
  1052. CanvasItemEditor::get_singleton()->update_viewport();
  1053. }
  1054. } else if (tool == TOOL_PASTING) {
  1055. Point2 ofs = over_tile - rectangle.position;
  1056. Vector<int> ids;
  1057. _start_undo(TTR("Paste"));
  1058. ids.push_back(0);
  1059. for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
  1060. ids.write[0] = E->get().cell;
  1061. _set_cell(E->get().pos + ofs, ids, E->get().flip_h, E->get().flip_v, E->get().transpose, E->get().autotile_coord);
  1062. }
  1063. _finish_undo();
  1064. CanvasItemEditor::get_singleton()->update_viewport();
  1065. return true; // We want to keep the Pasting tool.
  1066. } else if (tool == TOOL_SELECTING) {
  1067. CanvasItemEditor::get_singleton()->update_viewport();
  1068. } else if (tool == TOOL_BUCKET) {
  1069. PoolVector<Vector2> points = _bucket_fill(over_tile);
  1070. if (points.size() == 0) {
  1071. return false;
  1072. }
  1073. _start_undo(TTR("Bucket Fill"));
  1074. Dictionary op;
  1075. op["id"] = get_selected_tiles();
  1076. op["flip_h"] = flip_h;
  1077. op["flip_v"] = flip_v;
  1078. op["transpose"] = transpose;
  1079. _fill_points(points, op);
  1080. _finish_undo();
  1081. // So the fill preview is cleared right after the click.
  1082. CanvasItemEditor::get_singleton()->update_viewport();
  1083. // We want to keep the bucket-tool active.
  1084. return true;
  1085. }
  1086. tool = TOOL_NONE;
  1087. _update_button_tool();
  1088. return true;
  1089. }
  1090. }
  1091. } else if (mb->get_button_index() == BUTTON_RIGHT) {
  1092. if (mb->is_pressed()) {
  1093. if (tool == TOOL_SELECTING || selection_active) {
  1094. tool = TOOL_NONE;
  1095. selection_active = false;
  1096. CanvasItemEditor::get_singleton()->update_viewport();
  1097. _update_button_tool();
  1098. return true;
  1099. }
  1100. if (tool == TOOL_PASTING) {
  1101. tool = TOOL_NONE;
  1102. copydata.clear();
  1103. CanvasItemEditor::get_singleton()->update_viewport();
  1104. _update_button_tool();
  1105. return true;
  1106. }
  1107. if (tool == TOOL_NONE) {
  1108. paint_undo.clear();
  1109. Point2 local = node->world_to_map(xform_inv.xform(mb->get_position()));
  1110. _start_undo(TTR("Erase TileMap"));
  1111. if (mb->get_shift()) {
  1112. if (mb->get_command()) {
  1113. tool = TOOL_RECTANGLE_ERASE;
  1114. } else {
  1115. tool = TOOL_LINE_ERASE;
  1116. }
  1117. selection_active = false;
  1118. rectangle_begin = local;
  1119. } else {
  1120. tool = TOOL_ERASING;
  1121. _set_cell(local, invalid_cell);
  1122. }
  1123. _update_button_tool();
  1124. return true;
  1125. }
  1126. } else {
  1127. if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
  1128. _finish_undo();
  1129. if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
  1130. CanvasItemEditor::get_singleton()->update_viewport();
  1131. }
  1132. tool = TOOL_NONE;
  1133. _update_button_tool();
  1134. return true;
  1135. } else if (tool == TOOL_BUCKET) {
  1136. Vector<int> ids;
  1137. ids.push_back(node->get_cell(over_tile.x, over_tile.y));
  1138. Dictionary pop;
  1139. pop["id"] = ids;
  1140. pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
  1141. pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
  1142. pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
  1143. PoolVector<Vector2> points = _bucket_fill(over_tile, true);
  1144. if (points.size() == 0) {
  1145. return false;
  1146. }
  1147. undo_redo->create_action(TTR("Bucket Fill"));
  1148. undo_redo->add_do_method(this, "_erase_points", points);
  1149. undo_redo->add_undo_method(this, "_fill_points", points, pop);
  1150. undo_redo->commit_action();
  1151. }
  1152. }
  1153. }
  1154. }
  1155. Ref<InputEventMouseMotion> mm = p_event;
  1156. if (mm.is_valid()) {
  1157. Point2i new_over_tile = node->world_to_map(xform_inv.xform(mm->get_position()));
  1158. Point2i old_over_tile = over_tile;
  1159. if (new_over_tile != over_tile) {
  1160. over_tile = new_over_tile;
  1161. CanvasItemEditor::get_singleton()->update_viewport();
  1162. }
  1163. if (refocus_over_tile) {
  1164. // editor lost focus; forget last tile position
  1165. old_over_tile = new_over_tile;
  1166. refocus_over_tile = false;
  1167. }
  1168. int tile_under = node->get_cell(over_tile.x, over_tile.y);
  1169. String tile_name = "none";
  1170. if (node->get_tileset()->has_tile(tile_under)) {
  1171. tile_name = node->get_tileset()->tile_get_name(tile_under);
  1172. }
  1173. tile_info->show();
  1174. tile_info->set_text(String::num(over_tile.x) + ", " + String::num(over_tile.y) + " [" + tile_name + "]");
  1175. if (tool == TOOL_PAINTING) {
  1176. // Paint using bresenham line to prevent holes in painting if the user moves fast.
  1177. Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
  1178. Vector<int> ids = get_selected_tiles();
  1179. for (int i = 0; i < points.size(); ++i) {
  1180. Point2i pos = points[i];
  1181. if (!paint_undo.has(pos)) {
  1182. paint_undo[pos] = _get_op_from_cell(pos);
  1183. }
  1184. _set_cell(pos, ids, flip_h, flip_v, transpose);
  1185. }
  1186. return true;
  1187. }
  1188. if (tool == TOOL_ERASING) {
  1189. // Erase using bresenham line to prevent holes in painting if the user moves fast.
  1190. Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
  1191. for (int i = 0; i < points.size(); ++i) {
  1192. Point2i pos = points[i];
  1193. _set_cell(pos, invalid_cell);
  1194. }
  1195. return true;
  1196. }
  1197. if (tool == TOOL_SELECTING) {
  1198. _select(rectangle_begin, over_tile);
  1199. return true;
  1200. }
  1201. if (tool == TOOL_LINE_PAINT || tool == TOOL_LINE_ERASE) {
  1202. Vector<int> ids = get_selected_tiles();
  1203. Vector<int> tmp_cell;
  1204. bool erasing = (tool == TOOL_LINE_ERASE);
  1205. tmp_cell.push_back(0);
  1206. if (erasing && paint_undo.size()) {
  1207. for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
  1208. tmp_cell.write[0] = E->get().idx;
  1209. _set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr);
  1210. }
  1211. }
  1212. paint_undo.clear();
  1213. if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
  1214. Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
  1215. for (int i = 0; i < points.size(); i++) {
  1216. paint_undo[points[i]] = _get_op_from_cell(points[i]);
  1217. if (erasing) {
  1218. _set_cell(points[i], invalid_cell);
  1219. }
  1220. }
  1221. CanvasItemEditor::get_singleton()->update_viewport();
  1222. }
  1223. return true;
  1224. }
  1225. if (tool == TOOL_RECTANGLE_PAINT || tool == TOOL_RECTANGLE_ERASE) {
  1226. Vector<int> tmp_cell;
  1227. tmp_cell.push_back(0);
  1228. _select(rectangle_begin, over_tile);
  1229. if (tool == TOOL_RECTANGLE_ERASE) {
  1230. if (paint_undo.size()) {
  1231. for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
  1232. tmp_cell.write[0] = E->get().idx;
  1233. _set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr);
  1234. }
  1235. }
  1236. paint_undo.clear();
  1237. for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
  1238. for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
  1239. Point2i tile = Point2i(j, i);
  1240. paint_undo[tile] = _get_op_from_cell(tile);
  1241. _set_cell(tile, invalid_cell);
  1242. }
  1243. }
  1244. }
  1245. return true;
  1246. }
  1247. if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
  1248. _pick_tile(over_tile);
  1249. return true;
  1250. }
  1251. }
  1252. Ref<InputEventKey> k = p_event;
  1253. if (k.is_valid() && k->is_pressed()) {
  1254. if (last_tool == TOOL_NONE && tool == TOOL_PICKING && k->get_scancode() == KEY_SHIFT && k->get_command()) {
  1255. // trying to draw a rectangle with the painting tool, so change to the correct tool
  1256. tool = last_tool;
  1257. CanvasItemEditor::get_singleton()->update_viewport();
  1258. _update_button_tool();
  1259. }
  1260. if (k->get_scancode() == KEY_ESCAPE) {
  1261. if (tool == TOOL_PASTING) {
  1262. copydata.clear();
  1263. } else if (tool == TOOL_SELECTING || selection_active) {
  1264. selection_active = false;
  1265. }
  1266. tool = TOOL_NONE;
  1267. CanvasItemEditor::get_singleton()->update_viewport();
  1268. _update_button_tool();
  1269. return true;
  1270. }
  1271. if (!mouse_over) {
  1272. // Editor shortcuts should not fire if mouse not in viewport.
  1273. return false;
  1274. }
  1275. if (ED_IS_SHORTCUT("tile_map_editor/paint_tile", p_event)) {
  1276. // NOTE: We do not set tool = TOOL_PAINTING as this begins painting
  1277. // immediately without pressing the left mouse button first.
  1278. tool = TOOL_NONE;
  1279. CanvasItemEditor::get_singleton()->update_viewport();
  1280. _update_button_tool();
  1281. return true;
  1282. }
  1283. if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) {
  1284. tool = TOOL_BUCKET;
  1285. CanvasItemEditor::get_singleton()->update_viewport();
  1286. _update_button_tool();
  1287. return true;
  1288. }
  1289. if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
  1290. _menu_option(OPTION_ERASE_SELECTION);
  1291. _update_button_tool();
  1292. return true;
  1293. }
  1294. if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
  1295. tool = TOOL_SELECTING;
  1296. selection_active = false;
  1297. CanvasItemEditor::get_singleton()->update_viewport();
  1298. _update_button_tool();
  1299. return true;
  1300. }
  1301. if (ED_IS_SHORTCUT("tile_map_editor/copy_selection", p_event)) {
  1302. _update_copydata();
  1303. if (selection_active) {
  1304. tool = TOOL_PASTING;
  1305. CanvasItemEditor::get_singleton()->update_viewport();
  1306. _update_button_tool();
  1307. return true;
  1308. }
  1309. }
  1310. if (ED_IS_SHORTCUT("tile_map_editor/cut_selection", p_event)) {
  1311. if (selection_active) {
  1312. _update_copydata();
  1313. _start_undo(TTR("Cut Selection"));
  1314. _erase_selection();
  1315. _finish_undo();
  1316. selection_active = false;
  1317. tool = TOOL_PASTING;
  1318. CanvasItemEditor::get_singleton()->update_viewport();
  1319. _update_button_tool();
  1320. return true;
  1321. }
  1322. }
  1323. if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
  1324. search_box->select_all();
  1325. search_box->grab_focus();
  1326. return true;
  1327. }
  1328. if (ED_IS_SHORTCUT("tile_map_editor/rotate_left", p_event)) {
  1329. _rotate(-1);
  1330. CanvasItemEditor::get_singleton()->update_viewport();
  1331. return true;
  1332. }
  1333. if (ED_IS_SHORTCUT("tile_map_editor/rotate_right", p_event)) {
  1334. _rotate(1);
  1335. CanvasItemEditor::get_singleton()->update_viewport();
  1336. return true;
  1337. }
  1338. if (ED_IS_SHORTCUT("tile_map_editor/flip_horizontal", p_event)) {
  1339. _flip_horizontal();
  1340. CanvasItemEditor::get_singleton()->update_viewport();
  1341. return true;
  1342. }
  1343. if (ED_IS_SHORTCUT("tile_map_editor/flip_vertical", p_event)) {
  1344. _flip_vertical();
  1345. CanvasItemEditor::get_singleton()->update_viewport();
  1346. return true;
  1347. }
  1348. if (ED_IS_SHORTCUT("tile_map_editor/clear_transform", p_event)) {
  1349. _clear_transform();
  1350. CanvasItemEditor::get_singleton()->update_viewport();
  1351. return true;
  1352. }
  1353. if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
  1354. transpose = !transpose;
  1355. _update_palette();
  1356. CanvasItemEditor::get_singleton()->update_viewport();
  1357. return true;
  1358. }
  1359. } else if (k.is_valid()) { // Release event.
  1360. if (tool == TOOL_NONE) {
  1361. if (k->get_scancode() == KEY_SHIFT && k->get_command()) {
  1362. tool = TOOL_PICKING;
  1363. _update_button_tool();
  1364. }
  1365. } else if (tool == TOOL_PICKING) {
  1366. #ifdef APPLE_STYLE_KEYS
  1367. if (k->get_scancode() == KEY_META) {
  1368. #else
  1369. if (k->get_scancode() == KEY_CONTROL) {
  1370. #endif
  1371. // Go back to that last tool if KEY_CONTROL was released.
  1372. tool = last_tool;
  1373. CanvasItemEditor::get_singleton()->update_viewport();
  1374. _update_button_tool();
  1375. }
  1376. }
  1377. }
  1378. return false;
  1379. }
  1380. void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
  1381. if (!node || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT) {
  1382. return;
  1383. }
  1384. _draw_grid(p_overlay, node->get_used_rect());
  1385. const Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
  1386. const Transform2D cell_xf = node->get_cell_transform();
  1387. if (selection_active) {
  1388. Vector<Vector2> points;
  1389. points.push_back(xform.xform(node->map_to_world((rectangle.position))));
  1390. points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, 0)))));
  1391. points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, rectangle.size.y + 1)))));
  1392. points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(0, rectangle.size.y + 1)))));
  1393. p_overlay->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4));
  1394. }
  1395. if (mouse_over && node->get_tileset().is_valid()) {
  1396. Vector2 endpoints[4] = {
  1397. node->map_to_world(over_tile, true),
  1398. node->map_to_world((over_tile + Point2(1, 0)), true),
  1399. node->map_to_world((over_tile + Point2(1, 1)), true),
  1400. node->map_to_world((over_tile + Point2(0, 1)), true)
  1401. };
  1402. for (int i = 0; i < 4; i++) {
  1403. if (node->get_half_offset() == TileMap::HALF_OFFSET_X && ABS(over_tile.y) & 1) {
  1404. endpoints[i] += cell_xf[0] * 0.5;
  1405. }
  1406. if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_X && ABS(over_tile.y) & 1) {
  1407. endpoints[i] += cell_xf[0] * -0.5;
  1408. }
  1409. if (node->get_half_offset() == TileMap::HALF_OFFSET_Y && ABS(over_tile.x) & 1) {
  1410. endpoints[i] += cell_xf[1] * 0.5;
  1411. }
  1412. if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_Y && ABS(over_tile.x) & 1) {
  1413. endpoints[i] += cell_xf[1] * -0.5;
  1414. }
  1415. endpoints[i] = xform.xform(endpoints[i]);
  1416. }
  1417. Color col;
  1418. if (node->get_cell(over_tile.x, over_tile.y) != TileMap::INVALID_CELL) {
  1419. col = Color(0.2, 0.8, 1.0, 0.8);
  1420. } else {
  1421. col = Color(1.0, 0.4, 0.2, 0.8);
  1422. }
  1423. for (int i = 0; i < 4; i++) {
  1424. p_overlay->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2);
  1425. }
  1426. bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview");
  1427. if (tool == TOOL_SELECTING || tool == TOOL_PICKING || !bucket_preview) {
  1428. return;
  1429. }
  1430. if (tool == TOOL_LINE_PAINT) {
  1431. if (paint_undo.empty()) {
  1432. return;
  1433. }
  1434. Vector<int> ids = get_selected_tiles();
  1435. if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) {
  1436. return;
  1437. }
  1438. // Making a Rect2i that encloses all the cells in paint_undo.
  1439. // I wonder if there is a cleaner way to do it.
  1440. const Point2i first_pos = paint_undo.front()->key();
  1441. int left = first_pos.x;
  1442. int right = first_pos.x;
  1443. int top = first_pos.y;
  1444. int bottom = first_pos.y;
  1445. for (Map<Point2i, CellOp>::Element *E = paint_undo.front()->next(); E; E = E->next()) {
  1446. const Point2i &pos = E->key();
  1447. left = MIN(pos.x, left);
  1448. right = MAX(pos.x, right);
  1449. top = MIN(pos.y, top);
  1450. bottom = MAX(pos.y, bottom);
  1451. }
  1452. _draw_grid(p_overlay, Rect2i(left, top, right - left + 1, bottom - top + 1));
  1453. for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
  1454. _draw_cell(p_overlay, ids[0], E->key(), flip_h, flip_v, transpose, autotile_coord, xform);
  1455. }
  1456. } else if (tool == TOOL_RECTANGLE_PAINT) {
  1457. Vector<int> ids = get_selected_tiles();
  1458. if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) {
  1459. return;
  1460. }
  1461. _draw_grid(p_overlay, rectangle);
  1462. for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
  1463. for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
  1464. _draw_cell(p_overlay, ids[0], Point2i(j, i), flip_h, flip_v, transpose, autotile_coord, xform);
  1465. }
  1466. }
  1467. } else if (tool == TOOL_PASTING) {
  1468. if (copydata.empty()) {
  1469. return;
  1470. }
  1471. Ref<TileSet> ts = node->get_tileset();
  1472. if (ts.is_null()) {
  1473. return;
  1474. }
  1475. Point2 ofs = over_tile - rectangle.position;
  1476. for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
  1477. if (!ts->has_tile(E->get().cell)) {
  1478. continue;
  1479. }
  1480. TileData tcd = E->get();
  1481. _draw_cell(p_overlay, tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, tcd.autotile_coord, xform);
  1482. }
  1483. Rect2i duplicate = rectangle;
  1484. duplicate.position = over_tile;
  1485. Vector<Vector2> points;
  1486. points.push_back(xform.xform(node->map_to_world(duplicate.position)));
  1487. points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, 0)))));
  1488. points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, duplicate.size.y + 1)))));
  1489. points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(0, duplicate.size.y + 1)))));
  1490. p_overlay->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2));
  1491. } else if (tool == TOOL_BUCKET) {
  1492. Vector<int> tiles = get_selected_tiles();
  1493. _draw_fill_preview(p_overlay, tiles[0], over_tile, flip_h, flip_v, transpose, autotile_coord, xform);
  1494. } else {
  1495. Vector<int> st = get_selected_tiles();
  1496. if (st.size() == 1 && st[0] == TileMap::INVALID_CELL) {
  1497. return;
  1498. }
  1499. _draw_grid(p_overlay, Rect2(over_tile, Size2(1, 1)));
  1500. _draw_cell(p_overlay, st[0], over_tile, flip_h, flip_v, transpose, autotile_coord, xform);
  1501. }
  1502. }
  1503. }
  1504. void TileMapEditor::edit(Node *p_tile_map) {
  1505. search_box->set_text("");
  1506. if (!canvas_item_editor_viewport) {
  1507. canvas_item_editor_viewport = CanvasItemEditor::get_singleton()->get_viewport_control();
  1508. }
  1509. if (node && node->is_connected("settings_changed", this, "_tileset_settings_changed")) {
  1510. node->disconnect("settings_changed", this, "_tileset_settings_changed");
  1511. }
  1512. if (p_tile_map) {
  1513. node = Object::cast_to<TileMap>(p_tile_map);
  1514. if (!canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter")) {
  1515. canvas_item_editor_viewport->connect("mouse_entered", this, "_canvas_mouse_enter");
  1516. }
  1517. if (!canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit")) {
  1518. canvas_item_editor_viewport->connect("mouse_exited", this, "_canvas_mouse_exit");
  1519. }
  1520. _update_palette();
  1521. } else {
  1522. node = nullptr;
  1523. if (canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter")) {
  1524. canvas_item_editor_viewport->disconnect("mouse_entered", this, "_canvas_mouse_enter");
  1525. }
  1526. if (canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit")) {
  1527. canvas_item_editor_viewport->disconnect("mouse_exited", this, "_canvas_mouse_exit");
  1528. }
  1529. _update_palette();
  1530. }
  1531. if (node && !node->is_connected("settings_changed", this, "_tileset_settings_changed")) {
  1532. node->connect("settings_changed", this, "_tileset_settings_changed");
  1533. }
  1534. _clear_bucket_cache();
  1535. }
  1536. void TileMapEditor::_tileset_settings_changed() {
  1537. _update_palette();
  1538. CanvasItemEditor::get_singleton()->update_viewport();
  1539. }
  1540. void TileMapEditor::_icon_size_changed(float p_value) {
  1541. if (node) {
  1542. palette->set_icon_scale(p_value);
  1543. manual_palette->set_icon_scale(p_value);
  1544. _update_palette();
  1545. }
  1546. }
  1547. void TileMapEditor::_bind_methods() {
  1548. ClassDB::bind_method(D_METHOD("_manual_toggled"), &TileMapEditor::_manual_toggled);
  1549. ClassDB::bind_method(D_METHOD("_priority_toggled"), &TileMapEditor::_priority_toggled);
  1550. ClassDB::bind_method(D_METHOD("_text_entered"), &TileMapEditor::_text_entered);
  1551. ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed);
  1552. ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input);
  1553. ClassDB::bind_method(D_METHOD("_button_tool_select"), &TileMapEditor::_button_tool_select);
  1554. ClassDB::bind_method(D_METHOD("_menu_option"), &TileMapEditor::_menu_option);
  1555. ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter);
  1556. ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit);
  1557. ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed);
  1558. ClassDB::bind_method(D_METHOD("_rotate"), &TileMapEditor::_rotate);
  1559. ClassDB::bind_method(D_METHOD("_flip_horizontal"), &TileMapEditor::_flip_horizontal);
  1560. ClassDB::bind_method(D_METHOD("_flip_vertical"), &TileMapEditor::_flip_vertical);
  1561. ClassDB::bind_method(D_METHOD("_clear_transform"), &TileMapEditor::_clear_transform);
  1562. ClassDB::bind_method(D_METHOD("_palette_selected"), &TileMapEditor::_palette_selected);
  1563. ClassDB::bind_method(D_METHOD("_palette_multi_selected"), &TileMapEditor::_palette_multi_selected);
  1564. ClassDB::bind_method(D_METHOD("_palette_input"), &TileMapEditor::_palette_input);
  1565. ClassDB::bind_method(D_METHOD("_fill_points"), &TileMapEditor::_fill_points);
  1566. ClassDB::bind_method(D_METHOD("_erase_points"), &TileMapEditor::_erase_points);
  1567. ClassDB::bind_method(D_METHOD("_icon_size_changed"), &TileMapEditor::_icon_size_changed);
  1568. ClassDB::bind_method(D_METHOD("_node_removed"), &TileMapEditor::_node_removed);
  1569. }
  1570. TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i &p_pos) {
  1571. CellOp op;
  1572. op.idx = node->get_cell(p_pos.x, p_pos.y);
  1573. if (op.idx != TileMap::INVALID_CELL) {
  1574. if (node->is_cell_x_flipped(p_pos.x, p_pos.y)) {
  1575. op.xf = true;
  1576. }
  1577. if (node->is_cell_y_flipped(p_pos.x, p_pos.y)) {
  1578. op.yf = true;
  1579. }
  1580. if (node->is_cell_transposed(p_pos.x, p_pos.y)) {
  1581. op.tr = true;
  1582. }
  1583. op.ac = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
  1584. }
  1585. return op;
  1586. }
  1587. void TileMapEditor::_rotate(int steps) {
  1588. const bool normal_rotation_matrix[][3] = {
  1589. { false, false, false },
  1590. { true, true, false },
  1591. { false, true, true },
  1592. { true, false, true }
  1593. };
  1594. const bool mirrored_rotation_matrix[][3] = {
  1595. { false, true, false },
  1596. { true, true, true },
  1597. { false, false, true },
  1598. { true, false, false }
  1599. };
  1600. if (transpose ^ flip_h ^ flip_v) {
  1601. // Odd number of flags activated = mirrored rotation
  1602. for (int i = 0; i < 4; i++) {
  1603. if (transpose == mirrored_rotation_matrix[i][0] &&
  1604. flip_h == mirrored_rotation_matrix[i][1] &&
  1605. flip_v == mirrored_rotation_matrix[i][2]) {
  1606. int new_id = Math::wrapi(i + steps, 0, 4);
  1607. transpose = mirrored_rotation_matrix[new_id][0];
  1608. flip_h = mirrored_rotation_matrix[new_id][1];
  1609. flip_v = mirrored_rotation_matrix[new_id][2];
  1610. break;
  1611. }
  1612. }
  1613. } else {
  1614. // Even number of flags activated = normal rotation
  1615. for (int i = 0; i < 4; i++) {
  1616. if (transpose == normal_rotation_matrix[i][0] &&
  1617. flip_h == normal_rotation_matrix[i][1] &&
  1618. flip_v == normal_rotation_matrix[i][2]) {
  1619. int new_id = Math::wrapi(i + steps, 0, 4);
  1620. transpose = normal_rotation_matrix[new_id][0];
  1621. flip_h = normal_rotation_matrix[new_id][1];
  1622. flip_v = normal_rotation_matrix[new_id][2];
  1623. break;
  1624. }
  1625. }
  1626. }
  1627. _update_palette();
  1628. }
  1629. void TileMapEditor::_flip_horizontal() {
  1630. flip_h = !flip_h;
  1631. _update_palette();
  1632. }
  1633. void TileMapEditor::_flip_vertical() {
  1634. flip_v = !flip_v;
  1635. _update_palette();
  1636. }
  1637. void TileMapEditor::_clear_transform() {
  1638. transpose = false;
  1639. flip_h = false;
  1640. flip_v = false;
  1641. _update_palette();
  1642. }
  1643. TileMapEditor::TileMapEditor(EditorNode *p_editor) {
  1644. node = nullptr;
  1645. manual_autotile = false;
  1646. priority_atlastile = false;
  1647. manual_position = Vector2(0, 0);
  1648. canvas_item_editor_viewport = nullptr;
  1649. editor = p_editor;
  1650. undo_redo = EditorNode::get_undo_redo();
  1651. tool = TOOL_NONE;
  1652. selection_active = false;
  1653. mouse_over = false;
  1654. flip_h = false;
  1655. flip_v = false;
  1656. transpose = false;
  1657. bucket_cache_tile = -1;
  1658. bucket_cache_visited = nullptr;
  1659. invalid_cell.resize(1);
  1660. invalid_cell.write[0] = TileMap::INVALID_CELL;
  1661. ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase Selection"), KEY_DELETE);
  1662. ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find Tile"), KEY_MASK_CMD + KEY_F);
  1663. ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"), KEY_T);
  1664. HBoxContainer *tool_hb = memnew(HBoxContainer);
  1665. add_child(tool_hb);
  1666. manual_button = memnew(CheckBox);
  1667. manual_button->set_text(TTR("Disable Autotile"));
  1668. manual_button->connect("toggled", this, "_manual_toggled");
  1669. add_child(manual_button);
  1670. priority_button = memnew(CheckBox);
  1671. priority_button->set_text(TTR("Enable Priority"));
  1672. priority_button->connect("toggled", this, "_priority_toggled");
  1673. add_child(priority_button);
  1674. search_box = memnew(LineEdit);
  1675. search_box->set_placeholder(TTR("Filter tiles"));
  1676. search_box->set_h_size_flags(SIZE_EXPAND_FILL);
  1677. search_box->connect("text_entered", this, "_text_entered");
  1678. search_box->connect("text_changed", this, "_text_changed");
  1679. search_box->connect("gui_input", this, "_sbox_input");
  1680. add_child(search_box);
  1681. size_slider = memnew(HSlider);
  1682. size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
  1683. size_slider->set_min(0.1f);
  1684. size_slider->set_max(4.0f);
  1685. size_slider->set_step(0.1f);
  1686. size_slider->set_value(1.0f);
  1687. size_slider->connect("value_changed", this, "_icon_size_changed");
  1688. add_child(size_slider);
  1689. int mw = EDITOR_GET("editors/tile_map/palette_min_width");
  1690. VSplitContainer *palette_container = memnew(VSplitContainer);
  1691. palette_container->set_v_size_flags(SIZE_EXPAND_FILL);
  1692. palette_container->set_custom_minimum_size(Size2(mw, 0));
  1693. add_child(palette_container);
  1694. // Add tile palette.
  1695. palette = memnew(ItemList);
  1696. palette->set_h_size_flags(SIZE_EXPAND_FILL);
  1697. palette->set_v_size_flags(SIZE_EXPAND_FILL);
  1698. palette->set_max_columns(0);
  1699. palette->set_icon_mode(ItemList::ICON_MODE_TOP);
  1700. palette->set_max_text_lines(2);
  1701. palette->set_select_mode(ItemList::SELECT_MULTI);
  1702. palette->add_constant_override("vseparation", 8 * EDSCALE);
  1703. palette->connect("item_selected", this, "_palette_selected");
  1704. palette->connect("multi_selected", this, "_palette_multi_selected");
  1705. palette->connect("gui_input", this, "_palette_input");
  1706. palette_container->add_child(palette);
  1707. // Add message for when no texture is selected.
  1708. info_message = memnew(Label);
  1709. info_message->set_text(TTR("Give a TileSet resource to this TileMap to use its tiles."));
  1710. info_message->set_valign(Label::VALIGN_CENTER);
  1711. info_message->set_align(Label::ALIGN_CENTER);
  1712. info_message->set_autowrap(true);
  1713. info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
  1714. info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
  1715. palette->add_child(info_message);
  1716. // Add autotile override palette.
  1717. manual_palette = memnew(ItemList);
  1718. manual_palette->set_h_size_flags(SIZE_EXPAND_FILL);
  1719. manual_palette->set_v_size_flags(SIZE_EXPAND_FILL);
  1720. manual_palette->set_max_columns(0);
  1721. manual_palette->set_icon_mode(ItemList::ICON_MODE_TOP);
  1722. manual_palette->set_max_text_lines(2);
  1723. manual_palette->hide();
  1724. palette_container->add_child(manual_palette);
  1725. // Add menu items.
  1726. toolbar = memnew(HBoxContainer);
  1727. toolbar->hide();
  1728. CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
  1729. toolbar->add_child(memnew(VSeparator));
  1730. // Tools.
  1731. paint_button = memnew(ToolButton);
  1732. paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P));
  1733. #ifdef OSX_ENABLED
  1734. paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Command+LMB: Rectangle Paint"));
  1735. #else
  1736. paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint"));
  1737. #endif
  1738. paint_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_NONE));
  1739. paint_button->set_toggle_mode(true);
  1740. toolbar->add_child(paint_button);
  1741. bucket_fill_button = memnew(ToolButton);
  1742. bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B));
  1743. bucket_fill_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_BUCKET));
  1744. bucket_fill_button->set_toggle_mode(true);
  1745. toolbar->add_child(bucket_fill_button);
  1746. picker_button = memnew(ToolButton);
  1747. picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I));
  1748. picker_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PICKING));
  1749. picker_button->set_toggle_mode(true);
  1750. toolbar->add_child(picker_button);
  1751. select_button = memnew(ToolButton);
  1752. select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M));
  1753. select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECTING));
  1754. select_button->set_toggle_mode(true);
  1755. toolbar->add_child(select_button);
  1756. _update_button_tool();
  1757. // Container to the right of the toolbar.
  1758. toolbar_right = memnew(HBoxContainer);
  1759. toolbar_right->hide();
  1760. toolbar_right->set_h_size_flags(SIZE_EXPAND_FILL);
  1761. toolbar_right->set_alignment(BoxContainer::ALIGN_END);
  1762. CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar_right);
  1763. // Tile position.
  1764. tile_info = memnew(Label);
  1765. tile_info->set_modulate(Color(1, 1, 1, 0.8));
  1766. tile_info->set_mouse_filter(MOUSE_FILTER_IGNORE);
  1767. tile_info->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
  1768. tile_info->add_color_override("font_color", Color(1, 1, 1, 0.8)); // Overlay has a fixed dark background.
  1769. // The tile info is only displayed after a tile has been hovered.
  1770. tile_info->hide();
  1771. CanvasItemEditor::get_singleton()->add_control_to_info_overlay(tile_info);
  1772. // Menu.
  1773. options = memnew(MenuButton);
  1774. options->set_text("TileMap");
  1775. options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
  1776. options->set_process_unhandled_key_input(false);
  1777. toolbar_right->add_child(options);
  1778. PopupMenu *p = options->get_popup();
  1779. p->add_shortcut(ED_SHORTCUT("tile_map_editor/cut_selection", TTR("Cut Selection"), KEY_MASK_CMD + KEY_X), OPTION_CUT);
  1780. p->add_shortcut(ED_SHORTCUT("tile_map_editor/copy_selection", TTR("Copy Selection"), KEY_MASK_CMD + KEY_C), OPTION_COPY);
  1781. p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION);
  1782. p->add_separator();
  1783. p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID);
  1784. p->connect("id_pressed", this, "_menu_option");
  1785. rotate_left_button = memnew(ToolButton);
  1786. rotate_left_button->set_tooltip(TTR("Rotate Left"));
  1787. rotate_left_button->set_focus_mode(FOCUS_NONE);
  1788. rotate_left_button->connect("pressed", this, "_rotate", varray(-1));
  1789. rotate_left_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_left", TTR("Rotate Left"), KEY_A));
  1790. tool_hb->add_child(rotate_left_button);
  1791. rotate_right_button = memnew(ToolButton);
  1792. rotate_right_button->set_tooltip(TTR("Rotate Right"));
  1793. rotate_right_button->set_focus_mode(FOCUS_NONE);
  1794. rotate_right_button->connect("pressed", this, "_rotate", varray(1));
  1795. rotate_right_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_right", TTR("Rotate Right"), KEY_S));
  1796. tool_hb->add_child(rotate_right_button);
  1797. flip_horizontal_button = memnew(ToolButton);
  1798. flip_horizontal_button->set_tooltip(TTR("Flip Horizontally"));
  1799. flip_horizontal_button->set_focus_mode(FOCUS_NONE);
  1800. flip_horizontal_button->connect("pressed", this, "_flip_horizontal");
  1801. flip_horizontal_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_horizontal", TTR("Flip Horizontally"), KEY_X));
  1802. tool_hb->add_child(flip_horizontal_button);
  1803. flip_vertical_button = memnew(ToolButton);
  1804. flip_vertical_button->set_tooltip(TTR("Flip Vertically"));
  1805. flip_vertical_button->set_focus_mode(FOCUS_NONE);
  1806. flip_vertical_button->connect("pressed", this, "_flip_vertical");
  1807. flip_vertical_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_vertical", TTR("Flip Vertically"), KEY_Z));
  1808. tool_hb->add_child(flip_vertical_button);
  1809. clear_transform_button = memnew(ToolButton);
  1810. clear_transform_button->set_tooltip(TTR("Clear Transform"));
  1811. clear_transform_button->set_focus_mode(FOCUS_NONE);
  1812. clear_transform_button->connect("pressed", this, "_clear_transform");
  1813. clear_transform_button->set_shortcut(ED_SHORTCUT("tile_map_editor/clear_transform", TTR("Clear Transform"), KEY_W));
  1814. tool_hb->add_child(clear_transform_button);
  1815. clear_transform_button->set_disabled(true);
  1816. }
  1817. TileMapEditor::~TileMapEditor() {
  1818. _clear_bucket_cache();
  1819. copydata.clear();
  1820. }
  1821. ///////////////////////////////////////////////////////////////
  1822. ///////////////////////////////////////////////////////////////
  1823. ///////////////////////////////////////////////////////////////
  1824. void TileMapEditorPlugin::_notification(int p_what) {
  1825. if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
  1826. switch ((int)EditorSettings::get_singleton()->get("editors/tile_map/editor_side")) {
  1827. case 0: { // Left.
  1828. CanvasItemEditor::get_singleton()->move_control_to_left_panel(tile_map_editor);
  1829. } break;
  1830. case 1: { // Right.
  1831. CanvasItemEditor::get_singleton()->move_control_to_right_panel(tile_map_editor);
  1832. } break;
  1833. }
  1834. }
  1835. }
  1836. void TileMapEditorPlugin::edit(Object *p_object) {
  1837. tile_map_editor->edit(Object::cast_to<Node>(p_object));
  1838. }
  1839. bool TileMapEditorPlugin::handles(Object *p_object) const {
  1840. return p_object->is_class("TileMap");
  1841. }
  1842. void TileMapEditorPlugin::make_visible(bool p_visible) {
  1843. if (p_visible) {
  1844. tile_map_editor->show();
  1845. tile_map_editor->get_toolbar()->show();
  1846. tile_map_editor->get_toolbar_right()->show();
  1847. // `tile_info` isn't shown here, as it's displayed after a tile has been hovered.
  1848. // Otherwise, a translucent black rectangle would be visible as there would be an
  1849. // empty Label in the CanvasItemEditor's info overlay.
  1850. // Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
  1851. CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT);
  1852. } else {
  1853. tile_map_editor->hide();
  1854. tile_map_editor->get_toolbar()->hide();
  1855. tile_map_editor->get_toolbar_right()->hide();
  1856. tile_map_editor->get_tile_info()->hide();
  1857. tile_map_editor->edit(nullptr);
  1858. }
  1859. }
  1860. TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
  1861. EDITOR_DEF("editors/tile_map/preview_size", 64);
  1862. EDITOR_DEF("editors/tile_map/palette_min_width", 80);
  1863. EDITOR_DEF("editors/tile_map/palette_item_hseparation", 8);
  1864. EDITOR_DEF("editors/tile_map/show_tile_names", true);
  1865. EDITOR_DEF("editors/tile_map/show_tile_ids", false);
  1866. EDITOR_DEF("editors/tile_map/sort_tiles_by_name", true);
  1867. EDITOR_DEF("editors/tile_map/bucket_fill_preview", true);
  1868. EDITOR_DEF("editors/tile_map/editor_side", 1);
  1869. EDITOR_DEF("editors/tile_map/display_grid", true);
  1870. EDITOR_DEF("editors/tile_map/grid_color", Color(1, 0.3, 0.1, 0.2));
  1871. EDITOR_DEF("editors/tile_map/axis_color", Color(1, 0.8, 0.2, 0.5));
  1872. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/tile_map/editor_side", PROPERTY_HINT_ENUM, "Left,Right"));
  1873. tile_map_editor = memnew(TileMapEditor(p_node));
  1874. switch ((int)EditorSettings::get_singleton()->get("editors/tile_map/editor_side")) {
  1875. case 0: { // Left.
  1876. CanvasItemEditor::get_singleton()->add_control_to_left_panel(tile_map_editor);
  1877. } break;
  1878. case 1: { // Right.
  1879. CanvasItemEditor::get_singleton()->add_control_to_right_panel(tile_map_editor);
  1880. } break;
  1881. }
  1882. tile_map_editor->hide();
  1883. }
  1884. TileMapEditorPlugin::~TileMapEditorPlugin() {
  1885. }