From 2f659443ba2110aaf478bc4cd8214f9b7cb093bb Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Wed, 22 Jul 2020 21:04:27 +0100 Subject: [PATCH] use thread safe events for file picker --- Editor/Editor.cpp | 101 +++++++++++++++++---------------- Editor/LightWindow.cpp | 9 +-- Editor/MaterialWindow.cpp | 66 +++++++++++---------- Editor/MeshWindow.cpp | 19 ++++--- Editor/PostprocessWindow.cpp | 12 ++-- Editor/SoundWindow.cpp | 8 +-- Editor/WeatherWindow.cpp | 10 ++-- WickedEngine/MainComponent.cpp | 4 ++ WickedEngine/wiEvent.cpp | 50 +++++++++++----- WickedEngine/wiEvent.h | 2 + WickedEngine/wiVersion.cpp | 2 +- 11 files changed, 163 insertions(+), 120 deletions(-) diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index fa79a4702..257c8cab8 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -692,24 +692,26 @@ void EditorComponent::Load() params.description = "Wicked Scene"; params.extensions.push_back("wiscene"); wiHelper::FileDialog(params, [this](std::string fileName) { + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + std::string filename = fileName; + if (filename.substr(filename.length() - 8).compare(".wiscene") != 0) + { + filename += ".wiscene"; + } + wiArchive archive(fileName, false); + if (archive.IsOpen()) + { + Scene& scene = wiScene::GetScene(); - if (fileName.substr(fileName.length() - 8).compare(".wiscene") != 0) - { - fileName += ".wiscene"; - } - wiArchive archive(fileName, false); - if (archive.IsOpen()) - { - Scene& scene = wiScene::GetScene(); + scene.Serialize(archive); - scene.Serialize(archive); - - ResetHistory(); - } - else - { - wiHelper::messageBox("Could not create " + fileName + "!"); - } + ResetHistory(); + } + else + { + wiHelper::messageBox("Could not create " + fileName + "!"); + } + }); }); }); GetGUI().AddWidget(saveButton); @@ -728,39 +730,40 @@ void EditorComponent::Load() params.extensions.push_back("gltf"); params.extensions.push_back("glb"); wiHelper::FileDialog(params, [&](std::string fileName) { + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + main->loader->addLoadingFunction([=](wiJobArgs args) { + string extension = wiHelper::toUpper(wiHelper::GetExtensionFromFileName(fileName)); - main->loader->addLoadingFunction([=](wiJobArgs args) { - string extension = wiHelper::toUpper(wiHelper::GetExtensionFromFileName(fileName)); - - if (!extension.compare("WISCENE")) // engine-serialized - { - wiScene::LoadModel(fileName); - } - else if (!extension.compare("OBJ")) // wavefront-obj - { - Scene scene; - ImportModel_OBJ(fileName, scene); - wiScene::GetScene().Merge(scene); - } - else if (!extension.compare("GLTF")) // text-based gltf - { - Scene scene; - ImportModel_GLTF(fileName, scene); - wiScene::GetScene().Merge(scene); - } - else if (!extension.compare("GLB")) // binary gltf - { - Scene scene; - ImportModel_GLTF(fileName, scene); - wiScene::GetScene().Merge(scene); - } + if (!extension.compare("WISCENE")) // engine-serialized + { + wiScene::LoadModel(fileName); + } + else if (!extension.compare("OBJ")) // wavefront-obj + { + Scene scene; + ImportModel_OBJ(fileName, scene); + wiScene::GetScene().Merge(scene); + } + else if (!extension.compare("GLTF")) // text-based gltf + { + Scene scene; + ImportModel_GLTF(fileName, scene); + wiScene::GetScene().Merge(scene); + } + else if (!extension.compare("GLB")) // binary gltf + { + Scene scene; + ImportModel_GLTF(fileName, scene); + wiScene::GetScene().Merge(scene); + } + }); + main->loader->onFinished([=] { + main->ActivatePath(this, 0.2f, wiColor::Black()); + weatherWnd->Update(); + }); + main->ActivatePath(main->loader.get(), 0.2f, wiColor::Black()); + ResetHistory(); }); - main->loader->onFinished([=] { - main->ActivatePath(this, 0.2f, wiColor::Black()); - weatherWnd->Update(); - }); - main->ActivatePath(main->loader.get(), 0.2f, wiColor::Black()); - ResetHistory(); }); }); GetGUI().AddWidget(modelButton); @@ -776,7 +779,9 @@ void EditorComponent::Load() params.description = "Lua script"; params.extensions.push_back("lua"); wiHelper::FileDialog(params, [](std::string fileName) { - wiLua::RunFile(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + wiLua::RunFile(fileName); + }); }); }); GetGUI().AddWidget(scriptButton); diff --git a/Editor/LightWindow.cpp b/Editor/LightWindow.cpp index 17980721a..08a0410be 100644 --- a/Editor/LightWindow.cpp +++ b/Editor/LightWindow.cpp @@ -273,10 +273,11 @@ LightWindow::LightWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, light, i](std::string fileName) { - light->lensFlareRimTextures[i] = wiResourceManager::Load(fileName); - light->lensFlareNames[i] = fileName; - fileName = wiHelper::GetFileNameFromPath(fileName); - lensflare_Button[i]->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + light->lensFlareRimTextures[i] = wiResourceManager::Load(fileName); + light->lensFlareNames[i] = fileName; + lensflare_Button[i]->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index c2d054aa6..8b8af75fd 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -423,11 +423,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->baseColorMap = wiResourceManager::Load(fileName); - material->baseColorMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_baseColor_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->baseColorMap = wiResourceManager::Load(fileName); + material->baseColorMapName = fileName; + material->SetDirty(); + texture_baseColor_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); @@ -481,11 +482,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->normalMap = wiResourceManager::Load(fileName); - material->normalMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_normal_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->normalMap = wiResourceManager::Load(fileName); + material->normalMapName = fileName; + material->SetDirty(); + texture_normal_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); @@ -539,11 +541,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->surfaceMap = wiResourceManager::Load(fileName); - material->surfaceMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_surface_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->surfaceMap = wiResourceManager::Load(fileName); + material->surfaceMapName = fileName; + material->SetDirty(); + texture_surface_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); @@ -597,11 +600,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->emissiveMap = wiResourceManager::Load(fileName); - material->emissiveMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_emissive_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->emissiveMap = wiResourceManager::Load(fileName); + material->emissiveMapName = fileName; + material->SetDirty(); + texture_emissive_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); @@ -655,11 +659,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->displacementMap = wiResourceManager::Load(fileName); - material->displacementMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_displacement_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->displacementMap = wiResourceManager::Load(fileName); + material->displacementMapName = fileName; + material->SetDirty(); + texture_displacement_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); @@ -714,11 +719,12 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [this, material](std::string fileName) { - material->occlusionMap = wiResourceManager::Load(fileName); - material->occlusionMapName = fileName; - material->SetDirty(); - fileName = wiHelper::GetFileNameFromPath(fileName); - texture_occlusion_Button->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + material->occlusionMap = wiResourceManager::Load(fileName); + material->occlusionMapName = fileName; + material->SetDirty(); + texture_occlusion_Button->SetText(wiHelper::GetFileNameFromPath(fileName)); + }); }); } }); diff --git a/Editor/MeshWindow.cpp b/Editor/MeshWindow.cpp index c980aaa8b..23e0ae065 100644 --- a/Editor/MeshWindow.cpp +++ b/Editor/MeshWindow.cpp @@ -468,17 +468,18 @@ MeshWindow::MeshWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [=](std::string fileName) { + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + if (this->rgb != nullptr) + { + stbi_image_free(this->rgb); + this->rgb = nullptr; + } - if (this->rgb != nullptr) - { - stbi_image_free(this->rgb); - this->rgb = nullptr; - } + int bpp; + this->rgb = stbi_load(fileName.c_str(), &this->width, &this->height, &bpp, channelCount); - int bpp; - this->rgb = stbi_load(fileName.c_str(), &this->width, &this->height, &bpp, channelCount); - - generate_mesh(width, height, rgb, channelCount, dimYSlider->GetValue()); + generate_mesh(width, height, rgb, channelCount, dimYSlider->GetValue()); + }); }); }); terrainGenWindow->AddWidget(heightmapButton); diff --git a/Editor/PostprocessWindow.cpp b/Editor/PostprocessWindow.cpp index c00c6d5c9..e5a765675 100644 --- a/Editor/PostprocessWindow.cpp +++ b/Editor/PostprocessWindow.cpp @@ -272,11 +272,13 @@ PostprocessWindow::PostprocessWindow(EditorComponent* editor) : GUI(&editor->Get params.extensions.push_back("jpg"); params.extensions.push_back("tga"); wiHelper::FileDialog(params, [=](std::string fileName) { - editor->renderPath->setColorGradingTexture(wiResourceManager::Load(fileName)); - if (editor->renderPath->getColorGradingTexture() != nullptr) - { - colorGradingButton->SetText(fileName); - } + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + editor->renderPath->setColorGradingTexture(wiResourceManager::Load(fileName)); + if (editor->renderPath->getColorGradingTexture() != nullptr) + { + colorGradingButton->SetText(fileName); + } + }); }); } else diff --git a/Editor/SoundWindow.cpp b/Editor/SoundWindow.cpp index 1855adbed..7d2981f37 100644 --- a/Editor/SoundWindow.cpp +++ b/Editor/SoundWindow.cpp @@ -73,16 +73,12 @@ SoundWindow::SoundWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.description = "Sound"; params.extensions.push_back("wav"); wiHelper::FileDialog(params, [=](std::string fileName) { - editor->main->loader->addLoadingFunction([=](wiJobArgs args) { + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { Entity entity = GetScene().Entity_CreateSound("editorSound", fileName); editor->ClearSelected(); editor->AddSelected(entity); SetEntity(entity); - }); - editor->main->loader->onFinished([=] { - editor->main->ActivatePath(editor, 0.2f, wiColor::Black()); - }); - editor->main->ActivatePath(editor->main->loader.get(), 0.2f, wiColor::Black()); + }); }); }); soundWindow->AddWidget(addButton); diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index c3da0428b..f99f1930c 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -132,10 +132,12 @@ WeatherWindow::WeatherWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) params.description = "Cubemap texture"; params.extensions.push_back("dds"); wiHelper::FileDialog(params, [=](std::string fileName) { - auto& weather = GetWeather(); - weather.skyMapName = fileName; - weather.skyMap = wiResourceManager::Load(fileName); - skyButton->SetText(fileName); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { + auto& weather = GetWeather(); + weather.skyMapName = fileName; + weather.skyMap = wiResourceManager::Load(fileName); + skyButton->SetText(fileName); + }); }); } else diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index b9c21b626..7695eaa6d 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -14,6 +14,7 @@ #include "wiStartupArguments.h" #include "wiFont.h" #include "wiImage.h" +#include "wiEvent.h" #include "wiGraphicsDevice_DX11.h" #include "wiGraphicsDevice_DX12.h" @@ -137,6 +138,9 @@ void MainComponent::Run() { // If the application is active, run Update loops: + // Wake up the events that need to be executed on the main thread, in thread safe manner: + wiEvent::FireEvent(SYSTEM_EVENT_THREAD_SAFE_POINT, 0); + const float dt = framerate_lock ? (1.0f / targetFrameRate) : deltaTime; fadeManager.Update(dt); diff --git a/WickedEngine/wiEvent.cpp b/WickedEngine/wiEvent.cpp index c7fc10321..62fd3fadb 100644 --- a/WickedEngine/wiEvent.cpp +++ b/WickedEngine/wiEvent.cpp @@ -1,14 +1,17 @@ #include "wiEvent.h" #include +#include #include +#include #include namespace wiEvent { struct EventManager { - std::unordered_map>> subscribers; + std::unordered_map*>> subscribers; + std::unordered_map>> subscribers_once; std::mutex locker; }; std::shared_ptr manager = std::make_shared(); @@ -17,14 +20,14 @@ namespace wiEvent { std::shared_ptr manager; int id = 0; - int index = -1; + std::function callback; ~EventInternal() { auto it = manager->subscribers.find(id); - if (it != manager->subscribers.end() && it->second.size() > index) + if (it != manager->subscribers.end()) { - it->second.erase(it->second.begin() + index); + it->second.remove(&callback); } } }; @@ -36,28 +39,49 @@ namespace wiEvent handle.internal_state = eventinternal; eventinternal->manager = manager; eventinternal->id = id; + eventinternal->callback = callback; manager->locker.lock(); - eventinternal->index = (int)manager->subscribers[id].size(); - manager->subscribers[id].push_back(callback); + manager->subscribers[id].push_back(&eventinternal->callback); manager->locker.unlock(); return handle; } + void Subscribe_Once(int id, std::function callback) + { + manager->locker.lock(); + manager->subscribers_once[id].push_back(callback); + manager->locker.unlock(); + } + void FireEvent(int id, uint64_t userdata) { manager->locker.lock(); - auto it = manager->subscribers.find(id); - if (it == manager->subscribers.end()) + // Callbacks that only live for once: { - manager->locker.unlock(); - return; + auto it = manager->subscribers_once.find(id); + if (it != manager->subscribers_once.end()) + { + auto& callbacks = it->second; + for (auto& callback : callbacks) + { + callback(userdata); + } + callbacks.clear(); + } } - auto& callbacks = it->second; - for (auto& callback : callbacks) + // Callbacks that live until deleted: { - callback(userdata); + auto it = manager->subscribers.find(id); + if (it != manager->subscribers.end()) + { + auto& callbacks = it->second; + for (auto& callback : callbacks) + { + (*callback)(userdata); + } + } } manager->locker.unlock(); } diff --git a/WickedEngine/wiEvent.h b/WickedEngine/wiEvent.h index 4ee5113e8..403cd2c8f 100644 --- a/WickedEngine/wiEvent.h +++ b/WickedEngine/wiEvent.h @@ -8,6 +8,7 @@ static const int SYSTEM_EVENT_RELOAD_SHADERS = -1; static const int SYSTEM_EVENT_CHANGE_RESOLUTION = -2; static const int SYSTEM_EVENT_CHANGE_RESOLUTION_SCALE = -3; static const int SYSTEM_EVENT_CHANGE_DPI = -4; +static const int SYSTEM_EVENT_THREAD_SAFE_POINT = -5; namespace wiEvent { @@ -18,5 +19,6 @@ namespace wiEvent }; Handle Subscribe(int id, std::function callback); + void Subscribe_Once(int id, std::function callback); void FireEvent(int id, uint64_t userdata); } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index bb0cbe504..bf9cfef4d 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking API changes const int minor = 47; // minor bug fixes, alterations, refactors, updates - const int revision = 9; + const int revision = 10; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);