3737#include " editor/editor_scale.h"
3838#include " editor/editor_settings.h"
3939#include " editor/editor_undo_redo_manager.h"
40+ #include " editor/gui/editor_toaster.h"
4041#include " editor/plugins/tiles/tile_set_editor.h"
4142#include " editor/progress_dialog.h"
4243
@@ -1679,6 +1680,9 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) {
16791680 case ADVANCED_AUTO_REMOVE_TILES : {
16801681 _auto_remove_tiles ();
16811682 } break ;
1683+ case ADVANCED_CLEANUP_TILES : {
1684+ _cleanup_outside_tiles ();
1685+ } break ;
16821686 }
16831687}
16841688
@@ -2141,44 +2145,6 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
21412145 }
21422146 internal_undo_redo->end_force_keep_in_merge_ends ();
21432147 }
2144-
2145- TileSetAtlasSourceProxyObject *atlas_source_proxy = Object::cast_to<TileSetAtlasSourceProxyObject>(p_edited);
2146- if (atlas_source_proxy) {
2147- Ref<TileSetAtlasSource> atlas_source = atlas_source_proxy->get_edited ();
2148- ERR_FAIL_COND (!atlas_source.is_valid ());
2149-
2150- UndoRedo *internal_undo_redo = undo_redo_man->get_history_for_object (atlas_source_proxy).undo_redo ;
2151- internal_undo_redo->start_force_keep_in_merge_ends ();
2152-
2153- PackedVector2Array arr;
2154- if (p_property == " texture" ) {
2155- arr = atlas_source->get_tiles_to_be_removed_on_change (p_new_value, atlas_source->get_margins (), atlas_source->get_separation (), atlas_source->get_texture_region_size ());
2156- } else if (p_property == " margins" ) {
2157- arr = atlas_source->get_tiles_to_be_removed_on_change (atlas_source->get_texture (), p_new_value, atlas_source->get_separation (), atlas_source->get_texture_region_size ());
2158- } else if (p_property == " separation" ) {
2159- arr = atlas_source->get_tiles_to_be_removed_on_change (atlas_source->get_texture (), atlas_source->get_margins (), p_new_value, atlas_source->get_texture_region_size ());
2160- } else if (p_property == " texture_region_size" ) {
2161- arr = atlas_source->get_tiles_to_be_removed_on_change (atlas_source->get_texture (), atlas_source->get_margins (), atlas_source->get_separation (), p_new_value);
2162- }
2163-
2164- if (!arr.is_empty ()) {
2165- // Get all properties assigned to a tile.
2166- List<PropertyInfo> properties;
2167- atlas_source->get_property_list (&properties);
2168-
2169- for (int i = 0 ; i < arr.size (); i++) {
2170- Vector2i coords = arr[i];
2171- String prefix = vformat (" %d:%d/" , coords.x , coords.y );
2172- for (PropertyInfo pi : properties) {
2173- if (pi.name .begins_with (prefix)) {
2174- ADD_UNDO (atlas_source_proxy, pi.name );
2175- }
2176- }
2177- }
2178- }
2179- internal_undo_redo->end_force_keep_in_merge_ends ();
2180- }
2181-
21822148#undef ADD_UNDO
21832149}
21842150
@@ -2208,6 +2174,14 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
22082174 tile_set->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_tile_set_changed));
22092175 }
22102176
2177+ if (tile_set_atlas_source) {
2178+ tile_set_atlas_source->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_update_source_texture));
2179+ if (atlas_source_texture.is_valid ()) {
2180+ atlas_source_texture->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles));
2181+ atlas_source_texture = Ref<Texture2D>();
2182+ }
2183+ }
2184+
22112185 // Clear the selection.
22122186 selection.clear ();
22132187
@@ -2223,6 +2197,11 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
22232197 tile_set->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_tile_set_changed));
22242198 }
22252199
2200+ if (tile_set_atlas_source) {
2201+ tile_set_atlas_source->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_update_source_texture));
2202+ _update_source_texture ();
2203+ }
2204+
22262205 if (read_only && tools_button_group->get_pressed_button () == tool_paint_button) {
22272206 tool_paint_button->set_pressed (false );
22282207 tool_setup_atlas_source_button->set_pressed (true );
@@ -2252,6 +2231,61 @@ void TileSetAtlasSourceEditor::init_new_atlases(const Vector<Ref<TileSetAtlasSou
22522231 confirm_auto_create_tiles->popup_centered ();
22532232}
22542233
2234+ void TileSetAtlasSourceEditor::_update_source_texture () {
2235+ if (tile_set_atlas_source && tile_set_atlas_source->get_texture () == atlas_source_texture) {
2236+ return ;
2237+ }
2238+
2239+ if (atlas_source_texture.is_valid ()) {
2240+ atlas_source_texture->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles));
2241+ atlas_source_texture = Ref<Texture2D>();
2242+ }
2243+
2244+ if (!tile_set_atlas_source || tile_set_atlas_source->get_texture ().is_null ()) {
2245+ return ;
2246+ }
2247+ atlas_source_texture = tile_set_atlas_source->get_texture ();
2248+ atlas_source_texture->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles), CONNECT_DEFERRED );
2249+ _check_outside_tiles ();
2250+ }
2251+
2252+ void TileSetAtlasSourceEditor::_check_outside_tiles () {
2253+ ERR_FAIL_NULL (tile_set_atlas_source);
2254+ outside_tiles_warning->set_visible (!read_only && tile_set_atlas_source->has_tiles_outside_texture ());
2255+ tool_advanced_menu_button->get_popup ()->set_item_disabled (tool_advanced_menu_button->get_popup ()->get_item_index (ADVANCED_CLEANUP_TILES ), !tile_set_atlas_source->has_tiles_outside_texture ());
2256+ }
2257+
2258+ void TileSetAtlasSourceEditor::_cleanup_outside_tiles () {
2259+ ERR_FAIL_NULL (tile_set_atlas_source);
2260+
2261+ List<PropertyInfo> list;
2262+ tile_set_atlas_source->get_property_list (&list);
2263+ HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles (list, tile_set_atlas_source);
2264+ Vector<Vector2i> tiles_outside = tile_set_atlas_source->get_tiles_outside_texture ();
2265+
2266+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton ();
2267+ undo_redo->create_action (TTR (" Remove Tiles Outside the Texture" ));
2268+
2269+ undo_redo->add_do_method (tile_set_atlas_source, " clear_tiles_outside_texture" );
2270+ for (const Vector2i &coords : tiles_outside) {
2271+ undo_redo->add_undo_method (tile_set_atlas_source, " create_tile" , coords);
2272+ if (per_tile.has (coords)) {
2273+ for (List<const PropertyInfo *>::Element *E_property = per_tile[coords].front (); E_property; E_property = E_property->next ()) {
2274+ String property = E_property->get ()->name ;
2275+ Variant value = tile_set_atlas_source->get (property);
2276+ if (value.get_type () != Variant::NIL ) {
2277+ undo_redo->add_undo_method (tile_set_atlas_source, " set" , E_property->get ()->name , value);
2278+ }
2279+ }
2280+ }
2281+ }
2282+
2283+ undo_redo->add_do_method (this , " _check_outside_tiles" );
2284+ undo_redo->add_undo_method (this , " _check_outside_tiles" );
2285+ undo_redo->commit_action ();
2286+ outside_tiles_warning->hide ();
2287+ }
2288+
22552289void TileSetAtlasSourceEditor::_auto_create_tiles () {
22562290 for (Ref<TileSetAtlasSource> &atlas_source : atlases_to_auto_create_tiles) {
22572291 if (atlas_source.is_valid ()) {
@@ -2374,8 +2408,8 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
23742408 tool_paint_button->set_icon (get_theme_icon (SNAME (" CanvasItem" ), SNAME (" EditorIcons" )));
23752409
23762410 tools_settings_erase_button->set_icon (get_theme_icon (SNAME (" Eraser" ), SNAME (" EditorIcons" )));
2377-
23782411 tool_advanced_menu_button->set_icon (get_theme_icon (SNAME (" GuiTabMenuHl" ), SNAME (" EditorIcons" )));
2412+ outside_tiles_warning->set_texture (get_theme_icon (SNAME (" StatusWarning" ), SNAME (" EditorIcons" )));
23792413
23802414 resize_handle = get_theme_icon (SNAME (" EditorHandle" ), SNAME (" EditorIcons" ));
23812415 resize_handle_disabled = get_theme_icon (SNAME (" EditorHandleDisabled" ), SNAME (" EditorIcons" ));
@@ -2424,6 +2458,7 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
24242458
24252459void TileSetAtlasSourceEditor::_bind_methods () {
24262460 ClassDB::bind_method (D_METHOD (" _set_selection_from_array" ), &TileSetAtlasSourceEditor::_set_selection_from_array);
2461+ ClassDB::bind_method (D_METHOD (" _check_outside_tiles" ), &TileSetAtlasSourceEditor::_check_outside_tiles);
24272462
24282463 ADD_SIGNAL (MethodInfo (" source_id_changed" , PropertyInfo (Variant::INT , " source_id" )));
24292464}
@@ -2566,9 +2601,16 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
25662601 tool_advanced_menu_button->set_flat (true );
25672602 tool_advanced_menu_button->get_popup ()->add_item (TTR (" Create Tiles in Non-Transparent Texture Regions" ), ADVANCED_AUTO_CREATE_TILES );
25682603 tool_advanced_menu_button->get_popup ()->add_item (TTR (" Remove Tiles in Fully Transparent Texture Regions" ), ADVANCED_AUTO_REMOVE_TILES );
2604+ tool_advanced_menu_button->get_popup ()->add_item (TTR (" Remove Tiles Outside the Texture" ), ADVANCED_CLEANUP_TILES );
25692605 tool_advanced_menu_button->get_popup ()->connect (" id_pressed" , callable_mp (this , &TileSetAtlasSourceEditor::_menu_option));
25702606 tool_settings->add_child (tool_advanced_menu_button);
25712607
2608+ outside_tiles_warning = memnew (TextureRect);
2609+ outside_tiles_warning->set_stretch_mode (TextureRect::STRETCH_KEEP_ASPECT_CENTERED );
2610+ outside_tiles_warning->set_tooltip_text (vformat (TTR (" The current atlas source has tiles outside the texture.\n You can clear it using \" %s\" option in the 3 dots menu." ), TTR (" Remove Tiles Outside the Texture" )));
2611+ outside_tiles_warning->hide ();
2612+ tool_settings->add_child (outside_tiles_warning);
2613+
25722614 _update_toolbar ();
25732615
25742616 // Right side of toolbar.
0 commit comments