From b0c01635fcf358378f0e15925d19e99615a46d1d Mon Sep 17 00:00:00 2001
From: Nazarii <nazarii.yablonskyi.pp.2022@lpnu.ua>
Date: Mon, 16 Sep 2024 23:47:43 +0300
Subject: [PATCH] Optimize TileMapLayerEditor

---
 .../plugins/tiles/tile_map_layer_editor.cpp   | 23 ++++++++++---------
 scene/resources/2d/tile_set.cpp               | 10 ++++++++
 scene/resources/2d/tile_set.h                 |  4 ++++
 3 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp
index dcfd92f6f9e0..d0481116563f 100644
--- a/editor/plugins/tiles/tile_map_layer_editor.cpp
+++ b/editor/plugins/tiles/tile_map_layer_editor.cpp
@@ -4251,19 +4251,20 @@ void TileMapLayerEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
 	Vector2i tile_shape_size = tile_set->get_tile_size();
 
 	// Draw tiles with invalid IDs in the grid.
-	TypedArray<Vector2i> used_cells = edited_layer->get_used_cells();
-	for (int i = 0; i < used_cells.size(); i++) {
-		Vector2i coords = used_cells[i];
-		int tile_source_id = edited_layer->get_cell_source_id(coords);
-		if (tile_source_id >= 0) {
-			Vector2i tile_atlas_coords = edited_layer->get_cell_atlas_coords(coords);
-			int tile_alternative_tile = edited_layer->get_cell_alternative_tile(coords);
+	const HashMap<Vector2i, CellData> &tile_map_layer_data = edited_layer->get_tile_map_layer_data();
 
-			TileSetSource *source = nullptr;
-			if (tile_set->has_source(tile_source_id)) {
-				source = *tile_set->get_source(tile_source_id);
-			}
+	for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+		const TileMapCell &c = E.value.cell;
+		if (c.source_id == TileSet::INVALID_SOURCE) {
+			continue;
+		}
+		const Vector2i &coords = E.key;
+		int tile_source_id = c.source_id;
+		if (tile_source_id >= 0) {
+			Vector2i tile_atlas_coords = c.get_atlas_coords();
+			int tile_alternative_tile = c.alternative_tile;
 
+			TileSetSource *source = tile_set->get_source_ptr(tile_source_id);
 			if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
 				// Generate a random color from the hashed identifier of the tiles.
 				Array to_hash;
diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp
index 229e18be23ad..2ec088c9e5c2 100644
--- a/scene/resources/2d/tile_set.cpp
+++ b/scene/resources/2d/tile_set.cpp
@@ -545,6 +545,16 @@ bool TileSet::has_source(int p_source_id) const {
 	return sources.has(p_source_id);
 }
 
+#ifdef TOOLS_ENABLED
+TileSetSource *TileSet::get_source_ptr(int p_source_id) const {
+	const Ref<TileSetSource> *source_ptr = sources.getptr(p_source_id);
+	if (source_ptr == nullptr) {
+		return nullptr;
+	}
+	return **source_ptr;
+}
+#endif
+
 Ref<TileSetSource> TileSet::get_source(int p_source_id) const {
 	ERR_FAIL_COND_V_MSG(!sources.has(p_source_id), nullptr, vformat("No TileSet atlas source with id %d.", p_source_id));
 
diff --git a/scene/resources/2d/tile_set.h b/scene/resources/2d/tile_set.h
index 15e1a16359e8..b6b4298fbe83 100644
--- a/scene/resources/2d/tile_set.h
+++ b/scene/resources/2d/tile_set.h
@@ -426,6 +426,10 @@ class TileSet : public Resource {
 	bool has_source(int p_source_id) const;
 	Ref<TileSetSource> get_source(int p_source_id) const;
 
+#ifdef TOOLS_ENABLED
+	TileSetSource *get_source_ptr(int p_source_id) const;
+#endif
+
 	// Rendering
 	void set_uv_clipping(bool p_uv_clipping);
 	bool is_uv_clipping() const;