Browse Source

Merge pull request #74717 from KoBeWi/tilesetmap_handler_plugin

Add separate editor plugin for TileMap and TileSet
Yuri Sizov 2 years ago
parent
commit
6c11fcd01a

+ 1 - 0
doc/classes/EditorPlugin.xml

@@ -326,6 +326,7 @@
 			<param index="0" name="object" type="Object" />
 			<param index="0" name="object" type="Object" />
 			<description>
 			<description>
 				Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_3d_gui_input] these will be called too.
 				Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_3d_gui_input] these will be called too.
+				[b]Note:[/b] Each plugin should handle only one type of objects at a time. If a plugin handes more types of objects and they are edited at the same time, it will result in errors.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="_has_main_screen" qualifiers="virtual const">
 		<method name="_has_main_screen" qualifiers="virtual const">

+ 29 - 29
editor/plugins/tiles/tile_map_editor.cpp

@@ -109,8 +109,8 @@ void TileMapEditorTilesPlugin::_update_toolbar() {
 	}
 	}
 }
 }
 
 
-Vector<TileMapEditorPlugin::TabData> TileMapEditorTilesPlugin::get_tabs() const {
-	Vector<TileMapEditorPlugin::TabData> tabs;
+Vector<TileMapSubEditorPlugin::TabData> TileMapEditorTilesPlugin::get_tabs() const {
+	Vector<TileMapSubEditorPlugin::TabData> tabs;
 	tabs.push_back({ toolbar, tiles_bottom_panel });
 	tabs.push_back({ toolbar, tiles_bottom_panel });
 	tabs.push_back({ toolbar, patterns_bottom_panel });
 	tabs.push_back({ toolbar, patterns_bottom_panel });
 	return tabs;
 	return tabs;
@@ -147,7 +147,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
 		old_source = -1;
 		old_source = -1;
 	}
 	}
 
 
-	List<int> source_ids = TilesEditorPlugin::get_singleton()->get_sorted_sources(tile_set);
+	List<int> source_ids = TilesEditorUtils::get_singleton()->get_sorted_sources(tile_set);
 	for (const int &source_id : source_ids) {
 	for (const int &source_id : source_ids) {
 		TileSetSource *source = *tile_set->get_source(source_id);
 		TileSetSource *source = *tile_set->get_source(source_id);
 
 
@@ -209,7 +209,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
 	}
 	}
 
 
 	// Synchronize the lists.
 	// Synchronize the lists.
-	TilesEditorPlugin::get_singleton()->set_sources_lists_current(sources_list->get_current());
+	TilesEditorUtils::get_singleton()->set_sources_lists_current(sources_list->get_current());
 }
 }
 
 
 void TileMapEditorTilesPlugin::_update_source_display() {
 void TileMapEditorTilesPlugin::_update_source_display() {
@@ -322,7 +322,7 @@ void TileMapEditorTilesPlugin::_update_patterns_list() {
 		int id = patterns_item_list->add_item("");
 		int id = patterns_item_list->add_item("");
 		patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
 		patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
 		patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
 		patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
-		TilesEditorPlugin::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapEditorTilesPlugin::_pattern_preview_done));
+		TilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapEditorTilesPlugin::_pattern_preview_done));
 	}
 	}
 
 
 	// Update the label visibility.
 	// Update the label visibility.
@@ -354,7 +354,7 @@ void TileMapEditorTilesPlugin::_update_atlas_view() {
 	ERR_FAIL_COND(!atlas_source);
 	ERR_FAIL_COND(!atlas_source);
 
 
 	tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
 	tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
-	TilesEditorPlugin::get_singleton()->synchronize_atlas_view(tile_atlas_view);
+	TilesEditorUtils::get_singleton()->synchronize_atlas_view(tile_atlas_view);
 	tile_atlas_control->queue_redraw();
 	tile_atlas_control->queue_redraw();
 }
 }
 
 
@@ -1386,7 +1386,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
 				for (int i = 0; i < sources_list->get_item_count(); i++) {
 				for (int i = 0; i < sources_list->get_item_count(); i++) {
 					if (int(sources_list->get_item_metadata(i)) == picked_source) {
 					if (int(sources_list->get_item_metadata(i)) == picked_source) {
 						sources_list->set_current(i);
 						sources_list->set_current(i);
-						TilesEditorPlugin::get_singleton()->set_sources_lists_current(i);
+						TilesEditorUtils::get_singleton()->set_sources_lists_current(i);
 						break;
 						break;
 					}
 					}
 				}
 				}
@@ -1720,7 +1720,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
 				if (frame > 0) {
 				if (frame > 0) {
 					color.a *= 0.3;
 					color.a *= 0.3;
 				}
 				}
-				TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E.get_atlas_coords(), frame), color);
+				TilesEditorUtils::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E.get_atlas_coords(), frame), color);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1729,7 +1729,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
 	if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
 	if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
 		for (int frame = 0; frame < atlas->get_tile_animation_frames_count(hovered_tile.get_atlas_coords()); frame++) {
 		for (int frame = 0; frame < atlas->get_tile_animation_frames_count(hovered_tile.get_atlas_coords()); frame++) {
 			Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
 			Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
-			TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color);
+			TilesEditorUtils::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(hovered_tile.get_atlas_coords(), frame), color);
 		}
 		}
 	}
 	}
 
 
@@ -1751,7 +1751,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
 			}
 			}
 		}
 		}
 		for (const Vector2i &E : to_draw) {
 		for (const Vector2i &E : to_draw) {
-			TilesEditorPlugin::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E));
+			TilesEditorUtils::draw_selection_rect(tile_atlas_control, atlas->get_tile_texture_region(E));
 		}
 		}
 	}
 	}
 }
 }
@@ -1900,7 +1900,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
 		if (E.source_id == source_id && E.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E.alternative_tile > 0) {
 		if (E.source_id == source_id && E.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E.alternative_tile > 0) {
 			Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.get_atlas_coords(), E.alternative_tile);
 			Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.get_atlas_coords(), E.alternative_tile);
 			if (rect != Rect2i()) {
 			if (rect != Rect2i()) {
-				TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect);
+				TilesEditorUtils::draw_selection_rect(alternative_tiles_control, rect);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1909,7 +1909,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
 	if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
 	if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
 		Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
 		Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
 		if (rect != Rect2i()) {
 		if (rect != Rect2i()) {
-			TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
+			TilesEditorUtils::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
 		}
 		}
 	}
 	}
 }
 }
