1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-07 17:36:07 +00:00

Prevent threading problems in TileMap

This commit is contained in:
A Thousand Ships
2024-02-27 15:54:09 +01:00
parent d8cbaa3a8b
commit 36e611fa83
3 changed files with 10 additions and 12 deletions

View File

@@ -5,7 +5,7 @@
</brief_description> </brief_description>
<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. 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]. To force an update earlier on, call [method update_internals].
</description> </description>
<tutorials> <tutorials>

View File

@@ -68,9 +68,6 @@ void TilesEditorUtils::_thread_func(void *ud) {
} }
void TilesEditorUtils::_thread() { void TilesEditorUtils::_thread() {
CallQueue queue;
MessageQueue::set_thread_singleton_override(&queue);
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();
@@ -130,8 +127,6 @@ void TilesEditorUtils::_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);
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); 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,11 +139,7 @@ void TilesEditorUtils::_thread() {
viewport->queue_free(); viewport->queue_free();
} }
} }
MessageQueue::get_singleton()->flush();
} }
MessageQueue::get_singleton()->flush();
pattern_thread_exited.set(); pattern_thread_exited.set();
} }

View File

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