Browse Source

Merge pull request #20352 from PJB3005/18-07-22-defer-tile-quad-update

Fix TileMap::set_cell performance regression
Rémi Verschelde 7 years ago
parent
commit
c02f639aa5
3 changed files with 18 additions and 6 deletions
  1. 11 0
      doc/classes/TileMap.xml
  2. 5 5
      scene/2d/tile_map.cpp
  3. 2 1
      scene/2d/tile_map.h

+ 11 - 0
doc/classes/TileMap.xml

@@ -153,6 +153,8 @@
 				Sets the tile index for the cell given by a Vector2.
 				Sets the tile index for the cell given by a Vector2.
 				An index of [code]-1[/code] clears the cell.
 				An index of [code]-1[/code] clears the cell.
 				Optionally, the tile can also be flipped, transposed, or given autotile coordinates.
 				Optionally, the tile can also be flipped, transposed, or given autotile coordinates.
+				Note that data such as navigation polygons and collision shapes are not immediately updated for performance reasons.
+				If you need these to be immediately updated, you can call [method update_dirty_quadrants].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="set_cellv">
 		<method name="set_cellv">
@@ -172,6 +174,8 @@
 				Sets the tile index for the given cell.
 				Sets the tile index for the given cell.
 				An index of [code]-1[/code] clears the cell.
 				An index of [code]-1[/code] clears the cell.
 				Optionally, the tile can also be flipped or transposed.
 				Optionally, the tile can also be flipped or transposed.
+				Note that data such as navigation polygons and collision shapes are not immediately updated for performance reasons.
+				If you need these to be immediately updated, you can call [method update_dirty_quadrants].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="set_collision_layer_bit">
 		<method name="set_collision_layer_bit">
@@ -217,6 +221,13 @@
 				Calling with invalid (or missing) parameters applies autotiling rules for the entire tilemap.
 				Calling with invalid (or missing) parameters applies autotiling rules for the entire tilemap.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="update_dirty_quadrants">
+			<return type="void">
+			</return>
+			<description>
+				Updates the tile map's quadrants, allowing things such as navigation and collision shapes to be immediately used if modified.
+			</description>
+		</method>
 		<method name="world_to_map" qualifiers="const">
 		<method name="world_to_map" qualifiers="const">
 			<return type="Vector2">
 			<return type="Vector2">
 			</return>
 			</return>

+ 5 - 5
scene/2d/tile_map.cpp

@@ -62,7 +62,7 @@ void TileMap::_notification(int p_what) {
 
 
 			pending_update = true;
 			pending_update = true;
 			_recreate_quadrants();
 			_recreate_quadrants();
-			_update_dirty_quadrants();
+			update_dirty_quadrants();
 			RID space = get_world_2d()->get_space();
 			RID space = get_world_2d()->get_space();
 			_update_quadrant_transform();
 			_update_quadrant_transform();
 			_update_quadrant_space(space);
 			_update_quadrant_space(space);
@@ -245,7 +245,7 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const
 	xform.elements[2].y += offset.y;
 	xform.elements[2].y += offset.y;
 }
 }
 
 
-void TileMap::_update_dirty_quadrants() {
+void TileMap::update_dirty_quadrants() {
 
 
 	if (!pending_update)
 	if (!pending_update)
 		return;
 		return;
@@ -721,7 +721,7 @@ void TileMap::_make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool updat
 		return;
 		return;
 
 
 	if (update) {
 	if (update) {
-		_update_dirty_quadrants();
+		call_deferred("update_dirty_quadrants");
 	}
 	}
 }
 }
 
 
@@ -1026,7 +1026,7 @@ void TileMap::_recreate_quadrants() {
 		Q->get().cells.insert(E->key());
 		Q->get().cells.insert(E->key());
 		_make_quadrant_dirty(Q, false);
 		_make_quadrant_dirty(Q, false);
 	}
 	}
-	_update_dirty_quadrants();
+	update_dirty_quadrants();
 }
 }
 
 
 void TileMap::_clear_quadrants() {
 void TileMap::_clear_quadrants() {
@@ -1630,7 +1630,7 @@ void TileMap::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("_clear_quadrants"), &TileMap::_clear_quadrants);
 	ClassDB::bind_method(D_METHOD("_clear_quadrants"), &TileMap::_clear_quadrants);
 	ClassDB::bind_method(D_METHOD("_recreate_quadrants"), &TileMap::_recreate_quadrants);
 	ClassDB::bind_method(D_METHOD("_recreate_quadrants"), &TileMap::_recreate_quadrants);
-	ClassDB::bind_method(D_METHOD("_update_dirty_quadrants"), &TileMap::_update_dirty_quadrants);
+	ClassDB::bind_method(D_METHOD("update_dirty_quadrants"), &TileMap::update_dirty_quadrants);
 
 
 	ClassDB::bind_method(D_METHOD("update_bitmask_area", "position"), &TileMap::update_bitmask_area);
 	ClassDB::bind_method(D_METHOD("update_bitmask_area", "position"), &TileMap::update_bitmask_area);
 	ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2()));
 	ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2()));

+ 2 - 1
scene/2d/tile_map.h

@@ -191,7 +191,6 @@ private:
 	void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true);
 	void _make_quadrant_dirty(Map<PosKey, Quadrant>::Element *Q, bool update = true);
 	void _recreate_quadrants();
 	void _recreate_quadrants();
 	void _clear_quadrants();
 	void _clear_quadrants();
-	void _update_dirty_quadrants();
 	void _update_quadrant_space(const RID &p_space);
 	void _update_quadrant_space(const RID &p_space);
 	void _update_quadrant_transform();
 	void _update_quadrant_transform();
 	void _recompute_rect_cache();
 	void _recompute_rect_cache();
@@ -251,6 +250,8 @@ public:
 	void update_cell_bitmask(int p_x, int p_y);
 	void update_cell_bitmask(int p_x, int p_y);
 	void update_dirty_bitmask();
 	void update_dirty_bitmask();
 
 
+	void update_dirty_quadrants();
+
 	void set_collision_layer(uint32_t p_layer);
 	void set_collision_layer(uint32_t p_layer);
 	uint32_t get_collision_layer() const;
 	uint32_t get_collision_layer() const;