@@ -2031,10 +2031,10 @@ void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer
 }
 }
 
 
 void TileMapEditorTilesPlugin::_set_source_sort(int p_sort) {
 void TileMapEditorTilesPlugin::_set_source_sort(int p_sort) {
-	for (int i = 0; i != TilesEditorPlugin::SOURCE_SORT_MAX; i++) {
+	for (int i = 0; i != TilesEditorUtils::SOURCE_SORT_MAX; i++) {
 		source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
 		source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
 	}
 	}
-	TilesEditorPlugin::get_singleton()->set_sorting_option(p_sort);
+	TilesEditorUtils::get_singleton()->set_sorting_option(p_sort);
 	_update_tile_set_sources_list();
 	_update_tile_set_sources_list();
 	EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "tile_source_sort", p_sort);
 	EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "tile_source_sort", p_sort);
 }
 }
@@ -2217,11 +2217,11 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
 
 
 	PopupMenu *p = source_sort_button->get_popup();
 	PopupMenu *p = source_sort_button->get_popup();
 	p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort));
 	p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort));
-	p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorPlugin::SOURCE_SORT_ID);
-	p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorPlugin::SOURCE_SORT_ID_REVERSE);
-	p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorPlugin::SOURCE_SORT_NAME);
-	p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorPlugin::SOURCE_SORT_NAME_REVERSE);
-	p->set_item_checked(TilesEditorPlugin::SOURCE_SORT_ID, true);
+	p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorUtils::SOURCE_SORT_ID);
+	p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorUtils::SOURCE_SORT_ID_REVERSE);
+	p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorUtils::SOURCE_SORT_NAME);
+	p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorUtils::SOURCE_SORT_NAME_REVERSE);
+	p->set_item_checked(TilesEditorUtils::SOURCE_SORT_ID, true);
 	sources_bottom_actions->add_child(source_sort_button);
 	sources_bottom_actions->add_child(source_sort_button);
 
 
 	sources_list = memnew(ItemList);
 	sources_list = memnew(ItemList);
@@ -2233,8 +2233,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
 	sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
 	sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
 	sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
 	sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
 	sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1));
 	sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1));
-	sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current));
-	sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button));
+	sources_list->connect("item_selected", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_sources_lists_current));
+	sources_list->connect("visibility_changed", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::synchronize_sources_list).bind(sources_list, source_sort_button));
 	sources_list->add_user_signal(MethodInfo("sort_request"));
 	sources_list->add_user_signal(MethodInfo("sort_request"));
 	sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list));
 	sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list));
 	split_container_left_side->add_child(sources_list);
 	split_container_left_side->add_child(sources_list);
@@ -2246,7 +2246,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
 	tile_atlas_view->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	tile_atlas_view->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	tile_atlas_view->set_texture_grid_visible(false);
 	tile_atlas_view->set_texture_grid_visible(false);
 	tile_atlas_view->set_tile_shape_grid_visible(false);
 	tile_atlas_view->set_tile_shape_grid_visible(false);
-	tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform));
+	tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_atlas_view_transform));
 	atlas_sources_split_container->add_child(tile_atlas_view);
 	atlas_sources_split_container->add_child(tile_atlas_view);
 
 
 	tile_atlas_control = memnew(Control);
 	tile_atlas_control = memnew(Control);
@@ -2353,8 +2353,8 @@ void TileMapEditorTerrainsPlugin::_update_toolbar() {
 	}
 	}
 }
 }
 
 
-Vector<TileMapEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() const {
-	Vector<TileMapEditorPlugin::TabData> tabs;
+Vector<TileMapSubEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() const {
+	Vector<TileMapSubEditorPlugin::TabData> tabs;
 	tabs.push_back({ toolbar, main_vbox_container });
 	tabs.push_back({ toolbar, main_vbox_container });
 	return tabs;
 	return tabs;
 }
 }
