tile_set_atlas_source_editor.cpp 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322
  1. /*************************************************************************/
  2. /* tile_set_atlas_source_editor.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 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_set_atlas_source_editor.h"
  31. #include "tiles_editor_plugin.h"
  32. #include "editor/editor_inspector.h"
  33. #include "editor/editor_scale.h"
  34. #include "editor/progress_dialog.h"
  35. #include "scene/gui/box_container.h"
  36. #include "scene/gui/button.h"
  37. #include "scene/gui/control.h"
  38. #include "scene/gui/item_list.h"
  39. #include "scene/gui/separator.h"
  40. #include "scene/gui/split_container.h"
  41. #include "scene/gui/tab_container.h"
  42. #include "core/core_string_names.h"
  43. #include "core/math/geometry_2d.h"
  44. #include "core/os/keyboard.h"
  45. void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) {
  46. ERR_FAIL_COND(p_id < 0);
  47. if (source_id == p_id) {
  48. return;
  49. }
  50. ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Atlas Source ID. Another source exists with id %d.", p_id));
  51. int previous_source = source_id;
  52. source_id = p_id; // source_id must be updated before, because it's used by the source list update.
  53. tile_set->set_source_id(previous_source, p_id);
  54. emit_signal(SNAME("changed"), "id");
  55. }
  56. int TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id() {
  57. return source_id;
  58. }
  59. bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_set(const StringName &p_name, const Variant &p_value) {
  60. bool valid = false;
  61. tile_set_atlas_source->set(p_name, p_value, &valid);
  62. if (valid) {
  63. emit_signal(SNAME("changed"), String(p_name).utf8().get_data());
  64. }
  65. return valid;
  66. }
  67. bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
  68. if (!tile_set_atlas_source) {
  69. return false;
  70. }
  71. bool valid = false;
  72. r_ret = tile_set_atlas_source->get(p_name, &valid);
  73. return valid;
  74. }
  75. void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
  76. p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
  77. p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, ""));
  78. p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, ""));
  79. p_list->push_back(PropertyInfo(Variant::VECTOR2I, "tile_size", PROPERTY_HINT_NONE, ""));
  80. }
  81. void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() {
  82. // -- Shape and layout --
  83. ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id);
  84. ClassDB::bind_method(D_METHOD("get_id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id);
  85. ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
  86. ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
  87. }
  88. void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id) {
  89. ERR_FAIL_COND(!p_tile_set.is_valid());
  90. ERR_FAIL_COND(!p_tile_set_atlas_source);
  91. ERR_FAIL_COND(p_source_id < 0);
  92. ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_atlas_source);
  93. // Disconnect to changes.
  94. if (tile_set_atlas_source) {
  95. tile_set_atlas_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
  96. }
  97. tile_set = p_tile_set;
  98. tile_set_atlas_source = p_tile_set_atlas_source;
  99. source_id = p_source_id;
  100. // Connect to changes.
  101. if (tile_set_atlas_source) {
  102. if (!tile_set_atlas_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
  103. tile_set_atlas_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
  104. }
  105. }
  106. notify_property_list_changed();
  107. }
  108. // -- Proxy object used by the tile inspector --
  109. bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
  110. if (!tile_set_atlas_source) {
  111. return false;
  112. }
  113. if (tiles.size() == 1) {
  114. const Vector2i &coords = tiles.front()->get().tile;
  115. const int &alternative = tiles.front()->get().alternative;
  116. if (alternative == 0 && p_name == "atlas_coords") {
  117. Vector2i as_vector2i = Vector2i(p_value);
  118. ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, as_vector2i), false);
  119. if (tiles_set_atlas_source_editor->selection.front()->get().tile == coords) {
  120. tiles_set_atlas_source_editor->selection.clear();
  121. tiles_set_atlas_source_editor->selection.insert({ as_vector2i, 0 });
  122. tiles_set_atlas_source_editor->_update_tile_id_label();
  123. }
  124. tile_set_atlas_source->move_tile_in_atlas(coords, as_vector2i);
  125. tiles.clear();
  126. tiles.insert({ as_vector2i, 0 });
  127. emit_signal(SNAME("changed"), "atlas_coords");
  128. return true;
  129. } else if (alternative == 0 && p_name == "size_in_atlas") {
  130. Vector2i as_vector2i = Vector2i(p_value);
  131. ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false);
  132. tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i);
  133. emit_signal(SNAME("changed"), "size_in_atlas");
  134. return true;
  135. } else if (alternative > 0 && p_name == "alternative_id") {
  136. int as_int = int(p_value);
  137. ERR_FAIL_COND_V(as_int < 0, false);
  138. ERR_FAIL_COND_V_MSG(tile_set_atlas_source->has_alternative_tile(coords, as_int), false, vformat("Cannot change alternative tile ID. Another alternative exists with id %d for tile at coords %s.", as_int, coords));
  139. if (tiles_set_atlas_source_editor->selection.front()->get().alternative == alternative) {
  140. tiles_set_atlas_source_editor->selection.clear();
  141. tiles_set_atlas_source_editor->selection.insert({ coords, as_int });
  142. }
  143. int previous_alternative_tile = alternative;
  144. tiles.clear();
  145. tiles.insert({ coords, as_int }); // tiles must be updated before.
  146. tile_set_atlas_source->set_alternative_tile_id(coords, previous_alternative_tile, as_int);
  147. emit_signal(SNAME("changed"), "alternative_id");
  148. return true;
  149. }
  150. }
  151. bool any_valid = false;
  152. for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) {
  153. const Vector2i &coords = E->get().tile;
  154. const int &alternative = E->get().alternative;
  155. bool valid = false;
  156. TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative));
  157. ERR_FAIL_COND_V(!tile_data, false);
  158. tile_data->set(p_name, p_value, &valid);
  159. any_valid |= valid;
  160. }
  161. if (any_valid) {
  162. emit_signal(SNAME("changed"), String(p_name).utf8().get_data());
  163. }
  164. return any_valid;
  165. }
  166. bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
  167. if (!tile_set_atlas_source) {
  168. return false;
  169. }
  170. if (tiles.size() == 1) {
  171. const Vector2i &coords = tiles.front()->get().tile;
  172. const int &alternative = tiles.front()->get().alternative;
  173. if (alternative == 0 && p_name == "atlas_coords") {
  174. r_ret = coords;
  175. return true;
  176. } else if (alternative == 0 && p_name == "size_in_atlas") {
  177. r_ret = tile_set_atlas_source->get_tile_size_in_atlas(coords);
  178. return true;
  179. } else if (alternative > 0 && p_name == "alternative_id") {
  180. r_ret = alternative;
  181. return true;
  182. }
  183. }
  184. for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) {
  185. // Return the first tile with a property matching the name.
  186. // Note: It's a little bit annoying, but the behavior is the same the one in MultiNodeEdit.
  187. const Vector2i &coords = E->get().tile;
  188. const int &alternative = E->get().alternative;
  189. TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative));
  190. ERR_FAIL_COND_V(!tile_data, false);
  191. bool valid = false;
  192. r_ret = tile_data->get(p_name, &valid);
  193. if (valid) {
  194. return true;
  195. }
  196. }
  197. return false;
  198. }
  199. void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
  200. if (!tile_set_atlas_source) {
  201. return;
  202. }
  203. if (tiles.size() == 1) {
  204. if (tiles.front()->get().alternative == 0) {
  205. p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords", PROPERTY_HINT_NONE, ""));
  206. p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas", PROPERTY_HINT_NONE, ""));
  207. } else {
  208. p_list->push_back(PropertyInfo(Variant::INT, "alternative_id", PROPERTY_HINT_NONE, ""));
  209. }
  210. }
  211. // Get the list of properties common to all tiles (similar to what's done in MultiNodeEdit).
  212. struct PropertyId {
  213. int occurence_id = 0;
  214. String property;
  215. bool operator<(const PropertyId &p_other) const {
  216. return occurence_id == p_other.occurence_id ? property < p_other.property : occurence_id < p_other.occurence_id;
  217. }
  218. };
  219. struct PLData {
  220. int uses = 0;
  221. PropertyInfo property_info;
  222. };
  223. Map<PropertyId, PLData> usage;
  224. List<PLData *> data_list;
  225. for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) {
  226. const Vector2i &coords = E->get().tile;
  227. const int &alternative = E->get().alternative;
  228. TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative));
  229. ERR_FAIL_COND(!tile_data);
  230. List<PropertyInfo> list;
  231. tile_data->get_property_list(&list);
  232. Map<String, int> counts; // Counts the number of time a property appears (useful for groups that may appear more than once)
  233. for (List<PropertyInfo>::Element *E_property = list.front(); E_property; E_property = E_property->next()) {
  234. const String &property_string = E_property->get().name;
  235. if (!tile_data->is_allowing_transform() && (property_string == "flip_h" || property_string == "flip_v" || property_string == "transpose")) {
  236. continue;
  237. }
  238. if (!counts.has(property_string)) {
  239. counts[property_string] = 1;
  240. } else {
  241. counts[property_string] += 1;
  242. }
  243. PropertyInfo stored_property_info = E_property->get();
  244. stored_property_info.usage |= PROPERTY_USAGE_STORAGE; // Ignore the storage flag in comparing properties.
  245. PropertyId id = { counts[property_string], property_string };
  246. if (!usage.has(id)) {
  247. usage[id] = { 1, stored_property_info };
  248. data_list.push_back(&usage[id]);
  249. } else if (usage[id].property_info == stored_property_info) {
  250. usage[id].uses += 1;
  251. }
  252. }
  253. }
  254. // Add only properties that are common to all tiles.
  255. for (const PLData *E : data_list) {
  256. if (E->uses == tiles.size()) {
  257. p_list->push_back(E->property_info);
  258. }
  259. }
  260. }
  261. void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles) {
  262. ERR_FAIL_COND(!p_tile_set_atlas_source);
  263. ERR_FAIL_COND(p_tiles.is_empty());
  264. for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) {
  265. ERR_FAIL_COND(E->get().tile == TileSetSource::INVALID_ATLAS_COORDS);
  266. ERR_FAIL_COND(E->get().alternative < 0);
  267. }
  268. // Disconnect to changes.
  269. for (Set<TileSelection>::Element *E = tiles.front(); E; E = E->next()) {
  270. const Vector2i &coords = E->get().tile;
  271. const int &alternative = E->get().alternative;
  272. if (tile_set_atlas_source && tile_set_atlas_source->has_tile(coords) && tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
  273. TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative));
  274. if (tile_data->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
  275. tile_data->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
  276. }
  277. }
  278. }
  279. tile_set_atlas_source = p_tile_set_atlas_source;
  280. tiles = Set<TileSelection>(p_tiles);
  281. // Connect to changes.
  282. for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) {
  283. const Vector2i &coords = E->get().tile;
  284. const int &alternative = E->get().alternative;
  285. if (tile_set_atlas_source->has_tile(coords) && tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
  286. TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative));
  287. if (!tile_data->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
  288. tile_data->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
  289. }
  290. }
  291. }
  292. notify_property_list_changed();
  293. }
  294. void TileSetAtlasSourceEditor::AtlasTileProxyObject::_bind_methods() {
  295. ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
  296. }
  297. void TileSetAtlasSourceEditor::_inspector_property_selected(String p_property) {
  298. selected_property = p_property;
  299. _update_atlas_view();
  300. _update_current_tile_data_editor();
  301. }
  302. void TileSetAtlasSourceEditor::_update_tile_id_label() {
  303. if (selection.size() == 1) {
  304. TileSelection selected = selection.front()->get();
  305. tool_tile_id_label->set_text(vformat("%d, %s, %d", tile_set_atlas_source_id, selected.tile, selected.alternative));
  306. tool_tile_id_label->set_tooltip(vformat(TTR("Selected tile:\nSource: %d\nAtlas coordinates: %s\nAlternative: %d"), tile_set_atlas_source_id, selected.tile, selected.alternative));
  307. tool_tile_id_label->show();
  308. } else {
  309. tool_tile_id_label->hide();
  310. }
  311. }
  312. void TileSetAtlasSourceEditor::_update_source_inspector() {
  313. // Update the proxy object.
  314. atlas_source_proxy_object->edit(tile_set, tile_set_atlas_source, tile_set_atlas_source_id);
  315. // Update the "clear outside texture" button.
  316. tool_advanced_menu_buttom->get_popup()->set_item_disabled(0, !tile_set_atlas_source->has_tiles_outside_texture());
  317. }
  318. void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
  319. // Fix selected.
  320. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  321. TileSelection selected = E->get();
  322. if (!tile_set_atlas_source->has_tile(selected.tile) || !tile_set_atlas_source->has_alternative_tile(selected.tile, selected.alternative)) {
  323. selection.erase(E);
  324. }
  325. }
  326. // Fix hovered.
  327. if (!tile_set_atlas_source->has_tile(hovered_base_tile_coords)) {
  328. hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
  329. }
  330. Vector2i coords = Vector2i(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
  331. int alternative = hovered_alternative_tile_coords.z;
  332. if (!tile_set_atlas_source->has_tile(coords) || !tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
  333. hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
  334. }
  335. }
  336. void TileSetAtlasSourceEditor::_update_atlas_source_inspector() {
  337. // Update visibility.
  338. bool visible = tools_button_group->get_pressed_button() == tool_setup_atlas_source_button;
  339. atlas_source_inspector_label->set_visible(visible);
  340. atlas_source_inspector->set_visible(visible);
  341. }
  342. void TileSetAtlasSourceEditor::_update_tile_inspector() {
  343. // Update visibility.
  344. if (tools_button_group->get_pressed_button() == tool_select_button) {
  345. if (!selection.is_empty()) {
  346. tile_proxy_object->edit(tile_set_atlas_source, selection);
  347. }
  348. tile_inspector_label->show();
  349. tile_inspector->set_visible(!selection.is_empty());
  350. tile_inspector_no_tile_selected_label->set_visible(selection.is_empty());
  351. } else {
  352. tile_inspector_label->hide();
  353. tile_inspector->hide();
  354. tile_inspector_no_tile_selected_label->hide();
  355. }
  356. }
  357. void TileSetAtlasSourceEditor::_update_tile_data_editors() {
  358. String previously_selected;
  359. if (tile_data_editors_tree && tile_data_editors_tree->get_selected()) {
  360. previously_selected = tile_data_editors_tree->get_selected()->get_metadata(0);
  361. }
  362. tile_data_editors_tree->clear();
  363. TreeItem *root = tile_data_editors_tree->create_item();
  364. TreeItem *group;
  365. #define ADD_TILE_DATA_EDITOR_GROUP(text) \
  366. group = tile_data_editors_tree->create_item(root); \
  367. group->set_custom_bg_color(0, group_color); \
  368. group->set_selectable(0, false); \
  369. group->set_disable_folding(true); \
  370. group->set_text(0, text);
  371. TreeItem *item;
  372. #define ADD_TILE_DATA_EDITOR(parent, text, property) \
  373. item = tile_data_editors_tree->create_item(parent); \
  374. item->set_text(0, text); \
  375. item->set_metadata(0, property); \
  376. if (property == previously_selected) { \
  377. item->select(0); \
  378. }
  379. // Theming.
  380. tile_data_editors_tree->add_theme_constant_override("vseparation", 1);
  381. tile_data_editors_tree->add_theme_constant_override("hseparation", 3);
  382. Color group_color = get_theme_color(SNAME("prop_category"), SNAME("Editor"));
  383. // List of editors.
  384. // --- Rendering ---
  385. ADD_TILE_DATA_EDITOR_GROUP("Rendering");
  386. ADD_TILE_DATA_EDITOR(group, "Texture Offset", "texture_offset");
  387. if (!tile_data_editors.has("texture_offset")) {
  388. TileDataTextureOffsetEditor *tile_data_texture_offset_editor = memnew(TileDataTextureOffsetEditor);
  389. tile_data_texture_offset_editor->hide();
  390. tile_data_texture_offset_editor->setup_property_editor(Variant::VECTOR2, "texture_offset");
  391. tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  392. tile_data_texture_offset_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  393. tile_data_editors["texture_offset"] = tile_data_texture_offset_editor;
  394. }
  395. ADD_TILE_DATA_EDITOR(group, "Modulate", "modulate");
  396. if (!tile_data_editors.has("modulate")) {
  397. TileDataDefaultEditor *tile_data_modulate_editor = memnew(TileDataDefaultEditor());
  398. tile_data_modulate_editor->hide();
  399. tile_data_modulate_editor->setup_property_editor(Variant::COLOR, "modulate", "", Color(1.0, 1.0, 1.0, 1.0));
  400. tile_data_modulate_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  401. tile_data_modulate_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  402. tile_data_editors["modulate"] = tile_data_modulate_editor;
  403. }
  404. ADD_TILE_DATA_EDITOR(group, "Z Index", "z_index");
  405. if (!tile_data_editors.has("z_index")) {
  406. TileDataDefaultEditor *tile_data_z_index_editor = memnew(TileDataDefaultEditor());
  407. tile_data_z_index_editor->hide();
  408. tile_data_z_index_editor->setup_property_editor(Variant::INT, "z_index");
  409. tile_data_z_index_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  410. tile_data_z_index_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  411. tile_data_editors["z_index"] = tile_data_z_index_editor;
  412. }
  413. ADD_TILE_DATA_EDITOR(group, "Y Sort Origin", "y_sort_origin");
  414. if (!tile_data_editors.has("y_sort_origin")) {
  415. TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
  416. tile_data_y_sort_editor->hide();
  417. tile_data_y_sort_editor->setup_property_editor(Variant::INT, "y_sort_origin");
  418. tile_data_y_sort_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  419. tile_data_y_sort_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  420. tile_data_editors["y_sort_origin"] = tile_data_y_sort_editor;
  421. }
  422. for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
  423. ADD_TILE_DATA_EDITOR(group, vformat("Occlusion Layer %d", i), vformat("occlusion_layer_%d", i));
  424. if (!tile_data_editors.has(vformat("occlusion_layer_%d", i))) {
  425. TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor());
  426. tile_data_occlusion_shape_editor->hide();
  427. tile_data_occlusion_shape_editor->set_occlusion_layer(i);
  428. tile_data_occlusion_shape_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  429. tile_data_occlusion_shape_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  430. tile_data_editors[vformat("occlusion_layer_%d", i)] = tile_data_occlusion_shape_editor;
  431. }
  432. }
  433. for (int i = tile_set->get_occlusion_layers_count(); tile_data_editors.has(vformat("occlusion_layer_%d", i)); i++) {
  434. tile_data_editors[vformat("occlusion_layer_%d", i)]->queue_delete();
  435. tile_data_editors.erase(vformat("occlusion_layer_%d", i));
  436. }
  437. // --- Rendering ---
  438. ADD_TILE_DATA_EDITOR(root, "Terrains", "terrain_set");
  439. if (!tile_data_editors.has("terrain_set")) {
  440. TileDataTerrainsEditor *tile_data_terrains_editor = memnew(TileDataTerrainsEditor);
  441. tile_data_terrains_editor->hide();
  442. tile_data_terrains_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  443. tile_data_terrains_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  444. tile_data_editors["terrain_set"] = tile_data_terrains_editor;
  445. }
  446. // --- Miscellaneous ---
  447. ADD_TILE_DATA_EDITOR(root, "Probability", "probability");
  448. if (!tile_data_editors.has("probability")) {
  449. TileDataDefaultEditor *tile_data_probability_editor = memnew(TileDataDefaultEditor());
  450. tile_data_probability_editor->hide();
  451. tile_data_probability_editor->setup_property_editor(Variant::FLOAT, "probability", "", 1.0);
  452. tile_data_probability_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  453. tile_data_probability_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  454. tile_data_editors["probability"] = tile_data_probability_editor;
  455. }
  456. // --- Physics ---
  457. ADD_TILE_DATA_EDITOR_GROUP("Physics");
  458. for (int i = 0; i < tile_set->get_physics_layers_count(); i++) {
  459. ADD_TILE_DATA_EDITOR(group, vformat("Physics Layer %d", i), vformat("physics_layer_%d", i));
  460. if (!tile_data_editors.has(vformat("physics_layer_%d", i))) {
  461. TileDataCollisionEditor *tile_data_collision_editor = memnew(TileDataCollisionEditor());
  462. tile_data_collision_editor->hide();
  463. tile_data_collision_editor->set_physics_layer(i);
  464. tile_data_collision_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  465. tile_data_collision_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  466. tile_data_editors[vformat("physics_layer_%d", i)] = tile_data_collision_editor;
  467. }
  468. }
  469. for (int i = tile_set->get_physics_layers_count(); tile_data_editors.has(vformat("physics_layer_%d", i)); i++) {
  470. tile_data_editors[vformat("physics_layer_%d", i)]->queue_delete();
  471. tile_data_editors.erase(vformat("physics_layer_%d", i));
  472. }
  473. // --- Navigation ---
  474. ADD_TILE_DATA_EDITOR_GROUP("Navigation");
  475. for (int i = 0; i < tile_set->get_navigation_layers_count(); i++) {
  476. ADD_TILE_DATA_EDITOR(group, vformat("Navigation Layer %d", i), vformat("navigation_layer_%d", i));
  477. if (!tile_data_editors.has(vformat("navigation_layer_%d", i))) {
  478. TileDataNavigationEditor *tile_data_navigation_editor = memnew(TileDataNavigationEditor());
  479. tile_data_navigation_editor->hide();
  480. tile_data_navigation_editor->set_navigation_layer(i);
  481. tile_data_navigation_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  482. tile_data_navigation_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  483. tile_data_editors[vformat("navigation_layer_%d", i)] = tile_data_navigation_editor;
  484. }
  485. }
  486. for (int i = tile_set->get_navigation_layers_count(); tile_data_editors.has(vformat("navigation_layer_%d", i)); i++) {
  487. tile_data_editors[vformat("navigation_layer_%d", i)]->queue_delete();
  488. tile_data_editors.erase(vformat("navigation_layer_%d", i));
  489. }
  490. // --- Custom Data ---
  491. ADD_TILE_DATA_EDITOR_GROUP("Custom Data");
  492. for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) {
  493. if (tile_set->get_custom_data_name(i).is_empty()) {
  494. ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), vformat("custom_data_%d", i));
  495. } else {
  496. ADD_TILE_DATA_EDITOR(group, tile_set->get_custom_data_name(i), vformat("custom_data_%d", i));
  497. }
  498. if (!tile_data_editors.has(vformat("custom_data_%d", i))) {
  499. TileDataDefaultEditor *tile_data_custom_data_editor = memnew(TileDataDefaultEditor());
  500. tile_data_custom_data_editor->hide();
  501. tile_data_custom_data_editor->setup_property_editor(tile_set->get_custom_data_type(i), vformat("custom_data_%d", i), tile_set->get_custom_data_name(i));
  502. tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::update));
  503. tile_data_custom_data_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::update));
  504. tile_data_editors[vformat("custom_data_%d", i)] = tile_data_custom_data_editor;
  505. }
  506. }
  507. for (int i = tile_set->get_custom_data_layers_count(); tile_data_editors.has(vformat("custom_data_%d", i)); i++) {
  508. tile_data_editors[vformat("custom_data_%d", i)]->queue_delete();
  509. tile_data_editors.erase(vformat("custom_data_%d", i));
  510. }
  511. #undef ADD_TILE_DATA_EDITOR_GROUP
  512. #undef ADD_TILE_DATA_EDITOR
  513. // Add tile data editors as children.
  514. for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) {
  515. // Tile Data Editor.
  516. TileDataEditor *tile_data_editor = E->get();
  517. if (!tile_data_editor->is_inside_tree()) {
  518. tile_data_painting_editor_container->add_child(tile_data_editor);
  519. }
  520. tile_data_editor->set_tile_set(tile_set);
  521. // Toolbar.
  522. Control *toolbar = tile_data_editor->get_toolbar();
  523. if (!toolbar->is_inside_tree()) {
  524. tool_settings_tile_data_toolbar_container->add_child(toolbar);
  525. }
  526. toolbar->hide();
  527. }
  528. // Update visibility.
  529. bool is_visible = tools_button_group->get_pressed_button() == tool_paint_button;
  530. tile_data_editor_dropdown_button->set_visible(is_visible);
  531. tile_data_editor_dropdown_button->set_text(TTR("Select a property editor"));
  532. tile_data_editors_label->set_visible(is_visible);
  533. }
  534. void TileSetAtlasSourceEditor::_update_current_tile_data_editor() {
  535. // Find the property to use.
  536. String property;
  537. if (tools_button_group->get_pressed_button() == tool_select_button && tile_inspector->is_visible() && !tile_inspector->get_selected_path().is_empty()) {
  538. Vector<String> components = tile_inspector->get_selected_path().split("/");
  539. if (components.size() >= 1) {
  540. property = components[0];
  541. // Workaround for terrains as they don't have a common first component.
  542. if (property.begins_with("terrains_")) {
  543. property = "terrain_set";
  544. }
  545. }
  546. } else if (tools_button_group->get_pressed_button() == tool_paint_button && tile_data_editors_tree->get_selected()) {
  547. property = tile_data_editors_tree->get_selected()->get_metadata(0);
  548. tile_data_editor_dropdown_button->set_text(tile_data_editors_tree->get_selected()->get_text(0));
  549. }
  550. // Hide all editors but the current one.
  551. for (Map<String, TileDataEditor *>::Element *E = tile_data_editors.front(); E; E = E->next()) {
  552. E->get()->hide();
  553. E->get()->get_toolbar()->hide();
  554. }
  555. if (tile_data_editors.has(property)) {
  556. current_tile_data_editor = tile_data_editors[property];
  557. } else {
  558. current_tile_data_editor = nullptr;
  559. }
  560. // Get the correct editor for the TileData's property.
  561. if (current_tile_data_editor) {
  562. current_tile_data_editor_toolbar = current_tile_data_editor->get_toolbar();
  563. current_property = property;
  564. current_tile_data_editor->set_visible(tools_button_group->get_pressed_button() == tool_paint_button);
  565. current_tile_data_editor_toolbar->set_visible(tools_button_group->get_pressed_button() == tool_paint_button);
  566. }
  567. }
  568. void TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_draw() {
  569. if (!has_theme_icon(SNAME("arrow"), SNAME("OptionButton"))) {
  570. return;
  571. }
  572. RID ci = tile_data_editor_dropdown_button->get_canvas_item();
  573. Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"), SNAME("OptionButton"));
  574. Color clr = Color(1, 1, 1);
  575. if (get_theme_constant(SNAME("modulate_arrow"))) {
  576. switch (tile_data_editor_dropdown_button->get_draw_mode()) {
  577. case BaseButton::DRAW_PRESSED:
  578. clr = get_theme_color(SNAME("font_pressed_color"));
  579. break;
  580. case BaseButton::DRAW_HOVER:
  581. clr = get_theme_color(SNAME("font_hover_color"));
  582. break;
  583. case BaseButton::DRAW_DISABLED:
  584. clr = get_theme_color(SNAME("font_disabled_color"));
  585. break;
  586. default:
  587. clr = get_theme_color(SNAME("font_color"));
  588. }
  589. }
  590. Size2 size = tile_data_editor_dropdown_button->get_size();
  591. Point2 ofs;
  592. if (is_layout_rtl()) {
  593. ofs = Point2(get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
  594. } else {
  595. ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin"), SNAME("OptionButton")), int(Math::abs((size.height - arrow->get_height()) / 2)));
  596. }
  597. arrow->draw(ci, ofs, clr);
  598. }
  599. void TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed() {
  600. Size2 size = tile_data_editor_dropdown_button->get_size();
  601. tile_data_editors_popup->set_position(tile_data_editor_dropdown_button->get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
  602. tile_data_editors_popup->set_size(Size2(size.width, 0));
  603. tile_data_editors_popup->popup();
  604. }
  605. void TileSetAtlasSourceEditor::_tile_data_editors_tree_selected() {
  606. tile_data_editors_popup->call_deferred(SNAME("hide"));
  607. _update_current_tile_data_editor();
  608. tile_atlas_control->update();
  609. tile_atlas_control_unscaled->update();
  610. alternative_tiles_control->update();
  611. alternative_tiles_control_unscaled->update();
  612. }
  613. void TileSetAtlasSourceEditor::_update_atlas_view() {
  614. // Update the atlas display.
  615. tile_atlas_view->set_atlas_source(*tile_set, tile_set_atlas_source, tile_set_atlas_source_id);
  616. // Create a bunch of buttons to add alternative tiles.
  617. for (int i = 0; i < alternative_tiles_control->get_child_count(); i++) {
  618. alternative_tiles_control->get_child(i)->queue_delete();
  619. }
  620. Vector2i pos;
  621. Vector2 texture_region_base_size = tile_set_atlas_source->get_texture_region_size();
  622. int texture_region_base_size_min = MIN(texture_region_base_size.x, texture_region_base_size.y);
  623. for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
  624. Vector2i tile_id = tile_set_atlas_source->get_tile_id(i);
  625. int alternative_count = tile_set_atlas_source->get_alternative_tiles_count(tile_id);
  626. if (alternative_count > 1) {
  627. // Compute the right extremity of alternative.
  628. int y_increment = 0;
  629. pos.x = 0;
  630. for (int j = 1; j < alternative_count; j++) {
  631. int alternative_id = tile_set_atlas_source->get_alternative_tile_id(tile_id, j);
  632. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(tile_id, alternative_id);
  633. pos.x = MAX(pos.x, rect.get_end().x);
  634. y_increment = MAX(y_increment, rect.size.y);
  635. }
  636. // Create and position the button.
  637. Button *button = memnew(Button);
  638. alternative_tiles_control->add_child(button);
  639. button->set_flat(true);
  640. button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
  641. button->add_theme_style_override("normal", memnew(StyleBoxEmpty));
  642. button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
  643. button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
  644. button->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
  645. button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
  646. button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min)));
  647. button->set_expand_icon(true);
  648. pos.y += y_increment;
  649. }
  650. }
  651. tile_atlas_view->set_padding(Side::SIDE_RIGHT, texture_region_base_size_min);
  652. // Redraw everything.
  653. tile_atlas_control->update();
  654. tile_atlas_control_unscaled->update();
  655. alternative_tiles_control->update();
  656. alternative_tiles_control_unscaled->update();
  657. tile_atlas_view->update();
  658. // Synchronize atlas view.
  659. TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view);
  660. }
  661. void TileSetAtlasSourceEditor::_update_toolbar() {
  662. // Show the tools and settings.
  663. if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
  664. if (current_tile_data_editor_toolbar) {
  665. current_tile_data_editor_toolbar->hide();
  666. }
  667. tool_settings_vsep->show();
  668. tools_settings_erase_button->show();
  669. tool_advanced_menu_buttom->show();
  670. } else if (tools_button_group->get_pressed_button() == tool_select_button) {
  671. if (current_tile_data_editor_toolbar) {
  672. current_tile_data_editor_toolbar->hide();
  673. }
  674. tool_settings_vsep->hide();
  675. tools_settings_erase_button->hide();
  676. tool_advanced_menu_buttom->hide();
  677. } else if (tools_button_group->get_pressed_button() == tool_paint_button) {
  678. if (current_tile_data_editor_toolbar) {
  679. current_tile_data_editor_toolbar->show();
  680. }
  681. tool_settings_vsep->hide();
  682. tools_settings_erase_button->hide();
  683. tool_advanced_menu_buttom->hide();
  684. }
  685. }
  686. void TileSetAtlasSourceEditor::_tile_atlas_control_mouse_exited() {
  687. hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
  688. tile_atlas_control->update();
  689. tile_atlas_control_unscaled->update();
  690. tile_atlas_view->update();
  691. }
  692. void TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed() {
  693. tile_atlas_control->update();
  694. tile_atlas_control_unscaled->update();
  695. }
  696. void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEvent> &p_event) {
  697. // Update the hovered coords.
  698. hovered_base_tile_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  699. // Forward the event to the current tile data editor if we are in the painting mode.
  700. if (tools_button_group->get_pressed_button() == tool_paint_button) {
  701. if (current_tile_data_editor) {
  702. current_tile_data_editor->forward_painting_atlas_gui_input(tile_atlas_view, tile_set_atlas_source, p_event);
  703. }
  704. // Update only what's needed.
  705. tile_set_atlas_source_changed_needs_update = false;
  706. tile_atlas_control->update();
  707. tile_atlas_control_unscaled->update();
  708. alternative_tiles_control->update();
  709. alternative_tiles_control_unscaled->update();
  710. tile_atlas_view->update();
  711. return;
  712. } else {
  713. // Handle the event.
  714. Ref<InputEventMouseMotion> mm = p_event;
  715. if (mm.is_valid()) {
  716. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  717. Vector2i last_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_last_mouse_pos);
  718. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  719. Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
  720. if (drag_type == DRAG_TYPE_NONE) {
  721. if (selection.size() == 1) {
  722. // Change the cursor depending on the hovered thing.
  723. TileSelection selected = selection.front()->get();
  724. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
  725. Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
  726. Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
  727. Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
  728. Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
  729. Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
  730. const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
  731. const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
  732. CursorShape cursor_shape = CURSOR_ARROW;
  733. bool can_grow[4];
  734. for (int i = 0; i < 4; i++) {
  735. can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
  736. can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
  737. }
  738. for (int i = 0; i < 4; i++) {
  739. Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
  740. if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
  741. cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
  742. }
  743. Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
  744. if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
  745. cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
  746. }
  747. }
  748. tile_atlas_control->set_default_cursor_shape(cursor_shape);
  749. }
  750. }
  751. } else if (drag_type == DRAG_TYPE_CREATE_BIG_TILE) {
  752. // Create big tile.
  753. new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  754. Rect2i new_rect = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  755. new_rect.size += Vector2i(1, 1);
  756. // Check if the new tile can fit in the new rect.
  757. if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
  758. // Move and resize the tile.
  759. tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
  760. drag_current_tile = new_rect.position;
  761. }
  762. } else if (drag_type == DRAG_TYPE_CREATE_TILES) {
  763. // Create tiles.
  764. last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  765. new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  766. Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
  767. for (int i = 0; i < line.size(); i++) {
  768. if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) {
  769. tile_set_atlas_source->create_tile(line[i]);
  770. drag_modified_tiles.insert(line[i]);
  771. }
  772. }
  773. drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
  774. } else if (drag_type == DRAG_TYPE_REMOVE_TILES) {
  775. // Remove tiles.
  776. last_base_tiles_coords = last_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  777. new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  778. Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
  779. for (int i = 0; i < line.size(); i++) {
  780. Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]);
  781. if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
  782. drag_modified_tiles.insert(base_tile_coords);
  783. }
  784. }
  785. drag_last_mouse_pos = tile_atlas_control->get_local_mouse_position();
  786. } else if (drag_type == DRAG_TYPE_MOVE_TILE) {
  787. // Move tile.
  788. Vector2 mouse_offset = (Vector2(tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile)) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
  789. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position() - mouse_offset);
  790. coords = coords.max(Vector2i(0, 0)).min(grid_size - Vector2i(1, 1));
  791. if (drag_current_tile != coords && tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, coords)) {
  792. tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, coords);
  793. selection.clear();
  794. selection.insert({ coords, 0 });
  795. drag_current_tile = coords;
  796. // Update only what's needed.
  797. tile_set_atlas_source_changed_needs_update = false;
  798. _update_tile_inspector();
  799. _update_atlas_view();
  800. _update_tile_id_label();
  801. _update_current_tile_data_editor();
  802. }
  803. } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) {
  804. if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) {
  805. drag_type = DRAG_TYPE_NONE;
  806. }
  807. } else if (drag_type >= DRAG_TYPE_RESIZE_TOP_LEFT && drag_type <= DRAG_TYPE_RESIZE_LEFT) {
  808. // Resizing a tile.
  809. new_base_tiles_coords = new_base_tiles_coords.max(Vector2i(-1, -1)).min(grid_size);
  810. Rect2i old_rect = Rect2i(drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
  811. Rect2i new_rect = old_rect;
  812. if (drag_type == DRAG_TYPE_RESIZE_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT) {
  813. new_rect.position.x = MIN(new_base_tiles_coords.x + 1, old_rect.get_end().x - 1);
  814. new_rect.size.x = old_rect.get_end().x - new_rect.position.x;
  815. }
  816. if (drag_type == DRAG_TYPE_RESIZE_TOP || drag_type == DRAG_TYPE_RESIZE_TOP_LEFT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT) {
  817. new_rect.position.y = MIN(new_base_tiles_coords.y + 1, old_rect.get_end().y - 1);
  818. new_rect.size.y = old_rect.get_end().y - new_rect.position.y;
  819. }
  820. if (drag_type == DRAG_TYPE_RESIZE_RIGHT || drag_type == DRAG_TYPE_RESIZE_TOP_RIGHT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
  821. new_rect.set_end(Vector2i(MAX(new_base_tiles_coords.x, old_rect.position.x + 1), new_rect.get_end().y));
  822. }
  823. if (drag_type == DRAG_TYPE_RESIZE_BOTTOM || drag_type == DRAG_TYPE_RESIZE_BOTTOM_LEFT || drag_type == DRAG_TYPE_RESIZE_BOTTOM_RIGHT) {
  824. new_rect.set_end(Vector2i(new_rect.get_end().x, MAX(new_base_tiles_coords.y, old_rect.position.y + 1)));
  825. }
  826. if (tile_set_atlas_source->can_move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size)) {
  827. tile_set_atlas_source->move_tile_in_atlas(drag_current_tile, new_rect.position, new_rect.size);
  828. selection.clear();
  829. selection.insert({ new_rect.position, 0 });
  830. drag_current_tile = new_rect.position;
  831. // Update only what's needed.
  832. tile_set_atlas_source_changed_needs_update = false;
  833. _update_tile_inspector();
  834. _update_atlas_view();
  835. _update_tile_id_label();
  836. _update_current_tile_data_editor();
  837. }
  838. }
  839. // Redraw for the hovered tile.
  840. tile_atlas_control->update();
  841. tile_atlas_control_unscaled->update();
  842. alternative_tiles_control->update();
  843. alternative_tiles_control_unscaled->update();
  844. tile_atlas_view->update();
  845. return;
  846. }
  847. Ref<InputEventMouseButton> mb = p_event;
  848. if (mb.is_valid()) {
  849. Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
  850. if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
  851. if (mb->is_pressed()) {
  852. // Left click pressed.
  853. if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
  854. if (tools_settings_erase_button->is_pressed()) {
  855. // Erasing
  856. if (mb->is_ctrl_pressed() || mb->is_shift_pressed()) {
  857. // Remove tiles using rect.
  858. // Setup the dragging info.
  859. drag_type = DRAG_TYPE_REMOVE_TILES_USING_RECT;
  860. drag_start_mouse_pos = mouse_local_pos;
  861. drag_last_mouse_pos = drag_start_mouse_pos;
  862. } else {
  863. // Remove tiles.
  864. // Setup the dragging info.
  865. drag_type = DRAG_TYPE_REMOVE_TILES;
  866. drag_start_mouse_pos = mouse_local_pos;
  867. drag_last_mouse_pos = drag_start_mouse_pos;
  868. // Remove a first tile.
  869. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  870. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  871. coords = tile_set_atlas_source->get_tile_at_coords(coords);
  872. }
  873. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  874. drag_modified_tiles.insert(coords);
  875. }
  876. }
  877. } else {
  878. // Creating
  879. if (mb->is_shift_pressed()) {
  880. // Create a big tile.
  881. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
  882. if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
  883. // Setup the dragging info, only if we start on an empty tile.
  884. drag_type = DRAG_TYPE_CREATE_BIG_TILE;
  885. drag_start_mouse_pos = mouse_local_pos;
  886. drag_last_mouse_pos = drag_start_mouse_pos;
  887. drag_current_tile = coords;
  888. // Create a tile.
  889. tile_set_atlas_source->create_tile(coords);
  890. }
  891. } else if (mb->is_ctrl_pressed()) {
  892. // Create tiles using rect.
  893. drag_type = DRAG_TYPE_CREATE_TILES_USING_RECT;
  894. drag_start_mouse_pos = mouse_local_pos;
  895. drag_last_mouse_pos = drag_start_mouse_pos;
  896. } else {
  897. // Create tiles.
  898. // Setup the dragging info.
  899. drag_type = DRAG_TYPE_CREATE_TILES;
  900. drag_start_mouse_pos = mouse_local_pos;
  901. drag_last_mouse_pos = drag_start_mouse_pos;
  902. // Create a first tile if needed.
  903. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  904. if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
  905. tile_set_atlas_source->create_tile(coords);
  906. drag_modified_tiles.insert(coords);
  907. }
  908. }
  909. }
  910. } else if (tools_button_group->get_pressed_button() == tool_select_button) {
  911. // Dragging a handle.
  912. drag_type = DRAG_TYPE_NONE;
  913. if (selection.size() == 1) {
  914. TileSelection selected = selection.front()->get();
  915. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
  916. Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
  917. Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
  918. Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
  919. Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
  920. const Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
  921. const Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
  922. CursorShape cursor_shape = CURSOR_ARROW;
  923. bool can_grow[4];
  924. for (int i = 0; i < 4; i++) {
  925. can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
  926. can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
  927. }
  928. for (int i = 0; i < 4; i++) {
  929. Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
  930. if (can_grow[i] && can_grow[(i + 3) % 4] && Rect2(pos, zoomed_size).has_point(mouse_local_pos)) {
  931. drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP_LEFT + i * 2);
  932. drag_start_mouse_pos = mouse_local_pos;
  933. drag_last_mouse_pos = drag_start_mouse_pos;
  934. drag_current_tile = selected.tile;
  935. drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
  936. cursor_shape = (i % 2) ? CURSOR_BDIAGSIZE : CURSOR_FDIAGSIZE;
  937. }
  938. Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
  939. if (can_grow[i] && Rect2((pos + next_pos) / 2.0, zoomed_size).has_point(mouse_local_pos)) {
  940. drag_type = (DragType)((int)DRAG_TYPE_RESIZE_TOP + i * 2);
  941. drag_start_mouse_pos = mouse_local_pos;
  942. drag_last_mouse_pos = drag_start_mouse_pos;
  943. drag_current_tile = selected.tile;
  944. drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
  945. cursor_shape = (i % 2) ? CURSOR_HSIZE : CURSOR_VSIZE;
  946. }
  947. }
  948. tile_atlas_control->set_default_cursor_shape(cursor_shape);
  949. }
  950. }
  951. // Selecting then dragging a tile.
  952. if (drag_type == DRAG_TYPE_NONE) {
  953. TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE };
  954. Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
  955. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  956. coords = tile_set_atlas_source->get_tile_at_coords(coords);
  957. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  958. selected = { coords, 0 };
  959. }
  960. }
  961. bool shift = mb->is_shift_pressed();
  962. if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
  963. // Start move dragging.
  964. drag_type = DRAG_TYPE_MOVE_TILE;
  965. drag_start_mouse_pos = mouse_local_pos;
  966. drag_last_mouse_pos = drag_start_mouse_pos;
  967. drag_current_tile = selected.tile;
  968. drag_start_tile_shape = Rect2i(selected.tile, tile_set_atlas_source->get_tile_size_in_atlas(selected.tile));
  969. tile_atlas_control->set_default_cursor_shape(CURSOR_MOVE);
  970. } else {
  971. // Start selection dragging.
  972. drag_type = DRAG_TYPE_RECT_SELECT;
  973. drag_start_mouse_pos = mouse_local_pos;
  974. drag_last_mouse_pos = drag_start_mouse_pos;
  975. }
  976. }
  977. }
  978. } else {
  979. // Left click released.
  980. _end_dragging();
  981. }
  982. tile_atlas_control->update();
  983. tile_atlas_control_unscaled->update();
  984. alternative_tiles_control->update();
  985. alternative_tiles_control_unscaled->update();
  986. tile_atlas_view->update();
  987. return;
  988. } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
  989. // Right click pressed.
  990. if (mb->is_pressed()) {
  991. drag_type = DRAG_TYPE_MAY_POPUP_MENU;
  992. drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position();
  993. } else {
  994. // Right click released.
  995. _end_dragging();
  996. }
  997. tile_atlas_control->update();
  998. tile_atlas_control_unscaled->update();
  999. alternative_tiles_control->update();
  1000. alternative_tiles_control_unscaled->update();
  1001. tile_atlas_view->update();
  1002. return;
  1003. }
  1004. }
  1005. }
  1006. }
  1007. void TileSetAtlasSourceEditor::_end_dragging() {
  1008. switch (drag_type) {
  1009. case DRAG_TYPE_CREATE_TILES:
  1010. undo_redo->create_action(TTR("Create tiles"));
  1011. for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) {
  1012. undo_redo->add_do_method(tile_set_atlas_source, "create_tile", E->get());
  1013. undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", E->get());
  1014. }
  1015. undo_redo->commit_action(false);
  1016. break;
  1017. case DRAG_TYPE_CREATE_BIG_TILE:
  1018. undo_redo->create_action(TTR("Create a tile"));
  1019. undo_redo->add_do_method(tile_set_atlas_source, "create_tile", drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
  1020. undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", drag_current_tile);
  1021. undo_redo->commit_action(false);
  1022. break;
  1023. case DRAG_TYPE_REMOVE_TILES: {
  1024. List<PropertyInfo> list;
  1025. tile_set_atlas_source->get_property_list(&list);
  1026. Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source);
  1027. undo_redo->create_action(TTR("Remove tiles"));
  1028. for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) {
  1029. Vector2i coords = E->get();
  1030. undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", coords);
  1031. undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", coords);
  1032. if (per_tile.has(coords)) {
  1033. for (List<const PropertyInfo *>::Element *E_property = per_tile[coords].front(); E_property; E_property = E_property->next()) {
  1034. String property = E_property->get()->name;
  1035. Variant value = tile_set_atlas_source->get(property);
  1036. if (value.get_type() != Variant::NIL) {
  1037. undo_redo->add_undo_method(tile_set_atlas_source, "set", E_property->get()->name, value);
  1038. }
  1039. }
  1040. }
  1041. }
  1042. undo_redo->commit_action();
  1043. } break;
  1044. case DRAG_TYPE_CREATE_TILES_USING_RECT: {
  1045. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1046. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1047. Rect2i area = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1048. area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size()));
  1049. undo_redo->create_action(TTR("Create tiles"));
  1050. for (int x = area.get_position().x; x < area.get_end().x; x++) {
  1051. for (int y = area.get_position().y; y < area.get_end().y; y++) {
  1052. Vector2i coords = Vector2i(x, y);
  1053. if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
  1054. undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords);
  1055. undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords);
  1056. }
  1057. }
  1058. }
  1059. undo_redo->commit_action();
  1060. } break;
  1061. case DRAG_TYPE_REMOVE_TILES_USING_RECT: {
  1062. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1063. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1064. Rect2i area = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1065. area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size()));
  1066. List<PropertyInfo> list;
  1067. tile_set_atlas_source->get_property_list(&list);
  1068. Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source);
  1069. Set<Vector2i> to_delete;
  1070. for (int x = area.get_position().x; x < area.get_end().x; x++) {
  1071. for (int y = area.get_position().y; y < area.get_end().y; y++) {
  1072. Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
  1073. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1074. to_delete.insert(coords);
  1075. }
  1076. }
  1077. }
  1078. undo_redo->create_action(TTR("Remove tiles"));
  1079. undo_redo->add_do_method(this, "_set_selection_from_array", Array());
  1080. for (Set<Vector2i>::Element *E = to_delete.front(); E; E = E->next()) {
  1081. Vector2i coords = E->get();
  1082. undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", coords);
  1083. undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", coords);
  1084. if (per_tile.has(coords)) {
  1085. for (List<const PropertyInfo *>::Element *E_property = per_tile[coords].front(); E_property; E_property = E_property->next()) {
  1086. String property = E_property->get()->name;
  1087. Variant value = tile_set_atlas_source->get(property);
  1088. if (value.get_type() != Variant::NIL) {
  1089. undo_redo->add_undo_method(tile_set_atlas_source, "set", E_property->get()->name, value);
  1090. }
  1091. }
  1092. }
  1093. }
  1094. undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
  1095. undo_redo->commit_action();
  1096. } break;
  1097. case DRAG_TYPE_MOVE_TILE:
  1098. if (drag_current_tile != drag_start_tile_shape.position) {
  1099. undo_redo->create_action(TTR("Move a tile"));
  1100. undo_redo->add_do_method(tile_set_atlas_source, "move_tile_in_atlas", drag_start_tile_shape.position, drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
  1101. undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
  1102. undo_redo->add_undo_method(tile_set_atlas_source, "move_tile_in_atlas", drag_current_tile, drag_start_tile_shape.position, drag_start_tile_shape.size);
  1103. Array array;
  1104. array.push_back(drag_start_tile_shape.position);
  1105. array.push_back(0);
  1106. undo_redo->add_undo_method(this, "_set_selection_from_array", array);
  1107. undo_redo->commit_action(false);
  1108. }
  1109. break;
  1110. case DRAG_TYPE_RECT_SELECT: {
  1111. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1112. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1113. ERR_FAIL_COND(start_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
  1114. ERR_FAIL_COND(new_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
  1115. Rect2i region = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1116. region.size += Vector2i(1, 1);
  1117. undo_redo->create_action(TTR("Select tiles"));
  1118. undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
  1119. // Determine if we clear, then add or remove to the selection.
  1120. bool add_to_selection = true;
  1121. if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
  1122. Vector2i coords = tile_set_atlas_source->get_tile_at_coords(start_base_tiles_coords);
  1123. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1124. if (selection.has({ coords, 0 })) {
  1125. add_to_selection = false;
  1126. }
  1127. }
  1128. } else {
  1129. selection.clear();
  1130. }
  1131. // Modify the selection.
  1132. for (int x = region.position.x; x < region.get_end().x; x++) {
  1133. for (int y = region.position.y; y < region.get_end().y; y++) {
  1134. Vector2i coords = Vector2i(x, y);
  1135. coords = tile_set_atlas_source->get_tile_at_coords(coords);
  1136. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1137. if (add_to_selection && !selection.has({ coords, 0 })) {
  1138. selection.insert({ coords, 0 });
  1139. } else if (!add_to_selection && selection.has({ coords, 0 })) {
  1140. selection.erase({ coords, 0 });
  1141. }
  1142. }
  1143. }
  1144. }
  1145. _update_tile_inspector();
  1146. _update_tile_id_label();
  1147. _update_current_tile_data_editor();
  1148. undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
  1149. undo_redo->commit_action(false);
  1150. } break;
  1151. case DRAG_TYPE_MAY_POPUP_MENU: {
  1152. Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
  1153. TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 };
  1154. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1155. selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile);
  1156. }
  1157. // Set the selection if needed.
  1158. if (selection.size() <= 1) {
  1159. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1160. undo_redo->create_action(TTR("Select tiles"));
  1161. undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
  1162. selection.clear();
  1163. selection.insert(selected);
  1164. undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
  1165. undo_redo->commit_action(false);
  1166. _update_tile_inspector();
  1167. _update_tile_id_label();
  1168. _update_current_tile_data_editor();
  1169. }
  1170. }
  1171. // Pops up the correct menu, depending on whether we have a tile or not.
  1172. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
  1173. // We have a tile.
  1174. menu_option_coords = selected.tile;
  1175. menu_option_alternative = 0;
  1176. base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
  1177. } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1178. // We don't have a tile, but can create one.
  1179. menu_option_coords = hovered_base_tile_coords;
  1180. menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
  1181. empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
  1182. }
  1183. } break;
  1184. case DRAG_TYPE_RESIZE_TOP_LEFT:
  1185. case DRAG_TYPE_RESIZE_TOP:
  1186. case DRAG_TYPE_RESIZE_TOP_RIGHT:
  1187. case DRAG_TYPE_RESIZE_RIGHT:
  1188. case DRAG_TYPE_RESIZE_BOTTOM_RIGHT:
  1189. case DRAG_TYPE_RESIZE_BOTTOM:
  1190. case DRAG_TYPE_RESIZE_BOTTOM_LEFT:
  1191. case DRAG_TYPE_RESIZE_LEFT:
  1192. if (drag_start_tile_shape != Rect2i(drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile))) {
  1193. undo_redo->create_action(TTR("Resize a tile"));
  1194. undo_redo->add_do_method(tile_set_atlas_source, "move_tile_in_atlas", drag_start_tile_shape.position, drag_current_tile, tile_set_atlas_source->get_tile_size_in_atlas(drag_current_tile));
  1195. undo_redo->add_do_method(this, "_set_selection_from_array", _get_selection_as_array());
  1196. undo_redo->add_undo_method(tile_set_atlas_source, "move_tile_in_atlas", drag_current_tile, drag_start_tile_shape.position, drag_start_tile_shape.size);
  1197. Array array;
  1198. array.push_back(drag_start_tile_shape.position);
  1199. array.push_back(0);
  1200. undo_redo->add_undo_method(this, "_set_selection_from_array", array);
  1201. undo_redo->commit_action(false);
  1202. }
  1203. break;
  1204. default:
  1205. break;
  1206. }
  1207. drag_modified_tiles.clear();
  1208. drag_type = DRAG_TYPE_NONE;
  1209. tile_atlas_control->set_default_cursor_shape(CURSOR_ARROW);
  1210. }
  1211. Map<Vector2i, List<const PropertyInfo *>> TileSetAtlasSourceEditor::_group_properties_per_tiles(const List<PropertyInfo> &r_list, const TileSetAtlasSource *p_atlas) {
  1212. // Group properties per tile.
  1213. Map<Vector2i, List<const PropertyInfo *>> per_tile;
  1214. for (const List<PropertyInfo>::Element *E_property = r_list.front(); E_property; E_property = E_property->next()) {
  1215. Vector<String> components = String(E_property->get().name).split("/", true, 1);
  1216. if (components.size() >= 1) {
  1217. Vector<String> coord_arr = components[0].split(":");
  1218. if (coord_arr.size() == 2 && coord_arr[0].is_valid_int() && coord_arr[1].is_valid_int()) {
  1219. Vector2i coords = Vector2i(coord_arr[0].to_int(), coord_arr[1].to_int());
  1220. per_tile[coords].push_back(&(E_property->get()));
  1221. }
  1222. }
  1223. }
  1224. return per_tile;
  1225. }
  1226. void TileSetAtlasSourceEditor::_menu_option(int p_option) {
  1227. switch (p_option) {
  1228. case TILE_DELETE: {
  1229. List<PropertyInfo> list;
  1230. tile_set_atlas_source->get_property_list(&list);
  1231. Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source);
  1232. undo_redo->create_action(TTR("Remove tile"));
  1233. // Remove tiles
  1234. Set<Vector2i> removed;
  1235. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1236. TileSelection selected = E->get();
  1237. if (selected.alternative == 0) {
  1238. // Remove a tile.
  1239. undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", selected.tile);
  1240. undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", selected.tile);
  1241. removed.insert(selected.tile);
  1242. if (per_tile.has(selected.tile)) {
  1243. for (List<const PropertyInfo *>::Element *E_property = per_tile[selected.tile].front(); E_property; E_property = E_property->next()) {
  1244. String property = E_property->get()->name;
  1245. Variant value = tile_set_atlas_source->get(property);
  1246. if (value.get_type() != Variant::NIL) {
  1247. undo_redo->add_undo_method(tile_set_atlas_source, "set", E_property->get()->name, value);
  1248. }
  1249. }
  1250. }
  1251. }
  1252. }
  1253. // Remove alternatives
  1254. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1255. TileSelection selected = E->get();
  1256. if (selected.alternative > 0 && !removed.has(selected.tile)) {
  1257. // Remove an alternative tile.
  1258. undo_redo->add_do_method(tile_set_atlas_source, "remove_alternative_tile", selected.tile, selected.alternative);
  1259. undo_redo->add_undo_method(tile_set_atlas_source, "create_alternative_tile", selected.tile, selected.alternative);
  1260. if (per_tile.has(selected.tile)) {
  1261. for (List<const PropertyInfo *>::Element *E_property = per_tile[selected.tile].front(); E_property; E_property = E_property->next()) {
  1262. Vector<String> components = E_property->get()->name.split("/", true, 2);
  1263. if (components.size() >= 2 && components[1].is_valid_int() && components[1].to_int() == selected.alternative) {
  1264. String property = E_property->get()->name;
  1265. Variant value = tile_set_atlas_source->get(property);
  1266. if (value.get_type() != Variant::NIL) {
  1267. undo_redo->add_undo_method(tile_set_atlas_source, "set", E_property->get()->name, value);
  1268. }
  1269. }
  1270. }
  1271. }
  1272. }
  1273. }
  1274. undo_redo->commit_action();
  1275. _update_fix_selected_and_hovered_tiles();
  1276. _update_tile_id_label();
  1277. } break;
  1278. case TILE_CREATE: {
  1279. undo_redo->create_action(TTR("Create a tile"));
  1280. undo_redo->add_do_method(tile_set_atlas_source, "create_tile", menu_option_coords);
  1281. Array array;
  1282. array.push_back(menu_option_coords);
  1283. array.push_back(0);
  1284. undo_redo->add_do_method(this, "_set_selection_from_array", array);
  1285. undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", menu_option_coords);
  1286. undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
  1287. undo_redo->commit_action();
  1288. _update_tile_id_label();
  1289. } break;
  1290. case TILE_CREATE_ALTERNATIVE: {
  1291. undo_redo->create_action(TTR("Create tile alternatives"));
  1292. Array array;
  1293. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1294. if (E->get().alternative == 0) {
  1295. int next_id = tile_set_atlas_source->get_next_alternative_tile_id(E->get().tile);
  1296. undo_redo->add_do_method(tile_set_atlas_source, "create_alternative_tile", E->get().tile, next_id);
  1297. array.push_back(E->get().tile);
  1298. array.push_back(next_id);
  1299. undo_redo->add_undo_method(tile_set_atlas_source, "remove_alternative_tile", E->get().tile, next_id);
  1300. }
  1301. }
  1302. undo_redo->add_do_method(this, "_set_selection_from_array", array);
  1303. undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
  1304. undo_redo->commit_action();
  1305. _update_tile_id_label();
  1306. } break;
  1307. case ADVANCED_CLEANUP_TILES_OUTSIDE_TEXTURE: {
  1308. tile_set_atlas_source->clear_tiles_outside_texture();
  1309. } break;
  1310. case ADVANCED_AUTO_CREATE_TILES: {
  1311. _auto_create_tiles();
  1312. } break;
  1313. case ADVANCED_AUTO_REMOVE_TILES: {
  1314. _auto_remove_tiles();
  1315. } break;
  1316. }
  1317. }
  1318. void TileSetAtlasSourceEditor::_unhandled_key_input(const Ref<InputEvent> &p_event) {
  1319. // Check for shortcuts.
  1320. if (ED_IS_SHORTCUT("tiles_editor/delete_tile", p_event)) {
  1321. if (tools_button_group->get_pressed_button() == tool_select_button && !selection.is_empty()) {
  1322. _menu_option(TILE_DELETE);
  1323. accept_event();
  1324. }
  1325. }
  1326. }
  1327. void TileSetAtlasSourceEditor::_set_selection_from_array(Array p_selection) {
  1328. ERR_FAIL_COND((p_selection.size() % 2) != 0);
  1329. selection.clear();
  1330. for (int i = 0; i < p_selection.size() / 2; i++) {
  1331. TileSelection selected = { p_selection[i * 2], p_selection[i * 2 + 1] };
  1332. if (tile_set_atlas_source->has_tile(selected.tile) && tile_set_atlas_source->has_alternative_tile(selected.tile, selected.alternative)) {
  1333. selection.insert(selected);
  1334. }
  1335. }
  1336. _update_tile_inspector();
  1337. _update_tile_id_label();
  1338. _update_atlas_view();
  1339. _update_current_tile_data_editor();
  1340. }
  1341. Array TileSetAtlasSourceEditor::_get_selection_as_array() {
  1342. Array output;
  1343. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1344. output.push_back(E->get().tile);
  1345. output.push_back(E->get().alternative);
  1346. }
  1347. return output;
  1348. }
  1349. void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
  1350. // Colors.
  1351. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  1352. 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);
  1353. // Draw the selected tile.
  1354. if (tools_button_group->get_pressed_button() == tool_select_button) {
  1355. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1356. TileSelection selected = E->get();
  1357. if (selected.alternative == 0) {
  1358. // Draw the rect.
  1359. Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
  1360. tile_atlas_control->draw_rect(region, selection_color, false);
  1361. }
  1362. }
  1363. if (selection.size() == 1) {
  1364. // Draw the resize handles (only when it's possible to expand).
  1365. TileSelection selected = selection.front()->get();
  1366. Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
  1367. Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
  1368. Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
  1369. Rect2 rect = region.grow_individual(zoomed_size.x, zoomed_size.y, 0, 0);
  1370. Vector2i coords[] = { Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 1) };
  1371. Vector2i directions[] = { Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0) };
  1372. bool can_grow[4];
  1373. for (int i = 0; i < 4; i++) {
  1374. can_grow[i] = tile_set_atlas_source->can_move_tile_in_atlas(selected.tile, selected.tile + directions[i]);
  1375. can_grow[i] |= (i % 2 == 0) ? size_in_atlas.y > 1 : size_in_atlas.x > 1;
  1376. }
  1377. for (int i = 0; i < 4; i++) {
  1378. Vector2 pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[i];
  1379. if (can_grow[i] && can_grow[(i + 3) % 4]) {
  1380. tile_atlas_control->draw_texture_rect(resize_handle, Rect2(pos, zoomed_size), false);
  1381. } else {
  1382. tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2(pos, zoomed_size), false);
  1383. }
  1384. Vector2 next_pos = rect.position + Vector2(rect.size.x, rect.size.y) * coords[(i + 1) % 4];
  1385. if (can_grow[i]) {
  1386. tile_atlas_control->draw_texture_rect(resize_handle, Rect2((pos + next_pos) / 2.0, zoomed_size), false);
  1387. } else {
  1388. tile_atlas_control->draw_texture_rect(resize_handle_disabled, Rect2((pos + next_pos) / 2.0, zoomed_size), false);
  1389. }
  1390. }
  1391. }
  1392. }
  1393. if (drag_type == DRAG_TYPE_REMOVE_TILES) {
  1394. // Draw the tiles to be removed.
  1395. for (Set<Vector2i>::Element *E = drag_modified_tiles.front(); E; E = E->next()) {
  1396. tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(E->get()), Color(0.0, 0.0, 0.0), false);
  1397. }
  1398. } else if (drag_type == DRAG_TYPE_RECT_SELECT || drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT) {
  1399. // Draw tiles to be removed.
  1400. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1401. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1402. Rect2i area = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1403. area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size()));
  1404. Color color = Color(0.0, 0.0, 0.0);
  1405. if (drag_type == DRAG_TYPE_RECT_SELECT) {
  1406. color = selection_color.lightened(0.2);
  1407. }
  1408. Set<Vector2i> to_paint;
  1409. for (int x = area.get_position().x; x < area.get_end().x; x++) {
  1410. for (int y = area.get_position().y; y < area.get_end().y; y++) {
  1411. Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
  1412. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1413. to_paint.insert(coords);
  1414. }
  1415. }
  1416. }
  1417. for (Set<Vector2i>::Element *E = to_paint.front(); E; E = E->next()) {
  1418. Vector2i coords = E->get();
  1419. tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(coords), color, false);
  1420. }
  1421. } else if (drag_type == DRAG_TYPE_CREATE_TILES_USING_RECT) {
  1422. // Draw tiles to be created.
  1423. Vector2i margins = tile_set_atlas_source->get_margins();
  1424. Vector2i separation = tile_set_atlas_source->get_separation();
  1425. Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
  1426. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1427. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1428. Rect2i area = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1429. area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size()));
  1430. for (int x = area.get_position().x; x < area.get_end().x; x++) {
  1431. for (int y = area.get_position().y; y < area.get_end().y; y++) {
  1432. Vector2i coords = Vector2i(x, y);
  1433. if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
  1434. Vector2i origin = margins + (coords * (tile_size + separation));
  1435. tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
  1436. }
  1437. }
  1438. }
  1439. }
  1440. // Draw the hovered tile.
  1441. if (drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT || drag_type == DRAG_TYPE_CREATE_TILES_USING_RECT) {
  1442. // Draw the rect.
  1443. Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
  1444. Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
  1445. Rect2i area = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
  1446. area.set_end((area.get_end() + Vector2i(1, 1)).min(tile_set_atlas_source->get_atlas_grid_size()));
  1447. Vector2i margins = tile_set_atlas_source->get_margins();
  1448. Vector2i separation = tile_set_atlas_source->get_separation();
  1449. Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
  1450. Vector2i origin = margins + (area.position * (tile_size + separation));
  1451. tile_atlas_control->draw_rect(Rect2i(origin, area.size * tile_size), Color(1.0, 1.0, 1.0), false);
  1452. } else {
  1453. Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
  1454. if (hovered_base_tile_coords.x >= 0 && hovered_base_tile_coords.y >= 0 && hovered_base_tile_coords.x < grid_size.x && hovered_base_tile_coords.y < grid_size.y) {
  1455. Vector2i hovered_tile = tile_set_atlas_source->get_tile_at_coords(hovered_base_tile_coords);
  1456. if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1457. // Draw existing hovered tile.
  1458. tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false);
  1459. } else {
  1460. // Draw empty tile, only in add/remove tiles mode.
  1461. if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) {
  1462. Vector2i margins = tile_set_atlas_source->get_margins();
  1463. Vector2i separation = tile_set_atlas_source->get_separation();
  1464. Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
  1465. Vector2i origin = margins + (hovered_base_tile_coords * (tile_size + separation));
  1466. tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
  1467. }
  1468. }
  1469. }
  1470. }
  1471. }
  1472. void TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw() {
  1473. if (current_tile_data_editor) {
  1474. // Draw the preview of the selected property.
  1475. for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
  1476. Vector2i coords = tile_set_atlas_source->get_tile_id(i);
  1477. Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(coords);
  1478. Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(coords, 0);
  1479. Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
  1480. xform.translate(position);
  1481. if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, 0 })) {
  1482. continue;
  1483. }
  1484. TileMapCell cell;
  1485. cell.source_id = tile_set_atlas_source_id;
  1486. cell.set_atlas_coords(coords);
  1487. cell.alternative_tile = 0;
  1488. current_tile_data_editor->draw_over_tile(tile_atlas_control_unscaled, xform, cell);
  1489. }
  1490. // Draw the selection on top of other.
  1491. if (tools_button_group->get_pressed_button() == tool_select_button) {
  1492. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1493. if (E->get().alternative != 0) {
  1494. continue;
  1495. }
  1496. Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(E->get().tile);
  1497. Vector2i position = (texture_region.position + texture_region.get_end()) / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(E->get().tile, 0);
  1498. Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
  1499. xform.translate(position);
  1500. TileMapCell cell;
  1501. cell.source_id = tile_set_atlas_source_id;
  1502. cell.set_atlas_coords(E->get().tile);
  1503. cell.alternative_tile = 0;
  1504. current_tile_data_editor->draw_over_tile(tile_atlas_control_unscaled, xform, cell, true);
  1505. }
  1506. }
  1507. // Call the TileData's editor custom draw function.
  1508. if (tools_button_group->get_pressed_button() == tool_paint_button) {
  1509. Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
  1510. current_tile_data_editor->forward_draw_over_atlas(tile_atlas_view, tile_set_atlas_source, tile_atlas_control_unscaled, xform);
  1511. }
  1512. }
  1513. }
  1514. void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event) {
  1515. // Update the hovered alternative tile.
  1516. hovered_alternative_tile_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position());
  1517. // Forward the event to the current tile data editor if we are in the painting mode.
  1518. if (tools_button_group->get_pressed_button() == tool_paint_button) {
  1519. if (current_tile_data_editor) {
  1520. current_tile_data_editor->forward_painting_alternatives_gui_input(tile_atlas_view, tile_set_atlas_source, p_event);
  1521. }
  1522. tile_atlas_control->update();
  1523. tile_atlas_control_unscaled->update();
  1524. alternative_tiles_control->update();
  1525. alternative_tiles_control_unscaled->update();
  1526. tile_atlas_view->update();
  1527. return;
  1528. }
  1529. Ref<InputEventMouseMotion> mm = p_event;
  1530. if (mm.is_valid()) {
  1531. tile_atlas_control->update();
  1532. tile_atlas_control_unscaled->update();
  1533. alternative_tiles_control->update();
  1534. alternative_tiles_control_unscaled->update();
  1535. }
  1536. Ref<InputEventMouseButton> mb = p_event;
  1537. if (mb.is_valid()) {
  1538. drag_type = DRAG_TYPE_NONE;
  1539. Vector2 mouse_local_pos = alternative_tiles_control->get_local_mouse_position();
  1540. if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
  1541. if (mb->is_pressed()) {
  1542. // Left click pressed.
  1543. if (tools_button_group->get_pressed_button() == tool_select_button) {
  1544. Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos);
  1545. selection.clear();
  1546. TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
  1547. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1548. selection.insert(selected);
  1549. }
  1550. _update_tile_inspector();
  1551. _update_tile_id_label();
  1552. }
  1553. }
  1554. } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
  1555. if (mb->is_pressed()) {
  1556. // Right click pressed
  1557. Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos);
  1558. selection.clear();
  1559. TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
  1560. if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
  1561. selection.insert(selected);
  1562. }
  1563. _update_tile_inspector();
  1564. _update_tile_id_label();
  1565. if (selection.size() == 1) {
  1566. selected = selection.front()->get();
  1567. menu_option_coords = selected.tile;
  1568. menu_option_alternative = selected.alternative;
  1569. alternative_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
  1570. }
  1571. }
  1572. }
  1573. tile_atlas_control->update();
  1574. tile_atlas_control_unscaled->update();
  1575. alternative_tiles_control->update();
  1576. alternative_tiles_control_unscaled->update();
  1577. }
  1578. }
  1579. void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() {
  1580. hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
  1581. tile_atlas_control->update();
  1582. tile_atlas_control_unscaled->update();
  1583. alternative_tiles_control->update();
  1584. alternative_tiles_control_unscaled->update();
  1585. }
  1586. void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
  1587. Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color");
  1588. 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);
  1589. // Update the hovered alternative tile.
  1590. if (tools_button_group->get_pressed_button() == tool_select_button) {
  1591. // Draw hovered tile.
  1592. Vector2i coords = Vector2(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
  1593. if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
  1594. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
  1595. if (rect != Rect2i()) {
  1596. alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
  1597. }
  1598. }
  1599. // Draw selected tile.
  1600. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1601. TileSelection selected = E->get();
  1602. if (selected.alternative >= 1) {
  1603. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative);
  1604. if (rect != Rect2i()) {
  1605. alternative_tiles_control->draw_rect(rect, selection_color, false);
  1606. }
  1607. }
  1608. }
  1609. }
  1610. }
  1611. void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() {
  1612. // Draw the preview of the selected property.
  1613. if (current_tile_data_editor) {
  1614. // Draw the preview of the currently selected property.
  1615. for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
  1616. Vector2i coords = tile_set_atlas_source->get_tile_id(i);
  1617. for (int j = 0; j < tile_set_atlas_source->get_alternative_tiles_count(coords); j++) {
  1618. int alternative_tile = tile_set_atlas_source->get_alternative_tile_id(coords, j);
  1619. if (alternative_tile == 0) {
  1620. continue;
  1621. }
  1622. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile);
  1623. Vector2 position = (rect.get_position() + rect.get_end()) / 2;
  1624. Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
  1625. xform.translate(position);
  1626. if (tools_button_group->get_pressed_button() == tool_select_button && selection.has({ coords, alternative_tile })) {
  1627. continue;
  1628. }
  1629. TileMapCell cell;
  1630. cell.source_id = tile_set_atlas_source_id;
  1631. cell.set_atlas_coords(coords);
  1632. cell.alternative_tile = alternative_tile;
  1633. current_tile_data_editor->draw_over_tile(alternative_tiles_control_unscaled, xform, cell);
  1634. }
  1635. }
  1636. // Draw the selection on top of other.
  1637. if (tools_button_group->get_pressed_button() == tool_select_button) {
  1638. for (Set<TileSelection>::Element *E = selection.front(); E; E = E->next()) {
  1639. if (E->get().alternative == 0) {
  1640. continue;
  1641. }
  1642. Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().tile, E->get().alternative);
  1643. Vector2 position = (rect.get_position() + rect.get_end()) / 2;
  1644. Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform();
  1645. xform.translate(position);
  1646. TileMapCell cell;
  1647. cell.source_id = tile_set_atlas_source_id;
  1648. cell.set_atlas_coords(E->get().tile);
  1649. cell.alternative_tile = E->get().alternative;
  1650. current_tile_data_editor->draw_over_tile(alternative_tiles_control_unscaled, xform, cell, true);
  1651. }
  1652. }
  1653. // Call the TileData's editor custom draw function.
  1654. if (tools_button_group->get_pressed_button() == tool_paint_button) {
  1655. Transform2D xform = tile_atlas_control->get_parent_control()->get_transform();
  1656. current_tile_data_editor->forward_draw_over_alternatives(tile_atlas_view, tile_set_atlas_source, alternative_tiles_control_unscaled, xform);
  1657. }
  1658. }
  1659. }
  1660. void TileSetAtlasSourceEditor::_tile_set_atlas_source_changed() {
  1661. tile_set_atlas_source_changed_needs_update = true;
  1662. }
  1663. void TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed(String p_what) {
  1664. if (p_what == "texture" && !atlas_source_proxy_object->get("texture").is_null()) {
  1665. confirm_auto_create_tiles->popup_centered();
  1666. } else if (p_what == "id") {
  1667. emit_signal(SNAME("source_id_changed"), atlas_source_proxy_object->get_id());
  1668. }
  1669. }
  1670. void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value) {
  1671. UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo);
  1672. ERR_FAIL_COND(!undo_redo);
  1673. #define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, tile_data->get(property));
  1674. AtlasTileProxyObject *tile_data = Object::cast_to<AtlasTileProxyObject>(p_edited);
  1675. if (tile_data) {
  1676. Vector<String> components = String(p_property).split("/", true, 2);
  1677. if (components.size() == 2 && components[1] == "polygons_count") {
  1678. int layer_index = components[0].trim_prefix("physics_layer_").to_int();
  1679. int new_polygons_count = p_new_value;
  1680. int old_polygons_count = tile_data->get(vformat("physics_layer_%d/polygons_count", layer_index));
  1681. if (new_polygons_count < old_polygons_count) {
  1682. for (int i = new_polygons_count - 1; i < old_polygons_count; i++) {
  1683. ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/points", layer_index, i));
  1684. ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way", layer_index, i));
  1685. ADD_UNDO(tile_data, vformat("physics_layer_%d/polygon_%d/one_way_margin", layer_index, i));
  1686. }
  1687. }
  1688. } else if (p_property == "terrain_set") {
  1689. int current_terrain_set = tile_data->get("terrain_set");
  1690. for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
  1691. TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
  1692. if (tile_set->is_valid_peering_bit_terrain(current_terrain_set, bit)) {
  1693. ADD_UNDO(tile_data, "terrains_peering_bit/" + String(TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[i]));
  1694. }
  1695. }
  1696. }
  1697. }
  1698. #undef ADD_UNDO
  1699. }
  1700. void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id) {
  1701. ERR_FAIL_COND(!p_tile_set.is_valid());
  1702. ERR_FAIL_COND(!p_tile_set_atlas_source);
  1703. ERR_FAIL_COND(p_source_id < 0);
  1704. ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_atlas_source);
  1705. if (p_tile_set == tile_set && p_tile_set_atlas_source == tile_set_atlas_source && p_source_id == tile_set_atlas_source_id) {
  1706. return;
  1707. }
  1708. // Remove listener for old objects.
  1709. if (tile_set_atlas_source) {
  1710. tile_set_atlas_source->disconnect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_set_atlas_source_changed));
  1711. }
  1712. // Clear the selection.
  1713. selection.clear();
  1714. // Change the edited object.
  1715. tile_set = p_tile_set;
  1716. tile_set_atlas_source = p_tile_set_atlas_source;
  1717. tile_set_atlas_source_id = p_source_id;
  1718. // Add the listener again.
  1719. if (tile_set_atlas_source) {
  1720. tile_set_atlas_source->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_set_atlas_source_changed));
  1721. }
  1722. // Update everything.
  1723. _update_source_inspector();
  1724. // Update the selected tile.
  1725. _update_fix_selected_and_hovered_tiles();
  1726. _update_tile_id_label();
  1727. _update_atlas_view();
  1728. _update_atlas_source_inspector();
  1729. _update_tile_inspector();
  1730. _update_tile_data_editors();
  1731. _update_current_tile_data_editor();
  1732. }
  1733. void TileSetAtlasSourceEditor::init_source() {
  1734. confirm_auto_create_tiles->popup_centered();
  1735. }
  1736. void TileSetAtlasSourceEditor::_auto_create_tiles() {
  1737. if (!tile_set_atlas_source) {
  1738. return;
  1739. }
  1740. Ref<Texture2D> texture = tile_set_atlas_source->get_texture();
  1741. if (texture.is_valid()) {
  1742. Vector2i margins = tile_set_atlas_source->get_margins();
  1743. Vector2i separation = tile_set_atlas_source->get_separation();
  1744. Vector2i texture_region_size = tile_set_atlas_source->get_texture_region_size();
  1745. Size2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
  1746. undo_redo->create_action(TTR("Create tiles in non-transparent texture regions"));
  1747. for (int y = 0; y < grid_size.y; y++) {
  1748. for (int x = 0; x < grid_size.x; x++) {
  1749. // Check if we have a tile at the coord
  1750. Vector2i coords = Vector2i(x, y);
  1751. if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
  1752. // Check if the texture is empty at the given coords.
  1753. Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size);
  1754. bool is_opaque = false;
  1755. for (int region_x = region.get_position().x; region_x < region.get_end().x; region_x++) {
  1756. for (int region_y = region.get_position().y; region_y < region.get_end().y; region_y++) {
  1757. if (texture->is_pixel_opaque(region_x, region_y)) {
  1758. is_opaque = true;
  1759. break;
  1760. }
  1761. }
  1762. if (is_opaque) {
  1763. break;
  1764. }
  1765. }
  1766. // If we do have opaque pixels, create a tile.
  1767. if (is_opaque) {
  1768. undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords);
  1769. undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords);
  1770. }
  1771. }
  1772. }
  1773. }
  1774. undo_redo->commit_action();
  1775. }
  1776. }
  1777. void TileSetAtlasSourceEditor::_auto_remove_tiles() {
  1778. if (!tile_set_atlas_source) {
  1779. return;
  1780. }
  1781. Ref<Texture2D> texture = tile_set_atlas_source->get_texture();
  1782. if (texture.is_valid()) {
  1783. Vector2i margins = tile_set_atlas_source->get_margins();
  1784. Vector2i separation = tile_set_atlas_source->get_separation();
  1785. Vector2i texture_region_size = tile_set_atlas_source->get_texture_region_size();
  1786. Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
  1787. undo_redo->create_action(TTR("Remove tiles in fully transparent texture regions"));
  1788. List<PropertyInfo> list;
  1789. tile_set_atlas_source->get_property_list(&list);
  1790. Map<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles(list, tile_set_atlas_source);
  1791. for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
  1792. Vector2i coords = tile_set_atlas_source->get_tile_id(i);
  1793. Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(coords);
  1794. // Skip tiles outside texture.
  1795. if ((coords.x + size_in_atlas.x) > grid_size.x || (coords.y + size_in_atlas.y) > grid_size.y) {
  1796. continue;
  1797. }
  1798. // Check if the texture is empty at the given coords.
  1799. Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size * size_in_atlas);
  1800. bool is_opaque = false;
  1801. for (int region_x = region.get_position().x; region_x < region.get_end().x; region_x++) {
  1802. for (int region_y = region.get_position().y; region_y < region.get_end().y; region_y++) {
  1803. if (texture->is_pixel_opaque(region_x, region_y)) {
  1804. is_opaque = true;
  1805. break;
  1806. }
  1807. }
  1808. if (is_opaque) {
  1809. break;
  1810. }
  1811. }
  1812. // If we do have opaque pixels, create a tile.
  1813. if (!is_opaque) {
  1814. undo_redo->add_do_method(tile_set_atlas_source, "remove_tile", coords);
  1815. undo_redo->add_undo_method(tile_set_atlas_source, "create_tile", coords);
  1816. if (per_tile.has(coords)) {
  1817. for (List<const PropertyInfo *>::Element *E_property = per_tile[coords].front(); E_property; E_property = E_property->next()) {
  1818. String property = E_property->get()->name;
  1819. Variant value = tile_set_atlas_source->get(property);
  1820. if (value.get_type() != Variant::NIL) {
  1821. undo_redo->add_undo_method(tile_set_atlas_source, "set", E_property->get()->name, value);
  1822. }
  1823. }
  1824. }
  1825. }
  1826. }
  1827. undo_redo->commit_action();
  1828. }
  1829. }
  1830. void TileSetAtlasSourceEditor::_notification(int p_what) {
  1831. switch (p_what) {
  1832. case NOTIFICATION_ENTER_TREE:
  1833. case NOTIFICATION_THEME_CHANGED:
  1834. tool_setup_atlas_source_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
  1835. tool_select_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
  1836. tool_paint_button->set_icon(get_theme_icon(SNAME("CanvasItem"), SNAME("EditorIcons")));
  1837. tools_settings_erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
  1838. tool_advanced_menu_buttom->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
  1839. resize_handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
  1840. resize_handle_disabled = get_theme_icon(SNAME("EditorHandleDisabled"), SNAME("EditorIcons"));
  1841. break;
  1842. case NOTIFICATION_INTERNAL_PROCESS:
  1843. if (tile_set_atlas_source_changed_needs_update) {
  1844. // Update everything.
  1845. _update_source_inspector();
  1846. // Update the selected tile.
  1847. _update_fix_selected_and_hovered_tiles();
  1848. _update_tile_id_label();
  1849. _update_atlas_view();
  1850. _update_atlas_source_inspector();
  1851. _update_tile_inspector();
  1852. _update_tile_data_editors();
  1853. _update_current_tile_data_editor();
  1854. tile_set_atlas_source_changed_needs_update = false;
  1855. }
  1856. break;
  1857. default:
  1858. break;
  1859. }
  1860. }
  1861. void TileSetAtlasSourceEditor::_bind_methods() {
  1862. ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &TileSetAtlasSourceEditor::_unhandled_key_input);
  1863. ClassDB::bind_method(D_METHOD("_set_selection_from_array"), &TileSetAtlasSourceEditor::_set_selection_from_array);
  1864. ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id")));
  1865. }
  1866. TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
  1867. set_process_unhandled_key_input(true);
  1868. set_process_internal(true);
  1869. // -- Right side --
  1870. HSplitContainer *split_container_right_side = memnew(HSplitContainer);
  1871. split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
  1872. add_child(split_container_right_side);
  1873. // Middle panel.
  1874. ScrollContainer *middle_panel = memnew(ScrollContainer);
  1875. middle_panel->set_enable_h_scroll(false);
  1876. middle_panel->set_custom_minimum_size(Size2i(200, 0) * EDSCALE);
  1877. split_container_right_side->add_child(middle_panel);
  1878. VBoxContainer *middle_vbox_container = memnew(VBoxContainer);
  1879. middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL);
  1880. middle_panel->add_child(middle_vbox_container);
  1881. // Tile inspector.
  1882. tile_inspector_label = memnew(Label);
  1883. tile_inspector_label->set_text(TTR("Tile Properties:"));
  1884. middle_vbox_container->add_child(tile_inspector_label);
  1885. tile_proxy_object = memnew(AtlasTileProxyObject(this));
  1886. tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
  1887. tile_inspector = memnew(EditorInspector);
  1888. tile_inspector->set_undo_redo(undo_redo);
  1889. tile_inspector->set_enable_v_scroll(false);
  1890. tile_inspector->edit(tile_proxy_object);
  1891. tile_inspector->set_use_folding(true);
  1892. tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected));
  1893. middle_vbox_container->add_child(tile_inspector);
  1894. tile_inspector_no_tile_selected_label = memnew(Label);
  1895. tile_inspector_no_tile_selected_label->set_align(Label::ALIGN_CENTER);
  1896. tile_inspector_no_tile_selected_label->set_text(TTR("No tile selected."));
  1897. middle_vbox_container->add_child(tile_inspector_no_tile_selected_label);
  1898. // Property values palette.
  1899. tile_data_editors_popup = memnew(Popup);
  1900. tile_data_editors_label = memnew(Label);
  1901. tile_data_editors_label->set_text(TTR("Paint Properties:"));
  1902. middle_vbox_container->add_child(tile_data_editors_label);
  1903. tile_data_editor_dropdown_button = memnew(Button);
  1904. tile_data_editor_dropdown_button->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_draw));
  1905. tile_data_editor_dropdown_button->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editor_dropdown_button_pressed));
  1906. middle_vbox_container->add_child(tile_data_editor_dropdown_button);
  1907. tile_data_editor_dropdown_button->add_child(tile_data_editors_popup);
  1908. tile_data_editors_tree = memnew(Tree);
  1909. tile_data_editors_tree->set_hide_root(true);
  1910. tile_data_editors_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
  1911. tile_data_editors_tree->set_h_scroll_enabled(false);
  1912. tile_data_editors_tree->set_v_scroll_enabled(false);
  1913. tile_data_editors_tree->connect("item_selected", callable_mp(this, &TileSetAtlasSourceEditor::_tile_data_editors_tree_selected));
  1914. tile_data_editors_popup->add_child(tile_data_editors_tree);
  1915. tile_data_painting_editor_container = memnew(VBoxContainer);
  1916. tile_data_painting_editor_container->set_h_size_flags(SIZE_EXPAND_FILL);
  1917. middle_vbox_container->add_child(tile_data_painting_editor_container);
  1918. // Atlas source inspector.
  1919. atlas_source_inspector_label = memnew(Label);
  1920. atlas_source_inspector_label->set_text(TTR("Atlas Properties:"));
  1921. middle_vbox_container->add_child(atlas_source_inspector_label);
  1922. atlas_source_proxy_object = memnew(TileSetAtlasSourceProxyObject());
  1923. atlas_source_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed));
  1924. atlas_source_inspector = memnew(EditorInspector);
  1925. atlas_source_inspector->set_undo_redo(undo_redo);
  1926. atlas_source_inspector->set_enable_v_scroll(false);
  1927. atlas_source_inspector->edit(atlas_source_proxy_object);
  1928. middle_vbox_container->add_child(atlas_source_inspector);
  1929. // Right panel.
  1930. VBoxContainer *right_panel = memnew(VBoxContainer);
  1931. right_panel->set_h_size_flags(SIZE_EXPAND_FILL);
  1932. right_panel->set_v_size_flags(SIZE_EXPAND_FILL);
  1933. split_container_right_side->add_child(right_panel);
  1934. // -- Dialogs --
  1935. confirm_auto_create_tiles = memnew(AcceptDialog);
  1936. confirm_auto_create_tiles->set_title(TTR("Auto Create Tiles in Non-Transparent Texture Regions?"));
  1937. confirm_auto_create_tiles->set_text(TTR("The atlas's texture was modified.\nWould you like to automatically create tiles in the atlas?"));
  1938. confirm_auto_create_tiles->get_ok_button()->set_text(TTR("Yes"));
  1939. confirm_auto_create_tiles->add_cancel_button()->set_text(TTR("No"));
  1940. confirm_auto_create_tiles->connect("confirmed", callable_mp(this, &TileSetAtlasSourceEditor::_auto_create_tiles));
  1941. add_child(confirm_auto_create_tiles);
  1942. // -- Toolbox --
  1943. tools_button_group.instantiate();
  1944. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles).unbind(1));
  1945. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_id_label).unbind(1));
  1946. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_source_inspector).unbind(1));
  1947. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_inspector).unbind(1));
  1948. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_tile_data_editors).unbind(1));
  1949. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_current_tile_data_editor).unbind(1));
  1950. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
  1951. tools_button_group->connect("pressed", callable_mp(this, &TileSetAtlasSourceEditor::_update_toolbar).unbind(1));
  1952. toolbox = memnew(HBoxContainer);
  1953. right_panel->add_child(toolbox);
  1954. tool_setup_atlas_source_button = memnew(Button);
  1955. tool_setup_atlas_source_button->set_flat(true);
  1956. tool_setup_atlas_source_button->set_toggle_mode(true);
  1957. tool_setup_atlas_source_button->set_pressed(true);
  1958. tool_setup_atlas_source_button->set_button_group(tools_button_group);
  1959. tool_setup_atlas_source_button->set_tooltip(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing)."));
  1960. toolbox->add_child(tool_setup_atlas_source_button);
  1961. tool_select_button = memnew(Button);
  1962. tool_select_button->set_flat(true);
  1963. tool_select_button->set_toggle_mode(true);
  1964. tool_select_button->set_pressed(false);
  1965. tool_select_button->set_button_group(tools_button_group);
  1966. tool_select_button->set_tooltip(TTR("Select tiles."));
  1967. toolbox->add_child(tool_select_button);
  1968. tool_paint_button = memnew(Button);
  1969. tool_paint_button->set_flat(true);
  1970. tool_paint_button->set_toggle_mode(true);
  1971. tool_paint_button->set_button_group(tools_button_group);
  1972. tool_paint_button->set_tooltip(TTR("Paint properties."));
  1973. toolbox->add_child(tool_paint_button);
  1974. // Tool settings.
  1975. tool_settings = memnew(HBoxContainer);
  1976. toolbox->add_child(tool_settings);
  1977. tool_settings_vsep = memnew(VSeparator);
  1978. tool_settings->add_child(tool_settings_vsep);
  1979. tool_settings_tile_data_toolbar_container = memnew(HBoxContainer);
  1980. tool_settings->add_child(tool_settings_tile_data_toolbar_container);
  1981. tools_settings_erase_button = memnew(Button);
  1982. tools_settings_erase_button->set_flat(true);
  1983. tools_settings_erase_button->set_toggle_mode(true);
  1984. tools_settings_erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", KEY_E));
  1985. tools_settings_erase_button->set_shortcut_context(this);
  1986. tool_settings->add_child(tools_settings_erase_button);
  1987. tool_advanced_menu_buttom = memnew(MenuButton);
  1988. tool_advanced_menu_buttom->set_flat(true);
  1989. tool_advanced_menu_buttom->get_popup()->add_item(TTR("Cleanup Tiles Outside Texture"), ADVANCED_CLEANUP_TILES_OUTSIDE_TEXTURE);
  1990. tool_advanced_menu_buttom->get_popup()->set_item_disabled(0, true);
  1991. tool_advanced_menu_buttom->get_popup()->add_item(TTR("Create Tiles in Non-Transparent Texture Regions"), ADVANCED_AUTO_CREATE_TILES);
  1992. tool_advanced_menu_buttom->get_popup()->add_item(TTR("Remove Tiles in Fully Transparent Texture Regions"), ADVANCED_AUTO_REMOVE_TILES);
  1993. tool_advanced_menu_buttom->get_popup()->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
  1994. toolbox->add_child(tool_advanced_menu_buttom);
  1995. _update_toolbar();
  1996. // Right side of toolbar.
  1997. Control *middle_space = memnew(Control);
  1998. middle_space->set_h_size_flags(SIZE_EXPAND_FILL);
  1999. toolbox->add_child(middle_space);
  2000. tool_tile_id_label = memnew(Label);
  2001. tool_tile_id_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
  2002. toolbox->add_child(tool_tile_id_label);
  2003. _update_tile_id_label();
  2004. // Tile atlas view.
  2005. tile_atlas_view = memnew(TileAtlasView);
  2006. tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
  2007. tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
  2008. tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform));
  2009. tile_atlas_view->connect("transform_changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed).unbind(2));
  2010. right_panel->add_child(tile_atlas_view);
  2011. base_tile_popup_menu = memnew(PopupMenu);
  2012. base_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), KEY_DELETE), TILE_DELETE);
  2013. base_tile_popup_menu->add_item(TTR("Create an Alternative Tile"), TILE_CREATE_ALTERNATIVE);
  2014. base_tile_popup_menu->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
  2015. tile_atlas_view->add_child(base_tile_popup_menu);
  2016. empty_base_tile_popup_menu = memnew(PopupMenu);
  2017. empty_base_tile_popup_menu->add_item(TTR("Create a Tile"), TILE_CREATE);
  2018. empty_base_tile_popup_menu->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
  2019. tile_atlas_view->add_child(empty_base_tile_popup_menu);
  2020. tile_atlas_control = memnew(Control);
  2021. tile_atlas_control->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_draw));
  2022. tile_atlas_control->connect("mouse_exited", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_mouse_exited));
  2023. tile_atlas_control->connect("gui_input", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_gui_input));
  2024. tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control);
  2025. tile_atlas_control_unscaled = memnew(Control);
  2026. tile_atlas_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
  2027. tile_atlas_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_control_unscaled_draw));
  2028. tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control_unscaled, false);
  2029. tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
  2030. alternative_tile_popup_menu = memnew(PopupMenu);
  2031. alternative_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete_tile", TTR("Delete"), KEY_DELETE), TILE_DELETE);
  2032. alternative_tile_popup_menu->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option));
  2033. tile_atlas_view->add_child(alternative_tile_popup_menu);
  2034. alternative_tiles_control = memnew(Control);
  2035. alternative_tiles_control->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_draw));
  2036. alternative_tiles_control->connect("mouse_exited", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited));
  2037. alternative_tiles_control->connect("gui_input", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input));
  2038. tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
  2039. alternative_tiles_control_unscaled = memnew(Control);
  2040. alternative_tiles_control_unscaled->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
  2041. alternative_tiles_control_unscaled->connect("draw", callable_mp(this, &TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw));
  2042. tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control_unscaled, false);
  2043. alternative_tiles_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
  2044. tile_atlas_view_missing_source_label = memnew(Label);
  2045. tile_atlas_view_missing_source_label->set_text(TTR("Add or select an atlas texture to the left panel."));
  2046. tile_atlas_view_missing_source_label->set_align(Label::ALIGN_CENTER);
  2047. tile_atlas_view_missing_source_label->set_valign(Label::VALIGN_CENTER);
  2048. tile_atlas_view_missing_source_label->set_h_size_flags(SIZE_EXPAND_FILL);
  2049. tile_atlas_view_missing_source_label->set_v_size_flags(SIZE_EXPAND_FILL);
  2050. tile_atlas_view_missing_source_label->hide();
  2051. right_panel->add_child(tile_atlas_view_missing_source_label);
  2052. }
  2053. TileSetAtlasSourceEditor::~TileSetAtlasSourceEditor() {
  2054. memdelete(tile_proxy_object);
  2055. memdelete(atlas_source_proxy_object);
  2056. }