tile_map_editor.cpp 165 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061
  1. /*************************************************************************/
  2. /* tile_map_editor.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 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 "tile_map_editor.h"
  31. #include "tiles_editor_plugin.h"
  32. #include "editor/editor_node.h"
  33. #include "editor/editor_resource_preview.h"
  34. #include "editor/editor_scale.h"
  35. #include "editor/editor_undo_redo_manager.h"
  36. #include "editor/plugins/canvas_item_editor_plugin.h"
  37. #include "scene/2d/camera_2d.h"
  38. #include "scene/gui/center_container.h"
  39. #include "scene/gui/split_container.h"
  40. #include "core/input/input.h"
  41. #include "core/math/geometry_2d.h"
  42. #include "core/os/keyboard.h"
  43. void TileMapEditorTilesPlugin::tile_set_changed() {
  44. _update_fix_selected_and_hovered();
  45. _update_tile_set_sources_list();
  46. _update_source_display();
  47. _update_patterns_list();
  48. }
  49. void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
  50. scatter_spinbox->set_editable(p_pressed);
  51. }
  52. void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
  53. scattering = p_value;
  54. }
  55. void TileMapEditorTilesPlugin::_update_toolbar() {
  56. // Stop draggig if needed.
  57. _stop_dragging();
  58. // Hide all settings.
  59. for (int i = 0; i < tools_settings->get_child_count(); i++) {
  60. Object::cast_to<CanvasItem>(tools_settings->get_child(i))->hide();
  61. }
  62. // Show only the correct settings.
  63. if (tool_buttons_group->get_pressed_button() == select_tool_button) {
  64. } else if (tool_buttons_group->get_pressed_button() == paint_tool_button) {
  65. tools_settings_vsep->show();
  66. picker_button->show();
  67. erase_button->show();
  68. tools_settings_vsep_2->show();
  69. random_tile_toggle->show();
  70. scatter_label->show();
  71. scatter_spinbox->show();
  72. } else if (tool_buttons_group->get_pressed_button() == line_tool_button) {
  73. tools_settings_vsep->show();
  74. picker_button->show();
  75. erase_button->show();
  76. tools_settings_vsep_2->show();
  77. random_tile_toggle->show();
  78. scatter_label->show();
  79. scatter_spinbox->show();
  80. } else if (tool_buttons_group->get_pressed_button() == rect_tool_button) {
  81. tools_settings_vsep->show();
  82. picker_button->show();
  83. erase_button->show();
  84. tools_settings_vsep_2->show();
  85. random_tile_toggle->show();
  86. scatter_label->show();
  87. scatter_spinbox->show();
  88. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button) {
  89. tools_settings_vsep->show();
  90. picker_button->show();
  91. erase_button->show();
  92. tools_settings_vsep_2->show();
  93. bucket_contiguous_checkbox->show();
  94. random_tile_toggle->show();
  95. scatter_label->show();
  96. scatter_spinbox->show();
  97. }
  98. }
  99. Vector<TileMapEditorPlugin::TabData> TileMapEditorTilesPlugin::get_tabs() const {
  100. Vector<TileMapEditorPlugin::TabData> tabs;
  101. tabs.push_back({ toolbar, tiles_bottom_panel });
  102. tabs.push_back({ toolbar, patterns_bottom_panel });
  103. return tabs;
  104. }
  105. void TileMapEditorTilesPlugin::_tab_changed() {
  106. if (tiles_bottom_panel->is_visible_in_tree()) {
  107. _update_selection_pattern_from_tileset_tiles_selection();
  108. } else if (patterns_bottom_panel->is_visible_in_tree()) {
  109. _update_selection_pattern_from_tileset_pattern_selection();
  110. }
  111. }
  112. void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
  113. // Update the sources.
  114. int old_current = sources_list->get_current();
  115. int old_source = -1;
  116. if (old_current > -1) {
  117. old_source = sources_list->get_item_metadata(old_current);
  118. }
  119. sources_list->clear();
  120. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  121. if (!tile_map) {
  122. return;
  123. }
  124. Ref<TileSet> tile_set = tile_map->get_tileset();
  125. if (!tile_set.is_valid()) {
  126. return;
  127. }
  128. if (!tile_set->has_source(old_source)) {
  129. old_source = -1;
  130. }
  131. List<int> source_ids = TilesEditorPlugin::get_singleton()->get_sorted_sources(tile_set);
  132. for (const int &source_id : source_ids) {
  133. TileSetSource *source = *tile_set->get_source(source_id);
  134. Ref<Texture2D> texture;
  135. String item_text;
  136. // Common to all type of sources.
  137. if (!source->get_name().is_empty()) {
  138. item_text = vformat(TTR("%s (id:%d)"), source->get_name(), source_id);
  139. }
  140. // Atlas source.
  141. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  142. if (atlas_source) {
  143. texture = atlas_source->get_texture();
  144. if (item_text.is_empty()) {
  145. if (texture.is_valid()) {
  146. item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id);
  147. } else {
  148. item_text = vformat(TTR("No Texture Atlas Source (ID: %d)"), source_id);
  149. }
  150. }
  151. }
  152. // Scene collection source.
  153. TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
  154. if (scene_collection_source) {
  155. texture = tiles_bottom_panel->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"));
  156. if (item_text.is_empty()) {
  157. item_text = vformat(TTR("Scene Collection Source (ID: %d)"), source_id);
  158. }
  159. }
  160. // Use default if not valid.
  161. if (item_text.is_empty()) {
  162. item_text = vformat(TTR("Unknown Type Source (ID: %d)"), source_id);
  163. }
  164. if (!texture.is_valid()) {
  165. texture = missing_atlas_texture_icon;
  166. }
  167. sources_list->add_item(item_text, texture);
  168. sources_list->set_item_metadata(-1, source_id);
  169. }
  170. if (sources_list->get_item_count() > 0) {
  171. if (old_source >= 0) {
  172. for (int i = 0; i < sources_list->get_item_count(); i++) {
  173. if ((int)sources_list->get_item_metadata(i) == old_source) {
  174. sources_list->set_current(i);
  175. sources_list->ensure_current_is_visible();
  176. break;
  177. }
  178. }
  179. } else {
  180. sources_list->set_current(0);
  181. }
  182. sources_list->emit_signal(SNAME("item_selected"), sources_list->get_current());
  183. }
  184. // Synchronize the lists.
  185. TilesEditorPlugin::get_singleton()->set_sources_lists_current(sources_list->get_current());
  186. }
  187. void TileMapEditorTilesPlugin::_update_source_display() {
  188. // Update the atlas display.
  189. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  190. if (!tile_map) {
  191. return;
  192. }
  193. Ref<TileSet> tile_set = tile_map->get_tileset();
  194. if (!tile_set.is_valid()) {
  195. return;
  196. }
  197. int source_index = sources_list->get_current();
  198. if (source_index >= 0 && source_index < sources_list->get_item_count()) {
  199. atlas_sources_split_container->show();
  200. missing_source_label->hide();
  201. int source_id = sources_list->get_item_metadata(source_index);
  202. TileSetSource *source = *tile_set->get_source(source_id);
  203. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  204. TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
  205. if (atlas_source) {
  206. tile_atlas_view->show();
  207. scene_tiles_list->hide();
  208. invalid_source_label->hide();
  209. _update_atlas_view();
  210. } else if (scenes_collection_source) {
  211. tile_atlas_view->hide();
  212. scene_tiles_list->show();
  213. invalid_source_label->hide();
  214. _update_scenes_collection_view();
  215. } else {
  216. tile_atlas_view->hide();
  217. scene_tiles_list->hide();
  218. invalid_source_label->show();
  219. }
  220. } else {
  221. atlas_sources_split_container->hide();
  222. missing_source_label->show();
  223. tile_atlas_view->hide();
  224. scene_tiles_list->hide();
  225. invalid_source_label->hide();
  226. }
  227. }
  228. void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) {
  229. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  230. if (!tile_map) {
  231. return;
  232. }
  233. Ref<TileSet> tile_set = tile_map->get_tileset();
  234. if (!tile_set.is_valid()) {
  235. return;
  236. }
  237. if (ED_IS_SHORTCUT("tiles_editor/paste", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
  238. select_last_pattern = true;
  239. int new_pattern_index = tile_set->get_patterns_count();
  240. undo_redo->create_action(TTR("Add TileSet pattern"));
  241. undo_redo->add_do_method(*tile_set, "add_pattern", tile_map_clipboard, new_pattern_index);
  242. undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index);
  243. undo_redo->commit_action();
  244. patterns_item_list->accept_event();
  245. }
  246. if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) {
  247. Vector<int> selected = patterns_item_list->get_selected_items();
  248. undo_redo->create_action(TTR("Remove TileSet patterns"));
  249. for (int i = 0; i < selected.size(); i++) {
  250. int pattern_index = selected[i];
  251. undo_redo->add_do_method(*tile_set, "remove_pattern", pattern_index);
  252. undo_redo->add_undo_method(*tile_set, "add_pattern", tile_set->get_pattern(pattern_index), pattern_index);
  253. }
  254. undo_redo->commit_action();
  255. patterns_item_list->accept_event();
  256. }
  257. }
  258. void TileMapEditorTilesPlugin::_pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture) {
  259. // TODO optimize ?
  260. for (int i = 0; i < patterns_item_list->get_item_count(); i++) {
  261. if (patterns_item_list->get_item_metadata(i) == p_pattern) {
  262. patterns_item_list->set_item_icon(i, p_texture);
  263. break;
  264. }
  265. }
  266. }
  267. void TileMapEditorTilesPlugin::_update_patterns_list() {
  268. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  269. if (!tile_map) {
  270. return;
  271. }
  272. Ref<TileSet> tile_set = tile_map->get_tileset();
  273. if (!tile_set.is_valid()) {
  274. return;
  275. }
  276. // Recreate the items.
  277. patterns_item_list->clear();
  278. for (int i = 0; i < tile_set->get_patterns_count(); i++) {
  279. int id = patterns_item_list->add_item("");
  280. patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
  281. TilesEditorPlugin::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapEditorTilesPlugin::_pattern_preview_done));
  282. }
  283. // Update the label visibility.
  284. patterns_help_label->set_visible(patterns_item_list->get_item_count() == 0);
  285. // Added a new pattern, thus select the last one.
  286. if (select_last_pattern) {
  287. patterns_item_list->select(tile_set->get_patterns_count() - 1);
  288. patterns_item_list->grab_focus();
  289. _update_selection_pattern_from_tileset_pattern_selection();
  290. }
  291. select_last_pattern = false;
  292. }
  293. void TileMapEditorTilesPlugin::_update_atlas_view() {
  294. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  295. if (!tile_map) {
  296. return;
  297. }
  298. Ref<TileSet> tile_set = tile_map->get_tileset();
  299. if (!tile_set.is_valid()) {
  300. return;
  301. }
  302. int source_id = sources_list->get_item_metadata(sources_list->get_current());
  303. TileSetSource *source = *tile_set->get_source(source_id);
  304. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  305. ERR_FAIL_COND(!atlas_source);
  306. tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
  307. TilesEditorPlugin::get_singleton()->synchronize_atlas_view(tile_atlas_view);
  308. tile_atlas_control->queue_redraw();
  309. }
  310. void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
  311. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  312. if (!tile_map) {
  313. return;
  314. }
  315. Ref<TileSet> tile_set = tile_map->get_tileset();
  316. if (!tile_set.is_valid()) {
  317. return;
  318. }
  319. int source_id = sources_list->get_item_metadata(sources_list->get_current());
  320. TileSetSource *source = *tile_set->get_source(source_id);
  321. TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
  322. ERR_FAIL_COND(!scenes_collection_source);
  323. // Clear the list.
  324. scene_tiles_list->clear();
  325. // Rebuild the list.
  326. for (int i = 0; i < scenes_collection_source->get_scene_tiles_count(); i++) {
  327. int scene_id = scenes_collection_source->get_scene_tile_id(i);
  328. Ref<PackedScene> scene = scenes_collection_source->get_scene_tile_scene(scene_id);
  329. int item_index = 0;
  330. if (scene.is_valid()) {
  331. item_index = scene_tiles_list->add_item(vformat("%s (Path: %s, ID: %d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
  332. Variant udata = i;
  333. EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
  334. } else {
  335. item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), tiles_bottom_panel->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")));
  336. }
  337. scene_tiles_list->set_item_metadata(item_index, scene_id);
  338. // Check if in selection.
  339. if (tile_set_selection.has(TileMapCell(source_id, Vector2i(), scene_id))) {
  340. scene_tiles_list->select(item_index, false);
  341. }
  342. }
  343. // Icon size update.
  344. int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
  345. scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
  346. }
  347. void TileMapEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
  348. int index = p_ud;
  349. if (index >= 0 && index < scene_tiles_list->get_item_count()) {
  350. scene_tiles_list->set_item_icon(index, p_preview);
  351. }
  352. }
  353. void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_selected) {
  354. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  355. if (!tile_map) {
  356. return;
  357. }
  358. Ref<TileSet> tile_set = tile_map->get_tileset();
  359. if (!tile_set.is_valid()) {
  360. return;
  361. }
  362. // Add or remove the Tile form the selection.
  363. int scene_id = scene_tiles_list->get_item_metadata(p_index);
  364. int source_id = sources_list->get_item_metadata(sources_list->get_current());
  365. TileSetSource *source = *tile_set->get_source(source_id);
  366. TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
  367. ERR_FAIL_COND(!scenes_collection_source);
  368. TileMapCell selected = TileMapCell(source_id, Vector2i(), scene_id);
  369. // Clear the selection if shift is not pressed.
  370. if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
  371. tile_set_selection.clear();
  372. }
  373. if (p_selected) {
  374. tile_set_selection.insert(selected);
  375. } else {
  376. if (tile_set_selection.has(selected)) {
  377. tile_set_selection.erase(selected);
  378. }
  379. }
  380. _update_selection_pattern_from_tileset_tiles_selection();
  381. }
  382. void TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
  383. if (p_mouse_button_index != MouseButton::LEFT) {
  384. return;
  385. }
  386. scene_tiles_list->deselect_all();
  387. tile_set_selection.clear();
  388. tile_map_selection.clear();
  389. selection_pattern.instantiate();
  390. _update_selection_pattern_from_tileset_tiles_selection();
  391. }
  392. void TileMapEditorTilesPlugin::_update_theme() {
  393. source_sort_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Sort"), SNAME("EditorIcons")));
  394. select_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
  395. paint_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
  396. line_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")));
  397. rect_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons")));
  398. bucket_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons")));
  399. picker_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
  400. erase_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
  401. random_tile_toggle->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("RandomNumberGenerator"), SNAME("EditorIcons")));
  402. missing_atlas_texture_icon = tiles_bottom_panel->get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
  403. }
  404. bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
  405. if (!(tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree())) {
  406. // If the bottom editor is not visible, we ignore inputs.
  407. return false;
  408. }
  409. if (CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT) {
  410. return false;
  411. }
  412. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  413. if (!tile_map) {
  414. return false;
  415. }
  416. if (tile_map_layer < 0) {
  417. return false;
  418. }
  419. ERR_FAIL_INDEX_V(tile_map_layer, tile_map->get_layers_count(), false);
  420. Ref<TileSet> tile_set = tile_map->get_tileset();
  421. if (!tile_set.is_valid()) {
  422. return false;
  423. }
  424. // Shortcuts
  425. if (ED_IS_SHORTCUT("tiles_editor/cut", p_event) || ED_IS_SHORTCUT("tiles_editor/copy", p_event)) {
  426. // Fill in the clipboard.
  427. if (!tile_map_selection.is_empty()) {
  428. tile_map_clipboard.instantiate();
  429. TypedArray<Vector2i> coords_array;
  430. for (const Vector2i &E : tile_map_selection) {
  431. coords_array.push_back(E);
  432. }
  433. tile_map_clipboard = tile_map->get_pattern(tile_map_layer, coords_array);
  434. }
  435. if (ED_IS_SHORTCUT("tiles_editor/cut", p_event)) {
  436. // Delete selected tiles.
  437. if (!tile_map_selection.is_empty()) {
  438. undo_redo->create_action(TTR("Delete tiles"));
  439. for (const Vector2i &E : tile_map_selection) {
  440. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  441. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E, tile_map->get_cell_source_id(tile_map_layer, E), tile_map->get_cell_atlas_coords(tile_map_layer, E), tile_map->get_cell_alternative_tile(tile_map_layer, E));
  442. }
  443. undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  444. tile_map_selection.clear();
  445. undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  446. undo_redo->commit_action();
  447. }
  448. }
  449. return true;
  450. }
  451. if (ED_IS_SHORTCUT("tiles_editor/paste", p_event)) {
  452. if (drag_type == DRAG_TYPE_NONE) {
  453. drag_type = DRAG_TYPE_CLIPBOARD_PASTE;
  454. }
  455. CanvasItemEditor::get_singleton()->update_viewport();
  456. return true;
  457. }
  458. if (ED_IS_SHORTCUT("tiles_editor/cancel", p_event)) {
  459. if (drag_type == DRAG_TYPE_CLIPBOARD_PASTE) {
  460. drag_type = DRAG_TYPE_NONE;
  461. CanvasItemEditor::get_singleton()->update_viewport();
  462. return true;
  463. }
  464. }
  465. if (ED_IS_SHORTCUT("tiles_editor/delete", p_event)) {
  466. // Delete selected tiles.
  467. if (!tile_map_selection.is_empty()) {
  468. undo_redo->create_action(TTR("Delete tiles"));
  469. for (const Vector2i &E : tile_map_selection) {
  470. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  471. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E, tile_map->get_cell_source_id(tile_map_layer, E), tile_map->get_cell_atlas_coords(tile_map_layer, E), tile_map->get_cell_alternative_tile(tile_map_layer, E));
  472. }
  473. undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  474. tile_map_selection.clear();
  475. undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  476. undo_redo->commit_action();
  477. }
  478. return true;
  479. }
  480. Ref<InputEventMouseMotion> mm = p_event;
  481. if (mm.is_valid()) {
  482. has_mouse = true;
  483. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  484. Vector2 mpos = xform.affine_inverse().xform(mm->get_position());
  485. switch (drag_type) {
  486. case DRAG_TYPE_PAINT: {
  487. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos, drag_erasing);
  488. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  489. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  490. continue;
  491. }
  492. Vector2i coords = E.key;
  493. if (!drag_modified.has(coords)) {
  494. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  495. }
  496. tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  497. }
  498. _fix_invalid_tiles_in_tile_map_selection();
  499. } break;
  500. case DRAG_TYPE_BUCKET: {
  501. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos));
  502. for (int i = 0; i < line.size(); i++) {
  503. if (!drag_modified.has(line[i])) {
  504. HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
  505. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  506. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  507. continue;
  508. }
  509. Vector2i coords = E.key;
  510. if (!drag_modified.has(coords)) {
  511. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  512. }
  513. tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  514. }
  515. }
  516. }
  517. _fix_invalid_tiles_in_tile_map_selection();
  518. } break;
  519. default:
  520. break;
  521. }
  522. drag_last_mouse_pos = mpos;
  523. CanvasItemEditor::get_singleton()->update_viewport();
  524. return true;
  525. }
  526. Ref<InputEventMouseButton> mb = p_event;
  527. if (mb.is_valid()) {
  528. has_mouse = true;
  529. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  530. Vector2 mpos = xform.affine_inverse().xform(mb->get_position());
  531. if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
  532. if (mb->is_pressed()) {
  533. // Pressed
  534. if (erase_button->is_pressed() || mb->get_button_index() == MouseButton::RIGHT) {
  535. drag_erasing = true;
  536. }
  537. if (drag_type == DRAG_TYPE_CLIPBOARD_PASTE) {
  538. // Cancel tile pasting on right-click
  539. if (mb->get_button_index() == MouseButton::RIGHT) {
  540. drag_type = DRAG_TYPE_NONE;
  541. }
  542. } else if (tool_buttons_group->get_pressed_button() == select_tool_button) {
  543. drag_start_mouse_pos = mpos;
  544. if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) {
  545. // Move the selection
  546. _update_selection_pattern_from_tilemap_selection(); // Make sure the pattern is up to date before moving.
  547. drag_type = DRAG_TYPE_MOVE;
  548. drag_modified.clear();
  549. for (const Vector2i &E : tile_map_selection) {
  550. Vector2i coords = E;
  551. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  552. tile_map->set_cell(tile_map_layer, coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  553. }
  554. } else {
  555. // Select tiles
  556. drag_type = DRAG_TYPE_SELECT;
  557. }
  558. } else {
  559. // Check if we are picking a tile.
  560. if (picker_button->is_pressed() || (Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) {
  561. drag_type = DRAG_TYPE_PICK;
  562. drag_start_mouse_pos = mpos;
  563. } else {
  564. // Paint otherwise.
  565. if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
  566. drag_type = DRAG_TYPE_PAINT;
  567. drag_start_mouse_pos = mpos;
  568. drag_modified.clear();
  569. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos, drag_erasing);
  570. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  571. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  572. continue;
  573. }
  574. Vector2i coords = E.key;
  575. if (!drag_modified.has(coords)) {
  576. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  577. }
  578. tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  579. }
  580. _fix_invalid_tiles_in_tile_map_selection();
  581. } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL))) {
  582. drag_type = DRAG_TYPE_LINE;
  583. drag_start_mouse_pos = mpos;
  584. drag_modified.clear();
  585. } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && Input::get_singleton()->is_key_pressed(Key::CTRL))) {
  586. drag_type = DRAG_TYPE_RECT;
  587. drag_start_mouse_pos = mpos;
  588. drag_modified.clear();
  589. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button) {
  590. drag_type = DRAG_TYPE_BUCKET;
  591. drag_start_mouse_pos = mpos;
  592. drag_modified.clear();
  593. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos));
  594. for (int i = 0; i < line.size(); i++) {
  595. if (!drag_modified.has(line[i])) {
  596. HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
  597. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  598. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  599. continue;
  600. }
  601. Vector2i coords = E.key;
  602. if (!drag_modified.has(coords)) {
  603. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  604. }
  605. tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  606. }
  607. }
  608. }
  609. _fix_invalid_tiles_in_tile_map_selection();
  610. }
  611. }
  612. }
  613. } else {
  614. // Released
  615. _stop_dragging();
  616. drag_erasing = false;
  617. }
  618. CanvasItemEditor::get_singleton()->update_viewport();
  619. return true;
  620. }
  621. drag_last_mouse_pos = mpos;
  622. }
  623. return false;
  624. }
  625. void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
  626. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  627. if (!tile_map) {
  628. return;
  629. }
  630. if (tile_map_layer < 0) {
  631. return;
  632. }
  633. ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
  634. Ref<TileSet> tile_set = tile_map->get_tileset();
  635. if (!tile_set.is_valid()) {
  636. return;
  637. }
  638. if (!tile_map->is_visible_in_tree()) {
  639. return;
  640. }
  641. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  642. Vector2i tile_shape_size = tile_set->get_tile_size();
  643. // Draw the selection.
  644. if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && tool_buttons_group->get_pressed_button() == select_tool_button) {
  645. // In select mode, we only draw the current selection if we are modifying it (pressing control or shift).
  646. if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) {
  647. // Do nothing
  648. } else {
  649. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  650. Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
  651. tile_map->draw_cells_outline(p_overlay, tile_map_selection, selection_color, xform);
  652. }
  653. }
  654. // Handle the preview of the tiles to be placed.
  655. if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
  656. HashMap<Vector2i, TileMapCell> preview;
  657. Rect2i drawn_grid_rect;
  658. if (drag_type == DRAG_TYPE_PICK) {
  659. // Draw the area being picked.
  660. Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos) - tile_map->world_to_map(drag_start_mouse_pos)).abs();
  661. rect.size += Vector2i(1, 1);
  662. for (int x = rect.position.x; x < rect.get_end().x; x++) {
  663. for (int y = rect.position.y; y < rect.get_end().y; y++) {
  664. Vector2i coords = Vector2i(x, y);
  665. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  666. Transform2D tile_xform;
  667. tile_xform.set_origin(tile_map->map_to_world(coords));
  668. tile_xform.set_scale(tile_shape_size);
  669. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false);
  670. }
  671. }
  672. }
  673. } else if (drag_type == DRAG_TYPE_SELECT) {
  674. // Draw the area being selected.
  675. Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos) - tile_map->world_to_map(drag_start_mouse_pos)).abs();
  676. rect.size += Vector2i(1, 1);
  677. RBSet<Vector2i> to_draw;
  678. for (int x = rect.position.x; x < rect.get_end().x; x++) {
  679. for (int y = rect.position.y; y < rect.get_end().y; y++) {
  680. Vector2i coords = Vector2i(x, y);
  681. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  682. to_draw.insert(coords);
  683. }
  684. }
  685. }
  686. tile_map->draw_cells_outline(p_overlay, to_draw, Color(1.0, 1.0, 1.0), xform);
  687. } else if (drag_type == DRAG_TYPE_MOVE) {
  688. if (!(patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position()))) {
  689. // Preview when moving.
  690. Vector2i top_left;
  691. if (!tile_map_selection.is_empty()) {
  692. top_left = tile_map_selection.front()->get();
  693. }
  694. for (const Vector2i &E : tile_map_selection) {
  695. top_left = top_left.min(E);
  696. }
  697. Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left);
  698. offset = tile_map->world_to_map(drag_last_mouse_pos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset);
  699. TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells();
  700. for (int i = 0; i < selection_used_cells.size(); i++) {
  701. Vector2i coords = tile_map->map_pattern(offset + top_left, selection_used_cells[i], selection_pattern);
  702. preview[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i]));
  703. }
  704. }
  705. } else if (drag_type == DRAG_TYPE_CLIPBOARD_PASTE) {
  706. // Preview when pasting.
  707. Vector2 mouse_offset = (Vector2(tile_map_clipboard->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
  708. TypedArray<Vector2i> clipboard_used_cells = tile_map_clipboard->get_used_cells();
  709. for (int i = 0; i < clipboard_used_cells.size(); i++) {
  710. Vector2i coords = tile_map->map_pattern(tile_map->world_to_map(drag_last_mouse_pos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard);
  711. preview[coords] = TileMapCell(tile_map_clipboard->get_cell_source_id(clipboard_used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(clipboard_used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(clipboard_used_cells[i]));
  712. }
  713. } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) {
  714. bool expand_grid = false;
  715. if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) {
  716. // Preview for a single pattern.
  717. preview = _draw_line(drag_last_mouse_pos, drag_last_mouse_pos, drag_last_mouse_pos, erase_button->is_pressed());
  718. expand_grid = true;
  719. } else if (tool_buttons_group->get_pressed_button() == line_tool_button || drag_type == DRAG_TYPE_LINE) {
  720. if (drag_type == DRAG_TYPE_NONE) {
  721. // Preview for a single pattern.
  722. preview = _draw_line(drag_last_mouse_pos, drag_last_mouse_pos, drag_last_mouse_pos, erase_button->is_pressed());
  723. expand_grid = true;
  724. } else if (drag_type == DRAG_TYPE_LINE) {
  725. // Preview for a line pattern.
  726. preview = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, drag_last_mouse_pos, drag_erasing);
  727. expand_grid = true;
  728. }
  729. } else if (drag_type == DRAG_TYPE_RECT) {
  730. // Preview for a rect pattern.
  731. preview = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos), drag_erasing);
  732. expand_grid = true;
  733. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) {
  734. // Preview for a fill pattern.
  735. preview = _draw_bucket_fill(tile_map->world_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed(), erase_button->is_pressed());
  736. }
  737. // Expand the grid if needed
  738. if (expand_grid && !preview.is_empty()) {
  739. drawn_grid_rect = Rect2i(preview.begin()->key, Vector2i(1, 1));
  740. for (const KeyValue<Vector2i, TileMapCell> &E : preview) {
  741. drawn_grid_rect.expand_to(E.key);
  742. }
  743. }
  744. }
  745. if (!preview.is_empty()) {
  746. const int fading = 5;
  747. // Draw the lines of the grid behind the preview.
  748. bool display_grid = EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid");
  749. if (display_grid) {
  750. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  751. if (drawn_grid_rect.size.x > 0 && drawn_grid_rect.size.y > 0) {
  752. drawn_grid_rect = drawn_grid_rect.grow(fading);
  753. for (int x = drawn_grid_rect.position.x; x < (drawn_grid_rect.position.x + drawn_grid_rect.size.x); x++) {
  754. for (int y = drawn_grid_rect.position.y; y < (drawn_grid_rect.position.y + drawn_grid_rect.size.y); y++) {
  755. Vector2i pos_in_rect = Vector2i(x, y) - drawn_grid_rect.position;
  756. // Fade out the border of the grid.
  757. float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
  758. float right_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.x, (float)(drawn_grid_rect.size.x - fading), (float)(pos_in_rect.x + 1)), 0.0f, 1.0f);
  759. float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
  760. float bottom_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.y, (float)(drawn_grid_rect.size.y - fading), (float)(pos_in_rect.y + 1)), 0.0f, 1.0f);
  761. float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
  762. Transform2D tile_xform;
  763. tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y)));
  764. tile_xform.set_scale(tile_shape_size);
  765. Color color = grid_color;
  766. color.a = color.a * opacity;
  767. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, false);
  768. }
  769. }
  770. }
  771. }
  772. // Draw the preview.
  773. for (const KeyValue<Vector2i, TileMapCell> &E : preview) {
  774. Transform2D tile_xform;
  775. tile_xform.set_origin(tile_map->map_to_world(E.key));
  776. tile_xform.set_scale(tile_set->get_tile_size());
  777. if (!(drag_erasing || erase_button->is_pressed()) && random_tile_toggle->is_pressed()) {
  778. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true);
  779. } else {
  780. if (tile_set->has_source(E.value.source_id)) {
  781. TileSetSource *source = *tile_set->get_source(E.value.source_id);
  782. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  783. if (atlas_source) {
  784. // Get tile data.
  785. TileData *tile_data = atlas_source->get_tile_data(E.value.get_atlas_coords(), E.value.alternative_tile);
  786. if (!tile_data) {
  787. continue;
  788. }
  789. // Compute the offset
  790. Rect2i source_rect = atlas_source->get_tile_texture_region(E.value.get_atlas_coords());
  791. Vector2i tile_offset = atlas_source->get_tile_effective_texture_offset(E.value.get_atlas_coords(), E.value.alternative_tile);
  792. // Compute the destination rectangle in the CanvasItem.
  793. Rect2 dest_rect;
  794. dest_rect.size = source_rect.size;
  795. bool transpose = tile_data->get_transpose();
  796. if (transpose) {
  797. dest_rect.position = (tile_map->map_to_world(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
  798. } else {
  799. dest_rect.position = (tile_map->map_to_world(E.key) - dest_rect.size / 2 - tile_offset);
  800. }
  801. dest_rect = xform.xform(dest_rect);
  802. if (tile_data->get_flip_h()) {
  803. dest_rect.size.x = -dest_rect.size.x;
  804. }
  805. if (tile_data->get_flip_v()) {
  806. dest_rect.size.y = -dest_rect.size.y;
  807. }
  808. // Get the tile modulation.
  809. Color modulate = tile_data->get_modulate();
  810. Color self_modulate = tile_map->get_self_modulate();
  811. modulate *= self_modulate;
  812. // Draw the tile.
  813. p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping());
  814. } else {
  815. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true);
  816. }
  817. } else {
  818. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(0.0, 0.0, 0.0, 0.5), true);
  819. }
  820. }
  821. }
  822. }
  823. }
  824. }
  825. void TileMapEditorTilesPlugin::_mouse_exited_viewport() {
  826. has_mouse = false;
  827. CanvasItemEditor::get_singleton()->update_viewport();
  828. }
  829. TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pattern) {
  830. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  831. if (!tile_map) {
  832. return TileMapCell();
  833. }
  834. Ref<TileSet> tile_set = tile_map->get_tileset();
  835. if (!tile_set.is_valid()) {
  836. return TileMapCell();
  837. }
  838. TypedArray<Vector2i> used_cells = p_pattern->get_used_cells();
  839. double sum = 0.0;
  840. for (int i = 0; i < used_cells.size(); i++) {
  841. int source_id = p_pattern->get_cell_source_id(used_cells[i]);
  842. Vector2i atlas_coords = p_pattern->get_cell_atlas_coords(used_cells[i]);
  843. int alternative_tile = p_pattern->get_cell_alternative_tile(used_cells[i]);
  844. TileSetSource *source = *tile_set->get_source(source_id);
  845. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  846. if (atlas_source) {
  847. TileData *tile_data = atlas_source->get_tile_data(atlas_coords, alternative_tile);
  848. ERR_FAIL_COND_V(!tile_data, TileMapCell());
  849. sum += tile_data->get_probability();
  850. } else {
  851. sum += 1.0;
  852. }
  853. }
  854. double empty_probability = sum * scattering;
  855. double current = 0.0;
  856. double rand = Math::random(0.0, sum + empty_probability);
  857. for (int i = 0; i < used_cells.size(); i++) {
  858. int source_id = p_pattern->get_cell_source_id(used_cells[i]);
  859. Vector2i atlas_coords = p_pattern->get_cell_atlas_coords(used_cells[i]);
  860. int alternative_tile = p_pattern->get_cell_alternative_tile(used_cells[i]);
  861. TileSetSource *source = *tile_set->get_source(source_id);
  862. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  863. if (atlas_source) {
  864. current += atlas_source->get_tile_data(atlas_coords, alternative_tile)->get_probability();
  865. } else {
  866. current += 1.0;
  867. }
  868. if (current >= rand) {
  869. return TileMapCell(source_id, atlas_coords, alternative_tile);
  870. }
  871. }
  872. return TileMapCell();
  873. }
  874. HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase) {
  875. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  876. if (!tile_map) {
  877. return HashMap<Vector2i, TileMapCell>();
  878. }
  879. Ref<TileSet> tile_set = tile_map->get_tileset();
  880. if (!tile_set.is_valid()) {
  881. return HashMap<Vector2i, TileMapCell>();
  882. }
  883. // Get or create the pattern.
  884. Ref<TileMapPattern> erase_pattern;
  885. erase_pattern.instantiate();
  886. erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  887. Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern;
  888. HashMap<Vector2i, TileMapCell> output;
  889. if (!pattern->is_empty()) {
  890. // Paint the tiles on the tile map.
  891. if (!p_erase && random_tile_toggle->is_pressed()) {
  892. // Paint a random tile.
  893. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(p_from_mouse_pos), tile_map->world_to_map(p_to_mouse_pos));
  894. for (int i = 0; i < line.size(); i++) {
  895. output.insert(line[i], _pick_random_tile(pattern));
  896. }
  897. } else {
  898. // Paint the pattern.
  899. // If we paint several tiles, we virtually move the mouse as if it was in the center of the "brush"
  900. Vector2 mouse_offset = (Vector2(pattern->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
  901. Vector2i last_hovered_cell = tile_map->world_to_map(p_from_mouse_pos - mouse_offset);
  902. Vector2i new_hovered_cell = tile_map->world_to_map(p_to_mouse_pos - mouse_offset);
  903. Vector2i drag_start_cell = tile_map->world_to_map(p_start_drag_mouse_pos - mouse_offset);
  904. TypedArray<Vector2i> used_cells = pattern->get_used_cells();
  905. Vector2i offset = Vector2i(Math::posmod(drag_start_cell.x, pattern->get_size().x), Math::posmod(drag_start_cell.y, pattern->get_size().y)); // Note: no posmodv for Vector2i for now. Meh.s
  906. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, (last_hovered_cell - offset) / pattern->get_size(), (new_hovered_cell - offset) / pattern->get_size());
  907. for (int i = 0; i < line.size(); i++) {
  908. Vector2i top_left = line[i] * pattern->get_size() + offset;
  909. for (int j = 0; j < used_cells.size(); j++) {
  910. Vector2i coords = tile_map->map_pattern(top_left, used_cells[j], pattern);
  911. output.insert(coords, TileMapCell(pattern->get_cell_source_id(used_cells[j]), pattern->get_cell_atlas_coords(used_cells[j]), pattern->get_cell_alternative_tile(used_cells[j])));
  912. }
  913. }
  914. }
  915. }
  916. return output;
  917. }
  918. HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
  919. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  920. if (!tile_map) {
  921. return HashMap<Vector2i, TileMapCell>();
  922. }
  923. Ref<TileSet> tile_set = tile_map->get_tileset();
  924. if (!tile_set.is_valid()) {
  925. return HashMap<Vector2i, TileMapCell>();
  926. }
  927. // Create the rect to draw.
  928. Rect2i rect = Rect2i(p_start_cell, p_end_cell - p_start_cell).abs();
  929. rect.size += Vector2i(1, 1);
  930. // Get or create the pattern.
  931. Ref<TileMapPattern> erase_pattern;
  932. erase_pattern.instantiate();
  933. erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  934. Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern;
  935. HashMap<Vector2i, TileMapCell> err_output;
  936. ERR_FAIL_COND_V(pattern->is_empty(), err_output);
  937. // Compute the offset to align things to the bottom or right.
  938. bool aligned_right = p_end_cell.x < p_start_cell.x;
  939. bool valigned_bottom = p_end_cell.y < p_start_cell.y;
  940. Vector2i offset = Vector2i(aligned_right ? -(pattern->get_size().x - (rect.get_size().x % pattern->get_size().x)) : 0, valigned_bottom ? -(pattern->get_size().y - (rect.get_size().y % pattern->get_size().y)) : 0);
  941. HashMap<Vector2i, TileMapCell> output;
  942. if (!pattern->is_empty()) {
  943. if (!p_erase && random_tile_toggle->is_pressed()) {
  944. // Paint a random tile.
  945. for (int x = 0; x < rect.size.x; x++) {
  946. for (int y = 0; y < rect.size.y; y++) {
  947. Vector2i coords = rect.position + Vector2i(x, y);
  948. output.insert(coords, _pick_random_tile(pattern));
  949. }
  950. }
  951. } else {
  952. // Paint the pattern.
  953. TypedArray<Vector2i> used_cells = pattern->get_used_cells();
  954. for (int x = 0; x <= rect.size.x / pattern->get_size().x; x++) {
  955. for (int y = 0; y <= rect.size.y / pattern->get_size().y; y++) {
  956. Vector2i pattern_coords = rect.position + Vector2i(x, y) * pattern->get_size() + offset;
  957. for (int j = 0; j < used_cells.size(); j++) {
  958. Vector2i coords = pattern_coords + used_cells[j];
  959. if (rect.has_point(coords)) {
  960. output.insert(coords, TileMapCell(pattern->get_cell_source_id(used_cells[j]), pattern->get_cell_atlas_coords(used_cells[j]), pattern->get_cell_alternative_tile(used_cells[j])));
  961. }
  962. }
  963. }
  964. }
  965. }
  966. }
  967. return output;
  968. }
  969. HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
  970. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  971. if (!tile_map) {
  972. return HashMap<Vector2i, TileMapCell>();
  973. }
  974. if (tile_map_layer < 0) {
  975. return HashMap<Vector2i, TileMapCell>();
  976. }
  977. HashMap<Vector2i, TileMapCell> output;
  978. ERR_FAIL_INDEX_V(tile_map_layer, tile_map->get_layers_count(), output);
  979. Ref<TileSet> tile_set = tile_map->get_tileset();
  980. if (!tile_set.is_valid()) {
  981. return HashMap<Vector2i, TileMapCell>();
  982. }
  983. // Get or create the pattern.
  984. Ref<TileMapPattern> erase_pattern;
  985. erase_pattern.instantiate();
  986. erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
  987. Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern;
  988. if (!pattern->is_empty()) {
  989. TileMapCell source_cell = tile_map->get_cell(tile_map_layer, p_coords);
  990. // If we are filling empty tiles, compute the tilemap boundaries.
  991. Rect2i boundaries;
  992. if (source_cell.source_id == TileSet::INVALID_SOURCE) {
  993. boundaries = tile_map->get_used_rect();
  994. }
  995. if (p_contiguous) {
  996. // Replace continuous tiles like the source.
  997. RBSet<Vector2i> already_checked;
  998. List<Vector2i> to_check;
  999. to_check.push_back(p_coords);
  1000. while (!to_check.is_empty()) {
  1001. Vector2i coords = to_check.back()->get();
  1002. to_check.pop_back();
  1003. if (!already_checked.has(coords)) {
  1004. if (source_cell.source_id == tile_map->get_cell_source_id(tile_map_layer, coords) &&
  1005. source_cell.get_atlas_coords() == tile_map->get_cell_atlas_coords(tile_map_layer, coords) &&
  1006. source_cell.alternative_tile == tile_map->get_cell_alternative_tile(tile_map_layer, coords) &&
  1007. (source_cell.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
  1008. if (!p_erase && random_tile_toggle->is_pressed()) {
  1009. // Paint a random tile.
  1010. output.insert(coords, _pick_random_tile(pattern));
  1011. } else {
  1012. // Paint the pattern.
  1013. Vector2i pattern_coords = (coords - p_coords) % pattern->get_size(); // Note: it would be good to have posmodv for Vector2i.
  1014. pattern_coords.x = pattern_coords.x < 0 ? pattern_coords.x + pattern->get_size().x : pattern_coords.x;
  1015. pattern_coords.y = pattern_coords.y < 0 ? pattern_coords.y + pattern->get_size().y : pattern_coords.y;
  1016. if (pattern->has_cell(pattern_coords)) {
  1017. output.insert(coords, TileMapCell(pattern->get_cell_source_id(pattern_coords), pattern->get_cell_atlas_coords(pattern_coords), pattern->get_cell_alternative_tile(pattern_coords)));
  1018. } else {
  1019. output.insert(coords, TileMapCell());
  1020. }
  1021. }
  1022. // Get surrounding tiles (handles different tile shapes).
  1023. TypedArray<Vector2i> around = tile_map->get_surrounding_tiles(coords);
  1024. for (int i = 0; i < around.size(); i++) {
  1025. to_check.push_back(around[i]);
  1026. }
  1027. }
  1028. already_checked.insert(coords);
  1029. }
  1030. }
  1031. } else {
  1032. // Replace all tiles like the source.
  1033. TypedArray<Vector2i> to_check;
  1034. if (source_cell.source_id == TileSet::INVALID_SOURCE) {
  1035. Rect2i rect = tile_map->get_used_rect();
  1036. if (rect.has_no_area()) {
  1037. rect = Rect2i(p_coords, Vector2i(1, 1));
  1038. }
  1039. for (int x = boundaries.position.x; x < boundaries.get_end().x; x++) {
  1040. for (int y = boundaries.position.y; y < boundaries.get_end().y; y++) {
  1041. to_check.append(Vector2i(x, y));
  1042. }
  1043. }
  1044. } else {
  1045. to_check = tile_map->get_used_cells(tile_map_layer);
  1046. }
  1047. for (int i = 0; i < to_check.size(); i++) {
  1048. Vector2i coords = to_check[i];
  1049. if (source_cell.source_id == tile_map->get_cell_source_id(tile_map_layer, coords) &&
  1050. source_cell.get_atlas_coords() == tile_map->get_cell_atlas_coords(tile_map_layer, coords) &&
  1051. source_cell.alternative_tile == tile_map->get_cell_alternative_tile(tile_map_layer, coords) &&
  1052. (source_cell.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
  1053. if (!p_erase && random_tile_toggle->is_pressed()) {
  1054. // Paint a random tile.
  1055. output.insert(coords, _pick_random_tile(pattern));
  1056. } else {
  1057. // Paint the pattern.
  1058. Vector2i pattern_coords = (coords - p_coords) % pattern->get_size(); // Note: it would be good to have posmodv for Vector2i.
  1059. pattern_coords.x = pattern_coords.x < 0 ? pattern_coords.x + pattern->get_size().x : pattern_coords.x;
  1060. pattern_coords.y = pattern_coords.y < 0 ? pattern_coords.y + pattern->get_size().y : pattern_coords.y;
  1061. if (pattern->has_cell(pattern_coords)) {
  1062. output.insert(coords, TileMapCell(pattern->get_cell_source_id(pattern_coords), pattern->get_cell_atlas_coords(pattern_coords), pattern->get_cell_alternative_tile(pattern_coords)));
  1063. } else {
  1064. output.insert(coords, TileMapCell());
  1065. }
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }
  1071. return output;
  1072. }
  1073. void TileMapEditorTilesPlugin::_stop_dragging() {
  1074. if (drag_type == DRAG_TYPE_NONE) {
  1075. return;
  1076. }
  1077. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1078. if (!tile_map) {
  1079. return;
  1080. }
  1081. if (tile_map_layer < 0) {
  1082. return;
  1083. }
  1084. ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
  1085. Ref<TileSet> tile_set = tile_map->get_tileset();
  1086. if (!tile_set.is_valid()) {
  1087. return;
  1088. }
  1089. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  1090. Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
  1091. switch (drag_type) {
  1092. case DRAG_TYPE_SELECT: {
  1093. undo_redo->create_action(TTR("Change selection"));
  1094. undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  1095. if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL)) {
  1096. tile_map_selection.clear();
  1097. }
  1098. Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs();
  1099. for (int x = rect.position.x; x <= rect.get_end().x; x++) {
  1100. for (int y = rect.position.y; y <= rect.get_end().y; y++) {
  1101. Vector2i coords = Vector2i(x, y);
  1102. if (Input::get_singleton()->is_key_pressed(Key::CTRL)) {
  1103. if (tile_map_selection.has(coords)) {
  1104. tile_map_selection.erase(coords);
  1105. }
  1106. } else {
  1107. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  1108. tile_map_selection.insert(coords);
  1109. }
  1110. }
  1111. }
  1112. }
  1113. undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  1114. undo_redo->commit_action(false);
  1115. _update_selection_pattern_from_tilemap_selection();
  1116. _update_tileset_selection_from_selection_pattern();
  1117. } break;
  1118. case DRAG_TYPE_MOVE: {
  1119. if (patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position())) {
  1120. // Restore the cells.
  1121. for (KeyValue<Vector2i, TileMapCell> kv : drag_modified) {
  1122. tile_map->set_cell(tile_map_layer, kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile);
  1123. }
  1124. // Creating a pattern in the pattern list.
  1125. select_last_pattern = true;
  1126. int new_pattern_index = tile_set->get_patterns_count();
  1127. undo_redo->create_action(TTR("Add TileSet pattern"));
  1128. undo_redo->add_do_method(*tile_set, "add_pattern", selection_pattern, new_pattern_index);
  1129. undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index);
  1130. undo_redo->commit_action();
  1131. } else {
  1132. // Get the top-left cell.
  1133. Vector2i top_left;
  1134. if (!tile_map_selection.is_empty()) {
  1135. top_left = tile_map_selection.front()->get();
  1136. }
  1137. for (const Vector2i &E : tile_map_selection) {
  1138. top_left = top_left.min(E);
  1139. }
  1140. // Get the offset from the mouse.
  1141. Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left);
  1142. offset = tile_map->world_to_map(mpos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset);
  1143. TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells();
  1144. // Build the list of cells to undo.
  1145. Vector2i coords;
  1146. HashMap<Vector2i, TileMapCell> cells_undo;
  1147. for (int i = 0; i < selection_used_cells.size(); i++) {
  1148. coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern);
  1149. cells_undo[coords] = TileMapCell(drag_modified[coords].source_id, drag_modified[coords].get_atlas_coords(), drag_modified[coords].alternative_tile);
  1150. coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
  1151. cells_undo[coords] = TileMapCell(tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
  1152. }
  1153. // Build the list of cells to do.
  1154. HashMap<Vector2i, TileMapCell> cells_do;
  1155. for (int i = 0; i < selection_used_cells.size(); i++) {
  1156. coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern);
  1157. cells_do[coords] = TileMapCell();
  1158. }
  1159. for (int i = 0; i < selection_used_cells.size(); i++) {
  1160. coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
  1161. cells_do[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i]));
  1162. }
  1163. // Move the tiles.
  1164. undo_redo->create_action(TTR("Move tiles"));
  1165. for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) {
  1166. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1167. }
  1168. for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) {
  1169. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1170. }
  1171. // Update the selection.
  1172. undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  1173. tile_map_selection.clear();
  1174. for (int i = 0; i < selection_used_cells.size(); i++) {
  1175. coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
  1176. tile_map_selection.insert(coords);
  1177. }
  1178. undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection());
  1179. undo_redo->commit_action();
  1180. }
  1181. } break;
  1182. case DRAG_TYPE_PICK: {
  1183. Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs();
  1184. rect.size += Vector2i(1, 1);
  1185. int picked_source = -1;
  1186. TypedArray<Vector2i> coords_array;
  1187. for (int x = rect.position.x; x < rect.get_end().x; x++) {
  1188. for (int y = rect.position.y; y < rect.get_end().y; y++) {
  1189. Vector2i coords = Vector2i(x, y);
  1190. int source = tile_map->get_cell_source_id(tile_map_layer, coords);
  1191. if (source != TileSet::INVALID_SOURCE) {
  1192. coords_array.push_back(coords);
  1193. if (picked_source == -1) {
  1194. picked_source = source;
  1195. } else if (picked_source != source) {
  1196. picked_source = -2;
  1197. }
  1198. }
  1199. }
  1200. }
  1201. if (picked_source >= 0) {
  1202. for (int i = 0; i < sources_list->get_item_count(); i++) {
  1203. if (int(sources_list->get_item_metadata(i)) == picked_source) {
  1204. sources_list->set_current(i);
  1205. break;
  1206. }
  1207. }
  1208. sources_list->ensure_current_is_visible();
  1209. TilesEditorPlugin::get_singleton()->set_sources_lists_current(picked_source);
  1210. }
  1211. Ref<TileMapPattern> new_selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array);
  1212. if (!new_selection_pattern->is_empty()) {
  1213. selection_pattern = new_selection_pattern;
  1214. _update_tileset_selection_from_selection_pattern();
  1215. }
  1216. picker_button->set_pressed(false);
  1217. } break;
  1218. case DRAG_TYPE_PAINT: {
  1219. undo_redo->create_action(TTR("Paint tiles"));
  1220. for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
  1221. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  1222. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1223. }
  1224. undo_redo->commit_action(false);
  1225. } break;
  1226. case DRAG_TYPE_LINE: {
  1227. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos, drag_erasing);
  1228. undo_redo->create_action(TTR("Paint tiles"));
  1229. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  1230. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  1231. continue;
  1232. }
  1233. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1234. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  1235. }
  1236. undo_redo->commit_action();
  1237. } break;
  1238. case DRAG_TYPE_RECT: {
  1239. HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing);
  1240. undo_redo->create_action(TTR("Paint tiles"));
  1241. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  1242. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  1243. continue;
  1244. }
  1245. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1246. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  1247. }
  1248. undo_redo->commit_action();
  1249. } break;
  1250. case DRAG_TYPE_BUCKET: {
  1251. undo_redo->create_action(TTR("Paint tiles"));
  1252. for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
  1253. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  1254. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  1255. }
  1256. undo_redo->commit_action(false);
  1257. } break;
  1258. case DRAG_TYPE_CLIPBOARD_PASTE: {
  1259. Vector2 mouse_offset = (Vector2(tile_map_clipboard->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
  1260. undo_redo->create_action(TTR("Paste tiles"));
  1261. TypedArray<Vector2i> used_cells = tile_map_clipboard->get_used_cells();
  1262. for (int i = 0; i < used_cells.size(); i++) {
  1263. Vector2i coords = tile_map->map_pattern(tile_map->world_to_map(mpos - mouse_offset), used_cells[i], tile_map_clipboard);
  1264. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, coords, tile_map_clipboard->get_cell_source_id(used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(used_cells[i]));
  1265. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, coords, tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
  1266. }
  1267. undo_redo->commit_action();
  1268. } break;
  1269. default:
  1270. break;
  1271. }
  1272. drag_type = DRAG_TYPE_NONE;
  1273. }
  1274. void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
  1275. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1276. if (!tile_map) {
  1277. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1278. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1279. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1280. tile_set_selection.clear();
  1281. patterns_item_list->deselect_all();
  1282. tile_map_selection.clear();
  1283. selection_pattern.instantiate();
  1284. return;
  1285. }
  1286. Ref<TileSet> tile_set = tile_map->get_tileset();
  1287. if (!tile_set.is_valid()) {
  1288. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1289. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1290. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1291. tile_set_selection.clear();
  1292. patterns_item_list->deselect_all();
  1293. tile_map_selection.clear();
  1294. selection_pattern.instantiate();
  1295. return;
  1296. }
  1297. int source_index = sources_list->get_current();
  1298. if (source_index < 0 || source_index >= sources_list->get_item_count()) {
  1299. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1300. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1301. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1302. tile_set_selection.clear();
  1303. patterns_item_list->deselect_all();
  1304. tile_map_selection.clear();
  1305. selection_pattern.instantiate();
  1306. return;
  1307. }
  1308. int source_id = sources_list->get_item_metadata(source_index);
  1309. // Clear hovered if needed.
  1310. if (source_id != hovered_tile.source_id ||
  1311. !tile_set->has_source(hovered_tile.source_id) ||
  1312. !tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) ||
  1313. !tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) {
  1314. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1315. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1316. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1317. }
  1318. // Selection if needed.
  1319. for (RBSet<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) {
  1320. const TileMapCell *selected = &(E->get());
  1321. if (!tile_set->has_source(selected->source_id) ||
  1322. !tile_set->get_source(selected->source_id)->has_tile(selected->get_atlas_coords()) ||
  1323. !tile_set->get_source(selected->source_id)->has_alternative_tile(selected->get_atlas_coords(), selected->alternative_tile)) {
  1324. tile_set_selection.erase(E);
  1325. }
  1326. }
  1327. if (!tile_map_selection.is_empty()) {
  1328. _update_selection_pattern_from_tilemap_selection();
  1329. } else if (tiles_bottom_panel->is_visible_in_tree()) {
  1330. _update_selection_pattern_from_tileset_tiles_selection();
  1331. } else {
  1332. _update_selection_pattern_from_tileset_pattern_selection();
  1333. }
  1334. }
  1335. void TileMapEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() {
  1336. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1337. if (!tile_map) {
  1338. return;
  1339. }
  1340. RBSet<Vector2i> to_remove;
  1341. for (Vector2i selected : tile_map_selection) {
  1342. TileMapCell cell = tile_map->get_cell(tile_map_layer, selected);
  1343. if (cell.source_id == TileSet::INVALID_SOURCE && cell.get_atlas_coords() == TileSetSource::INVALID_ATLAS_COORDS && cell.alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
  1344. to_remove.insert(selected);
  1345. }
  1346. }
  1347. for (Vector2i cell : to_remove) {
  1348. tile_map_selection.erase(cell);
  1349. }
  1350. }
  1351. void TileMapEditorTilesPlugin::patterns_item_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
  1352. if (p_mouse_button_index == MouseButton::LEFT) {
  1353. _update_selection_pattern_from_tileset_pattern_selection();
  1354. }
  1355. }
  1356. void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection() {
  1357. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1358. if (!tile_map) {
  1359. return;
  1360. }
  1361. Ref<TileSet> tile_set = tile_map->get_tileset();
  1362. if (!tile_set.is_valid()) {
  1363. return;
  1364. }
  1365. ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
  1366. selection_pattern.instantiate();
  1367. TypedArray<Vector2i> coords_array;
  1368. for (const Vector2i &E : tile_map_selection) {
  1369. coords_array.push_back(E);
  1370. }
  1371. selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array);
  1372. }
  1373. void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_selection() {
  1374. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1375. if (!tile_map) {
  1376. return;
  1377. }
  1378. Ref<TileSet> tile_set = tile_map->get_tileset();
  1379. if (!tile_set.is_valid()) {
  1380. return;
  1381. }
  1382. // Clear the tilemap selection.
  1383. tile_map_selection.clear();
  1384. // Clear the selected pattern.
  1385. selection_pattern.instantiate();
  1386. // Group per source.
  1387. HashMap<int, List<const TileMapCell *>> per_source;
  1388. for (const TileMapCell &E : tile_set_selection) {
  1389. per_source[E.source_id].push_back(&(E));
  1390. }
  1391. int vertical_offset = 0;
  1392. for (const KeyValue<int, List<const TileMapCell *>> &E_source : per_source) {
  1393. // Per source.
  1394. List<const TileMapCell *> unorganized;
  1395. Rect2i encompassing_rect_coords;
  1396. HashMap<Vector2i, const TileMapCell *> organized_pattern;
  1397. TileSetSource *source = *tile_set->get_source(E_source.key);
  1398. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  1399. if (atlas_source) {
  1400. // Organize using coordinates.
  1401. for (const TileMapCell *current : E_source.value) {
  1402. if (current->alternative_tile == 0) {
  1403. organized_pattern[current->get_atlas_coords()] = current;
  1404. } else {
  1405. unorganized.push_back(current);
  1406. }
  1407. }
  1408. // Compute the encompassing rect for the organized pattern.
  1409. HashMap<Vector2i, const TileMapCell *>::Iterator E_cell = organized_pattern.begin();
  1410. if (E_cell) {
  1411. encompassing_rect_coords = Rect2i(E_cell->key, Vector2i(1, 1));
  1412. for (; E_cell; ++E_cell) {
  1413. encompassing_rect_coords.expand_to(E_cell->key + Vector2i(1, 1));
  1414. encompassing_rect_coords.expand_to(E_cell->key);
  1415. }
  1416. }
  1417. } else {
  1418. // Add everything unorganized.
  1419. for (const TileMapCell *cell : E_source.value) {
  1420. unorganized.push_back(cell);
  1421. }
  1422. }
  1423. // Now add everything to the output pattern.
  1424. for (const KeyValue<Vector2i, const TileMapCell *> &E_cell : organized_pattern) {
  1425. selection_pattern->set_cell(E_cell.key - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell.value->source_id, E_cell.value->get_atlas_coords(), E_cell.value->alternative_tile);
  1426. }
  1427. Vector2i organized_size = selection_pattern->get_size();
  1428. int unorganized_index = 0;
  1429. for (const TileMapCell *cell : unorganized) {
  1430. selection_pattern->set_cell(Vector2(organized_size.x + unorganized_index, vertical_offset), cell->source_id, cell->get_atlas_coords(), cell->alternative_tile);
  1431. unorganized_index++;
  1432. }
  1433. vertical_offset += MAX(organized_size.y, 1);
  1434. }
  1435. CanvasItemEditor::get_singleton()->update_viewport();
  1436. }
  1437. void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection() {
  1438. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1439. if (!tile_map) {
  1440. return;
  1441. }
  1442. Ref<TileSet> tile_set = tile_map->get_tileset();
  1443. if (!tile_set.is_valid()) {
  1444. return;
  1445. }
  1446. // Clear the tilemap selection.
  1447. tile_map_selection.clear();
  1448. // Clear the selected pattern.
  1449. selection_pattern.instantiate();
  1450. if (patterns_item_list->get_selected_items().size() >= 1) {
  1451. selection_pattern = patterns_item_list->get_item_metadata(patterns_item_list->get_selected_items()[0]);
  1452. }
  1453. CanvasItemEditor::get_singleton()->update_viewport();
  1454. }
  1455. void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern() {
  1456. tile_set_selection.clear();
  1457. TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells();
  1458. for (int i = 0; i < used_cells.size(); i++) {
  1459. Vector2i coords = used_cells[i];
  1460. if (selection_pattern->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
  1461. tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords)));
  1462. }
  1463. }
  1464. _update_source_display();
  1465. tile_atlas_control->queue_redraw();
  1466. alternative_tiles_control->queue_redraw();
  1467. }
  1468. void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
  1469. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1470. if (!tile_map) {
  1471. return;
  1472. }
  1473. Ref<TileSet> tile_set = tile_map->get_tileset();
  1474. if (!tile_set.is_valid()) {
  1475. return;
  1476. }
  1477. int source_index = sources_list->get_current();
  1478. if (source_index < 0 || source_index >= sources_list->get_item_count()) {
  1479. return;
  1480. }
  1481. int source_id = sources_list->get_item_metadata(source_index);
  1482. if (!tile_set->has_source(source_id)) {
  1483. return;
  1484. }
  1485. TileSetAtlasSource *atlas = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
  1486. if (!atlas) {
  1487. return;
  1488. }
  1489. // Draw the selection.
  1490. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  1491. Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
  1492. for (const TileMapCell &E : tile_set_selection) {
  1493. if (E.source_id == source_id && E.alternative_tile == 0) {
  1494. for (int frame = 0; frame < atlas->get_tile_animation_frames_count(E.get_atlas_coords()); frame++) {
  1495. Color color = selection_color;
  1496. if (frame > 0) {
  1497. color.a *= 0.3;
  1498. }
  1499. tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E.get_atlas_coords(), frame), color, false);
  1500. }
  1501. }
  1502. }
  1503. // Draw the hovered tile.
  1504. if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
  1505. for (int frame = 0; frame < atlas->get_tile_animation_frames_count(hovered_tile.get_atlas_coords()); frame++) {
  1506. Color color = Color(1.0, 1.0, 1.0);
  1507. if (frame > 0) {
  1508. color.a *= 0.3;
  1509. }
  1510. tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color, false);
  1511. }
  1512. }
  1513. // Draw the selection rect.
  1514. if (tile_set_dragging_selection) {
  1515. Vector2i start_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_set_drag_start_mouse_pos);
  1516. Vector2i end_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1517. Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs();
  1518. region.size += Vector2i(1, 1);
  1519. RBSet<Vector2i> to_draw;
  1520. for (int x = region.position.x; x < region.get_end().x; x++) {
  1521. for (int y = region.position.y; y < region.get_end().y; y++) {
  1522. Vector2i tile = atlas->get_tile_at_coords(Vector2i(x, y));
  1523. if (tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1524. to_draw.insert(tile);
  1525. }
  1526. }
  1527. }
  1528. Color selection_rect_color = selection_color.lightened(0.2);
  1529. for (const Vector2i &E : to_draw) {
  1530. tile_atlas_control->draw_rect(atlas->get_tile_texture_region(E), selection_rect_color, false);
  1531. }
  1532. }
  1533. }
  1534. void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
  1535. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1536. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1537. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1538. tile_set_dragging_selection = false;
  1539. tile_atlas_control->queue_redraw();
  1540. }
  1541. void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEvent> &p_event) {
  1542. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1543. if (!tile_map) {
  1544. return;
  1545. }
  1546. Ref<TileSet> tile_set = tile_map->get_tileset();
  1547. if (!tile_set.is_valid()) {
  1548. return;
  1549. }
  1550. int source_index = sources_list->get_current();
  1551. if (source_index < 0 || source_index >= sources_list->get_item_count()) {
  1552. return;
  1553. }
  1554. int source_id = sources_list->get_item_metadata(source_index);
  1555. if (!tile_set->has_source(source_id)) {
  1556. return;
  1557. }
  1558. TileSetAtlasSource *atlas = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
  1559. if (!atlas) {
  1560. return;
  1561. }
  1562. // Update the hovered tile
  1563. hovered_tile.source_id = source_id;
  1564. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1565. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1566. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1567. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1568. coords = atlas->get_tile_at_coords(coords);
  1569. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1570. hovered_tile.set_atlas_coords(coords);
  1571. hovered_tile.alternative_tile = 0;
  1572. }
  1573. }
  1574. Ref<InputEventMouseMotion> mm = p_event;
  1575. if (mm.is_valid()) {
  1576. tile_atlas_control->queue_redraw();
  1577. alternative_tiles_control->queue_redraw();
  1578. }
  1579. Ref<InputEventMouseButton> mb = p_event;
  1580. if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
  1581. if (mb->is_pressed()) { // Pressed
  1582. tile_set_dragging_selection = true;
  1583. tile_set_drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position();
  1584. if (!mb->is_shift_pressed()) {
  1585. tile_set_selection.clear();
  1586. }
  1587. if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) {
  1588. if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) {
  1589. tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0));
  1590. } else {
  1591. tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0));
  1592. }
  1593. }
  1594. _update_selection_pattern_from_tileset_tiles_selection();
  1595. } else { // Released
  1596. if (tile_set_dragging_selection) {
  1597. if (!mb->is_shift_pressed()) {
  1598. tile_set_selection.clear();
  1599. }
  1600. // Compute the covered area.
  1601. Vector2i start_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_set_drag_start_mouse_pos);
  1602. Vector2i end_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1603. if (start_tile != TileSetSource::INVALID_ATLAS_COORDS && end_tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1604. Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs();
  1605. region.size += Vector2i(1, 1);
  1606. // To update the selection, we copy the selected/not selected status of the tiles we drag from.
  1607. Vector2i start_coords = atlas->get_tile_at_coords(start_tile);
  1608. if (mb->is_shift_pressed() && start_coords != TileSetSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) {
  1609. // Remove from the selection.
  1610. for (int x = region.position.x; x < region.get_end().x; x++) {
  1611. for (int y = region.position.y; y < region.get_end().y; y++) {
  1612. Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
  1613. if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) {
  1614. tile_set_selection.erase(TileMapCell(source_id, tile_coords, 0));
  1615. }
  1616. }
  1617. }
  1618. } else {
  1619. // Insert in the selection.
  1620. for (int x = region.position.x; x < region.get_end().x; x++) {
  1621. for (int y = region.position.y; y < region.get_end().y; y++) {
  1622. Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
  1623. if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1624. tile_set_selection.insert(TileMapCell(source_id, tile_coords, 0));
  1625. }
  1626. }
  1627. }
  1628. }
  1629. }
  1630. _update_selection_pattern_from_tileset_tiles_selection();
  1631. }
  1632. tile_set_dragging_selection = false;
  1633. }
  1634. tile_atlas_control->queue_redraw();
  1635. }
  1636. }
  1637. void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
  1638. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1639. if (!tile_map) {
  1640. return;
  1641. }
  1642. Ref<TileSet> tile_set = tile_map->get_tileset();
  1643. if (!tile_set.is_valid()) {
  1644. return;
  1645. }
  1646. int source_index = sources_list->get_current();
  1647. if (source_index < 0 || source_index >= sources_list->get_item_count()) {
  1648. return;
  1649. }
  1650. int source_id = sources_list->get_item_metadata(source_index);
  1651. if (!tile_set->has_source(source_id)) {
  1652. return;
  1653. }
  1654. TileSetAtlasSource *atlas = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
  1655. if (!atlas) {
  1656. return;
  1657. }
  1658. // Draw the selection.
  1659. for (const TileMapCell &E : tile_set_selection) {
  1660. if (E.source_id == source_id && E.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E.alternative_tile > 0) {
  1661. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.get_atlas_coords(), E.alternative_tile);
  1662. if (rect != Rect2i()) {
  1663. alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false);
  1664. }
  1665. }
  1666. }
  1667. // Draw hovered tile.
  1668. if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
  1669. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
  1670. if (rect != Rect2i()) {
  1671. alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
  1672. }
  1673. }
  1674. }
  1675. void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
  1676. hovered_tile.source_id = TileSet::INVALID_SOURCE;
  1677. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1678. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1679. tile_set_dragging_selection = false;
  1680. alternative_tiles_control->queue_redraw();
  1681. }
  1682. void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event) {
  1683. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  1684. if (!tile_map) {
  1685. return;
  1686. }
  1687. Ref<TileSet> tile_set = tile_map->get_tileset();
  1688. if (!tile_set.is_valid()) {
  1689. return;
  1690. }
  1691. int source_index = sources_list->get_current();
  1692. if (source_index < 0 || source_index >= sources_list->get_item_count()) {
  1693. return;
  1694. }
  1695. int source_id = sources_list->get_item_metadata(source_index);
  1696. if (!tile_set->has_source(source_id)) {
  1697. return;
  1698. }
  1699. TileSetAtlasSource *atlas = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
  1700. if (!atlas) {
  1701. return;
  1702. }
  1703. // Update the hovered tile
  1704. hovered_tile.source_id = source_id;
  1705. hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
  1706. hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1707. Vector3i alternative_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position());
  1708. Vector2i coords = Vector2i(alternative_coords.x, alternative_coords.y);
  1709. int alternative = alternative_coords.z;
  1710. if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetSource::INVALID_TILE_ALTERNATIVE) {
  1711. hovered_tile.set_atlas_coords(coords);
  1712. hovered_tile.alternative_tile = alternative;
  1713. }
  1714. Ref<InputEventMouseMotion> mm = p_event;
  1715. if (mm.is_valid()) {
  1716. tile_atlas_control->queue_redraw();
  1717. alternative_tiles_control->queue_redraw();
  1718. }
  1719. Ref<InputEventMouseButton> mb = p_event;
  1720. if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
  1721. if (mb->is_pressed()) { // Pressed
  1722. // Left click pressed.
  1723. if (!mb->is_shift_pressed()) {
  1724. tile_set_selection.clear();
  1725. }
  1726. if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
  1727. if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) {
  1728. tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile));
  1729. } else {
  1730. tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile));
  1731. }
  1732. }
  1733. _update_selection_pattern_from_tileset_tiles_selection();
  1734. }
  1735. tile_atlas_control->queue_redraw();
  1736. alternative_tiles_control->queue_redraw();
  1737. }
  1738. }
  1739. void TileMapEditorTilesPlugin::_set_tile_map_selection(const TypedArray<Vector2i> &p_selection) {
  1740. tile_map_selection.clear();
  1741. for (int i = 0; i < p_selection.size(); i++) {
  1742. tile_map_selection.insert(p_selection[i]);
  1743. }
  1744. _update_selection_pattern_from_tilemap_selection();
  1745. _update_tileset_selection_from_selection_pattern();
  1746. CanvasItemEditor::get_singleton()->update_viewport();
  1747. }
  1748. TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
  1749. TypedArray<Vector2i> output;
  1750. for (const Vector2i &E : tile_map_selection) {
  1751. output.push_back(E);
  1752. }
  1753. return output;
  1754. }
  1755. void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
  1756. _stop_dragging(); // Avoids staying in a wrong drag state.
  1757. if (tile_map_id != p_tile_map_id) {
  1758. tile_map_id = p_tile_map_id;
  1759. // Clear the selection.
  1760. tile_set_selection.clear();
  1761. patterns_item_list->deselect_all();
  1762. tile_map_selection.clear();
  1763. selection_pattern.instantiate();
  1764. }
  1765. tile_map_layer = p_tile_map_layer;
  1766. }
  1767. void TileMapEditorTilesPlugin::_set_source_sort(int p_sort) {
  1768. for (int i = 0; i != TilesEditorPlugin::SOURCE_SORT_MAX; i++) {
  1769. source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
  1770. }
  1771. TilesEditorPlugin::get_singleton()->set_sorting_option(p_sort);
  1772. _update_tile_set_sources_list();
  1773. }
  1774. void TileMapEditorTilesPlugin::_bind_methods() {
  1775. ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapEditorTilesPlugin::_scene_thumbnail_done);
  1776. ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapEditorTilesPlugin::_set_tile_map_selection);
  1777. ClassDB::bind_method(D_METHOD("_get_tile_map_selection"), &TileMapEditorTilesPlugin::_get_tile_map_selection);
  1778. }
  1779. TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
  1780. undo_redo = EditorNode::get_undo_redo();
  1781. CanvasItemEditor::get_singleton()
  1782. ->get_viewport_control()
  1783. ->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_mouse_exited_viewport));
  1784. // --- Shortcuts ---
  1785. ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KeyModifierMask::CMD | Key::X);
  1786. ED_SHORTCUT("tiles_editor/copy", TTR("Copy"), KeyModifierMask::CMD | Key::C);
  1787. ED_SHORTCUT("tiles_editor/paste", TTR("Paste"), KeyModifierMask::CMD | Key::V);
  1788. ED_SHORTCUT("tiles_editor/cancel", TTR("Cancel"), Key::ESCAPE);
  1789. ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), Key::KEY_DELETE);
  1790. // --- Initialize references ---
  1791. tile_map_clipboard.instantiate();
  1792. selection_pattern.instantiate();
  1793. // --- Toolbar ---
  1794. toolbar = memnew(HBoxContainer);
  1795. HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
  1796. tool_buttons_group.instantiate();
  1797. select_tool_button = memnew(Button);
  1798. select_tool_button->set_flat(true);
  1799. select_tool_button->set_toggle_mode(true);
  1800. select_tool_button->set_button_group(tool_buttons_group);
  1801. select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", "Selection", Key::S));
  1802. select_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
  1803. tilemap_tiles_tools_buttons->add_child(select_tool_button);
  1804. paint_tool_button = memnew(Button);
  1805. paint_tool_button->set_flat(true);
  1806. paint_tool_button->set_toggle_mode(true);
  1807. paint_tool_button->set_button_group(tool_buttons_group);
  1808. paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D));
  1809. paint_tool_button->set_tooltip_text(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle."));
  1810. paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
  1811. tilemap_tiles_tools_buttons->add_child(paint_tool_button);
  1812. line_tool_button = memnew(Button);
  1813. line_tool_button->set_flat(true);
  1814. line_tool_button->set_toggle_mode(true);
  1815. line_tool_button->set_button_group(tool_buttons_group);
  1816. line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L));
  1817. line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
  1818. tilemap_tiles_tools_buttons->add_child(line_tool_button);
  1819. rect_tool_button = memnew(Button);
  1820. rect_tool_button->set_flat(true);
  1821. rect_tool_button->set_toggle_mode(true);
  1822. rect_tool_button->set_button_group(tool_buttons_group);
  1823. rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R));
  1824. rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
  1825. tilemap_tiles_tools_buttons->add_child(rect_tool_button);
  1826. bucket_tool_button = memnew(Button);
  1827. bucket_tool_button->set_flat(true);
  1828. bucket_tool_button->set_toggle_mode(true);
  1829. bucket_tool_button->set_button_group(tool_buttons_group);
  1830. bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B));
  1831. bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
  1832. tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
  1833. toolbar->add_child(tilemap_tiles_tools_buttons);
  1834. // -- TileMap tool settings --
  1835. tools_settings = memnew(HBoxContainer);
  1836. toolbar->add_child(tools_settings);
  1837. tools_settings_vsep = memnew(VSeparator);
  1838. tools_settings->add_child(tools_settings_vsep);
  1839. // Picker
  1840. picker_button = memnew(Button);
  1841. picker_button->set_flat(true);
  1842. picker_button->set_toggle_mode(true);
  1843. picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P));
  1844. picker_button->set_tooltip_text(TTR("Alternatively hold Ctrl with other tools to pick tile."));
  1845. picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
  1846. tools_settings->add_child(picker_button);
  1847. // Erase button.
  1848. erase_button = memnew(Button);
  1849. erase_button->set_flat(true);
  1850. erase_button->set_toggle_mode(true);
  1851. erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E));
  1852. erase_button->set_tooltip_text(TTR("Alternatively use RMB to erase tiles."));
  1853. erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
  1854. tools_settings->add_child(erase_button);
  1855. // Separator 2.
  1856. tools_settings_vsep_2 = memnew(VSeparator);
  1857. tools_settings->add_child(tools_settings_vsep_2);
  1858. // Continuous checkbox.
  1859. bucket_contiguous_checkbox = memnew(CheckBox);
  1860. bucket_contiguous_checkbox->set_flat(true);
  1861. bucket_contiguous_checkbox->set_text(TTR("Contiguous"));
  1862. bucket_contiguous_checkbox->set_pressed(true);
  1863. tools_settings->add_child(bucket_contiguous_checkbox);
  1864. // Random tile checkbox.
  1865. random_tile_toggle = memnew(Button);
  1866. random_tile_toggle->set_flat(true);
  1867. random_tile_toggle->set_toggle_mode(true);
  1868. random_tile_toggle->set_tooltip_text(TTR("Place Random Tile"));
  1869. random_tile_toggle->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled));
  1870. tools_settings->add_child(random_tile_toggle);
  1871. // Random tile scattering.
  1872. scatter_label = memnew(Label);
  1873. scatter_label->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile."));
  1874. scatter_label->set_text(TTR("Scattering:"));
  1875. tools_settings->add_child(scatter_label);
  1876. scatter_spinbox = memnew(SpinBox);
  1877. scatter_spinbox->set_min(0.0);
  1878. scatter_spinbox->set_max(1000);
  1879. scatter_spinbox->set_step(0.001);
  1880. scatter_spinbox->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile."));
  1881. scatter_spinbox->get_line_edit()->add_theme_constant_override("minimum_character_width", 4);
  1882. scatter_spinbox->connect("value_changed", callable_mp(this, &TileMapEditorTilesPlugin::_on_scattering_spinbox_changed));
  1883. tools_settings->add_child(scatter_spinbox);
  1884. _on_random_tile_checkbox_toggled(false);
  1885. // Default tool.
  1886. paint_tool_button->set_pressed(true);
  1887. _update_toolbar();
  1888. // --- Bottom panel tiles ---
  1889. tiles_bottom_panel = memnew(VBoxContainer);
  1890. tiles_bottom_panel->connect("tree_entered", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
  1891. tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
  1892. tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging));
  1893. tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
  1894. tiles_bottom_panel->set_name(TTR("Tiles"));
  1895. missing_source_label = memnew(Label);
  1896. missing_source_label->set_text(TTR("This TileMap's TileSet has no source configured. Edit the TileSet resource to add one."));
  1897. missing_source_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1898. missing_source_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1899. missing_source_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
  1900. missing_source_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
  1901. missing_source_label->hide();
  1902. tiles_bottom_panel->add_child(missing_source_label);
  1903. atlas_sources_split_container = memnew(HSplitContainer);
  1904. atlas_sources_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1905. atlas_sources_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1906. tiles_bottom_panel->add_child(atlas_sources_split_container);
  1907. VBoxContainer *split_container_left_side = memnew(VBoxContainer);
  1908. split_container_left_side->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1909. split_container_left_side->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1910. split_container_left_side->set_stretch_ratio(0.25);
  1911. split_container_left_side->set_custom_minimum_size(Size2i(70, 0) * EDSCALE);
  1912. atlas_sources_split_container->add_child(split_container_left_side);
  1913. HBoxContainer *sources_bottom_actions = memnew(HBoxContainer);
  1914. sources_bottom_actions->set_alignment(HBoxContainer::ALIGNMENT_END);
  1915. source_sort_button = memnew(MenuButton);
  1916. source_sort_button->set_flat(true);
  1917. source_sort_button->set_tooltip_text(TTR("Sort sources"));
  1918. PopupMenu *p = source_sort_button->get_popup();
  1919. p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort));
  1920. p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorPlugin::SOURCE_SORT_ID);
  1921. p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorPlugin::SOURCE_SORT_ID_REVERSE);
  1922. p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorPlugin::SOURCE_SORT_NAME);
  1923. p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorPlugin::SOURCE_SORT_NAME_REVERSE);
  1924. p->set_item_checked(TilesEditorPlugin::SOURCE_SORT_ID, true);
  1925. sources_bottom_actions->add_child(source_sort_button);
  1926. sources_list = memnew(ItemList);
  1927. sources_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE);
  1928. sources_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1929. sources_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1930. sources_list->set_stretch_ratio(0.25);
  1931. sources_list->set_custom_minimum_size(Size2i(70, 0) * EDSCALE);
  1932. sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
  1933. sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
  1934. sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1));
  1935. sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current));
  1936. sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button));
  1937. sources_list->add_user_signal(MethodInfo("sort_request"));
  1938. sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list));
  1939. split_container_left_side->add_child(sources_list);
  1940. split_container_left_side->add_child(sources_bottom_actions);
  1941. // Tile atlas source.
  1942. tile_atlas_view = memnew(TileAtlasView);
  1943. tile_atlas_view->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1944. tile_atlas_view->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1945. tile_atlas_view->set_texture_grid_visible(false);
  1946. tile_atlas_view->set_tile_shape_grid_visible(false);
  1947. tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform));
  1948. atlas_sources_split_container->add_child(tile_atlas_view);
  1949. tile_atlas_control = memnew(Control);
  1950. tile_atlas_control->connect("draw", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_draw));
  1951. tile_atlas_control->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited));
  1952. tile_atlas_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_gui_input));
  1953. tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control);
  1954. alternative_tiles_control = memnew(Control);
  1955. alternative_tiles_control->connect("draw", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_draw));
  1956. alternative_tiles_control->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited));
  1957. alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input));
  1958. tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
  1959. // Scenes collection source.
  1960. scene_tiles_list = memnew(ItemList);
  1961. scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1962. scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1963. scene_tiles_list->set_drag_forwarding(this);
  1964. scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI);
  1965. scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected));
  1966. scene_tiles_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked));
  1967. scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
  1968. atlas_sources_split_container->add_child(scene_tiles_list);
  1969. // Invalid source label.
  1970. invalid_source_label = memnew(Label);
  1971. invalid_source_label->set_text(TTR("Invalid source selected."));
  1972. invalid_source_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  1973. invalid_source_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1974. invalid_source_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
  1975. invalid_source_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
  1976. invalid_source_label->hide();
  1977. atlas_sources_split_container->add_child(invalid_source_label);
  1978. // --- Bottom panel patterns ---
  1979. patterns_bottom_panel = memnew(VBoxContainer);
  1980. patterns_bottom_panel->set_name(TTR("Patterns"));
  1981. patterns_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
  1982. int thumbnail_size = 64;
  1983. patterns_item_list = memnew(ItemList);
  1984. patterns_item_list->set_max_columns(0);
  1985. patterns_item_list->set_icon_mode(ItemList::ICON_MODE_TOP);
  1986. patterns_item_list->set_fixed_column_width(thumbnail_size * 3 / 2);
  1987. patterns_item_list->set_max_text_lines(2);
  1988. patterns_item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
  1989. patterns_item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  1990. patterns_item_list->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_patterns_item_list_gui_input));
  1991. patterns_item_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1));
  1992. patterns_item_list->connect("item_activated", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection));
  1993. patterns_item_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::patterns_item_list_empty_clicked));
  1994. patterns_bottom_panel->add_child(patterns_item_list);
  1995. patterns_help_label = memnew(Label);
  1996. patterns_help_label->set_text(TTR("Drag and drop or paste a TileMap selection here to store a pattern."));
  1997. patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER);
  1998. patterns_item_list->add_child(patterns_help_label);
  1999. // Update.
  2000. _update_source_display();
  2001. }
  2002. TileMapEditorTilesPlugin::~TileMapEditorTilesPlugin() {
  2003. }
  2004. void TileMapEditorTerrainsPlugin::tile_set_changed() {
  2005. _update_terrains_cache();
  2006. _update_terrains_tree();
  2007. _update_tiles_list();
  2008. }
  2009. void TileMapEditorTerrainsPlugin::_update_toolbar() {
  2010. // Hide all settings.
  2011. for (int i = 0; i < tools_settings->get_child_count(); i++) {
  2012. Object::cast_to<CanvasItem>(tools_settings->get_child(i))->hide();
  2013. }
  2014. // Show only the correct settings.
  2015. if (tool_buttons_group->get_pressed_button() == paint_tool_button) {
  2016. tools_settings_vsep->show();
  2017. picker_button->show();
  2018. erase_button->show();
  2019. tools_settings_vsep_2->hide();
  2020. bucket_contiguous_checkbox->hide();
  2021. } else if (tool_buttons_group->get_pressed_button() == line_tool_button) {
  2022. tools_settings_vsep->show();
  2023. picker_button->show();
  2024. erase_button->show();
  2025. tools_settings_vsep_2->hide();
  2026. bucket_contiguous_checkbox->hide();
  2027. } else if (tool_buttons_group->get_pressed_button() == rect_tool_button) {
  2028. tools_settings_vsep->show();
  2029. picker_button->show();
  2030. erase_button->show();
  2031. tools_settings_vsep_2->hide();
  2032. bucket_contiguous_checkbox->hide();
  2033. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button) {
  2034. tools_settings_vsep->show();
  2035. picker_button->show();
  2036. erase_button->show();
  2037. tools_settings_vsep_2->show();
  2038. bucket_contiguous_checkbox->show();
  2039. }
  2040. }
  2041. Vector<TileMapEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() const {
  2042. Vector<TileMapEditorPlugin::TabData> tabs;
  2043. tabs.push_back({ toolbar, main_vbox_container });
  2044. return tabs;
  2045. }
  2046. HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_path_or_connect(const Vector<Vector2i> &p_to_paint, int p_terrain_set, int p_terrain, bool p_connect) const {
  2047. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2048. if (!tile_map) {
  2049. return HashMap<Vector2i, TileMapCell>();
  2050. }
  2051. Ref<TileSet> tile_set = tile_map->get_tileset();
  2052. if (!tile_set.is_valid()) {
  2053. return HashMap<Vector2i, TileMapCell>();
  2054. }
  2055. HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output;
  2056. if (p_connect) {
  2057. terrain_fill_output = tile_map->terrain_fill_connect(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
  2058. } else {
  2059. terrain_fill_output = tile_map->terrain_fill_path(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
  2060. }
  2061. // Make the painted path a set for faster lookups
  2062. HashSet<Vector2i> painted_set;
  2063. for (Vector2i coords : p_to_paint) {
  2064. painted_set.insert(coords);
  2065. }
  2066. HashMap<Vector2i, TileMapCell> output;
  2067. for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
  2068. if (painted_set.has(E.key)) {
  2069. // Paint a random tile with the correct terrain for the painted path.
  2070. output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
  2071. } else {
  2072. // Avoids updating the painted path from the output if the new pattern is the same as before.
  2073. bool keep_old = false;
  2074. TileMapCell cell = tile_map->get_cell(tile_map_layer, E.key);
  2075. if (cell.source_id != TileSet::INVALID_SOURCE) {
  2076. TileSetSource *source = *tile_set->get_source(cell.source_id);
  2077. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  2078. if (atlas_source) {
  2079. // Get tile data.
  2080. TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
  2081. if (tile_data && tile_data->get_terrains_pattern() == E.value) {
  2082. keep_old = true;
  2083. }
  2084. }
  2085. }
  2086. if (!keep_old) {
  2087. output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
  2088. }
  2089. }
  2090. }
  2091. return output;
  2092. }
  2093. HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_pattern(const Vector<Vector2i> &p_to_paint, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
  2094. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2095. if (!tile_map) {
  2096. return HashMap<Vector2i, TileMapCell>();
  2097. }
  2098. Ref<TileSet> tile_set = tile_map->get_tileset();
  2099. if (!tile_set.is_valid()) {
  2100. return HashMap<Vector2i, TileMapCell>();
  2101. }
  2102. HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = tile_map->terrain_fill_pattern(tile_map_layer, p_to_paint, p_terrain_set, p_terrains_pattern, false);
  2103. // Make the painted path a set for faster lookups
  2104. HashSet<Vector2i> painted_set;
  2105. for (Vector2i coords : p_to_paint) {
  2106. painted_set.insert(coords);
  2107. }
  2108. HashMap<Vector2i, TileMapCell> output;
  2109. for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &E : terrain_fill_output) {
  2110. if (painted_set.has(E.key)) {
  2111. // Paint a random tile with the correct terrain for the painted path.
  2112. output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
  2113. } else {
  2114. // Avoids updating the painted path from the output if the new pattern is the same as before.
  2115. TileMapCell cell = tile_map->get_cell(tile_map_layer, E.key);
  2116. if (cell.source_id != TileSet::INVALID_SOURCE) {
  2117. TileSetSource *source = *tile_set->get_source(cell.source_id);
  2118. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
  2119. if (atlas_source) {
  2120. // Get tile data.
  2121. TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
  2122. if (tile_data && !(tile_data->get_terrains_pattern() == E.value)) {
  2123. output[E.key] = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, E.value);
  2124. }
  2125. }
  2126. }
  2127. }
  2128. }
  2129. return output;
  2130. }
  2131. HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
  2132. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2133. if (!tile_map) {
  2134. return HashMap<Vector2i, TileMapCell>();
  2135. }
  2136. Ref<TileSet> tile_set = tile_map->get_tileset();
  2137. if (!tile_set.is_valid()) {
  2138. return HashMap<Vector2i, TileMapCell>();
  2139. }
  2140. if (selected_type == SELECTED_TYPE_CONNECT) {
  2141. return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, true);
  2142. } else if (selected_type == SELECTED_TYPE_PATH) {
  2143. return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, false);
  2144. } else { // SELECTED_TYPE_PATTERN
  2145. TileSet::TerrainsPattern terrains_pattern;
  2146. if (p_erase) {
  2147. terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
  2148. } else {
  2149. terrains_pattern = selected_terrains_pattern;
  2150. }
  2151. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell);
  2152. return _draw_terrain_pattern(line, selected_terrain_set, terrains_pattern);
  2153. }
  2154. }
  2155. HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
  2156. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2157. if (!tile_map) {
  2158. return HashMap<Vector2i, TileMapCell>();
  2159. }
  2160. Ref<TileSet> tile_set = tile_map->get_tileset();
  2161. if (!tile_set.is_valid()) {
  2162. return HashMap<Vector2i, TileMapCell>();
  2163. }
  2164. Rect2i rect;
  2165. rect.set_position(p_start_cell);
  2166. rect.set_end(p_end_cell);
  2167. rect = rect.abs();
  2168. Vector<Vector2i> to_draw;
  2169. for (int x = rect.position.x; x <= rect.get_end().x; x++) {
  2170. for (int y = rect.position.y; y <= rect.get_end().y; y++) {
  2171. to_draw.append(Vector2i(x, y));
  2172. }
  2173. }
  2174. if (selected_type == SELECTED_TYPE_CONNECT || selected_type == SELECTED_TYPE_PATH) {
  2175. return _draw_terrain_path_or_connect(to_draw, selected_terrain_set, selected_terrain, true);
  2176. } else { // SELECTED_TYPE_PATTERN
  2177. TileSet::TerrainsPattern terrains_pattern;
  2178. if (p_erase) {
  2179. terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
  2180. } else {
  2181. terrains_pattern = selected_terrains_pattern;
  2182. }
  2183. return _draw_terrain_pattern(to_draw, selected_terrain_set, terrains_pattern);
  2184. }
  2185. }
  2186. RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) {
  2187. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2188. if (!tile_map) {
  2189. return RBSet<Vector2i>();
  2190. }
  2191. Ref<TileSet> tile_set = tile_map->get_tileset();
  2192. if (!tile_set.is_valid()) {
  2193. return RBSet<Vector2i>();
  2194. }
  2195. TileMapCell source_cell = tile_map->get_cell(tile_map_layer, p_coords);
  2196. TileSet::TerrainsPattern source_pattern(*tile_set, selected_terrain_set);
  2197. if (source_cell.source_id != TileSet::INVALID_SOURCE) {
  2198. TileData *tile_data = nullptr;
  2199. Ref<TileSetSource> source = tile_set->get_source(source_cell.source_id);
  2200. Ref<TileSetAtlasSource> atlas_source = source;
  2201. if (atlas_source.is_valid()) {
  2202. tile_data = atlas_source->get_tile_data(source_cell.get_atlas_coords(), source_cell.alternative_tile);
  2203. }
  2204. if (!tile_data) {
  2205. return RBSet<Vector2i>();
  2206. }
  2207. source_pattern = tile_data->get_terrains_pattern();
  2208. }
  2209. // If we are filling empty tiles, compute the tilemap boundaries.
  2210. Rect2i boundaries;
  2211. if (source_cell.source_id == TileSet::INVALID_SOURCE) {
  2212. boundaries = tile_map->get_used_rect();
  2213. }
  2214. RBSet<Vector2i> output;
  2215. if (p_contiguous) {
  2216. // Replace continuous tiles like the source.
  2217. RBSet<Vector2i> already_checked;
  2218. List<Vector2i> to_check;
  2219. to_check.push_back(p_coords);
  2220. while (!to_check.is_empty()) {
  2221. Vector2i coords = to_check.back()->get();
  2222. to_check.pop_back();
  2223. if (!already_checked.has(coords)) {
  2224. // Get the candidate cell pattern.
  2225. TileSet::TerrainsPattern candidate_pattern(*tile_set, selected_terrain_set);
  2226. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  2227. TileData *tile_data = nullptr;
  2228. Ref<TileSetSource> source = tile_set->get_source(tile_map->get_cell_source_id(tile_map_layer, coords));
  2229. Ref<TileSetAtlasSource> atlas_source = source;
  2230. if (atlas_source.is_valid()) {
  2231. tile_data = atlas_source->get_tile_data(tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
  2232. }
  2233. if (tile_data) {
  2234. candidate_pattern = tile_data->get_terrains_pattern();
  2235. }
  2236. }
  2237. // Draw.
  2238. if (candidate_pattern == source_pattern && (!source_pattern.is_erase_pattern() || boundaries.has_point(coords))) {
  2239. output.insert(coords);
  2240. // Get surrounding tiles (handles different tile shapes).
  2241. TypedArray<Vector2i> around = tile_map->get_surrounding_tiles(coords);
  2242. for (int i = 0; i < around.size(); i++) {
  2243. to_check.push_back(around[i]);
  2244. }
  2245. }
  2246. already_checked.insert(coords);
  2247. }
  2248. }
  2249. } else {
  2250. // Replace all tiles like the source.
  2251. TypedArray<Vector2i> to_check;
  2252. if (source_cell.source_id == TileSet::INVALID_SOURCE) {
  2253. Rect2i rect = tile_map->get_used_rect();
  2254. if (rect.has_no_area()) {
  2255. rect = Rect2i(p_coords, Vector2i(1, 1));
  2256. }
  2257. for (int x = boundaries.position.x; x < boundaries.get_end().x; x++) {
  2258. for (int y = boundaries.position.y; y < boundaries.get_end().y; y++) {
  2259. to_check.append(Vector2i(x, y));
  2260. }
  2261. }
  2262. } else {
  2263. to_check = tile_map->get_used_cells(tile_map_layer);
  2264. }
  2265. for (int i = 0; i < to_check.size(); i++) {
  2266. Vector2i coords = to_check[i];
  2267. // Get the candidate cell pattern.
  2268. TileSet::TerrainsPattern candidate_pattern;
  2269. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  2270. TileData *tile_data = nullptr;
  2271. Ref<TileSetSource> source = tile_set->get_source(tile_map->get_cell_source_id(tile_map_layer, coords));
  2272. Ref<TileSetAtlasSource> atlas_source = source;
  2273. if (atlas_source.is_valid()) {
  2274. tile_data = atlas_source->get_tile_data(tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
  2275. }
  2276. if (tile_data) {
  2277. candidate_pattern = tile_data->get_terrains_pattern();
  2278. }
  2279. }
  2280. // Draw.
  2281. if (candidate_pattern == source_pattern && (!source_pattern.is_erase_pattern() || boundaries.has_point(coords))) {
  2282. output.insert(coords);
  2283. }
  2284. }
  2285. }
  2286. return output;
  2287. }
  2288. HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
  2289. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2290. if (!tile_map) {
  2291. return HashMap<Vector2i, TileMapCell>();
  2292. }
  2293. Ref<TileSet> tile_set = tile_map->get_tileset();
  2294. if (!tile_set.is_valid()) {
  2295. return HashMap<Vector2i, TileMapCell>();
  2296. }
  2297. RBSet<Vector2i> cells_to_draw = _get_cells_for_bucket_fill(p_coords, p_contiguous);
  2298. Vector<Vector2i> cells_to_draw_as_vector;
  2299. for (Vector2i cell : cells_to_draw) {
  2300. cells_to_draw_as_vector.append(cell);
  2301. }
  2302. if (selected_type == SELECTED_TYPE_CONNECT || selected_type == SELECTED_TYPE_PATH) {
  2303. return _draw_terrain_path_or_connect(cells_to_draw_as_vector, selected_terrain_set, selected_terrain, true);
  2304. } else { // SELECTED_TYPE_PATTERN
  2305. TileSet::TerrainsPattern terrains_pattern;
  2306. if (p_erase) {
  2307. terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
  2308. } else {
  2309. terrains_pattern = selected_terrains_pattern;
  2310. }
  2311. return _draw_terrain_pattern(cells_to_draw_as_vector, selected_terrain_set, terrains_pattern);
  2312. }
  2313. }
  2314. void TileMapEditorTerrainsPlugin::_stop_dragging() {
  2315. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2316. if (!tile_map) {
  2317. return;
  2318. }
  2319. Ref<TileSet> tile_set = tile_map->get_tileset();
  2320. if (!tile_set.is_valid()) {
  2321. return;
  2322. }
  2323. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  2324. Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
  2325. switch (drag_type) {
  2326. case DRAG_TYPE_PICK: {
  2327. Vector2i coords = tile_map->world_to_map(mpos);
  2328. TileMapCell cell = tile_map->get_cell(tile_map_layer, coords);
  2329. TileData *tile_data = nullptr;
  2330. Ref<TileSetSource> source = tile_set->get_source(cell.source_id);
  2331. Ref<TileSetAtlasSource> atlas_source = source;
  2332. if (atlas_source.is_valid()) {
  2333. tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
  2334. }
  2335. if (tile_data) {
  2336. TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern();
  2337. // Find the tree item for the right terrain set.
  2338. bool need_tree_item_switch = true;
  2339. TreeItem *tree_item = terrains_tree->get_selected();
  2340. int new_terrain_set = -1;
  2341. if (tree_item) {
  2342. Dictionary metadata_dict = tree_item->get_metadata(0);
  2343. if (metadata_dict.has("terrain_set") && metadata_dict.has("terrain_id")) {
  2344. int terrain_set = metadata_dict["terrain_set"];
  2345. int terrain_id = metadata_dict["terrain_id"];
  2346. if (per_terrain_terrains_patterns[terrain_set][terrain_id].has(terrains_pattern)) {
  2347. new_terrain_set = terrain_set;
  2348. need_tree_item_switch = false;
  2349. }
  2350. }
  2351. }
  2352. if (need_tree_item_switch) {
  2353. for (tree_item = terrains_tree->get_root()->get_first_child(); tree_item; tree_item = tree_item->get_next_visible()) {
  2354. Dictionary metadata_dict = tree_item->get_metadata(0);
  2355. if (metadata_dict.has("terrain_set") && metadata_dict.has("terrain_id")) {
  2356. int terrain_set = metadata_dict["terrain_set"];
  2357. int terrain_id = metadata_dict["terrain_id"];
  2358. if (per_terrain_terrains_patterns[terrain_set][terrain_id].has(terrains_pattern)) {
  2359. // Found
  2360. new_terrain_set = terrain_set;
  2361. tree_item->select(0);
  2362. _update_tiles_list();
  2363. break;
  2364. }
  2365. }
  2366. }
  2367. }
  2368. // Find the list item for the given tile.
  2369. if (tree_item) {
  2370. for (int i = 0; i < terrains_tile_list->get_item_count(); i++) {
  2371. Dictionary metadata_dict = terrains_tile_list->get_item_metadata(i);
  2372. if (int(metadata_dict["type"]) == SELECTED_TYPE_PATTERN) {
  2373. TileSet::TerrainsPattern in_meta_terrains_pattern(*tile_set, new_terrain_set);
  2374. in_meta_terrains_pattern.from_array(metadata_dict["terrains_pattern"]);
  2375. if (in_meta_terrains_pattern == terrains_pattern) {
  2376. terrains_tile_list->select(i);
  2377. break;
  2378. }
  2379. }
  2380. }
  2381. } else {
  2382. ERR_PRINT("Terrain tile not found.");
  2383. }
  2384. }
  2385. picker_button->set_pressed(false);
  2386. } break;
  2387. case DRAG_TYPE_PAINT: {
  2388. undo_redo->create_action(TTR("Paint terrain"));
  2389. for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
  2390. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  2391. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2392. }
  2393. undo_redo->commit_action(false);
  2394. } break;
  2395. case DRAG_TYPE_LINE: {
  2396. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing);
  2397. undo_redo->create_action(TTR("Paint terrain"));
  2398. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  2399. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  2400. continue;
  2401. }
  2402. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2403. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  2404. }
  2405. undo_redo->commit_action();
  2406. } break;
  2407. case DRAG_TYPE_RECT: {
  2408. HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing);
  2409. undo_redo->create_action(TTR("Paint terrain"));
  2410. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  2411. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  2412. continue;
  2413. }
  2414. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2415. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  2416. }
  2417. undo_redo->commit_action();
  2418. } break;
  2419. case DRAG_TYPE_BUCKET: {
  2420. undo_redo->create_action(TTR("Paint terrain"));
  2421. for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
  2422. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
  2423. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2424. }
  2425. undo_redo->commit_action(false);
  2426. } break;
  2427. default:
  2428. break;
  2429. }
  2430. drag_type = DRAG_TYPE_NONE;
  2431. }
  2432. void TileMapEditorTerrainsPlugin::_mouse_exited_viewport() {
  2433. has_mouse = false;
  2434. CanvasItemEditor::get_singleton()->update_viewport();
  2435. }
  2436. void TileMapEditorTerrainsPlugin::_update_selection() {
  2437. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2438. if (!tile_map) {
  2439. return;
  2440. }
  2441. Ref<TileSet> tile_set = tile_map->get_tileset();
  2442. if (!tile_set.is_valid()) {
  2443. return;
  2444. }
  2445. // Get the selected terrain.
  2446. selected_terrain_set = -1;
  2447. selected_terrains_pattern = TileSet::TerrainsPattern();
  2448. TreeItem *selected_tree_item = terrains_tree->get_selected();
  2449. if (selected_tree_item && selected_tree_item->get_metadata(0)) {
  2450. Dictionary metadata_dict = selected_tree_item->get_metadata(0);
  2451. // Selected terrain
  2452. selected_terrain_set = metadata_dict["terrain_set"];
  2453. selected_terrain = metadata_dict["terrain_id"];
  2454. // Selected mode/terrain pattern
  2455. if (erase_button->is_pressed()) {
  2456. selected_type = SELECTED_TYPE_PATTERN;
  2457. selected_terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
  2458. } else if (terrains_tile_list->is_anything_selected()) {
  2459. metadata_dict = terrains_tile_list->get_item_metadata(terrains_tile_list->get_selected_items()[0]);
  2460. if (int(metadata_dict["type"]) == SELECTED_TYPE_CONNECT) {
  2461. selected_type = SELECTED_TYPE_CONNECT;
  2462. } else if (int(metadata_dict["type"]) == SELECTED_TYPE_PATH) {
  2463. selected_type = SELECTED_TYPE_PATH;
  2464. } else if (int(metadata_dict["type"]) == SELECTED_TYPE_PATTERN) {
  2465. selected_type = SELECTED_TYPE_PATTERN;
  2466. selected_terrains_pattern = TileSet::TerrainsPattern(*tile_set, selected_terrain_set);
  2467. selected_terrains_pattern.from_array(metadata_dict["terrains_pattern"]);
  2468. } else {
  2469. ERR_FAIL();
  2470. }
  2471. }
  2472. }
  2473. }
  2474. bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
  2475. if (!main_vbox_container->is_visible_in_tree()) {
  2476. // If the bottom editor is not visible, we ignore inputs.
  2477. return false;
  2478. }
  2479. if (CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT) {
  2480. return false;
  2481. }
  2482. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2483. if (!tile_map) {
  2484. return false;
  2485. }
  2486. Ref<TileSet> tile_set = tile_map->get_tileset();
  2487. if (!tile_set.is_valid()) {
  2488. return false;
  2489. }
  2490. if (tile_map_layer < 0) {
  2491. return false;
  2492. }
  2493. ERR_FAIL_COND_V(tile_map_layer >= tile_map->get_layers_count(), false);
  2494. _update_selection();
  2495. Ref<InputEventMouseMotion> mm = p_event;
  2496. if (mm.is_valid()) {
  2497. has_mouse = true;
  2498. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  2499. Vector2 mpos = xform.affine_inverse().xform(mm->get_position());
  2500. switch (drag_type) {
  2501. case DRAG_TYPE_PAINT: {
  2502. if (selected_terrain_set >= 0) {
  2503. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos), drag_erasing);
  2504. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  2505. if (!drag_modified.has(E.key)) {
  2506. drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key);
  2507. }
  2508. tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2509. }
  2510. }
  2511. } break;
  2512. default:
  2513. break;
  2514. }
  2515. drag_last_mouse_pos = mpos;
  2516. CanvasItemEditor::get_singleton()->update_viewport();
  2517. return true;
  2518. }
  2519. Ref<InputEventMouseButton> mb = p_event;
  2520. if (mb.is_valid()) {
  2521. has_mouse = true;
  2522. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  2523. Vector2 mpos = xform.affine_inverse().xform(mb->get_position());
  2524. if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
  2525. if (mb->is_pressed()) {
  2526. // Pressed
  2527. if (erase_button->is_pressed() || mb->get_button_index() == MouseButton::RIGHT) {
  2528. drag_erasing = true;
  2529. }
  2530. if (picker_button->is_pressed()) {
  2531. drag_type = DRAG_TYPE_PICK;
  2532. } else {
  2533. // Paint otherwise.
  2534. if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
  2535. if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
  2536. return true;
  2537. }
  2538. drag_type = DRAG_TYPE_PAINT;
  2539. drag_start_mouse_pos = mpos;
  2540. drag_modified.clear();
  2541. Vector2i cell = tile_map->world_to_map(mpos);
  2542. HashMap<Vector2i, TileMapCell> to_draw = _draw_line(cell, cell, drag_erasing);
  2543. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  2544. drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key);
  2545. tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2546. }
  2547. } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL))) {
  2548. if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
  2549. return true;
  2550. }
  2551. drag_type = DRAG_TYPE_LINE;
  2552. drag_start_mouse_pos = mpos;
  2553. drag_modified.clear();
  2554. } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && Input::get_singleton()->is_key_pressed(Key::CTRL))) {
  2555. if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
  2556. return true;
  2557. }
  2558. drag_type = DRAG_TYPE_RECT;
  2559. drag_start_mouse_pos = mpos;
  2560. drag_modified.clear();
  2561. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button) {
  2562. if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
  2563. return true;
  2564. }
  2565. drag_type = DRAG_TYPE_BUCKET;
  2566. drag_start_mouse_pos = mpos;
  2567. drag_modified.clear();
  2568. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos));
  2569. for (int i = 0; i < line.size(); i++) {
  2570. if (!drag_modified.has(line[i])) {
  2571. HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
  2572. for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
  2573. if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
  2574. continue;
  2575. }
  2576. Vector2i coords = E.key;
  2577. if (!drag_modified.has(coords)) {
  2578. drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
  2579. }
  2580. tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
  2581. }
  2582. }
  2583. }
  2584. }
  2585. }
  2586. } else {
  2587. // Released
  2588. _stop_dragging();
  2589. drag_erasing = false;
  2590. }
  2591. CanvasItemEditor::get_singleton()->update_viewport();
  2592. return true;
  2593. }
  2594. drag_last_mouse_pos = mpos;
  2595. }
  2596. return false;
  2597. }
  2598. void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
  2599. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2600. if (!tile_map) {
  2601. return;
  2602. }
  2603. if (tile_map_layer < 0) {
  2604. return;
  2605. }
  2606. ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
  2607. Ref<TileSet> tile_set = tile_map->get_tileset();
  2608. if (!tile_set.is_valid()) {
  2609. return;
  2610. }
  2611. if (!tile_map->is_visible_in_tree()) {
  2612. return;
  2613. }
  2614. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  2615. Vector2i tile_shape_size = tile_set->get_tile_size();
  2616. // Handle the preview of the tiles to be placed.
  2617. if (main_vbox_container->is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
  2618. RBSet<Vector2i> preview;
  2619. Rect2i drawn_grid_rect;
  2620. if (drag_type == DRAG_TYPE_PICK) {
  2621. // Draw the area being picked.
  2622. Vector2i coords = tile_map->world_to_map(drag_last_mouse_pos);
  2623. if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
  2624. Transform2D tile_xform;
  2625. tile_xform.set_origin(tile_map->map_to_world(coords));
  2626. tile_xform.set_scale(tile_shape_size);
  2627. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false);
  2628. }
  2629. } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) {
  2630. bool expand_grid = false;
  2631. if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) {
  2632. // Preview for a single tile.
  2633. preview.insert(tile_map->world_to_map(drag_last_mouse_pos));
  2634. expand_grid = true;
  2635. } else if (tool_buttons_group->get_pressed_button() == line_tool_button || drag_type == DRAG_TYPE_LINE) {
  2636. if (drag_type == DRAG_TYPE_NONE) {
  2637. // Preview for a single tile.
  2638. preview.insert(tile_map->world_to_map(drag_last_mouse_pos));
  2639. } else if (drag_type == DRAG_TYPE_LINE) {
  2640. // Preview for a line.
  2641. Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos));
  2642. for (int i = 0; i < line.size(); i++) {
  2643. preview.insert(line[i]);
  2644. }
  2645. expand_grid = true;
  2646. }
  2647. } else if (drag_type == DRAG_TYPE_RECT) {
  2648. // Preview for a rect.
  2649. Rect2i rect;
  2650. rect.set_position(tile_map->world_to_map(drag_start_mouse_pos));
  2651. rect.set_end(tile_map->world_to_map(drag_last_mouse_pos));
  2652. rect = rect.abs();
  2653. HashMap<Vector2i, TileSet::TerrainsPattern> to_draw;
  2654. for (int x = rect.position.x; x <= rect.get_end().x; x++) {
  2655. for (int y = rect.position.y; y <= rect.get_end().y; y++) {
  2656. preview.insert(Vector2i(x, y));
  2657. }
  2658. }
  2659. expand_grid = true;
  2660. } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) {
  2661. // Preview for a fill.
  2662. preview = _get_cells_for_bucket_fill(tile_map->world_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed());
  2663. }
  2664. // Expand the grid if needed
  2665. if (expand_grid && !preview.is_empty()) {
  2666. drawn_grid_rect = Rect2i(preview.front()->get(), Vector2i(1, 1));
  2667. for (const Vector2i &E : preview) {
  2668. drawn_grid_rect.expand_to(E);
  2669. }
  2670. }
  2671. }
  2672. if (!preview.is_empty()) {
  2673. const int fading = 5;
  2674. // Draw the lines of the grid behind the preview.
  2675. bool display_grid = EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid");
  2676. if (display_grid) {
  2677. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  2678. if (drawn_grid_rect.size.x > 0 && drawn_grid_rect.size.y > 0) {
  2679. drawn_grid_rect = drawn_grid_rect.grow(fading);
  2680. for (int x = drawn_grid_rect.position.x; x < (drawn_grid_rect.position.x + drawn_grid_rect.size.x); x++) {
  2681. for (int y = drawn_grid_rect.position.y; y < (drawn_grid_rect.position.y + drawn_grid_rect.size.y); y++) {
  2682. Vector2i pos_in_rect = Vector2i(x, y) - drawn_grid_rect.position;
  2683. // Fade out the border of the grid.
  2684. float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
  2685. float right_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.x, (float)(drawn_grid_rect.size.x - fading), (float)(pos_in_rect.x + 1)), 0.0f, 1.0f);
  2686. float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
  2687. float bottom_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.y, (float)(drawn_grid_rect.size.y - fading), (float)(pos_in_rect.y + 1)), 0.0f, 1.0f);
  2688. float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
  2689. Transform2D tile_xform;
  2690. tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y)));
  2691. tile_xform.set_scale(tile_shape_size);
  2692. Color color = grid_color;
  2693. color.a = color.a * opacity;
  2694. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, false);
  2695. }
  2696. }
  2697. }
  2698. }
  2699. // Draw the preview.
  2700. for (const Vector2i &E : preview) {
  2701. Transform2D tile_xform;
  2702. tile_xform.set_origin(tile_map->map_to_world(E));
  2703. tile_xform.set_scale(tile_set->get_tile_size());
  2704. if (drag_erasing || erase_button->is_pressed()) {
  2705. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(0.0, 0.0, 0.0, 0.5), true);
  2706. } else {
  2707. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true);
  2708. }
  2709. }
  2710. }
  2711. }
  2712. }
  2713. void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
  2714. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2715. if (!tile_map) {
  2716. return;
  2717. }
  2718. Ref<TileSet> tile_set = tile_map->get_tileset();
  2719. if (!tile_set.is_valid()) {
  2720. return;
  2721. }
  2722. // Organizes tiles into structures.
  2723. per_terrain_terrains_patterns.resize(tile_set->get_terrain_sets_count());
  2724. for (int i = 0; i < tile_set->get_terrain_sets_count(); i++) {
  2725. per_terrain_terrains_patterns[i].resize(tile_set->get_terrains_count(i));
  2726. for (int j = 0; j < (int)per_terrain_terrains_patterns[i].size(); j++) {
  2727. per_terrain_terrains_patterns[i][j].clear();
  2728. }
  2729. }
  2730. for (int source_index = 0; source_index < tile_set->get_source_count(); source_index++) {
  2731. int source_id = tile_set->get_source_id(source_index);
  2732. Ref<TileSetSource> source = tile_set->get_source(source_id);
  2733. Ref<TileSetAtlasSource> atlas_source = source;
  2734. if (atlas_source.is_valid()) {
  2735. for (int tile_index = 0; tile_index < source->get_tiles_count(); tile_index++) {
  2736. Vector2i tile_id = source->get_tile_id(tile_index);
  2737. for (int alternative_index = 0; alternative_index < source->get_alternative_tiles_count(tile_id); alternative_index++) {
  2738. int alternative_id = source->get_alternative_tile_id(tile_id, alternative_index);
  2739. TileData *tile_data = atlas_source->get_tile_data(tile_id, alternative_id);
  2740. int terrain_set = tile_data->get_terrain_set();
  2741. if (terrain_set >= 0) {
  2742. ERR_FAIL_INDEX(terrain_set, (int)per_terrain_terrains_patterns.size());
  2743. TileMapCell cell;
  2744. cell.source_id = source_id;
  2745. cell.set_atlas_coords(tile_id);
  2746. cell.alternative_tile = alternative_id;
  2747. TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern();
  2748. // Terrain center bit
  2749. int terrain = terrains_pattern.get_terrain();
  2750. if (terrain >= 0 && terrain < (int)per_terrain_terrains_patterns[terrain_set].size()) {
  2751. per_terrain_terrains_patterns[terrain_set][terrain].insert(terrains_pattern);
  2752. }
  2753. // Terrain bits.
  2754. for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
  2755. TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
  2756. if (tile_set->is_valid_terrain_peering_bit(terrain_set, bit)) {
  2757. terrain = terrains_pattern.get_terrain_peering_bit(bit);
  2758. if (terrain >= 0 && terrain < (int)per_terrain_terrains_patterns[terrain_set].size()) {
  2759. per_terrain_terrains_patterns[terrain_set][terrain].insert(terrains_pattern);
  2760. }
  2761. }
  2762. }
  2763. }
  2764. }
  2765. }
  2766. }
  2767. }
  2768. }
  2769. void TileMapEditorTerrainsPlugin::_update_terrains_tree() {
  2770. terrains_tree->clear();
  2771. terrains_tree->create_item();
  2772. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2773. if (!tile_map) {
  2774. return;
  2775. }
  2776. Ref<TileSet> tile_set = tile_map->get_tileset();
  2777. if (!tile_set.is_valid()) {
  2778. return;
  2779. }
  2780. // Fill in the terrain list.
  2781. Vector<Vector<Ref<Texture2D>>> icons = tile_set->generate_terrains_icons(Size2(16, 16) * EDSCALE);
  2782. for (int terrain_set_index = 0; terrain_set_index < tile_set->get_terrain_sets_count(); terrain_set_index++) {
  2783. // Add an item for the terrain set.
  2784. TreeItem *terrain_set_tree_item = terrains_tree->create_item();
  2785. String matches;
  2786. if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) {
  2787. terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchCornersAndSides"), SNAME("EditorIcons")));
  2788. matches = String(TTR("Matches Corners and Sides"));
  2789. } else if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
  2790. terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchCorners"), SNAME("EditorIcons")));
  2791. matches = String(TTR("Matches Corners Only"));
  2792. } else {
  2793. terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons")));
  2794. matches = String(TTR("Matches Sides Only"));
  2795. }
  2796. terrain_set_tree_item->set_text(0, vformat("Terrain Set %d (%s)", terrain_set_index, matches));
  2797. terrain_set_tree_item->set_selectable(0, false);
  2798. for (int terrain_index = 0; terrain_index < tile_set->get_terrains_count(terrain_set_index); terrain_index++) {
  2799. // Add the item to the terrain list.
  2800. TreeItem *terrain_tree_item = terrains_tree->create_item(terrain_set_tree_item);
  2801. terrain_tree_item->set_text(0, tile_set->get_terrain_name(terrain_set_index, terrain_index));
  2802. terrain_tree_item->set_icon_max_width(0, 32 * EDSCALE);
  2803. terrain_tree_item->set_icon(0, icons[terrain_set_index][terrain_index]);
  2804. Dictionary metadata_dict;
  2805. metadata_dict["terrain_set"] = terrain_set_index;
  2806. metadata_dict["terrain_id"] = terrain_index;
  2807. terrain_tree_item->set_metadata(0, metadata_dict);
  2808. }
  2809. }
  2810. }
  2811. void TileMapEditorTerrainsPlugin::_update_tiles_list() {
  2812. terrains_tile_list->clear();
  2813. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  2814. if (!tile_map) {
  2815. return;
  2816. }
  2817. Ref<TileSet> tile_set = tile_map->get_tileset();
  2818. if (!tile_set.is_valid()) {
  2819. return;
  2820. }
  2821. TreeItem *selected_tree_item = terrains_tree->get_selected();
  2822. if (selected_tree_item && selected_tree_item->get_metadata(0)) {
  2823. Dictionary metadata_dict = selected_tree_item->get_metadata(0);
  2824. int selected_terrain_set = metadata_dict["terrain_set"];
  2825. int selected_terrain_id = metadata_dict["terrain_id"];
  2826. ERR_FAIL_INDEX(selected_terrain_set, tile_set->get_terrain_sets_count());
  2827. ERR_FAIL_INDEX(selected_terrain_id, tile_set->get_terrains_count(selected_terrain_set));
  2828. // Add the two first generic modes
  2829. int item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainConnect"), SNAME("EditorIcons")));
  2830. terrains_tile_list->set_item_tooltip(item_index, TTR("Connect mode: paints a terrain, then connects it with the surrounding tiles with the same terrain."));
  2831. Dictionary list_metadata_dict;
  2832. list_metadata_dict["type"] = SELECTED_TYPE_CONNECT;
  2833. terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
  2834. item_index = terrains_tile_list->add_icon_item(main_vbox_container->get_theme_icon(SNAME("TerrainPath"), SNAME("EditorIcons")));
  2835. terrains_tile_list->set_item_tooltip(item_index, TTR("Path mode: paints a terrain, thens connects it to the previous tile painted within the same stroke."));
  2836. list_metadata_dict = Dictionary();
  2837. list_metadata_dict["type"] = SELECTED_TYPE_PATH;
  2838. terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
  2839. // Sort the items in a map by the number of corresponding terrains.
  2840. RBMap<int, RBSet<TileSet::TerrainsPattern>> sorted;
  2841. for (const TileSet::TerrainsPattern &E : per_terrain_terrains_patterns[selected_terrain_set][selected_terrain_id]) {
  2842. // Count the number of matching sides/terrains.
  2843. int count = 0;
  2844. for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
  2845. TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
  2846. if (tile_set->is_valid_terrain_peering_bit(selected_terrain_set, bit) && E.get_terrain_peering_bit(bit) == selected_terrain_id) {
  2847. count++;
  2848. }
  2849. }
  2850. sorted[count].insert(E);
  2851. }
  2852. for (RBMap<int, RBSet<TileSet::TerrainsPattern>>::Element *E_set = sorted.back(); E_set; E_set = E_set->prev()) {
  2853. for (const TileSet::TerrainsPattern &E : E_set->get()) {
  2854. TileSet::TerrainsPattern terrains_pattern = E;
  2855. // Get the icon.
  2856. Ref<Texture2D> icon;
  2857. Rect2 region;
  2858. bool transpose = false;
  2859. double max_probability = -1.0;
  2860. for (const TileMapCell &cell : tile_set->get_tiles_for_terrains_pattern(selected_terrain_set, terrains_pattern)) {
  2861. Ref<TileSetSource> source = tile_set->get_source(cell.source_id);
  2862. Ref<TileSetAtlasSource> atlas_source = source;
  2863. if (atlas_source.is_valid()) {
  2864. TileData *tile_data = atlas_source->get_tile_data(cell.get_atlas_coords(), cell.alternative_tile);
  2865. if (tile_data->get_probability() > max_probability) {
  2866. icon = atlas_source->get_texture();
  2867. region = atlas_source->get_tile_texture_region(cell.get_atlas_coords());
  2868. if (tile_data->get_flip_h()) {
  2869. region.position.x += region.size.x;
  2870. region.size.x = -region.size.x;
  2871. }
  2872. if (tile_data->get_flip_v()) {
  2873. region.position.y += region.size.y;
  2874. region.size.y = -region.size.y;
  2875. }
  2876. transpose = tile_data->get_transpose();
  2877. max_probability = tile_data->get_probability();
  2878. }
  2879. }
  2880. }
  2881. // Create the ItemList's item.
  2882. item_index = terrains_tile_list->add_item("");
  2883. terrains_tile_list->set_item_icon(item_index, icon);
  2884. terrains_tile_list->set_item_icon_region(item_index, region);
  2885. terrains_tile_list->set_item_icon_transposed(item_index, transpose);
  2886. list_metadata_dict = Dictionary();
  2887. list_metadata_dict["type"] = SELECTED_TYPE_PATTERN;
  2888. list_metadata_dict["terrains_pattern"] = terrains_pattern.as_array();
  2889. terrains_tile_list->set_item_metadata(item_index, list_metadata_dict);
  2890. }
  2891. }
  2892. if (terrains_tile_list->get_item_count() > 0) {
  2893. terrains_tile_list->select(0);
  2894. }
  2895. }
  2896. }
  2897. void TileMapEditorTerrainsPlugin::_update_theme() {
  2898. paint_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
  2899. line_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")));
  2900. rect_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons")));
  2901. bucket_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons")));
  2902. picker_button->set_icon(main_vbox_container->get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
  2903. erase_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
  2904. _update_tiles_list();
  2905. }
  2906. void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
  2907. _stop_dragging(); // Avoids staying in a wrong drag state.
  2908. tile_map_id = p_tile_map_id;
  2909. tile_map_layer = p_tile_map_layer;
  2910. _update_terrains_cache();
  2911. _update_terrains_tree();
  2912. _update_tiles_list();
  2913. }
  2914. TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
  2915. undo_redo = EditorNode::get_undo_redo();
  2916. main_vbox_container = memnew(VBoxContainer);
  2917. main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
  2918. main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
  2919. main_vbox_container->set_name("Terrains");
  2920. HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer);
  2921. tilemap_tab_terrains->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  2922. tilemap_tab_terrains->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  2923. main_vbox_container->add_child(tilemap_tab_terrains);
  2924. terrains_tree = memnew(Tree);
  2925. terrains_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  2926. terrains_tree->set_stretch_ratio(0.25);
  2927. terrains_tree->set_custom_minimum_size(Size2i(70, 0) * EDSCALE);
  2928. terrains_tree->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
  2929. terrains_tree->set_hide_root(true);
  2930. terrains_tree->connect("item_selected", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_tiles_list));
  2931. tilemap_tab_terrains->add_child(terrains_tree);
  2932. terrains_tile_list = memnew(ItemList);
  2933. terrains_tile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  2934. terrains_tile_list->set_max_columns(0);
  2935. terrains_tile_list->set_same_column_width(true);
  2936. terrains_tile_list->set_fixed_icon_size(Size2(32, 32) * EDSCALE);
  2937. terrains_tile_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
  2938. tilemap_tab_terrains->add_child(terrains_tile_list);
  2939. // --- Toolbar ---
  2940. toolbar = memnew(HBoxContainer);
  2941. HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer);
  2942. tool_buttons_group.instantiate();
  2943. paint_tool_button = memnew(Button);
  2944. paint_tool_button->set_flat(true);
  2945. paint_tool_button->set_toggle_mode(true);
  2946. paint_tool_button->set_button_group(tool_buttons_group);
  2947. paint_tool_button->set_pressed(true);
  2948. paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D));
  2949. paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
  2950. tilemap_tiles_tools_buttons->add_child(paint_tool_button);
  2951. line_tool_button = memnew(Button);
  2952. line_tool_button->set_flat(true);
  2953. line_tool_button->set_toggle_mode(true);
  2954. line_tool_button->set_button_group(tool_buttons_group);
  2955. line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L));
  2956. line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
  2957. tilemap_tiles_tools_buttons->add_child(line_tool_button);
  2958. rect_tool_button = memnew(Button);
  2959. rect_tool_button->set_flat(true);
  2960. rect_tool_button->set_toggle_mode(true);
  2961. rect_tool_button->set_button_group(tool_buttons_group);
  2962. rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R));
  2963. rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
  2964. tilemap_tiles_tools_buttons->add_child(rect_tool_button);
  2965. bucket_tool_button = memnew(Button);
  2966. bucket_tool_button->set_flat(true);
  2967. bucket_tool_button->set_toggle_mode(true);
  2968. bucket_tool_button->set_button_group(tool_buttons_group);
  2969. bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B));
  2970. bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
  2971. tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
  2972. toolbar->add_child(tilemap_tiles_tools_buttons);
  2973. // -- TileMap tool settings --
  2974. tools_settings = memnew(HBoxContainer);
  2975. toolbar->add_child(tools_settings);
  2976. tools_settings_vsep = memnew(VSeparator);
  2977. tools_settings->add_child(tools_settings_vsep);
  2978. // Picker
  2979. picker_button = memnew(Button);
  2980. picker_button->set_flat(true);
  2981. picker_button->set_toggle_mode(true);
  2982. picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P));
  2983. picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
  2984. tools_settings->add_child(picker_button);
  2985. // Erase button.
  2986. erase_button = memnew(Button);
  2987. erase_button->set_flat(true);
  2988. erase_button->set_toggle_mode(true);
  2989. erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E));
  2990. erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
  2991. tools_settings->add_child(erase_button);
  2992. // Separator 2.
  2993. tools_settings_vsep_2 = memnew(VSeparator);
  2994. tools_settings->add_child(tools_settings_vsep_2);
  2995. // Continuous checkbox.
  2996. bucket_contiguous_checkbox = memnew(CheckBox);
  2997. bucket_contiguous_checkbox->set_flat(true);
  2998. bucket_contiguous_checkbox->set_text(TTR("Contiguous"));
  2999. bucket_contiguous_checkbox->set_pressed(true);
  3000. tools_settings->add_child(bucket_contiguous_checkbox);
  3001. }
  3002. TileMapEditorTerrainsPlugin::~TileMapEditorTerrainsPlugin() {
  3003. }
  3004. void TileMapEditor::_notification(int p_what) {
  3005. switch (p_what) {
  3006. case NOTIFICATION_ENTER_TREE:
  3007. case NOTIFICATION_THEME_CHANGED: {
  3008. missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
  3009. warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons"));
  3010. advanced_menu_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
  3011. toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
  3012. toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
  3013. toggle_highlight_selected_layer_button->set_icon(get_theme_icon(SNAME("TileMapHighlightSelected"), SNAME("EditorIcons")));
  3014. } break;
  3015. case NOTIFICATION_INTERNAL_PROCESS: {
  3016. if (is_visible_in_tree() && tileset_changed_needs_update) {
  3017. _update_bottom_panel();
  3018. _update_layers_selection();
  3019. tabs_plugins[tabs_bar->get_current_tab()]->tile_set_changed();
  3020. CanvasItemEditor::get_singleton()->update_viewport();
  3021. tileset_changed_needs_update = false;
  3022. }
  3023. } break;
  3024. case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
  3025. toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
  3026. } break;
  3027. case NOTIFICATION_VISIBILITY_CHANGED: {
  3028. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3029. if (tile_map) {
  3030. if (is_visible_in_tree()) {
  3031. tile_map->set_selected_layer(tile_map_layer);
  3032. } else {
  3033. tile_map->set_selected_layer(-1);
  3034. }
  3035. }
  3036. } break;
  3037. }
  3038. }
  3039. void TileMapEditor::_on_grid_toggled(bool p_pressed) {
  3040. EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
  3041. CanvasItemEditor::get_singleton()->update_viewport();
  3042. }
  3043. void TileMapEditor::_layers_selection_item_selected(int p_index) {
  3044. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3045. if (!tile_map || tile_map->get_layers_count() <= 0) {
  3046. return;
  3047. }
  3048. tile_map_layer = p_index;
  3049. _update_layers_selection();
  3050. }
  3051. void TileMapEditor::_advanced_menu_button_id_pressed(int p_id) {
  3052. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3053. if (!tile_map) {
  3054. return;
  3055. }
  3056. Ref<TileSet> tile_set = tile_map->get_tileset();
  3057. if (!tile_set.is_valid()) {
  3058. return;
  3059. }
  3060. if (p_id == 0) { // Replace Tile Proxies
  3061. undo_redo->create_action(TTR("Replace Tiles with Proxies"));
  3062. for (int layer_index = 0; layer_index < tile_map->get_layers_count(); layer_index++) {
  3063. TypedArray<Vector2i> used_cells = tile_map->get_used_cells(layer_index);
  3064. for (int i = 0; i < used_cells.size(); i++) {
  3065. Vector2i cell_coords = used_cells[i];
  3066. TileMapCell from = tile_map->get_cell(layer_index, cell_coords);
  3067. Array to_array = tile_set->map_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
  3068. TileMapCell to;
  3069. to.source_id = to_array[0];
  3070. to.set_atlas_coords(to_array[1]);
  3071. to.alternative_tile = to_array[2];
  3072. if (from != to) {
  3073. undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
  3074. undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
  3075. }
  3076. }
  3077. }
  3078. undo_redo->commit_action();
  3079. }
  3080. }
  3081. void TileMapEditor::_update_bottom_panel() {
  3082. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3083. if (!tile_map) {
  3084. return;
  3085. }
  3086. Ref<TileSet> tile_set = tile_map->get_tileset();
  3087. // Update the visibility of controls.
  3088. missing_tileset_label->set_visible(!tile_set.is_valid());
  3089. for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) {
  3090. tabs_data[tab_index].panel->hide();
  3091. }
  3092. if (tile_set.is_valid()) {
  3093. tabs_data[tabs_bar->get_current_tab()].panel->show();
  3094. }
  3095. }
  3096. Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell) {
  3097. ERR_FAIL_COND_V(!p_tile_map, Vector<Vector2i>());
  3098. Ref<TileSet> tile_set = p_tile_map->get_tileset();
  3099. ERR_FAIL_COND_V(!tile_set.is_valid(), Vector<Vector2i>());
  3100. if (tile_set->get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
  3101. return Geometry2D::bresenham_line(p_from_cell, p_to_cell);
  3102. } else {
  3103. // Adapt the bresenham line algorithm to half-offset shapes.
  3104. // See this blog post: http://zvold.blogspot.com/2010/01/bresenhams-line-drawing-algorithm-on_26.html
  3105. Vector<Point2i> points;
  3106. bool transposed = tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL;
  3107. p_from_cell = TileMap::transform_coords_layout(p_from_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
  3108. p_to_cell = TileMap::transform_coords_layout(p_to_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
  3109. if (transposed) {
  3110. SWAP(p_from_cell.x, p_from_cell.y);
  3111. SWAP(p_to_cell.x, p_to_cell.y);
  3112. }
  3113. Vector2i delta = p_to_cell - p_from_cell;
  3114. delta = Vector2i(2 * delta.x + ABS(p_to_cell.y % 2) - ABS(p_from_cell.y % 2), delta.y);
  3115. Vector2i sign = delta.sign();
  3116. Vector2i current = p_from_cell;
  3117. points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
  3118. int err = 0;
  3119. if (ABS(delta.y) < ABS(delta.x)) {
  3120. Vector2i err_step = 3 * delta.abs();
  3121. while (current != p_to_cell) {
  3122. err += err_step.y;
  3123. if (err > ABS(delta.x)) {
  3124. if (sign.x == 0) {
  3125. current += Vector2(sign.y, 0);
  3126. } else {
  3127. current += Vector2(bool(current.y % 2) ^ (sign.x < 0) ? sign.x : 0, sign.y);
  3128. }
  3129. err -= err_step.x;
  3130. } else {
  3131. current += Vector2i(sign.x, 0);
  3132. err += err_step.y;
  3133. }
  3134. points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
  3135. }
  3136. } else {
  3137. Vector2i err_step = delta.abs();
  3138. while (current != p_to_cell) {
  3139. err += err_step.x;
  3140. if (err > 0) {
  3141. if (sign.x == 0) {
  3142. current += Vector2(0, sign.y);
  3143. } else {
  3144. current += Vector2(bool(current.y % 2) ^ (sign.x < 0) ? sign.x : 0, sign.y);
  3145. }
  3146. err -= err_step.y;
  3147. } else {
  3148. if (sign.x == 0) {
  3149. current += Vector2(0, sign.y);
  3150. } else {
  3151. current += Vector2(bool(current.y % 2) ^ (sign.x > 0) ? -sign.x : 0, sign.y);
  3152. }
  3153. err += err_step.y;
  3154. }
  3155. points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
  3156. }
  3157. }
  3158. return points;
  3159. }
  3160. }
  3161. void TileMapEditor::_tile_map_changed() {
  3162. tileset_changed_needs_update = true;
  3163. }
  3164. void TileMapEditor::_tab_changed(int p_tab_id) {
  3165. // Make the plugin edit the correct tilemap.
  3166. tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
  3167. // Update toolbar.
  3168. for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) {
  3169. tabs_data[tab_index].toolbar->hide();
  3170. }
  3171. tabs_data[p_tab_id].toolbar->show();
  3172. // Update visible panel.
  3173. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3174. for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) {
  3175. tabs_data[tab_index].panel->hide();
  3176. }
  3177. if (tile_map && tile_map->get_tileset().is_valid()) {
  3178. tabs_data[tabs_bar->get_current_tab()].panel->show();
  3179. }
  3180. // Graphical update.
  3181. tabs_data[tabs_bar->get_current_tab()].panel->queue_redraw();
  3182. CanvasItemEditor::get_singleton()->update_viewport();
  3183. }
  3184. void TileMapEditor::_layers_select_next_or_previous(bool p_next) {
  3185. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3186. if (!tile_map) {
  3187. return;
  3188. }
  3189. if (tile_map->get_layers_count() < 1) {
  3190. return;
  3191. }
  3192. if (tile_map_layer < 0) {
  3193. tile_map_layer = 0;
  3194. }
  3195. int inc = p_next ? 1 : -1;
  3196. int origin_layer = tile_map_layer;
  3197. tile_map_layer = Math::posmod((tile_map_layer + inc), tile_map->get_layers_count());
  3198. while (tile_map_layer != origin_layer) {
  3199. if (tile_map->is_layer_enabled(tile_map_layer)) {
  3200. break;
  3201. }
  3202. tile_map_layer = Math::posmod((tile_map_layer + inc), tile_map->get_layers_count());
  3203. }
  3204. _update_layers_selection();
  3205. }
  3206. void TileMapEditor::_update_layers_selection() {
  3207. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3208. if (!tile_map) {
  3209. return;
  3210. }
  3211. // Update the selected layer.
  3212. if (is_visible_in_tree() && tile_map->get_layers_count() >= 1) {
  3213. tile_map_layer = CLAMP(tile_map_layer, 0, tile_map->get_layers_count() - 1);
  3214. // Search for an enabled layer if the current one is not.
  3215. int origin_layer = tile_map_layer;
  3216. while (tile_map_layer >= 0 && !tile_map->is_layer_enabled(tile_map_layer)) {
  3217. tile_map_layer--;
  3218. }
  3219. if (tile_map_layer < 0) {
  3220. tile_map_layer = origin_layer;
  3221. while (tile_map_layer < tile_map->get_layers_count() && !tile_map->is_layer_enabled(tile_map_layer)) {
  3222. tile_map_layer++;
  3223. }
  3224. }
  3225. if (tile_map_layer >= tile_map->get_layers_count()) {
  3226. tile_map_layer = -1;
  3227. }
  3228. } else {
  3229. tile_map_layer = -1;
  3230. }
  3231. tile_map->set_selected_layer(toggle_highlight_selected_layer_button->is_pressed() ? tile_map_layer : -1);
  3232. layers_selection_button->clear();
  3233. if (tile_map->get_layers_count() > 0) {
  3234. // Build the list of layers.
  3235. for (int i = 0; i < tile_map->get_layers_count(); i++) {
  3236. String name = tile_map->get_layer_name(i);
  3237. layers_selection_button->add_item(name.is_empty() ? vformat(TTR("Layer %d"), i) : name, i);
  3238. layers_selection_button->set_item_disabled(i, !tile_map->is_layer_enabled(i));
  3239. }
  3240. layers_selection_button->set_disabled(false);
  3241. layers_selection_button->select(tile_map_layer);
  3242. } else {
  3243. layers_selection_button->set_disabled(true);
  3244. layers_selection_button->set_text(TTR("No Layers"));
  3245. }
  3246. tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
  3247. }
  3248. void TileMapEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
  3249. Ref<EditorUndoRedoManager> undo_redo = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
  3250. ERR_FAIL_COND(undo_redo.is_null());
  3251. TileMap *tile_map = Object::cast_to<TileMap>(p_edited);
  3252. if (!tile_map) {
  3253. return;
  3254. }
  3255. // Compute the array indices to save.
  3256. int begin = 0;
  3257. int end;
  3258. if (p_array_prefix == "layer_") {
  3259. end = tile_map->get_layers_count();
  3260. } else {
  3261. ERR_FAIL_MSG("Invalid array prefix for TileSet.");
  3262. }
  3263. if (p_from_index < 0) {
  3264. // Adding new.
  3265. if (p_to_pos >= 0) {
  3266. begin = p_to_pos;
  3267. } else {
  3268. end = 0; // Nothing to save when adding at the end.
  3269. }
  3270. } else if (p_to_pos < 0) {
  3271. // Removing.
  3272. begin = p_from_index;
  3273. } else {
  3274. // Moving.
  3275. begin = MIN(p_from_index, p_to_pos);
  3276. end = MIN(MAX(p_from_index, p_to_pos) + 1, end);
  3277. }
  3278. #define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, obj->get(property));
  3279. // Save layers' properties.
  3280. if (p_from_index < 0) {
  3281. undo_redo->add_undo_method(tile_map, "remove_layer", p_to_pos < 0 ? tile_map->get_layers_count() : p_to_pos);
  3282. } else if (p_to_pos < 0) {
  3283. undo_redo->add_undo_method(tile_map, "add_layer", p_from_index);
  3284. }
  3285. List<PropertyInfo> properties;
  3286. tile_map->get_property_list(&properties);
  3287. for (PropertyInfo pi : properties) {
  3288. if (pi.name.begins_with(p_array_prefix)) {
  3289. String str = pi.name.trim_prefix(p_array_prefix);
  3290. int to_char_index = 0;
  3291. while (to_char_index < str.length()) {
  3292. if (!is_digit(str[to_char_index])) {
  3293. break;
  3294. }
  3295. to_char_index++;
  3296. }
  3297. if (to_char_index > 0) {
  3298. int array_index = str.left(to_char_index).to_int();
  3299. if (array_index >= begin && array_index < end) {
  3300. ADD_UNDO(tile_map, pi.name);
  3301. }
  3302. }
  3303. }
  3304. }
  3305. #undef ADD_UNDO
  3306. if (p_from_index < 0) {
  3307. undo_redo->add_do_method(tile_map, "add_layer", p_to_pos);
  3308. } else if (p_to_pos < 0) {
  3309. undo_redo->add_do_method(tile_map, "remove_layer", p_from_index);
  3310. } else {
  3311. undo_redo->add_do_method(tile_map, "move_layer", p_from_index, p_to_pos);
  3312. }
  3313. }
  3314. bool TileMapEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
  3315. if (ED_IS_SHORTCUT("tiles_editor/select_next_layer", p_event) && p_event->is_pressed()) {
  3316. _layers_select_next_or_previous(true);
  3317. return true;
  3318. }
  3319. if (ED_IS_SHORTCUT("tiles_editor/select_previous_layer", p_event) && p_event->is_pressed()) {
  3320. _layers_select_next_or_previous(false);
  3321. return true;
  3322. }
  3323. return tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_gui_input(p_event);
  3324. }
  3325. void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
  3326. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3327. if (!tile_map) {
  3328. return;
  3329. }
  3330. Ref<TileSet> tile_set = tile_map->get_tileset();
  3331. if (!tile_set.is_valid()) {
  3332. return;
  3333. }
  3334. if (!tile_map->is_visible_in_tree()) {
  3335. return;
  3336. }
  3337. Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform();
  3338. Transform2D xform_inv = xform.affine_inverse();
  3339. Vector2i tile_shape_size = tile_set->get_tile_size();
  3340. // Draw tiles with invalid IDs in the grid.
  3341. if (tile_map_layer >= 0) {
  3342. ERR_FAIL_COND(tile_map_layer >= tile_map->get_layers_count());
  3343. TypedArray<Vector2i> used_cells = tile_map->get_used_cells(tile_map_layer);
  3344. for (int i = 0; i < used_cells.size(); i++) {
  3345. Vector2i coords = used_cells[i];
  3346. int tile_source_id = tile_map->get_cell_source_id(tile_map_layer, coords);
  3347. if (tile_source_id >= 0) {
  3348. Vector2i tile_atlas_coords = tile_map->get_cell_atlas_coords(tile_map_layer, coords);
  3349. int tile_alternative_tile = tile_map->get_cell_alternative_tile(tile_map_layer, coords);
  3350. TileSetSource *source = nullptr;
  3351. if (tile_set->has_source(tile_source_id)) {
  3352. source = *tile_set->get_source(tile_source_id);
  3353. }
  3354. if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
  3355. // Generate a random color from the hashed values of the tiles.
  3356. Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile);
  3357. if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) {
  3358. // Only display the pattern if we have no proxy tile.
  3359. Array to_hash;
  3360. to_hash.push_back(tile_source_id);
  3361. to_hash.push_back(tile_atlas_coords);
  3362. to_hash.push_back(tile_alternative_tile);
  3363. uint32_t hash = RandomPCG(to_hash.hash()).rand();
  3364. Color color;
  3365. color = color.from_hsv(
  3366. (float)((hash >> 24) & 0xFF) / 256.0,
  3367. Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
  3368. Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
  3369. 0.8);
  3370. // Draw the scaled tile.
  3371. Transform2D tile_xform;
  3372. tile_xform.set_origin(tile_map->map_to_world(coords));
  3373. tile_xform.set_scale(tile_shape_size);
  3374. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture);
  3375. }
  3376. // Draw the warning icon.
  3377. Vector2::Axis min_axis = missing_tile_texture->get_size().min_axis_index();
  3378. Vector2 icon_size;
  3379. icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3;
  3380. icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]);
  3381. Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
  3382. p_overlay->draw_texture_rect(missing_tile_texture, rect);
  3383. }
  3384. }
  3385. }
  3386. }
  3387. // Fading on the border.
  3388. const int fading = 5;
  3389. // Determine the drawn area.
  3390. Size2 screen_size = p_overlay->get_size();
  3391. Rect2i screen_rect;
  3392. screen_rect.position = tile_map->world_to_map(xform_inv.xform(Vector2()));
  3393. screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(Vector2(0, screen_size.height))));
  3394. screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(Vector2(screen_size.width, 0))));
  3395. screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(screen_size)));
  3396. screen_rect = screen_rect.grow(1);
  3397. Rect2i tilemap_used_rect = tile_map->get_used_rect();
  3398. Rect2i displayed_rect = tilemap_used_rect.intersection(screen_rect);
  3399. displayed_rect = displayed_rect.grow(fading);
  3400. // Reduce the drawn area to avoid crashes if needed.
  3401. int max_size = 100;
  3402. if (displayed_rect.size.x > max_size) {
  3403. displayed_rect = displayed_rect.grow_individual(-(displayed_rect.size.x - max_size) / 2, 0, -(displayed_rect.size.x - max_size) / 2, 0);
  3404. }
  3405. if (displayed_rect.size.y > max_size) {
  3406. displayed_rect = displayed_rect.grow_individual(0, -(displayed_rect.size.y - max_size) / 2, 0, -(displayed_rect.size.y - max_size) / 2);
  3407. }
  3408. // Draw the grid.
  3409. bool display_grid = EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid");
  3410. if (display_grid) {
  3411. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  3412. for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
  3413. for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
  3414. Vector2i pos_in_rect = Vector2i(x, y) - displayed_rect.position;
  3415. // Fade out the border of the grid.
  3416. float left_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.x), 0.0f, 1.0f);
  3417. float right_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.x, (float)(displayed_rect.size.x - fading), (float)(pos_in_rect.x + 1)), 0.0f, 1.0f);
  3418. float top_opacity = CLAMP(Math::inverse_lerp(0.0f, (float)fading, (float)pos_in_rect.y), 0.0f, 1.0f);
  3419. float bottom_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.y, (float)(displayed_rect.size.y - fading), (float)(pos_in_rect.y + 1)), 0.0f, 1.0f);
  3420. float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
  3421. Transform2D tile_xform;
  3422. tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y)));
  3423. tile_xform.set_scale(tile_shape_size);
  3424. Color color = grid_color;
  3425. color.a = color.a * opacity;
  3426. tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, false);
  3427. }
  3428. }
  3429. }
  3430. // Draw the IDs for debug.
  3431. /*Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
  3432. for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
  3433. for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
  3434. p_overlay->draw_string(font, xform.xform(tile_map->map_to_world(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y)));
  3435. }
  3436. }*/
  3437. // Draw the plugins.
  3438. tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_draw_over_viewport(p_overlay);
  3439. }
  3440. void TileMapEditor::edit(TileMap *p_tile_map) {
  3441. if (p_tile_map && p_tile_map->get_instance_id() == tile_map_id) {
  3442. return;
  3443. }
  3444. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3445. if (tile_map) {
  3446. // Unselect layer if we are changing tile_map.
  3447. if (tile_map != p_tile_map) {
  3448. tile_map->set_selected_layer(-1);
  3449. }
  3450. // Disconnect to changes.
  3451. tile_map->disconnect("changed", callable_mp(this, &TileMapEditor::_tile_map_changed));
  3452. }
  3453. if (p_tile_map) {
  3454. // Change the edited object.
  3455. tile_map_id = p_tile_map->get_instance_id();
  3456. tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
  3457. // Connect to changes.
  3458. if (!tile_map->is_connected("changed", callable_mp(this, &TileMapEditor::_tile_map_changed))) {
  3459. tile_map->connect("changed", callable_mp(this, &TileMapEditor::_tile_map_changed));
  3460. }
  3461. } else {
  3462. tile_map_id = ObjectID();
  3463. }
  3464. _update_layers_selection();
  3465. // Call the plugins.
  3466. tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
  3467. _tile_map_changed();
  3468. }
  3469. TileMapEditor::TileMapEditor() {
  3470. undo_redo = EditorNode::get_undo_redo();
  3471. set_process_internal(true);
  3472. // Shortcuts.
  3473. ED_SHORTCUT("tiles_editor/select_next_layer", TTR("Select Next Tile Map Layer"), Key::PAGEUP);
  3474. ED_SHORTCUT("tiles_editor/select_previous_layer", TTR("Select Previous Tile Map Layer"), Key::PAGEDOWN);
  3475. // TileMap editor plugins
  3476. tile_map_editor_plugins.push_back(memnew(TileMapEditorTilesPlugin));
  3477. tile_map_editor_plugins.push_back(memnew(TileMapEditorTerrainsPlugin));
  3478. // TabBar.
  3479. tabs_bar = memnew(TabBar);
  3480. tabs_bar->set_clip_tabs(false);
  3481. for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
  3482. Vector<TileMapEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
  3483. for (int tab_index = 0; tab_index < tabs_vector.size(); tab_index++) {
  3484. tabs_bar->add_tab(tabs_vector[tab_index].panel->get_name());
  3485. tabs_data.push_back(tabs_vector[tab_index]);
  3486. tabs_plugins.push_back(tile_map_editor_plugins[plugin_index]);
  3487. }
  3488. }
  3489. tabs_bar->connect("tab_changed", callable_mp(this, &TileMapEditor::_tab_changed));
  3490. // --- TileMap toolbar ---
  3491. tile_map_toolbar = memnew(HBoxContainer);
  3492. tile_map_toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
  3493. add_child(tile_map_toolbar);
  3494. // Tabs.
  3495. tile_map_toolbar->add_child(tabs_bar);
  3496. // Tabs toolbars.
  3497. for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) {
  3498. tabs_data[tab_index].toolbar->hide();
  3499. if (!tabs_data[tab_index].toolbar->get_parent()) {
  3500. tile_map_toolbar->add_child(tabs_data[tab_index].toolbar);
  3501. }
  3502. }
  3503. // Wide empty separation control.
  3504. tile_map_toolbar->add_spacer();
  3505. // Layer selector.
  3506. layers_selection_button = memnew(OptionButton);
  3507. layers_selection_button->set_custom_minimum_size(Size2(200, 0));
  3508. layers_selection_button->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
  3509. layers_selection_button->set_tooltip_text(TTR("TileMap Layers"));
  3510. layers_selection_button->connect("item_selected", callable_mp(this, &TileMapEditor::_layers_selection_item_selected));
  3511. tile_map_toolbar->add_child(layers_selection_button);
  3512. toggle_highlight_selected_layer_button = memnew(Button);
  3513. toggle_highlight_selected_layer_button->set_flat(true);
  3514. toggle_highlight_selected_layer_button->set_toggle_mode(true);
  3515. toggle_highlight_selected_layer_button->set_pressed(true);
  3516. toggle_highlight_selected_layer_button->connect("pressed", callable_mp(this, &TileMapEditor::_update_layers_selection));
  3517. toggle_highlight_selected_layer_button->set_tooltip_text(TTR("Highlight Selected TileMap Layer"));
  3518. tile_map_toolbar->add_child(toggle_highlight_selected_layer_button);
  3519. tile_map_toolbar->add_child(memnew(VSeparator));
  3520. // Grid toggle.
  3521. toggle_grid_button = memnew(Button);
  3522. toggle_grid_button->set_flat(true);
  3523. toggle_grid_button->set_toggle_mode(true);
  3524. toggle_grid_button->set_tooltip_text(TTR("Toggle grid visibility."));
  3525. toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled));
  3526. tile_map_toolbar->add_child(toggle_grid_button);
  3527. // Advanced settings menu button.
  3528. advanced_menu_button = memnew(MenuButton);
  3529. advanced_menu_button->set_flat(true);
  3530. advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies"));
  3531. advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapEditor::_advanced_menu_button_id_pressed));
  3532. tile_map_toolbar->add_child(advanced_menu_button);
  3533. missing_tileset_label = memnew(Label);
  3534. missing_tileset_label->set_text(TTR("The edited TileMap node has no TileSet resource."));
  3535. missing_tileset_label->set_h_size_flags(SIZE_EXPAND_FILL);
  3536. missing_tileset_label->set_v_size_flags(SIZE_EXPAND_FILL);
  3537. missing_tileset_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
  3538. missing_tileset_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
  3539. missing_tileset_label->hide();
  3540. add_child(missing_tileset_label);
  3541. for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) {
  3542. add_child(tabs_data[tab_index].panel);
  3543. tabs_data[tab_index].panel->set_v_size_flags(SIZE_EXPAND_FILL);
  3544. tabs_data[tab_index].panel->set_visible(tab_index == 0);
  3545. tabs_data[tab_index].panel->set_h_size_flags(SIZE_EXPAND_FILL);
  3546. }
  3547. _tab_changed(0);
  3548. // Registers UndoRedo inspector callback.
  3549. EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("TileMap"), callable_mp(this, &TileMapEditor::_move_tile_map_array_element));
  3550. }
  3551. TileMapEditor::~TileMapEditor() {
  3552. for (int i = 0; i < tile_map_editor_plugins.size(); i++) {
  3553. memdelete(tile_map_editor_plugins[i]);
  3554. }
  3555. }