@@ -3549,7 +3549,7 @@ void TileMapEditor::_update_bottom_panel() {
 
 
 	// Update the visibility of controls.
 	// Update the visibility of controls.
 	missing_tileset_label->set_visible(!tile_set.is_valid());
 	missing_tileset_label->set_visible(!tile_set.is_valid());
-	for (TileMapEditorPlugin::TabData &tab_data : tabs_data) {
+	for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
 		tab_data.panel->hide();
 		tab_data.panel->hide();
 	}
 	}
 	if (tile_set.is_valid()) {
 	if (tile_set.is_valid()) {
@@ -3639,14 +3639,14 @@ void TileMapEditor::_tab_changed(int p_tab_id) {
 	tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
 	tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
 
 
 	// Update toolbar.
 	// Update toolbar.
-	for (TileMapEditorPlugin::TabData &tab_data : tabs_data) {
+	for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
 		tab_data.toolbar->hide();
 		tab_data.toolbar->hide();
 	}
 	}
 	tabs_data[p_tab_id].toolbar->show();
 	tabs_data[p_tab_id].toolbar->show();
 
 
 	// Update visible panel.
 	// Update visible panel.
 	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
 	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-	for (TileMapEditorPlugin::TabData &tab_data : tabs_data) {
+	for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
 		tab_data.panel->hide();
 		tab_data.panel->hide();
 	}
 	}
 	if (tile_map && tile_map->get_tileset().is_valid()) {
 	if (tile_map && tile_map->get_tileset().is_valid()) {
@@ -4006,7 +4006,7 @@ TileMapEditor::TileMapEditor() {
 	tabs_bar = memnew(TabBar);
 	tabs_bar = memnew(TabBar);
 	tabs_bar->set_clip_tabs(false);
 	tabs_bar->set_clip_tabs(false);
 	for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
 	for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
-		Vector<TileMapEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
+		Vector<TileMapSubEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
 		for (int tab_index = 0; tab_index < tabs_vector.size(); tab_index++) {
 		for (int tab_index = 0; tab_index < tabs_vector.size(); tab_index++) {
 			tabs_bar->add_tab(tabs_vector[tab_index].panel->get_name());
 			tabs_bar->add_tab(tabs_vector[tab_index].panel->get_name());
 			tabs_data.push_back(tabs_vector[tab_index]);
 			tabs_data.push_back(tabs_vector[tab_index]);
@@ -4024,7 +4024,7 @@ TileMapEditor::TileMapEditor() {
 	tile_map_toolbar->add_child(tabs_bar);
 	tile_map_toolbar->add_child(tabs_bar);
 
 
 	// Tabs toolbars.
 	// Tabs toolbars.
-	for (TileMapEditorPlugin::TabData &tab_data : tabs_data) {
+	for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
 		tab_data.toolbar->hide();
 		tab_data.toolbar->hide();
 		if (!tab_data.toolbar->get_parent()) {
 		if (!tab_data.toolbar->get_parent()) {
 			tile_map_toolbar->add_child(tab_data.toolbar);
 			tile_map_toolbar->add_child(tab_data.toolbar);

+ 8 - 8
editor/plugins/tiles/tile_map_editor.h

@@ -48,7 +48,7 @@
 #include "scene/gui/tab_bar.h"
 #include "scene/gui/tab_bar.h"
 #include "scene/gui/tree.h"
 #include "scene/gui/tree.h"
 
 
-class TileMapEditorPlugin : public Object {
+class TileMapSubEditorPlugin : public Object {
 public:
 public:
 	struct TabData {
 	struct TabData {
 		Control *toolbar = nullptr;
 		Control *toolbar = nullptr;
@@ -65,8 +65,8 @@ public:
 	virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer){};
 	virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer){};
 };
 };
 
 
-class TileMapEditorTilesPlugin : public TileMapEditorPlugin {
-	GDCLASS(TileMapEditorTilesPlugin, TileMapEditorPlugin);
+class TileMapEditorTilesPlugin : public TileMapSubEditorPlugin {
+	GDCLASS(TileMapEditorTilesPlugin, TileMapSubEditorPlugin);
 
 
 private:
 private:
 	ObjectID tile_map_id;
 	ObjectID tile_map_id;
@@ -219,8 +219,8 @@ public:
 	~TileMapEditorTilesPlugin();
 	~TileMapEditorTilesPlugin();
 };
 };
 
 
-class TileMapEditorTerrainsPlugin : public TileMapEditorPlugin {
-	GDCLASS(TileMapEditorTerrainsPlugin, TileMapEditorPlugin);
+class TileMapEditorTerrainsPlugin : public TileMapSubEditorPlugin {
+	GDCLASS(TileMapEditorTerrainsPlugin, TileMapSubEditorPlugin);
 
 
 private:
 private:
 	ObjectID tile_map_id;
 	ObjectID tile_map_id;
@@ -321,7 +321,7 @@ private:
 	int tile_map_layer = -1;
 	int tile_map_layer = -1;
 
 
 	// Vector to keep plugins.
 	// Vector to keep plugins.
-	Vector<TileMapEditorPlugin *> tile_map_editor_plugins;
+	Vector<TileMapSubEditorPlugin *> tile_map_editor_plugins;
 
 
 	// Toolbar.
 	// Toolbar.
 	HFlowContainer *tile_map_toolbar = nullptr;
 	HFlowContainer *tile_map_toolbar = nullptr;
@@ -339,8 +339,8 @@ private:
 	// Bottom panel.
 	// Bottom panel.
 	Label *missing_tileset_label = nullptr;
 	Label *missing_tileset_label = nullptr;
 	TabBar *tabs_bar = nullptr;
 	TabBar *tabs_bar = nullptr;
-	LocalVector<TileMapEditorPlugin::TabData> tabs_data;
-	LocalVector<TileMapEditorPlugin *> tabs_plugins;
+	LocalVector<TileMapSubEditorPlugin::TabData> tabs_data;
+	LocalVector<TileMapSubEditorPlugin *> tabs_plugins;
 	void _update_bottom_panel();
 	void _update_bottom_panel();
 
 
 	// TileMap.
 	// TileMap.

+ 11 - 11
editor/plugins/tiles/tile_set_atlas_source_editor.cpp

@@ -1014,7 +1014,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
 	tile_atlas_view->queue_redraw();
 	tile_atlas_view->queue_redraw();
 
 
 	// Synchronize atlas view.
 	// Synchronize atlas view.
-	TilesEditorPlugin::get_singleton()->synchronize_atlas_view(tile_atlas_view);
+	TilesEditorUtils::get_singleton()->synchronize_atlas_view(tile_atlas_view);
 }
 }
 
 
 void TileSetAtlasSourceEditor::_update_toolbar() {
 void TileSetAtlasSourceEditor::_update_toolbar() {
@@ -1724,7 +1724,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 				for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(selected.tile); frame++) {
 				for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(selected.tile); frame++) {
 					Color color = Color(0.0, 1.0, 0.0, frame == 0 ? 1.0 : 0.3);
 					Color color = Color(0.0, 1.0, 0.0, frame == 0 ? 1.0 : 0.3);
 					Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile, frame);
 					Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile, frame);
-					TilesEditorPlugin::draw_selection_rect(tile_atlas_control, region, color);
+					TilesEditorUtils::draw_selection_rect(tile_atlas_control, region, color);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -1766,7 +1766,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 		// Draw the tiles to be removed.
 		// Draw the tiles to be removed.
 		for (const Vector2i &E : drag_modified_tiles) {
 		for (const Vector2i &E : drag_modified_tiles) {
 			for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(E); frame++) {
 			for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(E); frame++) {
-				TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(E, frame), Color(0.0, 0.0, 0.0));
+				TilesEditorUtils::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(E, frame), Color(0.0, 0.0, 0.0));
 			}
 			}
 		}
 		}
 	} else if (drag_type == DRAG_TYPE_RECT_SELECT || drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT) {
 	} else if (drag_type == DRAG_TYPE_RECT_SELECT || drag_type == DRAG_TYPE_REMOVE_TILES_USING_RECT) {
@@ -1793,7 +1793,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 
 
 		for (const Vector2i &E : to_paint) {
 		for (const Vector2i &E : to_paint) {
 			Vector2i coords = E;
 			Vector2i coords = E;
-			TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(coords), color);
+			TilesEditorUtils::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(coords), color);
 		}
 		}
 	} else if (drag_type == DRAG_TYPE_CREATE_TILES_USING_RECT) {
 	} else if (drag_type == DRAG_TYPE_CREATE_TILES_USING_RECT) {
 		// Draw tiles to be created.
 		// Draw tiles to be created.
@@ -1810,7 +1810,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 				Vector2i coords = Vector2i(x, y);
 				Vector2i coords = Vector2i(x, y);
 				if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
 				if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
 					Vector2i origin = margins + (coords * (tile_size + separation));
 					Vector2i origin = margins + (coords * (tile_size + separation));
-					TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
+					TilesEditorUtils::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
 				}
 				}
 			}
 			}
 		}
 		}
