浏览代码

Prevent threading problems in `TileMap`

A Thousand Ships 1 年之前
父节点
当前提交
36e611fa83
共有 3 个文件被更改,包括 10 次插入12 次删除
  1. 1 1
      doc/classes/TileMap.xml
  2. 0 9
      editor/plugins/tiles/tiles_editor_plugin.cpp
  3. 9 2
      scene/2d/tile_map.cpp

+ 1 - 1
doc/classes/TileMap.xml

@@ -5,7 +5,7 @@
 	</brief_description>
 	<description>
 		Node for 2D tile-based maps. Tilemaps use a [TileSet] which contain a list of tiles which are used to create grid-based maps. A TileMap may have several layers, layouting tiles on top of each other.
-		For performance reasons, all TileMap updates are batched at the end of a frame. Notably, this means that scene tiles from a [TileSetScenesCollectionSource] may be initialized after their parent.
+		For performance reasons, all TileMap updates are batched at the end of a frame. Notably, this means that scene tiles from a [TileSetScenesCollectionSource] may be initialized after their parent. This is only queued when inside the scene tree.
 		To force an update earlier on, call [method update_internals].
 	</description>
 	<tutorials>

+ 0 - 9
editor/plugins/tiles/tiles_editor_plugin.cpp

@@ -68,9 +68,6 @@ void TilesEditorUtils::_thread_func(void *ud) {
 }
 
 void TilesEditorUtils::_thread() {
-	CallQueue queue;
-	MessageQueue::set_thread_singleton_override(&queue);
-
 	pattern_thread_exited.clear();
 	while (!pattern_thread_exit.is_set()) {
 		pattern_preview_sem.wait();
@@ -130,8 +127,6 @@ void TilesEditorUtils::_thread() {
 				// Add the viewport at the last moment to avoid rendering too early.
 				EditorNode::get_singleton()->call_deferred("add_child", viewport);
 
-				MessageQueue::get_singleton()->flush();
-
 				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();
@@ -144,11 +139,7 @@ void TilesEditorUtils::_thread() {
 				viewport->queue_free();
 			}
 		}
-
-		MessageQueue::get_singleton()->flush();
 	}
-
-	MessageQueue::get_singleton()->flush();
 	pattern_thread_exited.set();
 }
 

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

@@ -3023,6 +3023,8 @@ void TileMap::_notification(int p_what) {
 			for (Ref<TileMapLayer> &layer : layers) {
 				layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_TREE);
 			}
+			// Update on exit to prevent threading problems.
+			_internal_update();
 		} break;
 
 		case TileMap::NOTIFICATION_ENTER_CANVAS: {
@@ -3035,6 +3037,8 @@ void TileMap::_notification(int p_what) {
 			for (Ref<TileMapLayer> &layer : layers) {
 				layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_IN_CANVAS);
 			}
+			// Update on exit to prevent threading problems.
+			_internal_update();
 		} break;
 
 		case NOTIFICATION_DRAW: {
@@ -3109,8 +3113,11 @@ void TileMap::queue_internal_update() {
 	if (pending_update) {
 		return;
 	}
-	pending_update = true;
-	callable_mp(this, &TileMap::_internal_update).call_deferred();
+	// Don't update when outside the tree, it doesn't do anything useful, and causes threading problems.
+	if (is_inside_tree()) {
+		pending_update = true;
+		callable_mp(this, &TileMap::_internal_update).call_deferred();
+	}
 }
 
 void TileMap::_internal_update() {