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
@@ -1677,6 +1678,9 @@ void TileSetAtlasSourceEditor::_menu_option(int p_option) {
16771678 case ADVANCED_AUTO_REMOVE_TILES : {
16781679 _auto_remove_tiles ();
16791680 } break ;
1681+ case ADVANCED_CLEANUP_TILES : {
1682+ _cleanup_outside_tiles ();
1683+ } break ;
16801684 }
16811685}
16821686
@@ -2137,44 +2141,6 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
21372141 }
21382142 internal_undo_redo->end_force_keep_in_merge_ends ();
21392143 }
2140-
2141- TileSetAtlasSourceProxyObject *atlas_source_proxy = Object::cast_to<TileSetAtlasSourceProxyObject>(p_edited);
2142- if (atlas_source_proxy) {
2143- Ref<TileSetAtlasSource> atlas_source = atlas_source_proxy->get_edited ();
2144- ERR_FAIL_COND (!atlas_source.is_valid ());
2145-
2146- UndoRedo *internal_undo_redo = undo_redo_man->get_history_for_object (atlas_source_proxy).undo_redo ;
2147- internal_undo_redo->start_force_keep_in_merge_ends ();
2148-
2149- PackedVector2Array arr;
2150- if (p_property == " texture" ) {
2151- 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 ());
2152- } else if (p_property == " margins" ) {
2153- 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 ());
2154- } else if (p_property == " separation" ) {
2155- 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 ());
2156- } else if (p_property == " texture_region_size" ) {
2157- 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);
2158- }
2159-
2160- if (!arr.is_empty ()) {
2161- // Get all properties assigned to a tile.
2162- List<PropertyInfo> properties;
2163- atlas_source->get_property_list (&properties);
2164-
2165- for (int i = 0 ; i < arr.size (); i++) {
2166- Vector2i coords = arr[i];
2167- String prefix = vformat (" %d:%d/" , coords.x , coords.y );
2168- for (PropertyInfo pi : properties) {
2169- if (pi.name .begins_with (prefix)) {
2170- ADD_UNDO (atlas_source_proxy, pi.name );
2171- }
2172- }
2173- }
2174- }
2175- internal_undo_redo->end_force_keep_in_merge_ends ();
2176- }
2177-
21782144#undef ADD_UNDO
21792145}
21802146
@@ -2204,6 +2170,14 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
22042170 tile_set->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_tile_set_changed));
22052171 }
22062172
2173+ if (tile_set_atlas_source) {
2174+ tile_set_atlas_source->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_update_source_texture));
2175+ if (atlas_source_texture.is_valid ()) {
2176+ atlas_source_texture->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles));
2177+ atlas_source_texture = Ref<Texture2D>();
2178+ }
2179+ }
2180+
22072181 // Clear the selection.
22082182 selection.clear ();
22092183
@@ -2219,6 +2193,11 @@ void TileSetAtlasSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetAtlasSource
22192193 tile_set->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_tile_set_changed));
22202194 }
22212195
2196+ if (tile_set_atlas_source) {
2197+ tile_set_atlas_source->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_update_source_texture));
2198+ _update_source_texture ();
2199+ }
2200+
22222201 if (read_only && tools_button_group->get_pressed_button () == tool_paint_button) {
22232202 tool_paint_button->set_pressed (false );
22242203 tool_setup_atlas_source_button->set_pressed (true );
@@ -2247,6 +2226,61 @@ void TileSetAtlasSourceEditor::init_source() {
22472226 confirm_auto_create_tiles->popup_centered ();
22482227}
22492228
2229+ void TileSetAtlasSourceEditor::_update_source_texture () {
2230+ if (tile_set_atlas_source && tile_set_atlas_source->get_texture () == atlas_source_texture) {
2231+ return ;
2232+ }
2233+
2234+ if (atlas_source_texture.is_valid ()) {
2235+ atlas_source_texture->disconnect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles));
2236+ atlas_source_texture = Ref<Texture2D>();
2237+ }
2238+
2239+ if (!tile_set_atlas_source || tile_set_atlas_source->get_texture ().is_null ()) {
2240+ return ;
2241+ }
2242+ atlas_source_texture = tile_set_atlas_source->get_texture ();
2243+ atlas_source_texture->connect_changed (callable_mp (this , &TileSetAtlasSourceEditor::_check_outside_tiles), CONNECT_DEFERRED );
2244+ _check_outside_tiles ();
2245+ }
2246+
2247+ void TileSetAtlasSourceEditor::_check_outside_tiles () {
2248+ ERR_FAIL_NULL (tile_set_atlas_source);
2249+ outside_tiles_warning->set_visible (!read_only && tile_set_atlas_source->has_tiles_outside_texture ());
2250+ 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 ());
2251+ }
2252+
2253+ void TileSetAtlasSourceEditor::_cleanup_outside_tiles () {
2254+ ERR_FAIL_NULL (tile_set_atlas_source);
2255+
2256+ List<PropertyInfo> list;
2257+ tile_set_atlas_source->get_property_list (&list);
2258+ HashMap<Vector2i, List<const PropertyInfo *>> per_tile = _group_properties_per_tiles (list, tile_set_atlas_source);
2259+ Vector<Vector2i> tiles_outside = tile_set_atlas_source->get_tiles_outside_texture ();
2260+
2261+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton ();
2262+ undo_redo->create_action (TTR (" Remove Tiles Outside the Texture" ));
2263+
2264+ undo_redo->add_do_method (tile_set_atlas_source, " clear_tiles_outside_texture" );
2265+ for (const Vector2i &coords : tiles_outside) {
2266+ undo_redo->add_undo_method (tile_set_atlas_source, " create_tile" , coords);
2267+ if (per_tile.has (coords)) {
2268+ for (List<const PropertyInfo *>::Element *E_property = per_tile[coords].front (); E_property; E_property = E_property->next ()) {
2269+ String property = E_property->get ()->name ;
2270+ Variant value = tile_set_atlas_source->get (property);
2271+ if (value.get_type () != Variant::NIL ) {
2272+ undo_redo->add_undo_method (tile_set_atlas_source, " set" , E_property->get ()->name , value);
2273+ }
2274+ }
2275+ }
2276+ }
2277+
2278+ undo_redo->add_do_method (this , " _check_outside_tiles" );
2279+ undo_redo->add_undo_method (this , " _check_outside_tiles" );
2280+ undo_redo->commit_action ();
2281+ outside_tiles_warning->hide ();
2282+ }
2283+
22502284void TileSetAtlasSourceEditor::_auto_create_tiles () {
22512285 if (!tile_set_atlas_source) {
22522286 return ;
@@ -2363,8 +2397,8 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
23632397 tool_paint_button->set_icon (get_theme_icon (SNAME (" CanvasItem" ), SNAME (" EditorIcons" )));
23642398
23652399 tools_settings_erase_button->set_icon (get_theme_icon (SNAME (" Eraser" ), SNAME (" EditorIcons" )));
2366-
23672400 tool_advanced_menu_button->set_icon (get_theme_icon (SNAME (" GuiTabMenuHl" ), SNAME (" EditorIcons" )));
2401+ outside_tiles_warning->set_texture (get_theme_icon (SNAME (" StatusWarning" ), SNAME (" EditorIcons" )));
23682402
23692403 resize_handle = get_theme_icon (SNAME (" EditorHandle" ), SNAME (" EditorIcons" ));
23702404 resize_handle_disabled = get_theme_icon (SNAME (" EditorHandleDisabled" ), SNAME (" EditorIcons" ));
@@ -2413,6 +2447,7 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
24132447
24142448void TileSetAtlasSourceEditor::_bind_methods () {
24152449 ClassDB::bind_method (D_METHOD (" _set_selection_from_array" ), &TileSetAtlasSourceEditor::_set_selection_from_array);
2450+ ClassDB::bind_method (D_METHOD (" _check_outside_tiles" ), &TileSetAtlasSourceEditor::_check_outside_tiles);
24162451
24172452 ADD_SIGNAL (MethodInfo (" source_id_changed" , PropertyInfo (Variant::INT , " source_id" )));
24182453}
@@ -2555,9 +2590,16 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
25552590 tool_advanced_menu_button->set_flat (true );
25562591 tool_advanced_menu_button->get_popup ()->add_item (TTR (" Create Tiles in Non-Transparent Texture Regions" ), ADVANCED_AUTO_CREATE_TILES );
25572592 tool_advanced_menu_button->get_popup ()->add_item (TTR (" Remove Tiles in Fully Transparent Texture Regions" ), ADVANCED_AUTO_REMOVE_TILES );
2593+ tool_advanced_menu_button->get_popup ()->add_item (TTR (" Remove Tiles Outside the Texture" ), ADVANCED_CLEANUP_TILES );
25582594 tool_advanced_menu_button->get_popup ()->connect (" id_pressed" , callable_mp (this , &TileSetAtlasSourceEditor::_menu_option));
25592595 tool_settings->add_child (tool_advanced_menu_button);
25602596
2597+ outside_tiles_warning = memnew (TextureRect);
2598+ outside_tiles_warning->set_stretch_mode (TextureRect::STRETCH_KEEP_ASPECT_CENTERED );
2599+ 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" )));
2600+ outside_tiles_warning->hide ();
2601+ tool_settings->add_child (outside_tiles_warning);
2602+
25612603 _update_toolbar ();
25622604
25632605 // Right side of toolbar.
0 commit comments