@@ -1827,7 +1827,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 		Vector2i separation = tile_set_atlas_source->get_separation();
 		Vector2i separation = tile_set_atlas_source->get_separation();
 		Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
 		Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
 		Vector2i origin = margins + (area.position * (tile_size + separation));
 		Vector2i origin = margins + (area.position * (tile_size + separation));
-		TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, area.size * tile_size));
+		TilesEditorUtils::draw_selection_rect(tile_atlas_control, Rect2i(origin, area.size * tile_size));
 	} else {
 	} else {
 		Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
 		Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
 		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) {
 		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) {
@@ -1836,7 +1836,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 				// Draw existing hovered tile.
 				// Draw existing hovered tile.
 				for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(hovered_tile); frame++) {
 				for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(hovered_tile); frame++) {
 					Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
 					Color color = Color(1.0, 0.8, 0.0, frame == 0 ? 0.6 : 0.3);
-					TilesEditorPlugin::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(hovered_tile, frame), color);
+					TilesEditorUtils::draw_selection_rect(tile_atlas_control, tile_set_atlas_source->get_tile_texture_region(hovered_tile, frame), color);
 				}
 				}
 			} else {
 			} else {
 				// Draw empty tile, only in add/remove tiles mode.
 				// Draw empty tile, only in add/remove tiles mode.
@@ -1845,7 +1845,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
 					Vector2i separation = tile_set_atlas_source->get_separation();
 					Vector2i separation = tile_set_atlas_source->get_separation();
 					Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
 					Vector2i tile_size = tile_set_atlas_source->get_texture_region_size();
 					Vector2i origin = margins + (hovered_base_tile_coords * (tile_size + separation));
 					Vector2i origin = margins + (hovered_base_tile_coords * (tile_size + separation));
-					TilesEditorPlugin::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
+					TilesEditorUtils::draw_selection_rect(tile_atlas_control, Rect2i(origin, tile_size));
 				}
 				}
 			}
 			}
 		}
 		}
@@ -2004,7 +2004,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
 		if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
 		if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
 			Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
 			Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
 			if (rect != Rect2i()) {
 			if (rect != Rect2i()) {
-				TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
+				TilesEditorUtils::draw_selection_rect(alternative_tiles_control, rect, Color(1.0, 0.8, 0.0, 0.5));
 			}
 			}
 		}
 		}
 
 
@@ -2014,7 +2014,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
 			if (selected.alternative >= 1) {
 			if (selected.alternative >= 1) {
 				Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative);
 				Rect2i rect = tile_atlas_view->get_alternative_tile_rect(selected.tile, selected.alternative);
 				if (rect != Rect2i()) {
 				if (rect != Rect2i()) {
-					TilesEditorPlugin::draw_selection_rect(alternative_tiles_control, rect);
+					TilesEditorUtils::draw_selection_rect(alternative_tiles_control, rect);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -2580,7 +2580,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
 	tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
 	tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
 	tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
 	tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
 	tile_atlas_view->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
 	tile_atlas_view->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
-	tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform));
+	tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_atlas_view_transform));
 	tile_atlas_view->connect("transform_changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed).unbind(2));
 	tile_atlas_view->connect("transform_changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed).unbind(2));
 	right_panel->add_child(tile_atlas_view);
 	right_panel->add_child(tile_atlas_view);
 
 

+ 12 - 12
editor/plugins/tiles/tile_set_editor.cpp

@@ -149,7 +149,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
 	sources_list->clear();
 	sources_list->clear();
 
 
 	// Update the atlas sources.
 	// Update the atlas sources.
-	List<int> source_ids = TilesEditorPlugin::get_singleton()->get_sorted_sources(tile_set);
+	List<int> source_ids = TilesEditorUtils::get_singleton()->get_sorted_sources(tile_set);
 	for (const int &source_id : source_ids) {
 	for (const int &source_id : source_ids) {
 		TileSetSource *source = *tile_set->get_source(source_id);
 		TileSetSource *source = *tile_set->get_source(source_id);
 
 
@@ -221,7 +221,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
 	_source_selected(sources_list->get_current());
 	_source_selected(sources_list->get_current());
 
 
 	// Synchronize the lists.
 	// Synchronize the lists.
-	TilesEditorPlugin::get_singleton()->set_sources_lists_current(sources_list->get_current());
+	TilesEditorUtils::get_singleton()->set_sources_lists_current(sources_list->get_current());
 }
 }
 
 
 void TileSetEditor::_texture_file_selected(const String &p_path) {
 void TileSetEditor::_texture_file_selected(const String &p_path) {
@@ -352,8 +352,8 @@ void TileSetEditor::_sources_advanced_menu_id_pressed(int p_id_pressed) {
 }
 }
 
 
 void TileSetEditor::_set_source_sort(int p_sort) {
 void TileSetEditor::_set_source_sort(int p_sort) {
-	TilesEditorPlugin::get_singleton()->set_sorting_option(p_sort);
-	for (int i = 0; i != TilesEditorPlugin::SOURCE_SORT_MAX; i++) {
+	TilesEditorUtils::get_singleton()->set_sorting_option(p_sort);
+	for (int i = 0; i != TilesEditorUtils::SOURCE_SORT_MAX; i++) {
 		source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
 		source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
 	}
 	}
 
 
@@ -450,7 +450,7 @@ void TileSetEditor::_update_patterns_list() {
 		int id = patterns_item_list->add_item("");
 		int id = patterns_item_list->add_item("");
 		patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
 		patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
 		patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
 		patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
-		TilesEditorPlugin::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileSetEditor::_pattern_preview_done));
+		TilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileSetEditor::_pattern_preview_done));
 	}
 	}
 
 
 	// Update the label visibility.
 	// Update the label visibility.
