From a90e318a1914748cfb2943b91d6e1d8b9ddd7d60 Mon Sep 17 00:00:00 2001 From: Brian Semrau Date: Fri, 5 Nov 2021 02:43:03 -0400 Subject: [PATCH] Fix previews sometimes displaying wrong/blank image --- editor/plugins/editor_preview_plugins.cpp | 50 +++++++++++--------- editor/plugins/editor_preview_plugins.h | 12 +++-- editor/plugins/tiles/tiles_editor_plugin.cpp | 13 ++--- editor/plugins/tiles/tiles_editor_plugin.h | 3 +- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 15c15ae6b2..9702c7e734 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -297,8 +297,14 @@ EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() { ////////////////////////////////////////////////////////////////// +void EditorMaterialPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorMaterialPreviewPlugin::_preview_done)); +} + void EditorMaterialPreviewPlugin::_preview_done() { - preview_done.set(); + preview_done.post(); } bool EditorMaterialPreviewPlugin::handles(const String &p_type) const { @@ -316,14 +322,9 @@ Ref EditorMaterialPreviewPlugin::generate(const RES &p_from, const Si if (material->get_shader_mode() == Shader::MODE_SPATIAL) { RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Vector(), Object::CONNECT_ONESHOT); - preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorMaterialPreviewPlugin::_preview_done)); - - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID()); @@ -695,8 +696,14 @@ EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() { /////////////////////////////////////////////////////////////////////////// +void EditorMeshPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorMeshPreviewPlugin::_preview_done)); +} + void EditorMeshPreviewPlugin::_preview_done() { - preview_done.set(); + preview_done.post(); } bool EditorMeshPreviewPlugin::handles(const String &p_type) const { @@ -727,14 +734,9 @@ Ref EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 xform.origin.z -= rot_aabb.size.z * 2; RS::get_singleton()->instance_set_transform(mesh_instance, xform); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast(this), &EditorMeshPreviewPlugin::_generate_frame_started), Vector(), Object::CONNECT_ONESHOT); - preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorMeshPreviewPlugin::_preview_done)); - - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_FAIL_COND_V(img.is_null(), Ref()); @@ -806,8 +808,14 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() { /////////////////////////////////////////////////////////////////////////// +void EditorFontPreviewPlugin::_generate_frame_started() { + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorFontPreviewPlugin::_preview_done)); +} + void EditorFontPreviewPlugin::_preview_done() { - preview_done.set(); + preview_done.post(); } bool EditorFontPreviewPlugin::handles(const String &p_type) const { @@ -845,13 +853,9 @@ Ref EditorFontPreviewPlugin::generate_from_path(const String &p_path, font->draw_string(canvas_item, pos, sample, HALIGN_LEFT, -1.f, 50, Color(1, 1, 1)); - preview_done.clear(); - RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture - RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &EditorFontPreviewPlugin::_preview_done)); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector(), Object::CONNECT_ONESHOT); - while (!preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + preview_done.wait(); RS::get_singleton()->canvas_item_clear(canvas_item); diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index c24dabf679..bf52f5771d 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -92,8 +92,9 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - mutable SafeFlag preview_done; + Semaphore preview_done; + void _generate_frame_started(); void _preview_done(); public: @@ -133,8 +134,9 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator { RID light2; RID light_instance2; RID camera; - mutable SafeFlag preview_done; + Semaphore preview_done; + void _generate_frame_started(); void _preview_done(); public: @@ -152,8 +154,9 @@ class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator { RID viewport_texture; RID canvas; RID canvas_item; - mutable SafeFlag preview_done; + Semaphore preview_done; + void _generate_frame_started(); void _preview_done(); public: @@ -168,8 +171,9 @@ public: class EditorTileMapPatternPreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTileMapPatternPreviewPlugin, EditorResourcePreviewGenerator); - mutable SafeFlag preview_done; + Semaphore preview_done; + void _generate_frame_started(); void _preview_done(); public: diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index 8e2c16906d..47dfc57b0f 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -47,8 +47,12 @@ TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr; +void TilesEditorPlugin::_preview_frame_started() { + RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &TilesEditorPlugin::_pattern_preview_done)); +} + void TilesEditorPlugin::_pattern_preview_done() { - pattern_preview_done.set(); + pattern_preview_done.post(); } void TilesEditorPlugin::_thread_func(void *ud) { @@ -112,12 +116,9 @@ void TilesEditorPlugin::_thread() { // Add the viewport at the lasst moment to avoid rendering too early. EditorNode::get_singleton()->add_child(viewport); - pattern_preview_done.clear(); - RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast(this), &TilesEditorPlugin::_pattern_preview_done)); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast(this), &TilesEditorPlugin::_preview_frame_started), Vector(), Object::CONNECT_ONESHOT); - while (!pattern_preview_done.is_set()) { - OS::get_singleton()->delay_usec(10); - } + pattern_preview_done.wait(); Ref image = viewport->get_texture()->get_image(); Ref image_texture; diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index 34feee965f..33493040f6 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -77,7 +77,8 @@ private: Thread pattern_preview_thread; SafeFlag pattern_thread_exit; SafeFlag pattern_thread_exited; - mutable SafeFlag pattern_preview_done; + Semaphore pattern_preview_done; + void _preview_frame_started(); void _pattern_preview_done(); static void _thread_func(void *ud); void _thread();