diff --git a/Editor/App_Windows.cpp b/Editor/App_Windows.cpp index 994bb41af..a778465ea 100644 --- a/Editor/App_Windows.cpp +++ b/Editor/App_Windows.cpp @@ -90,7 +90,7 @@ public: m_logicalWidth = window.Bounds().Width; m_logicalHeight = window.Bounds().Height; - main.SetWindow(&window); + main.SetWindow(window); } void Load(winrt::hstring const&) noexcept @@ -145,7 +145,7 @@ protected: m_logicalWidth = sender.Bounds().Width; m_logicalHeight = sender.Bounds().Height; - float dpiscale = wiPlatform::GetDPIScaling(); + float dpiscale = wiRenderer::GetDevice()->GetDPIScaling(); uint64_t data = 0; data |= int(m_logicalWidth * dpiscale); data |= int(m_logicalHeight * dpiscale) << 16; diff --git a/Editor/main_SDL2.cpp b/Editor/main_SDL2.cpp index d8eace34e..ea1bbedf6 100644 --- a/Editor/main_SDL2.cpp +++ b/Editor/main_SDL2.cpp @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) //TODO read config.ini int x = 1920, y = 0, w = 1080, h = 0; + bool fullscreen = false; bool borderless = false; string voidStr = ""; @@ -68,7 +69,7 @@ int main(int argc, char *argv[]) file >> voidStr >> enabled; if (enabled != 0) { - file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> editor.fullscreen >> voidStr >> borderless; + file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> fullscreen >> voidStr >> borderless; } } file.close(); @@ -82,7 +83,7 @@ int main(int argc, char *argv[]) throw sdl2::SDLError("Error creating window"); } - if(editor.fullscreen) SDL_SetWindowFullscreen(window.get(), SDL_TRUE); + if(fullscreen) SDL_SetWindowFullscreen(window.get(), SDL_TRUE); editor.SetWindow(window.get()); diff --git a/Editor/main_Windows.cpp b/Editor/main_Windows.cpp index 4d8e2333d..d52820108 100644 --- a/Editor/main_Windows.cpp +++ b/Editor/main_Windows.cpp @@ -117,6 +117,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) hInst = hInstance; // Store instance handle in our global variable int x = CW_USEDEFAULT, y = 0, w = CW_USEDEFAULT, h = 0; + bool fullscreen = false; bool borderless = false; string voidStr = ""; @@ -127,7 +128,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) file >> voidStr >> enabled; if (enabled != 0) { - file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> editor.fullscreen >> voidStr >> borderless; + file >> voidStr >> x >> voidStr >> y >> voidStr >> w >> voidStr >> h >> voidStr >> fullscreen >> voidStr >> borderless; } } file.close(); @@ -158,7 +159,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) return FALSE; } - editor.SetWindow(hWnd); + editor.SetWindow(hWnd, fullscreen); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); @@ -242,6 +243,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_INPUT: wiRawInput::ParseMessage((void*)lParam); break; + case WM_KILLFOCUS: + editor.is_window_active = false; + break; + case WM_SETFOCUS: + editor.is_window_active = true; + break; case WM_PAINT: { PAINTSTRUCT ps; diff --git a/README.md b/README.md index 6cddb92bc..10718bff4 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ If you have questions or stuck, please use the `linux` communication channel on // Declare main component once per application: MainComponent main; -// Set the window to render to like this: +// Assign window that you will render to: main.SetWindow(hWnd); // Run the application: diff --git a/Template_UWP/Main.cpp b/Template_UWP/Main.cpp index 7300526b0..7ad4b9c42 100644 --- a/Template_UWP/Main.cpp +++ b/Template_UWP/Main.cpp @@ -89,7 +89,7 @@ public: m_logicalWidth = window.Bounds().Width; m_logicalHeight = window.Bounds().Height; - main.SetWindow(&window); + main.SetWindow(window); } void Load(winrt::hstring const &) noexcept @@ -144,7 +144,7 @@ protected: m_logicalWidth = sender.Bounds().Width; m_logicalHeight = sender.Bounds().Height; - float dpiscale = wiPlatform::GetDPIScaling(); + float dpiscale = wiRenderer::GetDevice()->GetDPIScaling(); uint64_t data = 0; data |= int(m_logicalWidth * dpiscale); data |= int(m_logicalHeight * dpiscale) << 16; diff --git a/Template_Windows/main.cpp b/Template_Windows/main.cpp index ebc8b3a25..2377086ff 100644 --- a/Template_Windows/main.cpp +++ b/Template_Windows/main.cpp @@ -188,6 +188,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; } break; + case WM_KILLFOCUS: + main.is_window_active = false; + break; + case WM_SETFOCUS: + main.is_window_active = true; + break; case WM_PAINT: { PAINTSTRUCT ps; diff --git a/Tests/main_Windows.cpp b/Tests/main_Windows.cpp index fcb4c6dc2..5d7d8ad29 100644 --- a/Tests/main_Windows.cpp +++ b/Tests/main_Windows.cpp @@ -184,6 +184,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_INPUT: wiRawInput::ParseMessage((void*)lParam); break; + case WM_KILLFOCUS: + tests.is_window_active = false; + break; + case WM_SETFOCUS: + tests.is_window_active = true; + break; case WM_PAINT: { PAINTSTRUCT ps; diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 1fd2772db..49ec1a436 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -38,75 +38,6 @@ void MainComponent::Initialize() wiHelper::GetOriginalWorkingDirectory(); - // User can also create a graphics device if custom logic is desired, but they must do before this function! - if (wiRenderer::GetDevice() == nullptr) - { - auto window = wiPlatform::GetWindow(); - - bool debugdevice = wiStartupArguments::HasArgument("debugdevice"); - - bool use_dx11 = wiStartupArguments::HasArgument("dx11"); - bool use_dx12 = wiStartupArguments::HasArgument("dx12"); - bool use_vulkan = wiStartupArguments::HasArgument("vulkan"); - -#ifndef WICKEDENGINE_BUILD_DX11 - if (use_dx11) { - wiHelper::messageBox("The engine was built without DX11 support!", "Error"); - use_dx11 = false; - } -#endif -#ifndef WICKEDENGINE_BUILD_DX12 - if (use_dx12) { - wiHelper::messageBox("The engine was built without DX12 support!", "Error"); - use_dx12 = false; - } -#endif -#ifndef WICKEDENGINE_BUILD_VULKAN - if (use_vulkan) { - wiHelper::messageBox("The engine was built without Vulkan support!", "Error"); - use_vulkan = false; - } -#endif - - if (!use_dx11 && !use_dx12 && !use_vulkan) - { -#if defined(WICKEDENGINE_BUILD_DX11) - use_dx11 = true; -#elif defined(WICKEDENGINE_BUILD_DX12) - use_dx12 = true; -#elif defined(WICKEDENGINE_BUILD_VULKAN) - use_vulkan = true; -#else - wiBackLog::post("No rendering backend is enabled! Please enable at least one so we can use it as default"); - assert(false); -#endif - } - assert(use_dx11 || use_dx12 || use_vulkan); - - if (use_vulkan) - { -#ifdef WICKEDENGINE_BUILD_VULKAN - wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "spirv/"); - wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); -#endif - } - else if (use_dx12) - { -#ifdef WICKEDENGINE_BUILD_DX12 - wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "hlsl6/"); - wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); -#endif - } - else if (use_dx11) - { -#ifdef WICKEDENGINE_BUILD_DX11 - wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); -#endif - } - - } - - wiInitializer::InitializeComponentsAsync(); } @@ -162,7 +93,7 @@ void MainComponent::Run() deltaTime = float(std::max(0.0, timer.elapsed() / 1000.0)); timer.record(); - if (wiPlatform::IsWindowActive()) + if (is_window_active) { // If the application is active, run Update loops: @@ -277,12 +208,14 @@ void MainComponent::Compose(CommandList cmd) GetActivePath()->Compose(cmd); } + GraphicsDevice* device = wiRenderer::GetDevice(); + if (fadeManager.IsActive()) { // display fade rect static wiImageParams fx; - fx.siz.x = (float)wiRenderer::GetDevice()->GetScreenWidth(); - fx.siz.y = (float)wiRenderer::GetDevice()->GetScreenHeight(); + fx.siz.x = (float)device->GetScreenWidth(); + fx.siz.y = (float)device->GetScreenHeight(); fx.opacity = fadeManager.opacity; wiImage::Draw(wiTextureHelper::getColor(fadeManager.color), fx, cmd); } @@ -308,19 +241,19 @@ void MainComponent::Compose(CommandList cmd) #endif #ifdef WICKEDENGINE_BUILD_DX11 - if (dynamic_cast(wiRenderer::GetDevice())) + if (dynamic_cast(device)) { ss << "[DX11]"; } #endif #ifdef WICKEDENGINE_BUILD_DX12 - if (dynamic_cast(wiRenderer::GetDevice())) + if (dynamic_cast(device)) { ss << "[DX12]"; } #endif #ifdef WICKEDENGINE_BUILD_VULKAN - if (dynamic_cast(wiRenderer::GetDevice())) + if (dynamic_cast(device)) { ss << "[Vulkan]"; } @@ -329,7 +262,7 @@ void MainComponent::Compose(CommandList cmd) #ifdef _DEBUG ss << "[DEBUG]"; #endif - if (wiRenderer::GetDevice()->IsDebugDevice()) + if (device->IsDebugDevice()) { ss << "[debugdevice]"; } @@ -337,7 +270,7 @@ void MainComponent::Compose(CommandList cmd) } if (infoDisplay.resolution) { - ss << "Resolution: " << wiRenderer::GetDevice()->GetResolutionWidth() << " x " << wiRenderer::GetDevice()->GetResolutionHeight() << " (" << wiPlatform::GetDPI() << " dpi)" << endl; + ss << "Resolution: " << device->GetResolutionWidth() << " x " << device->GetResolutionHeight() << " (" << device->GetDPI() << " dpi)" << endl; } if (infoDisplay.fpsinfo) { @@ -375,7 +308,7 @@ void MainComponent::Compose(CommandList cmd) if (infoDisplay.colorgrading_helper) { - wiImage::Draw(wiTextureHelper::getColorGradeDefault(), wiImageParams(0, 0, 256.0f / wiPlatform::GetDPIScaling(), 16.0f / wiPlatform::GetDPIScaling()), cmd); + wiImage::Draw(wiTextureHelper::getColorGradeDefault(), wiImageParams(0, 0, 256.0f / device->GetDPIScaling(), 16.0f / device->GetDPIScaling()), cmd); } } @@ -386,9 +319,71 @@ void MainComponent::Compose(CommandList cmd) wiProfiler::EndRange(range); // Compose } -void MainComponent::SetWindow(wiPlatform::window_type window) +void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) { - wiPlatform::GetWindowState().window = window; - wiPlatform::InitDPI(); + // User can also create a graphics device if custom logic is desired, but they must do before this function! + if (wiRenderer::GetDevice() == nullptr) + { + bool debugdevice = wiStartupArguments::HasArgument("debugdevice"); + + bool use_dx11 = wiStartupArguments::HasArgument("dx11"); + bool use_dx12 = wiStartupArguments::HasArgument("dx12"); + bool use_vulkan = wiStartupArguments::HasArgument("vulkan"); + +#ifndef WICKEDENGINE_BUILD_DX11 + if (use_dx11) { + wiHelper::messageBox("The engine was built without DX11 support!", "Error"); + use_dx11 = false; + } +#endif +#ifndef WICKEDENGINE_BUILD_DX12 + if (use_dx12) { + wiHelper::messageBox("The engine was built without DX12 support!", "Error"); + use_dx12 = false; + } +#endif +#ifndef WICKEDENGINE_BUILD_VULKAN + if (use_vulkan) { + wiHelper::messageBox("The engine was built without Vulkan support!", "Error"); + use_vulkan = false; + } +#endif + + if (!use_dx11 && !use_dx12 && !use_vulkan) + { +#if defined(WICKEDENGINE_BUILD_DX11) + use_dx11 = true; +#elif defined(WICKEDENGINE_BUILD_DX12) + use_dx12 = true; +#elif defined(WICKEDENGINE_BUILD_VULKAN) + use_vulkan = true; +#else + wiBackLog::post("No rendering backend is enabled! Please enable at least one so we can use it as default"); + assert(false); +#endif + } + assert(use_dx11 || use_dx12 || use_vulkan); + + if (use_vulkan) + { +#ifdef WICKEDENGINE_BUILD_VULKAN + wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "spirv/"); + wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); +#endif + } + else if (use_dx12) + { +#ifdef WICKEDENGINE_BUILD_DX12 + wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "hlsl6/"); + wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); +#endif + } + else if (use_dx11) + { +#ifdef WICKEDENGINE_BUILD_DX11 + wiRenderer::SetDevice(std::make_shared(window, fullscreen, debugdevice)); +#endif + } + } } diff --git a/WickedEngine/MainComponent.h b/WickedEngine/MainComponent.h index c65f04b1d..679635bb3 100644 --- a/WickedEngine/MainComponent.h +++ b/WickedEngine/MainComponent.h @@ -26,7 +26,7 @@ protected: int fps_avg_counter = 0; public: - bool fullscreen = false; + bool is_window_active = true; // Runs the main engine loop void Run(); @@ -61,7 +61,7 @@ public: virtual void Compose(wiGraphics::CommandList cmd); // You need to call this before calling Run() or Initialize() if you want to render - void SetWindow(wiPlatform::window_type); + void SetWindow(wiPlatform::window_type, bool fullscreen = false); struct InfoDisplayer diff --git a/WickedEngine/wiFont.cpp b/WickedEngine/wiFont.cpp index b6db44cbd..84adfa794 100644 --- a/WickedEngine/wiFont.cpp +++ b/WickedEngine/wiFont.cpp @@ -369,7 +369,7 @@ void UpdatePendingGlyphs() const int borderPadding = 1; // Font resolution is upscaled to make it sharper: - const float upscaling = std::max(2.0f, wiPlatform::GetDPIScaling()); + const float upscaling = std::max(2.0f, wiRenderer::GetDevice()->GetDPIScaling()); for (int32_t hash : pendingGlyphs) { diff --git a/WickedEngine/wiGraphicsDevice.cpp b/WickedEngine/wiGraphicsDevice.cpp index ebae8dfa5..1580a5ccf 100644 --- a/WickedEngine/wiGraphicsDevice.cpp +++ b/WickedEngine/wiGraphicsDevice.cpp @@ -1,5 +1,5 @@ #include "wiGraphicsDevice.h" -#include "wiPlatform.h" +#include "wiEvent.h" using namespace wiGraphics; @@ -160,9 +160,9 @@ bool GraphicsDevice::IsFormatStencilSupport(FORMAT value) const float GraphicsDevice::GetScreenWidth() const { - return (float)GetResolutionWidth() / wiPlatform::GetDPIScaling(); + return (float)GetResolutionWidth() / GetDPIScaling(); } float GraphicsDevice::GetScreenHeight() const { - return (float)GetResolutionHeight() / wiPlatform::GetDPIScaling(); + return (float)GetResolutionHeight() / GetDPIScaling(); } diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index b21594800..9e8a59883 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -1,6 +1,7 @@ #pragma once #include "CommonInclude.h" #include "wiGraphics.h" +#include "wiEvent.h" #include @@ -26,6 +27,9 @@ namespace wiGraphics uint32_t VARIABLE_RATE_SHADING_TILE_SIZE = 0; uint64_t TIMESTAMP_FREQUENCY = 0; + int dpi = 96; + wiEvent::Handle dpi_change_event = wiEvent::Subscribe(SYSTEM_EVENT_CHANGE_DPI, [this](uint64_t userdata) { dpi = int(userdata & 0xFFFF); }); + public: virtual bool CreateBuffer(const GPUBufferDesc *pDesc, const SubresourceData* pInitialData, GPUBuffer *pBuffer) = 0; virtual bool CreateTexture(const TextureDesc* pDesc, const SubresourceData *pInitialData, Texture *pTexture) = 0; @@ -75,6 +79,9 @@ namespace wiGraphics // Returns native resolution height of back buffer in pixels: inline int GetResolutionHeight() const { return RESOLUTIONHEIGHT; } + constexpr int GetDPI() const { return dpi; } + constexpr float GetDPIScaling() const { return (float)GetDPI() / 96.f; } + // Returns the width of the screen with DPI scaling applied (subpixel size): float GetScreenWidth() const; // Returns the height of the screen with DPI scaling applied (subpixel size): diff --git a/WickedEngine/wiGraphicsDevice_DX11.cpp b/WickedEngine/wiGraphicsDevice_DX11.cpp index 1950265a0..d20a4bf83 100644 --- a/WickedEngine/wiGraphicsDevice_DX11.cpp +++ b/WickedEngine/wiGraphicsDevice_DX11.cpp @@ -1332,15 +1332,16 @@ GraphicsDevice_DX11::GraphicsDevice_DX11(wiPlatform::window_type window, bool fu FULLSCREEN = fullscreen; #ifndef PLATFORM_UWP + dpi = GetDpiForWindow(window); RECT rect; GetClientRect(window, &rect); RESOLUTIONWIDTH = rect.right - rect.left; RESOLUTIONHEIGHT = rect.bottom - rect.top; #else PLATFORM_UWP - float dpiscale = wiPlatform::GetDPIScaling(); - auto uwpwindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread(); - RESOLUTIONWIDTH = int(uwpwindow.Bounds().Width * dpiscale); - RESOLUTIONHEIGHT = int(uwpwindow.Bounds().Height * dpiscale); + dpi = (int)winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView().LogicalDpi(); + float dpiscale = GetDPIScaling(); + RESOLUTIONWIDTH = int(window.Bounds().Width * dpiscale); + RESOLUTIONHEIGHT = int(window.Bounds().Height * dpiscale); #endif @@ -1455,7 +1456,7 @@ GraphicsDevice_DX11::GraphicsDevice_DX11(wiPlatform::window_type window, bool fu #else sd.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; - hr = pIDXGIFactory->CreateSwapChainForCoreWindow(device.Get(), static_cast(winrt::get_abi(uwpwindow)), &sd, nullptr, &swapChain); + hr = pIDXGIFactory->CreateSwapChainForCoreWindow(device.Get(), static_cast(winrt::get_abi(window)), &sd, nullptr, &swapChain); #endif if (FAILED(hr)) diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index f5a7bc84d..be973ffd3 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -2291,15 +2291,16 @@ using namespace DX12_Internal; FULLSCREEN = fullscreen; #ifndef PLATFORM_UWP + dpi = GetDpiForWindow(window); RECT rect; GetClientRect(window, &rect); RESOLUTIONWIDTH = rect.right - rect.left; RESOLUTIONHEIGHT = rect.bottom - rect.top; #else PLATFORM_UWP - float dpiscale = wiPlatform::GetDPIScaling(); - auto uwpwindow = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread(); - RESOLUTIONWIDTH = int(uwpwindow.Bounds().Width * dpiscale); - RESOLUTIONHEIGHT = int(uwpwindow.Bounds().Height * dpiscale); + dpi = (int)winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView().LogicalDpi(); + float dpiscale = GetDPIScaling(); + RESOLUTIONWIDTH = int(window.Bounds().Width * dpiscale); + RESOLUTIONHEIGHT = int(window.Bounds().Height * dpiscale); #endif @@ -2466,7 +2467,7 @@ using namespace DX12_Internal; #else sd.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; - hr = factory->CreateSwapChainForCoreWindow(directQueue.Get(), static_cast(winrt::get_abi(uwpwindow)), &sd, nullptr, &_swapChain); + hr = factory->CreateSwapChainForCoreWindow(directQueue.Get(), static_cast(winrt::get_abi(window)), &sd, nullptr, &_swapChain); #endif if (FAILED(hr)) diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 4fd3c0f2a..ec22efd05 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -2086,6 +2086,7 @@ using namespace Vulkan_Internal; FULLSCREEN = fullscreen; #ifdef _WIN32 + dpi = GetDpiForWindow(window); RECT rect; GetClientRect(window, &rect); RESOLUTIONWIDTH = rect.right - rect.left; diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index e36b0a8f4..6633e2a4e 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -53,7 +53,7 @@ namespace wiHelper { #ifdef _WIN32 #ifndef PLATFORM_UWP - MessageBoxA(wiPlatform::GetWindow(), msg.c_str(), caption.c_str(), 0); + MessageBoxA(GetActiveWindow(), msg.c_str(), caption.c_str(), 0); #else wstring wmessage, wcaption; StringConvert(msg, wmessage); @@ -406,16 +406,17 @@ namespace wiHelper #else using namespace winrt::Windows::Storage; using namespace winrt::Windows::Storage::Streams; + using namespace winrt::Windows::Foundation; wstring wstr; string filepath = ExpandPath(fileName); StringConvert(filepath, wstr); bool success = false; - std::thread([&] { + auto async_helper = [&]() -> IAsyncAction { try { - auto file = StorageFile::GetFileFromPathAsync(wstr).get(); - auto buffer = FileIO::ReadBufferAsync(file).get(); + auto file = co_await StorageFile::GetFileFromPathAsync(wstr); + auto buffer = co_await FileIO::ReadBufferAsync(file); auto reader = DataReader::FromBuffer(buffer); auto size = buffer.Length(); data.resize((size_t)size); @@ -430,14 +431,23 @@ namespace wiHelper switch (ex.code()) { case E_ACCESSDENIED: - wiBackLog::post(("Opening file failed: " + fileName + "\nReason: Permission Denied!").c_str()); + wiBackLog::post(("Opening file failed: " + fileName + " | Reason: Permission Denied!").c_str()); break; default: break; } } - }).join(); + }; + + if (winrt::impl::is_sta_thread()) + { + std::thread([&] { async_helper().get(); }).join(); // can't block coroutine from ui thread + } + else + { + async_helper().get(); + } if (success) { @@ -469,6 +479,7 @@ namespace wiHelper using namespace winrt::Windows::Storage; using namespace winrt::Windows::Storage::Streams; + using namespace winrt::Windows::Foundation; wstring wstr; string filepath = ExpandPath(fileName); StringConvert(filepath, wstr); @@ -481,12 +492,12 @@ namespace wiHelper CloseHandle(filehandle); bool success = false; - std::thread([&] { + auto async_helper = [&]() -> IAsyncAction { try { - auto file = StorageFile::GetFileFromPathAsync(wstr).get(); + auto file = co_await StorageFile::GetFileFromPathAsync(wstr); winrt::array_view dataarray(data, (winrt::array_view::size_type)size); - FileIO::WriteBytesAsync(file, dataarray).get(); + co_await FileIO::WriteBytesAsync(file, dataarray); success = true; } catch (winrt::hresult_error const& ex) @@ -494,14 +505,23 @@ namespace wiHelper switch (ex.code()) { case E_ACCESSDENIED: - wiBackLog::post(("Opening file failed: " + fileName + "\nReason: Permission Denied!").c_str()); + wiBackLog::post(("Opening file failed: " + fileName + " | Reason: Permission Denied!").c_str()); break; default: break; } } - }).join(); + }; + + if (winrt::impl::is_sta_thread()) + { + std::thread([&] { async_helper().get(); }).join(); // can't block coroutine from ui thread + } + else + { + async_helper().get(); + } if (success) { @@ -521,6 +541,7 @@ namespace wiHelper return exists; #else using namespace winrt::Windows::Storage; + using namespace winrt::Windows::Foundation; string filepath = ExpandPath(fileName); string directory, name; SplitPath(filepath, directory, name); @@ -529,11 +550,11 @@ namespace wiHelper StringConvert(name, wname); bool success = false; - std::thread([&] { + auto async_helper = [&]() -> IAsyncAction { try { - auto folder = StorageFolder::GetFolderFromPathAsync(wdir).get(); - auto item = folder.TryGetItemAsync(wname).get(); + auto folder = co_await StorageFolder::GetFolderFromPathAsync(wdir); + auto item = co_await folder.TryGetItemAsync(wname); if (item) { success = true; @@ -544,126 +565,28 @@ namespace wiHelper switch (ex.code()) { case E_ACCESSDENIED: - wiBackLog::post(("Opening file failed: " + fileName + "\nReason: Permission Denied!").c_str()); + wiBackLog::post(("Opening file failed: " + fileName + " | Reason: Permission Denied!").c_str()); break; default: break; } } - }).join(); + }; + + if (winrt::impl::is_sta_thread()) + { + std::thread([&] { async_helper().get(); }).join(); // can't block coroutine from ui thread + } + else + { + async_helper().get(); + } return success; #endif } -#ifdef PLATFORM_UWP - winrt::fire_and_forget filedialoghelper(FileDialogParams params, std::function onSuccess) - { - using namespace winrt::Windows::Storage; - using namespace winrt::Windows::Storage::Pickers; - using namespace winrt::Windows::Storage::AccessCache; - - switch (params.type) - { - default: - case FileDialogParams::OPEN: - { - FileOpenPicker picker; - picker.ViewMode(PickerViewMode::List); - picker.SuggestedStartLocation(PickerLocationId::Objects3D); - - for (auto& x : params.extensions) - { - wstring wstr; - StringConvert(x, wstr); - wstr = L"." + wstr; - picker.FileTypeFilter().Append(wstr); - } - - auto file = co_await picker.PickSingleFileAsync(); - - if (file) - { - auto futureaccess = StorageApplicationPermissions::FutureAccessList(); - futureaccess.Clear(); - futureaccess.Add(file); - wstring wstr = file.Path().data(); - string str; - StringConvert(wstr, str); - - // The desktop file picker also modifies the working directory: - SetWorkingDirectory(GetDirectoryFromPath(str)); - - // Need to verify that parent folder is accessible: - auto folder = co_await file.GetParentAsync(); - if (folder) - { - onSuccess(str); - } - else - { - // Folder not accessible: - auto msg = winrt::Windows::UI::Popups::MessageDialog( - L"No permission to folder!\nPlease pick the current folder to receive permission!\nOtherwise, some files might fail to load.", - L"Warning!").ShowAsync().get(); - - FolderPicker folderpicker; - folderpicker.ViewMode(PickerViewMode::List); - folderpicker.SuggestedStartLocation(PickerLocationId::ComputerFolder); - - for (auto& x : params.extensions) - { - wstring wstr; - StringConvert(x, wstr); - wstr = L"." + wstr; - folderpicker.FileTypeFilter().Append(wstr); - } - - auto folder = co_await folderpicker.PickSingleFolderAsync(); - if (folder) - { - futureaccess.Add(folder); - onSuccess(str); - } - } - } - } - break; - case FileDialogParams::SAVE: - { - FileSavePicker picker; - picker.SuggestedStartLocation(PickerLocationId::Objects3D); - - wstring wdesc; - StringConvert(params.description, wdesc); - winrt::Windows::Foundation::Collections::IVector extensions{ winrt::single_threaded_vector() }; - for (auto& x : params.extensions) - { - wstring wstr; - StringConvert(x, wstr); - wstr = L"." + wstr; - extensions.Append(wstr); - } - picker.FileTypeChoices().Insert(wdesc, extensions); - - auto file = co_await picker.PickSaveFileAsync(); - if (file) - { - auto futureaccess = StorageApplicationPermissions::FutureAccessList(); - futureaccess.Clear(); - futureaccess.Add(file); - wstring wstr = file.Path().data(); - string str; - StringConvert(wstr, str); - onSuccess(str); - } - } - break; - } - } -#endif // PLATFORM_UWP - void FileDialog(const FileDialogParams& params, std::function onSuccess) { #ifdef _WIN32 @@ -738,7 +661,79 @@ namespace wiHelper }).detach(); #else + auto filedialoghelper = [](FileDialogParams params, std::function onSuccess) -> winrt::fire_and_forget { + using namespace winrt::Windows::Storage; + using namespace winrt::Windows::Storage::Pickers; + using namespace winrt::Windows::Storage::AccessCache; + + switch (params.type) + { + default: + case FileDialogParams::OPEN: + { + FileOpenPicker picker; + picker.ViewMode(PickerViewMode::List); + picker.SuggestedStartLocation(PickerLocationId::Objects3D); + + for (auto& x : params.extensions) + { + wstring wstr; + StringConvert(x, wstr); + wstr = L"." + wstr; + picker.FileTypeFilter().Append(wstr); + } + + auto file = co_await picker.PickSingleFileAsync(); + + if (file) + { + auto futureaccess = StorageApplicationPermissions::FutureAccessList(); + futureaccess.Clear(); + futureaccess.Add(file); + wstring wstr = file.Path().data(); + string str; + StringConvert(wstr, str); + + // The desktop file picker also modifies the working directory: + SetWorkingDirectory(GetDirectoryFromPath(str)); + + onSuccess(str); + } + } + break; + case FileDialogParams::SAVE: + { + FileSavePicker picker; + picker.SuggestedStartLocation(PickerLocationId::Objects3D); + + wstring wdesc; + StringConvert(params.description, wdesc); + winrt::Windows::Foundation::Collections::IVector extensions{ winrt::single_threaded_vector() }; + for (auto& x : params.extensions) + { + wstring wstr; + StringConvert(x, wstr); + wstr = L"." + wstr; + extensions.Append(wstr); + } + picker.FileTypeChoices().Insert(wdesc, extensions); + + auto file = co_await picker.PickSaveFileAsync(); + if (file) + { + auto futureaccess = StorageApplicationPermissions::FutureAccessList(); + futureaccess.Clear(); + futureaccess.Add(file); + wstring wstr = file.Path().data(); + string str; + StringConvert(wstr, str); + onSuccess(str); + } + } + break; + } + }; filedialoghelper(params, onSuccess); #endif // PLATFORM_UWP diff --git a/WickedEngine/wiInput.cpp b/WickedEngine/wiInput.cpp index 95b03cd63..c360d80ce 100644 --- a/WickedEngine/wiInput.cpp +++ b/WickedEngine/wiInput.cpp @@ -112,6 +112,18 @@ namespace wiInput mouse.left_button_press |= KEY_DOWN(VK_LBUTTON); mouse.middle_button_press |= KEY_DOWN(VK_MBUTTON); mouse.right_button_press |= KEY_DOWN(VK_RBUTTON); + +#ifndef PLATFORM_UWP + // Since raw input doesn't contain absolute mouse position, we get it with regular winapi: + HWND hWnd = GetActiveWindow(); + POINT p; + GetCursorPos(&p); + ScreenToClient(hWnd, &p); + const float dpiscaling = (float)GetDpiForWindow(hWnd) / 96.0f; + mouse.position.x = (float)p.x / dpiscaling; + mouse.position.y = (float)p.y / dpiscaling; +#endif // PLATFORM_UWP + #elif SDL2 wiSDLInput::GetMouseState(&mouse); wiSDLInput::GetKeyboardState(&keyboard); @@ -704,25 +716,18 @@ namespace wiInput } XMFLOAT4 GetPointer() { -#if defined(_WIN32) && !defined(PLATFORM_UWP) - POINT p; - GetCursorPos(&p); - ScreenToClient(wiPlatform::GetWindow(), &p); - const float dpiscaling = wiPlatform::GetDPIScaling(); - return XMFLOAT4((float)p.x / dpiscaling, (float)p.y / dpiscaling, mouse.delta_wheel, mouse.pressure); -#else return XMFLOAT4(mouse.position.x, mouse.position.y, mouse.delta_wheel, mouse.pressure); -#endif } void SetPointer(const XMFLOAT4& props) { #ifdef _WIN32 #ifndef PLATFORM_UWP - const float dpiscaling = wiPlatform::GetDPIScaling(); + HWND hWnd = GetActiveWindow(); + const float dpiscaling = (float)GetDpiForWindow(hWnd) / 96.0f; POINT p; p.x = (LONG)(props.x * dpiscaling); p.y = (LONG)(props.y * dpiscaling); - ClientToScreen(wiPlatform::GetWindow(), &p); + ClientToScreen(hWnd, &p); SetCursorPos(p.x, p.y); #else auto window = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread(); diff --git a/WickedEngine/wiPlatform.h b/WickedEngine/wiPlatform.h index 41cf4c132..304ad602b 100644 --- a/WickedEngine/wiPlatform.h +++ b/WickedEngine/wiPlatform.h @@ -37,7 +37,7 @@ namespace wiPlatform #ifndef PLATFORM_UWP using window_type = HWND; #else - using window_type = const winrt::Windows::UI::Core::CoreWindow*; + using window_type = const winrt::Windows::UI::Core::CoreWindow&; #endif // PLATFORM_UWP #elif SDL2 using window_type = SDL_Window*; @@ -45,65 +45,6 @@ namespace wiPlatform using window_type = int; #endif // _WIN32 - struct WindowState - { - window_type window; - int dpi = 96; - }; - inline WindowState& GetWindowState() - { - static WindowState state; - return state; - } - - inline window_type& GetWindow() - { - return GetWindowState().window; - } - inline bool IsWindowActive() - { -#ifdef _WIN32 -#ifndef PLATFORM_UWP - return GetForegroundWindow() == GetWindow(); -#else - return true; -#endif // PLATFORM_UWP -#else - return true; -#endif // _WIN32 - } - inline void InitDPI() - { -#ifdef _WIN32 -#ifndef PLATFORM_UWP - GetWindowState().dpi = (int)GetDpiForWindow(GetWindow()); -#else - GetWindowState().dpi = (int)winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView().LogicalDpi(); -#endif // PLATFORM_UWP -#elif SDL2 - int displayIndex = 0; - float ddpi; - float hdpi; - float vdpi; - int ret = SDL_GetDisplayDPI(displayIndex, &ddpi, &hdpi, &vdpi); - if (ret == 0) { - //TODO setting the correct DPI resolution messes up with the correct mouse position. - // I believe it's because SDL2 is reporting the correct pixel position while windows is reporting - // a corrected version of the mouse position that needs to be interpreted depending on the DPI. - //GetWindowState().dpi = ddpi; - } else { - std::clog << "Could not infer Display DPI from SDL: " << SDL_GetError() << std::endl; - } -#endif // _WIN32 - } - inline int GetDPI() - { - return GetWindowState().dpi; - } - inline float GetDPIScaling() - { - return (float)GetDPI() / 96.0f; - } inline void Exit() { #ifdef _WIN32 diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 16341be93..bb7817a66 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -2391,11 +2391,6 @@ void Initialize() device->SetResolution(width, height); }); - static wiEvent::Handle handle4 = wiEvent::Subscribe(SYSTEM_EVENT_CHANGE_DPI, [](uint64_t userdata) { - int dpi = userdata & 0xFFFF; - wiPlatform::GetWindowState().dpi = dpi; - }); - wiBackLog::post("wiRenderer Initialized"); } void ClearWorld(Scene& scene) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 858ef4236..92bee2da2 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 53; // minor bug fixes, alterations, refactors, updates - const int revision = 10; + const int revision = 11; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);