@@ -854,19 +854,19 @@ TileSetEditor::TileSetEditor() {
 
 
 	PopupMenu *p = source_sort_button->get_popup();
 	PopupMenu *p = source_sort_button->get_popup();
 	p->connect("id_pressed", callable_mp(this, &TileSetEditor::_set_source_sort));
 	p->connect("id_pressed", callable_mp(this, &TileSetEditor::_set_source_sort));
-	p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorPlugin::SOURCE_SORT_ID);
-	p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorPlugin::SOURCE_SORT_ID_REVERSE);
-	p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorPlugin::SOURCE_SORT_NAME);
-	p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorPlugin::SOURCE_SORT_NAME_REVERSE);
-	p->set_item_checked(TilesEditorPlugin::SOURCE_SORT_ID, true);
+	p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorUtils::SOURCE_SORT_ID);
+	p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorUtils::SOURCE_SORT_ID_REVERSE);
+	p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorUtils::SOURCE_SORT_NAME);
+	p->add_radio_check_item(TTR("Sort by Name (Descending)"), TilesEditorUtils::SOURCE_SORT_NAME_REVERSE);
+	p->set_item_checked(TilesEditorUtils::SOURCE_SORT_ID, true);
 
 
 	sources_list = memnew(ItemList);
 	sources_list = memnew(ItemList);
 	sources_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE);
 	sources_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE);
 	sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
 	sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
 	sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
 	sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
 	sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
 	sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
-	sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current));
-	sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list).bind(sources_list, source_sort_button));
+	sources_list->connect("item_selected", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_sources_lists_current));
+	sources_list->connect("visibility_changed", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::synchronize_sources_list).bind(sources_list, source_sort_button));
 	sources_list->add_user_signal(MethodInfo("sort_request"));
 	sources_list->add_user_signal(MethodInfo("sort_request"));
 	sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1));
 	sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1));
 	sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
 	sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);

+ 139 - 170
editor/plugins/tiles/tiles_editor_plugin.cpp

@@ -38,6 +38,7 @@
 #include "editor/editor_node.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"
 #include "editor/editor_settings.h"
+#include "editor/inspector_dock.h"
 #include "editor/plugins/canvas_item_editor_plugin.h"
 #include "editor/plugins/canvas_item_editor_plugin.h"
 
 
 #include "scene/2d/tile_map.h"
 #include "scene/2d/tile_map.h"
@@ -48,23 +49,24 @@
 #include "scene/resources/image_texture.h"
 #include "scene/resources/image_texture.h"
 #include "scene/resources/tile_set.h"
 #include "scene/resources/tile_set.h"
 
 
-TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr;
+TilesEditorUtils *TilesEditorUtils::singleton = nullptr;
+TileMapEditorPlugin *local_singleton = nullptr;
 
 
-void TilesEditorPlugin::_preview_frame_started() {
-	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_pattern_preview_done));
+void TilesEditorUtils::_preview_frame_started() {
+	RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<TilesEditorUtils *>(this), &TilesEditorUtils::_pattern_preview_done));
 }
 }
 
 
-void TilesEditorPlugin::_pattern_preview_done() {
+void TilesEditorUtils::_pattern_preview_done() {
 	pattern_preview_done.post();
 	pattern_preview_done.post();
 }
 }
 
 
-void TilesEditorPlugin::_thread_func(void *ud) {
-	TilesEditorPlugin *te = static_cast<TilesEditorPlugin *>(ud);
+void TilesEditorUtils::_thread_func(void *ud) {
+	TilesEditorUtils *te = static_cast<TilesEditorUtils *>(ud);
 	set_current_thread_safe_for_nodes(true);
 	set_current_thread_safe_for_nodes(true);
 	te->_thread();
 	te->_thread();
 }
 }
 
 
-void TilesEditorPlugin::_thread() {
+void TilesEditorUtils::_thread() {
 	pattern_thread_exited.clear();
 	pattern_thread_exited.clear();
 	while (!pattern_thread_exit.is_set()) {
 	while (!pattern_thread_exit.is_set()) {
 		pattern_preview_sem.wait();
 		pattern_preview_sem.wait();
@@ -124,7 +126,7 @@ void TilesEditorPlugin::_thread() {
 				// Add the viewport at the last moment to avoid rendering too early.
 				// Add the viewport at the last moment to avoid rendering too early.
 				EditorNode::get_singleton()->call_deferred("add_child", viewport);
 				EditorNode::get_singleton()->call_deferred("add_child", viewport);
 
 
-				RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONE_SHOT);
+				RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorUtils *>(this), &TilesEditorUtils::_preview_frame_started), Object::CONNECT_ONE_SHOT);
 
 
 				pattern_preview_done.wait();
 				pattern_preview_done.wait();
 
 
@@ -144,85 +146,7 @@ void TilesEditorPlugin::_thread() {
 	pattern_thread_exited.set();
 	pattern_thread_exited.set();
 }
 }
 
 
-void TilesEditorPlugin::_tile_map_changed() {
-	tile_map_changed_needs_update = true;
-}
-
-void TilesEditorPlugin::_update_editors() {
-	// If tile_map is not edited, we change the edited only if we are not editing a tile_set.
-	if (tile_set.is_valid()) {
-		tileset_editor->edit(tile_set);
-	}
-
-	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-	if (tile_map) {
-		tilemap_editor->edit(tile_map);
-	} else {
-		tilemap_editor->edit(nullptr);
-	}
-
-	// Update the viewport.
-	CanvasItemEditor::get_singleton()->update_viewport();
-
-	// Make sure the tile set editor is visible if we have one assigned.
-	tileset_editor_button->set_visible(is_visible && tile_set.is_valid());
-	tilemap_editor_button->set_visible(is_visible && tile_map);
-
-	// Update visibility of bottom panel buttons.
-	if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) {
-		if (tile_map) {
-			EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor);
-		} else {
-			EditorNode::get_singleton()->hide_bottom_panel();
-		}
-	}
-}
-
-void TilesEditorPlugin::_notification(int p_what) {
-	switch (p_what) {
-		case NOTIFICATION_INTERNAL_PROCESS: {
-			if (tile_map_changed_needs_update) {
-				TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-				if (tile_map) {
-					tile_set = tile_map->get_tileset();
-				}
-				_update_editors();
-				tile_map_changed_needs_update = false;
-			}
-		} break;
-	}
-}
-
-void TilesEditorPlugin::make_visible(bool p_visible) {
-	if (p_visible || is_tile_map_selected()) {
-		// Disable and hide invalid editors.
-		TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-		tileset_editor_button->set_visible(tile_set.is_valid());
-		tilemap_editor_button->set_visible(tile_map);
-		if (tile_map && (!is_editing_tile_set || !p_visible)) {
-			EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor);
-		} else {
-			EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
-		}
-		is_visible = true;
-	} else {
-		tileset_editor_button->hide();
-		tilemap_editor_button->hide();
-		EditorNode::get_singleton()->hide_bottom_panel();
-		is_visible = false;
-	}
-}
-
-bool TilesEditorPlugin::is_tile_map_selected() {
-	TypedArray<Node> selection = EditorInterface::get_singleton()->get_selection()->get_selected_nodes();
-	if (selection.size() == 1 && Object::cast_to<TileMap>(selection[0])) {
-		return true;
-	}
-
-	return false;
-}
-
-void TilesEditorPlugin::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback) {
+void TilesEditorUtils::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback) {
 	ERR_FAIL_COND(!p_tile_set.is_valid());
 	ERR_FAIL_COND(!p_tile_set.is_valid());
 	ERR_FAIL_COND(!p_pattern.is_valid());
 	ERR_FAIL_COND(!p_pattern.is_valid());
 	{
 	{
@@ -232,11 +156,11 @@ void TilesEditorPlugin::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileM
 	pattern_preview_sem.post();
 	pattern_preview_sem.post();
 }
 }
 
 
-void TilesEditorPlugin::set_sources_lists_current(int p_current) {
+void TilesEditorUtils::set_sources_lists_current(int p_current) {
 	atlas_sources_lists_current = p_current;
 	atlas_sources_lists_current = p_current;
 }
 }
 
 
-void TilesEditorPlugin::synchronize_sources_list(Object *p_current_list, Object *p_current_sort_button) {
+void TilesEditorUtils::synchronize_sources_list(Object *p_current_list, Object *p_current_sort_button) {
 	ItemList *item_list = Object::cast_to<ItemList>(p_current_list);
 	ItemList *item_list = Object::cast_to<ItemList>(p_current_list);
 	MenuButton *sorting_button = Object::cast_to<MenuButton>(p_current_sort_button);
 	MenuButton *sorting_button = Object::cast_to<MenuButton>(p_current_sort_button);
 	ERR_FAIL_COND(!item_list);
 	ERR_FAIL_COND(!item_list);
@@ -264,12 +188,12 @@ void TilesEditorPlugin::synchronize_sources_list(Object *p_current_list, Object
 	}
 	}
 }
 }
 
 
