From c33bcf76e99a5b638d78e1cc9dbacccef22c9f4b Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 01:29:32 +0300 Subject: [PATCH 01/18] Added multi-viewport feature --- imgui-SFML.cpp | 448 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 439 insertions(+), 9 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 9711079..4971c3e 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -24,6 +24,14 @@ #include #include + +// For multi-viewport support enable/disable +#define VIEWPORTS_ENABLE + +#if defined(VIEWPORTS_ENABLE) && defined(_WIN32) +#include +#endif + #ifdef ANDROID #ifdef USE_JNI @@ -176,7 +184,7 @@ struct TriggerInfo { }; struct WindowContext { - const sf::Window* window; + sf::Window* const window; ImGuiContext* imContext; sf::Texture fontTexture; // internal font atlas which is used if user doesn't set a custom @@ -207,12 +215,63 @@ struct WindowContext { #endif #endif +#ifdef VIEWPORTS_ENABLE + const bool imContextOwner; // Context owner/main viewport + const bool isRenderWindow; + + WindowContext(const WindowContext&) = delete; // non construction-copyable + WindowContext& operator=(const WindowContext&) = delete; // non copyable + + WindowContext(sf::RenderWindow* w, ImGuiContext* context = nullptr) + : WindowContext(w, context, true) { } + + WindowContext(sf::Window* w, ImGuiContext* context = nullptr, bool isRenderWindow = false) + : window(w), imContextOwner(context == nullptr), isRenderWindow(isRenderWindow) + { + if (context) { + imContext = context; + } else { + imContext = ::ImGui::CreateContext(); + } + + windowHasFocus = window->hasFocus(); + mouseMoved = false; + for (int i = 0; i < 3; ++i) { + mousePressed[i] = false; + touchDown[i] = false; + } + lastCursor = ImGuiMouseCursor_COUNT; + + joystickId = getConnectedJoystickId(); + for (int i = 0; i < sf::Joystick::ButtonCount; ++i) { + joystickMapping[i] = ImGuiKey_None; + } + + for (int i = 0; i < ImGuiMouseCursor_COUNT; ++i) { + mouseCursorLoaded[i] = false; + } + +#ifdef ANDROID +#ifdef USE_JNI + wantTextInput = false; +#endif +#endif + } + + ~WindowContext() { + if (imContextOwner) + ::ImGui::DestroyContext(imContext); + else + delete window; + } + +#else WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable - WindowContext(const sf::Window* w) { - window = w; - imContext = ImGui::CreateContext(); + WindowContext(sf::Window* w) : window(w) + { + imContext = ::ImGui::CreateContext(); windowHasFocus = window->hasFocus(); mouseMoved = false; @@ -238,12 +297,42 @@ struct WindowContext { #endif } - ~WindowContext() { ImGui::DestroyContext(imContext); } + ~WindowContext() { ::ImGui::DestroyContext(imContext); } +#endif }; std::vector> s_windowContexts; WindowContext* s_currWindowCtx = nullptr; + +#ifdef VIEWPORTS_ENABLE +// VIEWPORT functions +void SFML_CreateWindow(ImGuiViewport* viewport); +void SFML_DestroyWindow(ImGuiViewport* viewport); +void SFML_ShowWindow(ImGuiViewport* viewport); +void SFML_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos); +ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport); +void SFML_SetWindowSize(ImGuiViewport* viewport, ImVec2 size); +ImVec2 SFML_GetWindowSize(ImGuiViewport* viewport); +void SFML_SetWindowFocus(ImGuiViewport* viewport); +bool SFML_GetWindowFocus(ImGuiViewport* viewport); +bool SFML_GetWindowMinimized(ImGuiViewport* viewport); +void SFML_SetWindowTitle(ImGuiViewport* viewport, const char* str); +//void SFML_SetWindowAlpha(ImGuiViewport* viewport, float alpha); +void SFML_UpdateWindow(ImGuiViewport* viewport); +void SFML_RenderWindow(ImGuiViewport* viewport, void*); +void SFML_SwapBuffers(ImGuiViewport* viewport, void*); +//float SFML_GetWindowDpiScale(ImGuiViewport* viewport); +//void SFML_OnChangedViewport(ImGuiViewport* viewport); +//int SFML_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); + +void SFML_UpdateMonitors(); + +void SFML_InitInterface(WindowContext* windowContext); +void SFML_ShutdownInterface(); + +#endif + } // end of anonymous namespace namespace ImGui { @@ -274,6 +363,12 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; +#ifdef VIEWPORTS_ENABLE + io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; + io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; + SFML_InitInterface(s_currWindowCtx); + SFML_UpdateMonitors(); +#endif io.BackendPlatformName = "imgui_impl_sfml"; s_currWindowCtx->joystickId = getConnectedJoystickId(); @@ -555,8 +650,14 @@ void ProcessEvent(const sf::Event& event) { if (s_currWindowCtx->windowHasFocus) { switch (event.type) { - case sf::Event::MouseMoved: - io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y); + case sf::Event::MouseMoved: + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } + else { + io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y); + } s_currWindowCtx->mouseMoved = true; break; case sf::Event::MouseButtonPressed: // fall-through @@ -661,22 +762,166 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { updateMouseCursor(window); } + ImGui::GetMainViewport()->Pos = window.getPosition() + sf::Vector2i(0, 24); + if (!s_currWindowCtx->mouseMoved) { if (sf::Touch::isDown(0)) s_currWindowCtx->touchPos = sf::Touch::getPosition(0, window); Update(s_currWindowCtx->touchPos, static_cast(target.getSize()), dt); } else { - Update(sf::Mouse::getPosition(window), static_cast(target.getSize()), dt); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + Update(sf::Mouse::getPosition(), static_cast(target.getSize()), dt); + else + Update(sf::Mouse::getPosition(window), static_cast(target.getSize()), dt); } } void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::Time dt) { assert(s_currWindowCtx && "No current window is set - forgot to call ImGui::SFML::Init?"); - ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(displaySize.x, displaySize.y); io.DeltaTime = dt.asSeconds(); +#ifdef VIEWPORTS_ENABLE + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + SFML_UpdateMonitors(); + + for (auto& viewport : ImGui::GetPlatformIO().Viewports) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + if (wc->imContextOwner) continue; + sf::Event event; + + while (wc->window->pollEvent(event)) { + if (wc->window->hasFocus()) { + switch (event.type) { + case sf::Event::MouseMoved: + { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } + wc->mouseMoved = true; + break; + case sf::Event::MouseButtonPressed: // fall-through + case sf::Event::MouseButtonReleased: { + int button = event.mouseButton.button; + if (button >= 0 && button < 3) { + if (event.type == sf::Event::MouseButtonPressed) { + wc->mousePressed[event.mouseButton.button] = true; + io.AddMouseButtonEvent(button, true); + } else { + io.AddMouseButtonEvent(button, false); + } + } + } break; + case sf::Event::TouchBegan: // fall-through + case sf::Event::TouchEnded: { + wc->mouseMoved = false; + int button = event.touch.finger; + if (event.type == sf::Event::TouchBegan && button >= 0 && button < 3) { + wc->touchDown[event.touch.finger] = true; + } + } break; + case sf::Event::MouseWheelScrolled: + if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel || + (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel && + io.KeyShift)) { + io.AddMouseWheelEvent(0, event.mouseWheelScroll.delta); + } else if (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel) { + io.AddMouseWheelEvent(event.mouseWheelScroll.delta, 0); + } + break; + case sf::Event::KeyPressed: // fall-through + case sf::Event::KeyReleased: { + bool down = (event.type == sf::Event::KeyPressed); + + ImGuiKey mod = keycodeToImGuiMod(event.key.code); + // The modifier booleans are not reliable when it's the modifier + // itself that's being pressed. Detect these presses directly. + if (mod != ImGuiKey_None) { + io.AddKeyEvent(mod, down); + } else { + io.AddKeyEvent(ImGuiKey_ModCtrl, event.key.control); + io.AddKeyEvent(ImGuiKey_ModShift, event.key.shift); + io.AddKeyEvent(ImGuiKey_ModAlt, event.key.alt); + io.AddKeyEvent(ImGuiKey_ModSuper, event.key.system); + } + + ImGuiKey key = keycodeToImGuiKey(event.key.code); + io.AddKeyEvent(key, down); + io.SetKeyEventNativeData(key, event.key.code, -1); + } break; + case sf::Event::TextEntered: + // Don't handle the event for unprintable characters + if (event.text.unicode < ' ' || event.text.unicode == 127) { + break; + } + io.AddInputCharacter(event.text.unicode); + break; + case sf::Event::JoystickConnected: + if (wc->joystickId == NULL_JOYSTICK_ID) { + wc->joystickId = event.joystickConnect.joystickId; + } + break; + case sf::Event::JoystickDisconnected: + if (wc->joystickId == event.joystickConnect.joystickId) { // used gamepad + // was + // disconnected + wc->joystickId = getConnectedJoystickId(); + } + break; + default: + break; + } + } + + switch (event.type) { + case sf::Event::LostFocus: { + io.AddFocusEvent(false); + wc->windowHasFocus = false; + } break; + case sf::Event::GainedFocus: + io.AddFocusEvent(true); + wc->windowHasFocus = true; + break; + default: + break; + } + } + } + } + + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + const ImVec2 mouse_pos_prev = io.MousePos; + + for (auto& viewport : platform_io.Viewports) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + sf::Window* window = (sf::Window*)viewport->PlatformHandle; + + if (window->hasFocus()) { + if (io.WantSetMousePos) { + sf::Mouse::setPosition({ static_cast(mouse_pos_prev.x - viewport->Pos.x), + static_cast(mouse_pos_prev.y - viewport->Pos.y) }, + *window); + } + sf::Vector2i mousePos; + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + mousePos = sf::Mouse::getPosition(); + else + mousePos = sf::Mouse::getPosition(*window); + + io.AddMousePosEvent(mousePos.x, mousePos.y); + + for (unsigned int i = 0; i < 3; i++) { + io.MouseDown[i] = wc->touchDown[i] || sf::Touch::isDown(i) || wc->mousePressed[i] || + sf::Mouse::isButtonPressed((sf::Mouse::Button)i); + wc->mousePressed[i] = false; + wc->touchDown[i] = false; + } + } + } + +#else if (s_currWindowCtx->windowHasFocus) { if (io.WantSetMousePos) { sf::Vector2i newMousePos(static_cast(io.MousePos.x), @@ -693,6 +938,7 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T s_currWindowCtx->touchDown[i] = false; } } +#endif #ifdef ANDROID #ifdef USE_JNI @@ -741,6 +987,11 @@ void Render() { } void Shutdown(const sf::Window& window) { +#ifdef VIEWPORTS_ENABLE + SetCurrentWindow(window); + SFML_ShutdownInterface(); +#endif // VIEWPORTS_ENABLE + bool needReplacement = (s_currWindowCtx->window->getSystemHandle() == window.getSystemHandle()); // remove window's context @@ -768,6 +1019,13 @@ void Shutdown(const sf::Window& window) { } void Shutdown() { +#ifdef VIEWPORTS_ENABLE + for (auto& ctx : s_windowContexts) { + ImGui::SetCurrentContext(ctx->imContext); + SFML_ShutdownInterface(); + } +#endif // VIEWPORTS_ENABLE + s_currWindowCtx = nullptr; ImGui::SetCurrentContext(nullptr); @@ -1403,4 +1661,176 @@ void updateMouseCursor(sf::Window& window) { } } + +#ifdef VIEWPORTS_ENABLE + +void SFML_CreateWindow(ImGuiViewport* viewport) { + sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(viewport->Size.x, viewport->Size.y), "", sf::Style::None); + window->setVisible(false); + WindowContext* data = IM_NEW(WindowContext)(window, ImGui::GetCurrentContext(), true); + data->windowHasFocus = true; + viewport->PlatformUserData = data; + viewport->PlatformHandle = window; +} + +void SFML_DestroyWindow(ImGuiViewport* viewport) { + if (WindowContext* wc = (WindowContext*)viewport->PlatformUserData) { + if (!wc->imContextOwner) { + wc->window->close(); + IM_DELETE(wc); + } + } + viewport->PlatformUserData = nullptr; + viewport->PlatformHandle = nullptr; +} + +void SFML_ShowWindow(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->setVisible(true); +} + +void SFML_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->setPosition(pos); +} + +ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + +#ifdef _WIN32 + RECT clientAreaRect; + HWND hwnd = wc->window->getSystemHandle(); + GetClientRect(hwnd, &clientAreaRect); + MapWindowPoints(hwnd, NULL, (LPPOINT)&clientAreaRect, 2); + return { (float)clientAreaRect.left, (float)clientAreaRect.top }; +#else + if (wc->imContextOwner) return wc->window->getPosition() + sf::Vector2i(0, 24); + return wc->window->getPosition(); +#endif +} + +void SFML_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->setSize(size); +} + +ImVec2 SFML_GetWindowSize(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + return wc->window->getSize(); +} + +void SFML_SetWindowFocus(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->requestFocus(); +} + +bool SFML_GetWindowFocus(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + return wc->window->hasFocus(); +} + +bool SFML_GetWindowMinimized(ImGuiViewport* viewport) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + return false; // tell imgui that window is allways maximized +} + +void SFML_SetWindowTitle(ImGuiViewport* viewport, const char* str) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->setTitle(str); +} + +void SFML_UpdateWindow(ImGuiViewport* viewport) { + // TODO: implement or delete +} + +void SFML_RenderWindow(ImGuiViewport* viewport, void*) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + if (!wc->imContextOwner) { + IM_ASSERT(wc->isRenderWindow); + sf::RenderWindow* window = (sf::RenderWindow*)wc->window; + window->setActive(true); + window->resetGLStates(); + window->pushGLStates(); + RenderDrawLists(viewport->DrawData); + window->popGLStates(); + } +} + +void SFML_SwapBuffers(ImGuiViewport* viewport, void*) { + WindowContext* wc = (WindowContext*)viewport->PlatformUserData; + wc->window->display(); +} + +#ifdef _WIN32 +static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, + LPARAM dwData) { + int* Count = (int*)dwData; + (*Count)++; + return TRUE; +} +#endif // _WIN32 + +void SFML_UpdateMonitors() { +#ifdef _WIN32 + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Monitors.resize(0); + + MONITORENUMPROC proc = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, + LPARAM dwData) -> BOOL { + ImGuiPlatformIO& platform_io = *((ImGuiPlatformIO*)dwData); + ImGuiPlatformMonitor monitor; + + MONITORINFOEXW mi; + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + + GetMonitorInfoW(hMonitor, (MONITORINFO*)&mi); + + monitor.MainPos = ImVec2(mi.rcMonitor.left, mi.rcMonitor.top); + monitor.MainSize = + ImVec2(mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top); + monitor.WorkPos = ImVec2(mi.rcWork.left, mi.rcWork.top); + monitor.WorkSize = + ImVec2(mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top); + + platform_io.Monitors.push_back(monitor); + return TRUE; + }; + + // if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count)) + EnumDisplayMonitors(NULL, NULL, proc, (LPARAM)&platform_io); +#else + #error "Update monitors is only implemented for windows." +#endif // _WIN32 +} + +void SFML_InitInterface(WindowContext* windowContext) { + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_CreateWindow = SFML_CreateWindow; + platform_io.Platform_DestroyWindow = SFML_DestroyWindow; + platform_io.Platform_ShowWindow = SFML_ShowWindow; + platform_io.Platform_SetWindowPos = SFML_SetWindowPos; + platform_io.Platform_GetWindowPos = SFML_GetWindowPos; + platform_io.Platform_SetWindowSize = SFML_SetWindowSize; + platform_io.Platform_GetWindowSize = SFML_GetWindowSize; + platform_io.Platform_SetWindowFocus = SFML_SetWindowFocus; + platform_io.Platform_GetWindowFocus = SFML_GetWindowFocus; + platform_io.Platform_GetWindowMinimized = SFML_GetWindowMinimized; + platform_io.Platform_SetWindowTitle = SFML_SetWindowTitle; + //platform_io.Platform_SetWindowAlpha = SFML_SetWindowAlpha; + platform_io.Platform_UpdateWindow = SFML_UpdateWindow; + platform_io.Platform_RenderWindow = SFML_RenderWindow; + platform_io.Platform_SwapBuffers = SFML_SwapBuffers; + + ImGuiViewport* mainViewport = ImGui::GetMainViewport(); + mainViewport->PlatformUserData = windowContext; + mainViewport->PlatformHandle = windowContext->window; +} + +void SFML_ShutdownInterface() { + ImGui::DestroyPlatformWindows(); +} + +#endif // VIEWPORTS_ENABLE + } // end of anonymous namespace From f9c5686c0da89a1139e2dbe786262102ecd1a253 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 01:30:09 +0300 Subject: [PATCH 02/18] Added code for multi-viewports --- examples/minimal/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/minimal/main.cpp b/examples/minimal/main.cpp index 2c19abd..3cd9d3d 100644 --- a/examples/minimal/main.cpp +++ b/examples/minimal/main.cpp @@ -7,10 +7,14 @@ #include #include +#include + int main() { - sf::RenderWindow window(sf::VideoMode(640, 480), "ImGui + SFML = <3"); + sf::RenderWindow window(sf::VideoMode(1280, 720), "ImGui + SFML = <3"); window.setFramerateLimit(60); ImGui::SFML::Init(window); + // Comment/uncomment this to disable/enable viewports + ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; sf::CircleShape shape(100.f); shape.setFillColor(sf::Color::Green); @@ -37,6 +41,10 @@ int main() { window.clear(); window.draw(shape); ImGui::SFML::Render(window); + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } window.display(); } From 669d0d957be3075578895fe911932b4c8e3ae99e Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 01:30:56 +0300 Subject: [PATCH 03/18] Ignored Visual Studio folder --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f953e9f..073e942 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ Ignore folders named build build/** Build/** + +Ignore Visual Studio folder +.vs/** \ No newline at end of file From ff095de837dff7841620813656728b6086ba7c4a Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 14:57:31 +0300 Subject: [PATCH 04/18] Commented viewports code, so that example works with ImGui master branch. --- examples/minimal/main.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/minimal/main.cpp b/examples/minimal/main.cpp index 3cd9d3d..44afcf8 100644 --- a/examples/minimal/main.cpp +++ b/examples/minimal/main.cpp @@ -14,7 +14,9 @@ int main() { window.setFramerateLimit(60); ImGui::SFML::Init(window); // Comment/uncomment this to disable/enable viewports - ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + // Must be using docking branch of ImGui + //ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable + // | ImGuiConfigFlags_DockingEnable; sf::CircleShape shape(100.f); shape.setFillColor(sf::Color::Green); @@ -41,10 +43,12 @@ int main() { window.clear(); window.draw(shape); ImGui::SFML::Render(window); - if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } + // Comment/uncomment this to disable/enable viewports + // Must be using docking branch of ImGui + //if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + // ImGui::UpdatePlatformWindows(); + // ImGui::RenderPlatformWindowsDefault(); + //} window.display(); } From 33bde7fd5678858da5aa2f1c5979b873fa5c802c Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 15:00:57 +0300 Subject: [PATCH 05/18] Implemented mouse hovered viewport. --- imgui-SFML.cpp | 73 +++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 4971c3e..47accdd 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -218,6 +218,7 @@ struct WindowContext { #ifdef VIEWPORTS_ENABLE const bool imContextOwner; // Context owner/main viewport const bool isRenderWindow; + bool mouseHovered; WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable @@ -233,9 +234,9 @@ struct WindowContext { } else { imContext = ::ImGui::CreateContext(); } - windowHasFocus = window->hasFocus(); mouseMoved = false; + mouseHovered = false; for (int i = 0; i < 3; ++i) { mousePressed[i] = false; touchDown[i] = false; @@ -306,28 +307,7 @@ WindowContext* s_currWindowCtx = nullptr; #ifdef VIEWPORTS_ENABLE -// VIEWPORT functions -void SFML_CreateWindow(ImGuiViewport* viewport); -void SFML_DestroyWindow(ImGuiViewport* viewport); -void SFML_ShowWindow(ImGuiViewport* viewport); -void SFML_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos); -ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport); -void SFML_SetWindowSize(ImGuiViewport* viewport, ImVec2 size); -ImVec2 SFML_GetWindowSize(ImGuiViewport* viewport); -void SFML_SetWindowFocus(ImGuiViewport* viewport); -bool SFML_GetWindowFocus(ImGuiViewport* viewport); -bool SFML_GetWindowMinimized(ImGuiViewport* viewport); -void SFML_SetWindowTitle(ImGuiViewport* viewport, const char* str); -//void SFML_SetWindowAlpha(ImGuiViewport* viewport, float alpha); -void SFML_UpdateWindow(ImGuiViewport* viewport); -void SFML_RenderWindow(ImGuiViewport* viewport, void*); -void SFML_SwapBuffers(ImGuiViewport* viewport, void*); -//float SFML_GetWindowDpiScale(ImGuiViewport* viewport); -//void SFML_OnChangedViewport(ImGuiViewport* viewport); -//int SFML_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); - void SFML_UpdateMonitors(); - void SFML_InitInterface(WindowContext* windowContext); void SFML_ShutdownInterface(); @@ -366,6 +346,7 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF #ifdef VIEWPORTS_ENABLE io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; + io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; SFML_InitInterface(s_currWindowCtx); SFML_UpdateMonitors(); #endif @@ -741,6 +722,22 @@ void ProcessEvent(const sf::Event& event) { io.AddFocusEvent(true); s_currWindowCtx->windowHasFocus = true; break; +#ifdef VIEWPORTS_ENABLE + case sf::Event::MouseEntered: + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } else { + sf::Vector2i mousePos = sf::Mouse::getPosition(*s_currWindowCtx->window); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } + s_currWindowCtx->mouseHovered = true; + break; + case sf::Event::MouseLeft: + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + s_currWindowCtx->mouseHovered = false; + break; +#endif // VIEWPORT_ENABLE default: break; } @@ -762,8 +759,6 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { updateMouseCursor(window); } - ImGui::GetMainViewport()->Pos = window.getPosition() + sf::Vector2i(0, 24); - if (!s_currWindowCtx->mouseMoved) { if (sf::Touch::isDown(0)) s_currWindowCtx->touchPos = sf::Touch::getPosition(0, window); @@ -884,6 +879,17 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T io.AddFocusEvent(true); wc->windowHasFocus = true; break; + case sf::Event::MouseEntered: + { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } + wc->mouseHovered = true; + break; + case sf::Event::MouseLeft: + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + wc->mouseHovered = false; + break; default: break; } @@ -892,16 +898,17 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T } ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - const ImVec2 mouse_pos_prev = io.MousePos; + const ImVec2 mousePosPrev = io.MousePos; + ImGuiID mouseViewportID = 0; - for (auto& viewport : platform_io.Viewports) { + for (auto* viewport : platform_io.Viewports) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; sf::Window* window = (sf::Window*)viewport->PlatformHandle; if (window->hasFocus()) { if (io.WantSetMousePos) { - sf::Mouse::setPosition({ static_cast(mouse_pos_prev.x - viewport->Pos.x), - static_cast(mouse_pos_prev.y - viewport->Pos.y) }, + sf::Mouse::setPosition({static_cast(mousePosPrev.x - viewport->Pos.x), + static_cast(mousePosPrev.y - viewport->Pos.y)}, *window); } sf::Vector2i mousePos; @@ -919,8 +926,15 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T wc->touchDown[i] = false; } } + + const bool windowNoInput = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0; + + if (wc->mouseHovered && !windowNoInput) mouseViewportID = viewport->ID; } + if (io.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) + io.AddMouseViewportEvent(mouseViewportID); + #else if (s_currWindowCtx->windowHasFocus) { if (io.WantSetMousePos) { @@ -1740,7 +1754,6 @@ void SFML_SetWindowTitle(ImGuiViewport* viewport, const char* str) { } void SFML_UpdateWindow(ImGuiViewport* viewport) { - // TODO: implement or delete } void SFML_RenderWindow(ImGuiViewport* viewport, void*) { @@ -1800,7 +1813,7 @@ void SFML_UpdateMonitors() { // if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count)) EnumDisplayMonitors(NULL, NULL, proc, (LPARAM)&platform_io); #else - #error "Update monitors is only implemented for windows." + #error "Update monitors is only implemented for Windows." #endif // _WIN32 } From 603a94c86e48781767d4eea3557958eaed30c71b Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 17:17:22 +0300 Subject: [PATCH 06/18] Included VideoMode.hpp header --- imgui-SFML.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 47accdd..c879b1a 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include From a274dbeafff5e13b765fa0e104c15cf92066f0d2 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 17:32:34 +0300 Subject: [PATCH 07/18] Added preprocessor statement to compile with SFML3 --- imgui-SFML.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index c879b1a..d8b1542 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -1680,7 +1680,15 @@ void updateMouseCursor(sf::Window& window) { #ifdef VIEWPORTS_ENABLE void SFML_CreateWindow(ImGuiViewport* viewport) { - sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(viewport->Size.x, viewport->Size.y), "", sf::Style::None); +#if SFML_VERSION_MAJOR >= 3 + sf::RenderWindow* window = + new sf::RenderWindow(sf::VideoMode({viewport->Size.x, viewport->Size.y}), "", + sf::Style::None); +#else + sf::RenderWindow* window = + new sf::RenderWindow(sf::VideoMode(viewport->Size.x, viewport->Size.y), "", + sf::Style::None); +#endif window->setVisible(false); WindowContext* data = IM_NEW(WindowContext)(window, ImGui::GetCurrentContext(), true); data->windowHasFocus = true; From 1b9effba905db7f6b4e5b4c5951f508a05dcd460 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Thu, 16 Jun 2022 17:34:53 +0300 Subject: [PATCH 08/18] Added typecast. --- imgui-SFML.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index d8b1542..e60d9e6 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -1681,9 +1681,9 @@ void updateMouseCursor(sf::Window& window) { void SFML_CreateWindow(ImGuiViewport* viewport) { #if SFML_VERSION_MAJOR >= 3 - sf::RenderWindow* window = - new sf::RenderWindow(sf::VideoMode({viewport->Size.x, viewport->Size.y}), "", - sf::Style::None); + sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode({(unsigned)viewport->Size.x, + (unsigned)viewport->Size.y}), + "", sf::Style::None); #else sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(viewport->Size.x, viewport->Size.y), "", From 7098ec18c3017f1361ea857fa349557e1417cb8e Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Fri, 17 Jun 2022 21:54:24 +0300 Subject: [PATCH 09/18] Changed cast, from unsigned to unsigned int --- imgui-SFML.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index e60d9e6..8d54c1b 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -1681,8 +1681,8 @@ void updateMouseCursor(sf::Window& window) { void SFML_CreateWindow(ImGuiViewport* viewport) { #if SFML_VERSION_MAJOR >= 3 - sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode({(unsigned)viewport->Size.x, - (unsigned)viewport->Size.y}), + sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode({(unsigned int)viewport->Size.x, + (unsigned int)viewport->Size.y}), "", sf::Style::None); #else sf::RenderWindow* window = From bdbedb7760cbf89acbed7ba246d33c333eeacc38 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Fri, 17 Jun 2022 22:20:05 +0300 Subject: [PATCH 10/18] Changed VIEWPORTS_ENABLE to IMGUI_SFML_VIEWPORTS_ENABLE --- imgui-SFML.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 8d54c1b..41f52b6 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -27,9 +27,9 @@ // For multi-viewport support enable/disable -#define VIEWPORTS_ENABLE +#define IMGUI_SFML_VIEWPORTS_ENABLE -#if defined(VIEWPORTS_ENABLE) && defined(_WIN32) +#if defined(IMGUI_SFML_VIEWPORTS_ENABLE) && defined(_WIN32) #include #endif @@ -216,7 +216,7 @@ struct WindowContext { #endif #endif -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE const bool imContextOwner; // Context owner/main viewport const bool isRenderWindow; bool mouseHovered; @@ -307,7 +307,7 @@ std::vector> s_windowContexts; WindowContext* s_currWindowCtx = nullptr; -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE void SFML_UpdateMonitors(); void SFML_InitInterface(WindowContext* windowContext); void SFML_ShutdownInterface(); @@ -344,7 +344,7 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; @@ -723,7 +723,7 @@ void ProcessEvent(const sf::Event& event) { io.AddFocusEvent(true); s_currWindowCtx->windowHasFocus = true; break; -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE case sf::Event::MouseEntered: if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { sf::Vector2i mousePos = sf::Mouse::getPosition(); @@ -779,7 +779,7 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T io.DisplaySize = ImVec2(displaySize.x, displaySize.y); io.DeltaTime = dt.asSeconds(); -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { SFML_UpdateMonitors(); @@ -1002,10 +1002,10 @@ void Render() { } void Shutdown(const sf::Window& window) { -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE SetCurrentWindow(window); SFML_ShutdownInterface(); -#endif // VIEWPORTS_ENABLE +#endif // IMGUI_SFML_VIEWPORTS_ENABLE bool needReplacement = (s_currWindowCtx->window->getSystemHandle() == window.getSystemHandle()); @@ -1034,12 +1034,12 @@ void Shutdown(const sf::Window& window) { } void Shutdown() { -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE for (auto& ctx : s_windowContexts) { ImGui::SetCurrentContext(ctx->imContext); SFML_ShutdownInterface(); } -#endif // VIEWPORTS_ENABLE +#endif // IMGUI_SFML_VIEWPORTS_ENABLE s_currWindowCtx = nullptr; ImGui::SetCurrentContext(nullptr); @@ -1677,7 +1677,7 @@ void updateMouseCursor(sf::Window& window) { } -#ifdef VIEWPORTS_ENABLE +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE void SFML_CreateWindow(ImGuiViewport* viewport) { #if SFML_VERSION_MAJOR >= 3 @@ -1853,6 +1853,6 @@ void SFML_ShutdownInterface() { ImGui::DestroyPlatformWindows(); } -#endif // VIEWPORTS_ENABLE +#endif // IMGUI_SFML_VIEWPORTS_ENABLE } // end of anonymous namespace From 64a42335fa19d5c1f0343afc390c39ff2d14ae44 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Fri, 17 Jun 2022 22:31:24 +0300 Subject: [PATCH 11/18] Deleted const modifiers next to bool in WindowContext struct. Renamed imContextOwner to isImContextOwner --- imgui-SFML.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 41f52b6..192a78a 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -217,8 +217,8 @@ struct WindowContext { #endif #ifdef IMGUI_SFML_VIEWPORTS_ENABLE - const bool imContextOwner; // Context owner/main viewport - const bool isRenderWindow; + bool isImContextOwner; // Context owner/main viewport + bool isRenderWindow; bool mouseHovered; WindowContext(const WindowContext&) = delete; // non construction-copyable @@ -228,7 +228,7 @@ struct WindowContext { : WindowContext(w, context, true) { } WindowContext(sf::Window* w, ImGuiContext* context = nullptr, bool isRenderWindow = false) - : window(w), imContextOwner(context == nullptr), isRenderWindow(isRenderWindow) + : window(w), isImContextOwner(context == nullptr), isRenderWindow(isRenderWindow) { if (context) { imContext = context; @@ -261,7 +261,7 @@ struct WindowContext { } ~WindowContext() { - if (imContextOwner) + if (isImContextOwner) ::ImGui::DestroyContext(imContext); else delete window; @@ -785,7 +785,7 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T for (auto& viewport : ImGui::GetPlatformIO().Viewports) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; - if (wc->imContextOwner) continue; + if (wc->isImContextOwner) continue; sf::Event event; while (wc->window->pollEvent(event)) { @@ -1698,7 +1698,7 @@ void SFML_CreateWindow(ImGuiViewport* viewport) { void SFML_DestroyWindow(ImGuiViewport* viewport) { if (WindowContext* wc = (WindowContext*)viewport->PlatformUserData) { - if (!wc->imContextOwner) { + if (!wc->isImContextOwner) { wc->window->close(); IM_DELETE(wc); } @@ -1727,7 +1727,7 @@ ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport) { MapWindowPoints(hwnd, NULL, (LPPOINT)&clientAreaRect, 2); return { (float)clientAreaRect.left, (float)clientAreaRect.top }; #else - if (wc->imContextOwner) return wc->window->getPosition() + sf::Vector2i(0, 24); + if (wc->isImContextOwner) return wc->window->getPosition() + sf::Vector2i(0, 24); return wc->window->getPosition(); #endif } @@ -1767,7 +1767,7 @@ void SFML_UpdateWindow(ImGuiViewport* viewport) { void SFML_RenderWindow(ImGuiViewport* viewport, void*) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; - if (!wc->imContextOwner) { + if (!wc->isImContextOwner) { IM_ASSERT(wc->isRenderWindow); sf::RenderWindow* window = (sf::RenderWindow*)wc->window; window->setActive(true); From 978c1d02b3227082cef99aea2110bff8abc9f1cd Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Fri, 17 Jun 2022 23:09:35 +0300 Subject: [PATCH 12/18] Removed unnecessary #ifdef in WindowContext struct. Changed WindowContext contructors. Tidied-up SFML_RenderWindow --- imgui-SFML.cpp | 60 ++++++++++---------------------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 192a78a..7f609ee 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -216,7 +216,6 @@ struct WindowContext { #endif #endif -#ifdef IMGUI_SFML_VIEWPORTS_ENABLE bool isImContextOwner; // Context owner/main viewport bool isRenderWindow; bool mouseHovered; @@ -224,10 +223,10 @@ struct WindowContext { WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable - WindowContext(sf::RenderWindow* w, ImGuiContext* context = nullptr) - : WindowContext(w, context, true) { } + WindowContext(sf::Window* w) + : WindowContext(w, nullptr, true) { } - WindowContext(sf::Window* w, ImGuiContext* context = nullptr, bool isRenderWindow = false) + WindowContext(sf::Window* w, ImGuiContext* context, bool isRenderWindow) : window(w), isImContextOwner(context == nullptr), isRenderWindow(isRenderWindow) { if (context) { @@ -266,41 +265,6 @@ struct WindowContext { else delete window; } - -#else - WindowContext(const WindowContext&) = delete; // non construction-copyable - WindowContext& operator=(const WindowContext&) = delete; // non copyable - - WindowContext(sf::Window* w) : window(w) - { - imContext = ::ImGui::CreateContext(); - - windowHasFocus = window->hasFocus(); - mouseMoved = false; - for (int i = 0; i < 3; ++i) { - mousePressed[i] = false; - touchDown[i] = false; - } - lastCursor = ImGuiMouseCursor_COUNT; - - joystickId = getConnectedJoystickId(); - for (int i = 0; i < sf::Joystick::ButtonCount; ++i) { - joystickMapping[i] = ImGuiKey_None; - } - - for (int i = 0; i < ImGuiMouseCursor_COUNT; ++i) { - mouseCursorLoaded[i] = false; - } - -#ifdef ANDROID -#ifdef USE_JNI - wantTextInput = false; -#endif -#endif - } - - ~WindowContext() { ::ImGui::DestroyContext(imContext); } -#endif }; std::vector> s_windowContexts; @@ -1767,15 +1731,15 @@ void SFML_UpdateWindow(ImGuiViewport* viewport) { void SFML_RenderWindow(ImGuiViewport* viewport, void*) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; - if (!wc->isImContextOwner) { - IM_ASSERT(wc->isRenderWindow); - sf::RenderWindow* window = (sf::RenderWindow*)wc->window; - window->setActive(true); - window->resetGLStates(); - window->pushGLStates(); - RenderDrawLists(viewport->DrawData); - window->popGLStates(); - } + if (wc->isImContextOwner) return; + + IM_ASSERT(wc->isRenderWindow); + sf::RenderWindow* window = (sf::RenderWindow*)wc->window; + window->setActive(true); + window->resetGLStates(); + window->pushGLStates(); + RenderDrawLists(viewport->DrawData); + window->popGLStates(); } void SFML_SwapBuffers(ImGuiViewport* viewport, void*) { From a946dc074747119b501fb14fa98a487f6f622610 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sat, 18 Jun 2022 00:15:44 +0300 Subject: [PATCH 13/18] Added CMake option IMGUI_SFML_ENABLE_VIEWPORTS --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2837a3..7779c22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ endif() option(IMGUI_SFML_BUILD_EXAMPLES "Build ImGui_SFML examples" OFF) option(IMGUI_SFML_FIND_SFML "Use find_package to find SFML" ON) option(IMGUI_SFML_IMGUI_DEMO "Build imgui_demo.cpp" OFF) - +option(IMGUI_SFML_ENABLE_VIEWPORTS "Enable ImGui viewport support" OFF) # If you want to use your own user config when compiling ImGui, please set the following variables # For example, if you have your config in /path/to/dir/with/config/myconfig.h, set the variables as follows: # @@ -126,6 +126,10 @@ if(NOT IMGUI_SFML_USE_DEFAULT_CONFIG) endif() endif() +if(IMGUI_SFML_ENABLE_VIEWPORTS) + target_compile_definitions(ImGui-SFML PUBLIC IMGUI_SFML_VIEWPORTS_ENABLE) +endif() + target_compile_definitions(ImGui-SFML PUBLIC IMGUI_USER_CONFIG="${IMGUI_SFML_CONFIG_NAME}" From 71b208a29460c2aacb5a013b9b0bd7731343d013 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sat, 18 Jun 2022 00:16:34 +0300 Subject: [PATCH 14/18] Deleted IMGUI_SFML_VIEWPORTS_ENABLE macro definition --- imgui-SFML.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 7f609ee..067be16 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -26,9 +26,6 @@ #include -// For multi-viewport support enable/disable -#define IMGUI_SFML_VIEWPORTS_ENABLE - #if defined(IMGUI_SFML_VIEWPORTS_ENABLE) && defined(_WIN32) #include #endif From c0137fc8f74ed947b2f7a0c697687e445f992fa7 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sat, 18 Jun 2022 21:11:39 +0300 Subject: [PATCH 15/18] Wrapped code in #ifdef to maintain compatibility with ImGui master branch --- imgui-SFML.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 067be16..8c491f5 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -594,11 +594,14 @@ void ProcessEvent(const sf::Event& event) { if (s_currWindowCtx->windowHasFocus) { switch (event.type) { case sf::Event::MouseMoved: +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { sf::Vector2i mousePos = sf::Mouse::getPosition(); io.AddMousePosEvent(mousePos.x, mousePos.y); } - else { + else +#endif // IMGUI_SFML_VIEWPORTS_ENABLE + { io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y); } s_currWindowCtx->mouseMoved = true; @@ -726,10 +729,15 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { Update(s_currWindowCtx->touchPos, static_cast(target.getSize()), dt); } else { - if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE + if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { Update(sf::Mouse::getPosition(), static_cast(target.getSize()), dt); - else + } + else +#endif // IMGUI_SFML_VIEWPORTS_ENABLE + { Update(sf::Mouse::getPosition(window), static_cast(target.getSize()), dt); + } } } From 3e17accd6c25bb00bf3c1288ca6cc7c49ea34f05 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sat, 18 Jun 2022 21:22:25 +0300 Subject: [PATCH 16/18] Deleted unnecessary code --- imgui-SFML.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 8c491f5..cf005e7 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -1696,7 +1696,6 @@ ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport) { MapWindowPoints(hwnd, NULL, (LPPOINT)&clientAreaRect, 2); return { (float)clientAreaRect.left, (float)clientAreaRect.top }; #else - if (wc->isImContextOwner) return wc->window->getPosition() + sf::Vector2i(0, 24); return wc->window->getPosition(); #endif } From 87679d699941f189d1f88c5b4242175da5d3b574 Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sun, 19 Jun 2022 07:32:08 +0300 Subject: [PATCH 17/18] Added neccessary code for Linux. --- imgui-SFML.cpp | 66 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index cf005e7..8560d12 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -25,11 +25,18 @@ #include #include - -#if defined(IMGUI_SFML_VIEWPORTS_ENABLE) && defined(_WIN32) -#include +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE + #if defined(_WIN32) + #include + #elif defined(__linux__) + #include + #include + + #undef None // collides with sf::Style::None + #endif #endif + #ifdef ANDROID #ifdef USE_JNI @@ -216,21 +223,26 @@ struct WindowContext { bool isImContextOwner; // Context owner/main viewport bool isRenderWindow; bool mouseHovered; + float titleBarHeight; WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable - WindowContext(sf::Window* w) - : WindowContext(w, nullptr, true) { } + WindowContext(sf::Window* w) : + WindowContext(w, nullptr) { } - WindowContext(sf::Window* w, ImGuiContext* context, bool isRenderWindow) - : window(w), isImContextOwner(context == nullptr), isRenderWindow(isRenderWindow) + WindowContext(sf::Window* w, ImGuiContext* context) : + window(w), isImContextOwner(context == nullptr), + titleBarHeight(0.f) { if (context) { imContext = context; } else { imContext = ::ImGui::CreateContext(); } + + isRenderWindow = dynamic_cast(w) != nullptr; + windowHasFocus = window->hasFocus(); mouseMoved = false; mouseHovered = false; @@ -311,6 +323,10 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; SFML_InitInterface(s_currWindowCtx); SFML_UpdateMonitors(); + + sf::Vector2i windowMousePos = sf::Mouse::getPosition(window); + sf::Vector2i globalMousePos = sf::Mouse::getPosition(); + s_currWindowCtx->titleBarHeight = globalMousePos.y - (window.getPosition().y + windowMousePos.y); #endif io.BackendPlatformName = "imgui_impl_sfml"; @@ -1659,7 +1675,7 @@ void SFML_CreateWindow(ImGuiViewport* viewport) { sf::Style::None); #endif window->setVisible(false); - WindowContext* data = IM_NEW(WindowContext)(window, ImGui::GetCurrentContext(), true); + WindowContext* data = IM_NEW(WindowContext)(window, ImGui::GetCurrentContext()); data->windowHasFocus = true; viewport->PlatformUserData = data; viewport->PlatformHandle = window; @@ -1689,14 +1705,17 @@ void SFML_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) { ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; -#ifdef _WIN32 +#if defined(_WIN32) RECT clientAreaRect; HWND hwnd = wc->window->getSystemHandle(); GetClientRect(hwnd, &clientAreaRect); MapWindowPoints(hwnd, NULL, (LPPOINT)&clientAreaRect, 2); return { (float)clientAreaRect.left, (float)clientAreaRect.top }; #else - return wc->window->getPosition(); + // Probably will give a bad result as sfml window origin is top left corner + // of the title bar. This results that main viewport's coordinates are offsetted + // in reference to MousePos. + return wc->window->getPosition() + sf::Vector2i(0, wc->titleBarHeight); #endif } @@ -1761,10 +1780,10 @@ static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT l #endif // _WIN32 void SFML_UpdateMonitors() { -#ifdef _WIN32 ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Monitors.resize(0); +#if defined(_WIN32) MONITORENUMPROC proc = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { ImGuiPlatformIO& platform_io = *((ImGuiPlatformIO*)dwData); @@ -1789,8 +1808,31 @@ void SFML_UpdateMonitors() { // if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count)) EnumDisplayMonitors(NULL, NULL, proc, (LPARAM)&platform_io); +#elif defined(__linux__) + static Display* display = nullptr; + if (display == nullptr) { + if (!(display = XOpenDisplay(0))) { + fprintf(stderr, "Could not open X display.\n"); + return; + } + } + + XRRScreenResources* screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); + + int nmonitors = 0; + XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors); + + for (int i = 0; i < nmonitors; i++) { + ImGuiPlatformMonitor monitor; + XRRCrtcInfo* screen_info = XRRGetCrtcInfo(display, screen_res, screen_res->crtcs[i]); + + monitor.MainPos = monitor.WorkPos = ImVec2(screen_info->x, screen_info->y); + monitor.MainSize = monitor.WorkSize = ImVec2(screen_info->width, screen_info->width); + + platform_io.Monitors.push_back(monitor); + } #else - #error "Update monitors is only implemented for Windows." + #error "Update monitors is not implemented for this platform." #endif // _WIN32 } From 35771ad185256437e5fe0bc42d4f3d8bb25c8e6f Mon Sep 17 00:00:00 2001 From: nocheacosador Date: Sun, 19 Jun 2022 07:53:54 +0300 Subject: [PATCH 18/18] Changed how window position is passed to ImGui. Formatting changes. --- imgui-SFML.cpp | 101 +++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 8560d12..d240641 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -25,17 +25,16 @@ #include #include -#ifdef IMGUI_SFML_VIEWPORTS_ENABLE - #if defined(_WIN32) - #include - #elif defined(__linux__) - #include - #include - - #undef None // collides with sf::Style::None - #endif -#endif +#ifdef IMGUI_SFML_VIEWPORTS_ENABLE +#if defined(_WIN32) +#include +#elif defined(__linux__) +#include +#include +#undef None // collides with sf::Style::None +#endif +#endif #ifdef ANDROID #ifdef USE_JNI @@ -228,13 +227,11 @@ struct WindowContext { WindowContext(const WindowContext&) = delete; // non construction-copyable WindowContext& operator=(const WindowContext&) = delete; // non copyable - WindowContext(sf::Window* w) : - WindowContext(w, nullptr) { } + WindowContext(sf::Window* w) : WindowContext(w, nullptr) { + } - WindowContext(sf::Window* w, ImGuiContext* context) : - window(w), isImContextOwner(context == nullptr), - titleBarHeight(0.f) - { + WindowContext(sf::Window* w, ImGuiContext* context) : + window(w), isImContextOwner(context == nullptr), titleBarHeight(0.f) { if (context) { imContext = context; } else { @@ -268,7 +265,7 @@ struct WindowContext { #endif } - ~WindowContext() { + ~WindowContext() { if (isImContextOwner) ::ImGui::DestroyContext(imContext); else @@ -279,7 +276,6 @@ struct WindowContext { std::vector> s_windowContexts; WindowContext* s_currWindowCtx = nullptr; - #ifdef IMGUI_SFML_VIEWPORTS_ENABLE void SFML_UpdateMonitors(); void SFML_InitInterface(WindowContext* windowContext); @@ -326,7 +322,8 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF sf::Vector2i windowMousePos = sf::Mouse::getPosition(window); sf::Vector2i globalMousePos = sf::Mouse::getPosition(); - s_currWindowCtx->titleBarHeight = globalMousePos.y - (window.getPosition().y + windowMousePos.y); + s_currWindowCtx->titleBarHeight = + globalMousePos.y - (window.getPosition().y + windowMousePos.y); #endif io.BackendPlatformName = "imgui_impl_sfml"; @@ -609,13 +606,12 @@ void ProcessEvent(const sf::Event& event) { if (s_currWindowCtx->windowHasFocus) { switch (event.type) { - case sf::Event::MouseMoved: + case sf::Event::MouseMoved: #ifdef IMGUI_SFML_VIEWPORTS_ENABLE if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { sf::Vector2i mousePos = sf::Mouse::getPosition(); io.AddMousePosEvent(mousePos.x, mousePos.y); - } - else + } else #endif // IMGUI_SFML_VIEWPORTS_ENABLE { io.AddMousePosEvent(event.mouseMove.x, event.mouseMove.y); @@ -748,8 +744,7 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { #ifdef IMGUI_SFML_VIEWPORTS_ENABLE if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { Update(sf::Mouse::getPosition(), static_cast(target.getSize()), dt); - } - else + } else #endif // IMGUI_SFML_VIEWPORTS_ENABLE { Update(sf::Mouse::getPosition(window), static_cast(target.getSize()), dt); @@ -760,7 +755,7 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) { void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::Time dt) { assert(s_currWindowCtx && "No current window is set - forgot to call ImGui::SFML::Init?"); ImGuiIO& io = ImGui::GetIO(); - + io.DisplaySize = ImVec2(displaySize.x, displaySize.y); io.DeltaTime = dt.asSeconds(); @@ -776,11 +771,10 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T while (wc->window->pollEvent(event)) { if (wc->window->hasFocus()) { switch (event.type) { - case sf::Event::MouseMoved: - { - sf::Vector2i mousePos = sf::Mouse::getPosition(); - io.AddMousePosEvent(mousePos.x, mousePos.y); - } + case sf::Event::MouseMoved: { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } wc->mouseMoved = true; break; case sf::Event::MouseButtonPressed: // fall-through @@ -865,11 +859,10 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T io.AddFocusEvent(true); wc->windowHasFocus = true; break; - case sf::Event::MouseEntered: - { - sf::Vector2i mousePos = sf::Mouse::getPosition(); - io.AddMousePosEvent(mousePos.x, mousePos.y); - } + case sf::Event::MouseEntered: { + sf::Vector2i mousePos = sf::Mouse::getPosition(); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } wc->mouseHovered = true; break; case sf::Event::MouseLeft: @@ -882,7 +875,7 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T } } } - + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); const ImVec2 mousePosPrev = io.MousePos; ImGuiID mouseViewportID = 0; @@ -902,7 +895,7 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T mousePos = sf::Mouse::getPosition(); else mousePos = sf::Mouse::getPosition(*window); - + io.AddMousePosEvent(mousePos.x, mousePos.y); for (unsigned int i = 0; i < 3; i++) { @@ -1661,7 +1654,6 @@ void updateMouseCursor(sf::Window& window) { } } - #ifdef IMGUI_SFML_VIEWPORTS_ENABLE void SFML_CreateWindow(ImGuiViewport* viewport) { @@ -1705,18 +1697,11 @@ void SFML_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) { ImVec2 SFML_GetWindowPos(ImGuiViewport* viewport) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; -#if defined(_WIN32) - RECT clientAreaRect; - HWND hwnd = wc->window->getSystemHandle(); - GetClientRect(hwnd, &clientAreaRect); - MapWindowPoints(hwnd, NULL, (LPPOINT)&clientAreaRect, 2); - return { (float)clientAreaRect.left, (float)clientAreaRect.top }; -#else - // Probably will give a bad result as sfml window origin is top left corner - // of the title bar. This results that main viewport's coordinates are offsetted - // in reference to MousePos. + // SFML window origin is top left corner of the title bar. + // This results in that main viewport's coordinates are offsetted + // in reference to MousePos, because ImGUi expects coordinates of + // client area. return wc->window->getPosition() + sf::Vector2i(0, wc->titleBarHeight); -#endif } void SFML_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { @@ -1741,7 +1726,7 @@ bool SFML_GetWindowFocus(ImGuiViewport* viewport) { bool SFML_GetWindowMinimized(ImGuiViewport* viewport) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; - return false; // tell imgui that window is allways maximized + return false; // tell imgui that window is allways maximized } void SFML_SetWindowTitle(ImGuiViewport* viewport, const char* str) { @@ -1755,7 +1740,7 @@ void SFML_UpdateWindow(ImGuiViewport* viewport) { void SFML_RenderWindow(ImGuiViewport* viewport, void*) { WindowContext* wc = (WindowContext*)viewport->PlatformUserData; if (wc->isImContextOwner) return; - + IM_ASSERT(wc->isRenderWindow); sf::RenderWindow* window = (sf::RenderWindow*)wc->window; window->setActive(true); @@ -1810,29 +1795,29 @@ void SFML_UpdateMonitors() { EnumDisplayMonitors(NULL, NULL, proc, (LPARAM)&platform_io); #elif defined(__linux__) static Display* display = nullptr; - if (display == nullptr) { + if (display == nullptr) { if (!(display = XOpenDisplay(0))) { fprintf(stderr, "Could not open X display.\n"); return; } } - XRRScreenResources* screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); + XRRScreenResources* screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); - int nmonitors = 0; - XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors); + int nmonitors = 0; + XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors); for (int i = 0; i < nmonitors; i++) { ImGuiPlatformMonitor monitor; XRRCrtcInfo* screen_info = XRRGetCrtcInfo(display, screen_res, screen_res->crtcs[i]); - + monitor.MainPos = monitor.WorkPos = ImVec2(screen_info->x, screen_info->y); monitor.MainSize = monitor.WorkSize = ImVec2(screen_info->width, screen_info->width); platform_io.Monitors.push_back(monitor); } #else - #error "Update monitors is not implemented for this platform." +#error "Update monitors is not implemented for this platform." #endif // _WIN32 } @@ -1849,7 +1834,7 @@ void SFML_InitInterface(WindowContext* windowContext) { platform_io.Platform_GetWindowFocus = SFML_GetWindowFocus; platform_io.Platform_GetWindowMinimized = SFML_GetWindowMinimized; platform_io.Platform_SetWindowTitle = SFML_SetWindowTitle; - //platform_io.Platform_SetWindowAlpha = SFML_SetWindowAlpha; + // platform_io.Platform_SetWindowAlpha = SFML_SetWindowAlpha; platform_io.Platform_UpdateWindow = SFML_UpdateWindow; platform_io.Platform_RenderWindow = SFML_RenderWindow; platform_io.Platform_SwapBuffers = SFML_SwapBuffers;