-void TilesEditorPlugin::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) {
+void TilesEditorUtils::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) {
 	atlas_view_zoom = p_zoom;
 	atlas_view_zoom = p_zoom;
 	atlas_view_scroll = p_scroll;
 	atlas_view_scroll = p_scroll;
 }
 }
 
 
-void TilesEditorPlugin::synchronize_atlas_view(Object *p_current) {
+void TilesEditorUtils::synchronize_atlas_view(Object *p_current) {
 	TileAtlasView *tile_atlas_view = Object::cast_to<TileAtlasView>(p_current);
 	TileAtlasView *tile_atlas_view = Object::cast_to<TileAtlasView>(p_current);
 	ERR_FAIL_COND(!tile_atlas_view);
 	ERR_FAIL_COND(!tile_atlas_view);
 
 
@@ -278,11 +202,11 @@ void TilesEditorPlugin::synchronize_atlas_view(Object *p_current) {
 	}
 	}
 }
 }
 
 
-void TilesEditorPlugin::set_sorting_option(int p_option) {
+void TilesEditorUtils::set_sorting_option(int p_option) {
 	source_sort = p_option;
 	source_sort = p_option;
 }
 }
 
 
-List<int> TilesEditorPlugin::get_sorted_sources(const Ref<TileSet> p_tile_set) const {
+List<int> TilesEditorUtils::get_sorted_sources(const Ref<TileSet> p_tile_set) const {
 	SourceNameComparator::tile_set = p_tile_set;
 	SourceNameComparator::tile_set = p_tile_set;
 	List<int> source_ids;
 	List<int> source_ids;
 
 
@@ -310,9 +234,9 @@ List<int> TilesEditorPlugin::get_sorted_sources(const Ref<TileSet> p_tile_set) c
 	return source_ids;
 	return source_ids;
 }
 }
 
 
-Ref<TileSet> TilesEditorPlugin::SourceNameComparator::tile_set;
+Ref<TileSet> TilesEditorUtils::SourceNameComparator::tile_set;
 
 
-bool TilesEditorPlugin::SourceNameComparator::operator()(const int &p_a, const int &p_b) const {
+bool TilesEditorUtils::SourceNameComparator::operator()(const int &p_a, const int &p_b) const {
 	String name_a;
 	String name_a;
 	String name_b;
 	String name_b;
 
 
@@ -359,104 +283,149 @@ bool TilesEditorPlugin::SourceNameComparator::operator()(const int &p_a, const i
 	return NaturalNoCaseComparator()(name_a, name_b);
 	return NaturalNoCaseComparator()(name_a, name_b);
 }
 }
 
 
-void TilesEditorPlugin::edit(Object *p_object) {
-	// Disconnect to changes.
-	TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-	if (tile_map) {
-		tile_map->disconnect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
-	}
+void TilesEditorUtils::draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color) {
+	real_t scale = p_ci->get_global_transform().get_scale().x * 0.5;
+	p_ci->draw_set_transform(p_rect.position, 0, Vector2(1, 1) / scale);
+	RS::get_singleton()->canvas_item_add_nine_patch(
+			p_ci->get_canvas_item(), Rect2(Vector2(), p_rect.size * scale), Rect2(), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("TileSelection"), SNAME("EditorIcons"))->get_rid(),
+			Vector2(2, 2), Vector2(2, 2), RS::NINE_PATCH_STRETCH, RS::NINE_PATCH_STRETCH, false, p_color);
+	p_ci->draw_set_transform_matrix(Transform2D());
+}
 
 
-	// Update edited objects.
-	tile_set = Ref<TileSet>();
-	is_editing_tile_set = false;
-
-	if (p_object) {
-		if (p_object->is_class("TileMap")) {
-			tile_map_id = p_object->get_instance_id();
-			tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
-			tile_set = tile_map->get_tileset();
-			EditorNode::get_singleton()->make_bottom_panel_item_visible(tilemap_editor);
-		} else if (p_object->is_class("TileSet")) {
-			tile_set = Ref<TileSet>(p_object);
-			if (tile_map) {
-				if (tile_map->get_tileset() != tile_set || !tile_map->is_inside_tree() || !is_tile_map_selected()) {
-					tile_map = nullptr;
-					tile_map_id = ObjectID();
-				}
-			}
-			is_editing_tile_set = true;
+TilesEditorUtils::TilesEditorUtils() {
+	singleton = this;
+	// Pattern preview generation thread.
+	pattern_preview_thread.start(_thread_func, this);
+}
+
+TilesEditorUtils::~TilesEditorUtils() {
+	if (pattern_preview_thread.is_started()) {
+		pattern_thread_exit.set();
+		pattern_preview_sem.post();
+		while (!pattern_thread_exited.is_set()) {
+			OS::get_singleton()->delay_usec(10000);
+			RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
 		}
 		}
+		pattern_preview_thread.wait_to_finish();
 	}
 	}
+	singleton = nullptr;
+}
 
 
-	// Update the editors.
-	_update_editors();
+void TileMapEditorPlugin::_tile_map_changed() {
+	if (tile_map_changed_needs_update) {
+		return;
+	}
+	tile_map_changed_needs_update = true;
+	callable_mp(this, &TileMapEditorPlugin::_update_tile_map).call_deferred();
+}
+
+void TileMapEditorPlugin::_update_tile_map() {
+	if (tile_map && tile_map->get_tileset().is_valid()) {
+		EditorNode::get_singleton()->edit_item(tile_map->get_tileset().ptr(), InspectorDock::get_inspector_singleton());
+	}
+	tile_map_changed_needs_update = false;
+}
+
+void TileMapEditorPlugin::_notification(int p_notification) {
+	if (p_notification == NOTIFICATION_EXIT_TREE) {
+		get_tree()->queue_delete(TilesEditorUtils::get_singleton());
+	}
+}
 
 
-	// If the tileset is being edited, the visibility function must be called
-	// here after _update_editors has been called.
-	if (is_editing_tile_set) {
-		EditorNode::get_singleton()->make_bottom_panel_item_visible(tileset_editor);
+void TileMapEditorPlugin::edit(Object *p_object) {
+	if (tile_map) {
+		tile_map->disconnect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
 	}
 	}
 
 
-	// Add change listener.
+	tile_map = Object::cast_to<TileMap>(p_object);
+
+	editor->edit(tile_map);
 	if (tile_map) {
 	if (tile_map) {
-		tile_map->connect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed));
+		tile_map->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
+
+		if (tile_map->get_tileset().is_valid()) {
+			EditorNode::get_singleton()->edit_item(tile_map->get_tileset().ptr(), InspectorDock::get_inspector_singleton());
+		}
 	}
 	}
 }
 }
 
 
-bool TilesEditorPlugin::handles(Object *p_object) const {
-	return p_object->is_class("TileMap") || p_object->is_class("TileSet");
+bool TileMapEditorPlugin::handles(Object *p_object) const {
+	return Object::cast_to<TileMap>(p_object) != nullptr;
 }
 }
 
 
-void TilesEditorPlugin::draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color) {
-	real_t scale = p_ci->get_global_transform().get_scale().x * 0.5;
-	p_ci->draw_set_transform(p_rect.position, 0, Vector2(1, 1) / scale);
-	RS::get_singleton()->canvas_item_add_nine_patch(
-			p_ci->get_canvas_item(), Rect2(Vector2(), p_rect.size * scale), Rect2(), EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("TileSelection"), SNAME("EditorIcons"))->get_rid(),
-			Vector2(2, 2), Vector2(2, 2), RS::NINE_PATCH_STRETCH, RS::NINE_PATCH_STRETCH, false, p_color);
-	p_ci->draw_set_transform_matrix(Transform2D());
+void TileMapEditorPlugin::make_visible(bool p_visible) {
+	if (p_visible) {
+		button->show();
+		EditorNode::get_singleton()->make_bottom_panel_item_visible(editor);
+	} else {
+		button->hide();
+		if (editor->is_visible_in_tree()) {
+			EditorNode::get_singleton()->hide_bottom_panel();
+		}
+	}
 }
 }
 
 
-TilesEditorPlugin::TilesEditorPlugin() {
-	set_process_internal(true);
+bool TileMapEditorPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+	return editor->forward_canvas_gui_input(p_event);
+}
 
 
-	// Update the singleton.
-	singleton = this;
+void TileMapEditorPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
+	editor->forward_canvas_draw_over_viewport(p_overlay);
+}
 
 
-	// Tileset editor.
-	tileset_editor = memnew(TileSetEditor);
-	tileset_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	tileset_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-	tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
-	tileset_editor->hide();
+bool TileMapEditorPlugin::is_editor_visible() const {
+	return editor->is_visible_in_tree();
+}
 
 
-	// Tilemap editor.
-	tilemap_editor = memnew(TileMapEditor);
-	tilemap_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	tilemap_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-	tilemap_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
-	tilemap_editor->hide();
+TileMapEditorPlugin::TileMapEditorPlugin() {
+	memnew(TilesEditorUtils);
+	local_singleton = this;
 
 
-	// Pattern preview generation thread.
-	pattern_preview_thread.start(_thread_func, this);
+	editor = memnew(TileMapEditor);
+	editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
+	editor->hide();
 
 
-	// Bottom buttons.
-	tileset_editor_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileSet"), tileset_editor);
-	tileset_editor_button->hide();
-	tilemap_editor_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileMap"), tilemap_editor);
-	tilemap_editor_button->hide();
+	button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileMap"), editor);
+	button->hide();
+}
 
 
-	// Initialization.
-	_update_editors();
+TileMapEditorPlugin::~TileMapEditorPlugin() {
+	local_singleton = nullptr;
 }
 }
 
 
-TilesEditorPlugin::~TilesEditorPlugin() {
-	if (pattern_preview_thread.is_started()) {
-		pattern_thread_exit.set();
-		pattern_preview_sem.post();
-		while (!pattern_thread_exited.is_set()) {
-			OS::get_singleton()->delay_usec(10000);
-			RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
+void TileSetEditorPlugin::edit(Object *p_object) {
+	editor->edit(Ref<TileSet>(p_object));
+}
+
+bool TileSetEditorPlugin::handles(Object *p_object) const {
+	return Object::cast_to<TileSet>(p_object) != nullptr;
+}
+
+void TileSetEditorPlugin::make_visible(bool p_visible) {
+	if (p_visible) {
+		button->show();
+		if (!local_singleton->is_editor_visible()) {
+			EditorNode::get_singleton()->make_bottom_panel_item_visible(editor);
+		}
+	} else {
+		button->hide();
+		if (editor->is_visible_in_tree()) {
+			EditorNode::get_singleton()->hide_bottom_panel();
 		}
 		}
-		pattern_preview_thread.wait_to_finish();
 	}
 	}
 }
 }
+
+TileSetEditorPlugin::TileSetEditorPlugin() {
+	DEV_ASSERT(local_singleton);
+
+	editor = memnew(TileSetEditor);
+	editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
+	editor->hide();
+
+	button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileSet"), editor);
+	button->hide();
+}

+ 45 - 32
editor/plugins/tiles/tiles_editor_plugin.h

@@ -38,10 +38,10 @@
 #include "tile_map_editor.h"
 #include "tile_map_editor.h"
 #include "tile_set_editor.h"
 #include "tile_set_editor.h"
 
 
-class TilesEditorPlugin : public EditorPlugin {
-	GDCLASS(TilesEditorPlugin, EditorPlugin);
+class TilesEditorUtils : public Object {
+	GDCLASS(TilesEditorUtils, Object);
 
 
-	static TilesEditorPlugin *singleton;
+	static TilesEditorUtils *singleton;
 
 
 public:
 public:
 	enum SourceSortOption {
 	enum SourceSortOption {
@@ -53,28 +53,11 @@ public:
 	};
 	};
 
 
 private:
 private:
-	bool is_visible = false;
-
-	bool tile_map_changed_needs_update = false;
-	ObjectID tile_map_id;
-	Ref<TileSet> tile_set;
-	bool is_editing_tile_set = false;
-
-	Button *tilemap_editor_button = nullptr;
-	TileMapEditor *tilemap_editor = nullptr;
-
-	Button *tileset_editor_button = nullptr;
-	TileSetEditor *tileset_editor = nullptr;
-
-	void _update_editors();
-
 	// For synchronization.
 	// For synchronization.
 	int atlas_sources_lists_current = 0;
 	int atlas_sources_lists_current = 0;
 	float atlas_view_zoom = 1.0;
 	float atlas_view_zoom = 1.0;
 	Vector2 atlas_view_scroll;
 	Vector2 atlas_view_scroll;
 
 
-	void _tile_map_changed();
-
 	// Source sorting.
 	// Source sorting.
 	int source_sort = SOURCE_SORT_ID;
 	int source_sort = SOURCE_SORT_ID;
 
 
@@ -101,16 +84,8 @@ private:
 	static void _thread_func(void *ud);
 	static void _thread_func(void *ud);
 	void _thread();
 	void _thread();
 
 
-protected:
-	void _notification(int p_what);
-
 public:
 public:
-	_FORCE_INLINE_ static TilesEditorPlugin *get_singleton() { return singleton; }
-
-	virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return tilemap_editor->forward_canvas_gui_input(p_event); }
-	virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); }
-
-	bool is_tile_map_selected();
+	_FORCE_INLINE_ static TilesEditorUtils *get_singleton() { return singleton; }
 
 
 	// Pattern preview API.
 	// Pattern preview API.
 	void queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback);
 	void queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback);
@@ -126,14 +101,52 @@ public:
 	void set_sorting_option(int p_option);
 	void set_sorting_option(int p_option);
 	List<int> get_sorted_sources(const Ref<TileSet> p_tile_set) const;
 	List<int> get_sorted_sources(const Ref<TileSet> p_tile_set) const;
 
 
+	static void draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color = Color(1.0, 1.0, 1.0));
+
+	TilesEditorUtils();
+	~TilesEditorUtils();
+};
+
+class TileMapEditorPlugin : public EditorPlugin {
+	GDCLASS(TileMapEditorPlugin, EditorPlugin);
+
+	TileMapEditor *editor = nullptr;
+	Button *button = nullptr;
+	TileMap *tile_map = nullptr;
+
+	bool tile_map_changed_needs_update = false;
+	void _tile_map_changed();
+	void _update_tile_map();
+
+protected:
+	void _notification(int p_notification);
+
+public:
 	virtual void edit(Object *p_object) override;
 	virtual void edit(Object *p_object) override;
 	virtual bool handles(Object *p_object) const override;
 	virtual bool handles(Object *p_object) const override;
 	virtual void make_visible(bool p_visible) override;
 	virtual void make_visible(bool p_visible) override;
 
 
-	static void draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color = Color(1.0, 1.0, 1.0));
+	virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
+	virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
+
+	bool is_editor_visible() const;
+
+	TileMapEditorPlugin();
+	~TileMapEditorPlugin();
+};
+
+class TileSetEditorPlugin : public EditorPlugin {
+	GDCLASS(TileSetEditorPlugin, EditorPlugin);
+
+	TileSetEditor *editor = nullptr;
+	Button *button = nullptr;
+
+public:
+	virtual void edit(Object *p_object) override;
+	virtual bool handles(Object *p_object) const override;
+	virtual void make_visible(bool p_visible) override;
 
 
-	TilesEditorPlugin();
-	~TilesEditorPlugin();
+	TileSetEditorPlugin();
 };
 };
 
 
 #endif // TILES_EDITOR_PLUGIN_H
 #endif // TILES_EDITOR_PLUGIN_H

+ 2 - 1
editor/register_editor_types.cpp

@@ -254,7 +254,8 @@ void register_editor_types() {
 	EditorPlugins::add_by_type<Cast2DEditorPlugin>();
 	EditorPlugins::add_by_type<Cast2DEditorPlugin>();
 	EditorPlugins::add_by_type<Skeleton2DEditorPlugin>();
 	EditorPlugins::add_by_type<Skeleton2DEditorPlugin>();
 	EditorPlugins::add_by_type<Sprite2DEditorPlugin>();
 	EditorPlugins::add_by_type<Sprite2DEditorPlugin>();
-	EditorPlugins::add_by_type<TilesEditorPlugin>();
+	EditorPlugins::add_by_type<TileMapEditorPlugin>();
+	EditorPlugins::add_by_type<TileSetEditorPlugin>();
 
 
 	// For correct doc generation.
 	// For correct doc generation.
 	GLOBAL_DEF("editor/run/main_run_args", "");
 	GLOBAL_DEF("editor/run/main_run_args", "");