diff --git a/README.md b/README.md index ee0492e..3303bae 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Dependencies ----- * [SFML](https://github.com/SFML/SFML) >= 3.0.0 -* [Dear ImGui](https://github.com/ocornut/imgui) >= 1.91.1, < 1.92.0 +* [Dear ImGui](https://github.com/ocornut/imgui) >= 1.91.1 Contributing ----- @@ -142,17 +142,13 @@ int main() { Fonts how-to --- -Default font is loaded if you don't pass `false` in `ImGui::SFML::Init`. Call `ImGui::SFML::Init(window, false);` if you don't want default font to be loaded. - * Load your fonts like this: ```cpp -IO.Fonts->Clear(); // clear fonts if you loaded some before (even if only default one was loaded) +IO.Fonts->Clear(); // You might want to clear the previous fonts (The default font will be loaded on ImGui::SFML::Update() if none is loaded) // IO.Fonts->AddFontDefault(); // this will load default font as well IO.Fonts->AddFontFromFileTTF("font1.ttf", 8.f); IO.Fonts->AddFontFromFileTTF("font2.ttf", 12.f); - -ImGui::SFML::UpdateFontTexture(); // important call: updates font texture ``` * And use them like this: diff --git a/imgui-SFML.cpp b/imgui-SFML.cpp index 5007741..948432b 100644 --- a/imgui-SFML.cpp +++ b/imgui-SFML.cpp @@ -9,17 +9,19 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include +#include #include - -#include +#include #include #include @@ -243,9 +245,6 @@ struct WindowContext const sf::Window* window; ImGuiContext* imContext{ImGui::CreateContext()}; - std::optional fontTexture; // internal font atlas which is used if user doesn't set - // a custom sf::Texture. - bool windowHasFocus; bool mouseMoved{false}; bool mousePressed[3] = {false}; @@ -264,6 +263,10 @@ struct WindowContext std::optional mouseCursors[ImGuiMouseCursor_COUNT]; +#if IMGUI_VERSION_NUM < 19200 + std::optional fontTexture; +#endif + #ifdef ANDROID #ifdef USE_JNI bool wantTextInput{false}; @@ -285,23 +288,102 @@ struct WindowContext std::vector> s_windowContexts; WindowContext* s_currWindowCtx = nullptr; +#if IMGUI_VERSION_NUM >= 19200 +std::map s_textureMap; + +void UpdateImguiTexture(ImTextureData* tex) +{ + if (tex->Status == ImTextureStatus_WantCreate) + { + assert(tex->BytesPerPixel == 4); // Only supports RGBA for now + + sf::Texture texture{sf::Vector2u(tex->Width, tex->Height)}; + texture.setRepeated(false); + texture.update(static_cast(tex->GetPixels())); + + auto id = convertGLTextureHandleToImTextureID(texture.getNativeHandle()); + tex->SetTexID(id); + tex->SetStatus(ImTextureStatus_OK); + s_textureMap.emplace(id, std::move(texture)); + } + else if (tex->Status == ImTextureStatus_WantUpdates) + { + if (auto found = s_textureMap.find(tex->GetTexID()); found != s_textureMap.end()) + { + auto& texture = found->second; + int pitch = tex->GetPitch(); + for (ImTextureRect& r : tex->Updates) + { + std::vector block; + block.resize(static_cast(r.w) * r.h * tex->BytesPerPixel); + const auto* pixels = static_cast(tex->GetPixelsAt(r.x, r.y)); + for (size_t y = 0; y < r.h; ++y) + { + memcpy(&block[y * r.w * tex->BytesPerPixel], + pixels + (y * pitch), + static_cast(r.w) * tex->BytesPerPixel); + } + + texture.update(block.data(), {r.w, r.h}, {r.x, r.y}); + } + tex->SetStatus(ImTextureStatus_OK); + } + } + else if (tex->Status == ImTextureStatus_WantDestroy) + { + const auto id = tex->GetTexID(); + tex->SetTexID(ImTextureID_Invalid); + tex->SetStatus(ImTextureStatus_Destroyed); + s_textureMap.erase(id); + } +} +#else +bool UpdateFontTexture() +{ + assert(s_currWindowCtx); + + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels = nullptr; + int width = 0; + int height = 0; + + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + sf::Texture newTexture; + if (!newTexture.resize(sf::Vector2u(sf::Vector2(width, height)))) + { + return false; + } + + newTexture.update(pixels); + + ImTextureID texID = convertGLTextureHandleToImTextureID(newTexture.getNativeHandle()); + io.Fonts->SetTexID(texID); + + s_currWindowCtx->fontTexture = std::move(newTexture); + + return true; +} +#endif + } // end of anonymous namespace namespace ImGui { namespace SFML { -bool Init(sf::RenderWindow& window, bool loadDefaultFont) + +bool Init(sf::RenderWindow& window) { - return Init(window, window, loadDefaultFont); + return Init(window, window); } -bool Init(sf::Window& window, sf::RenderTarget& target, bool loadDefaultFont) +bool Init(sf::Window& window, sf::RenderTarget& target) { - return Init(window, sf::Vector2f(target.getSize()), loadDefaultFont); + return Init(window, sf::Vector2f(target.getSize())); } -bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultFont) +bool Init(sf::Window& window, const sf::Vector2f& displaySize) { s_currWindowCtx = s_windowContexts.emplace_back(std::make_unique(&window)).get(); ImGui::SetCurrentContext(s_currWindowCtx->imContext); @@ -313,6 +395,9 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; +#if IMGUI_VERSION_NUM >= 19200 + io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; +#endif io.BackendPlatformName = "imgui_impl_sfml"; s_currWindowCtx->joystickId = getConnectedJoystickId(); @@ -338,13 +423,6 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF loadMouseCursor(ImGuiMouseCursor_ResizeNWSE, sf::Cursor::Type::SizeTopLeftBottomRight); loadMouseCursor(ImGuiMouseCursor_Hand, sf::Cursor::Type::Hand); - if (loadDefaultFont) - { - // this will load default font automatically - // No need to call AddDefaultFont - return UpdateFontTexture(); - } - return true; } @@ -550,8 +628,12 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T #endif #endif - assert(io.Fonts->Fonts.Size > 0); // You forgot to create and set up font - // atlas (see createFontTexture) +#if IMGUI_VERSION_NUM < 19200 + if (!io.Fonts->TexReady) + { + assert(UpdateFontTexture()); // Failed to create font texture + } +#endif // gamepad navigation if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) && s_currWindowCtx->joystickId != NULL_JOYSTICK_ID) @@ -595,6 +677,19 @@ void Shutdown(const sf::Window& window) { return ctx->window->getNativeHandle() == window.getNativeHandle(); }); assert(found != s_windowContexts.end() && "Window wasn't inited properly: forgot to call ImGui::SFML::Init(window)?"); + +#if IMGUI_VERSION_NUM >= 19200 + ImGui::SetCurrentContext((*found)->imContext); + for (ImTextureData* tex : ImGui::GetPlatformIO().Textures) + { + if (tex->RefCount == 1) + { + tex->SetStatus(ImTextureStatus_WantDestroy); + UpdateImguiTexture(tex); + } + } +#endif + s_windowContexts.erase(found); // s_currWindowCtx can become invalid here! // set current context to some window for convenience if needed @@ -622,39 +717,10 @@ void Shutdown() ImGui::SetCurrentContext(nullptr); s_windowContexts.clear(); -} - -bool UpdateFontTexture() -{ - assert(s_currWindowCtx); - - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels = nullptr; - int width = 0; - int height = 0; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - sf::Texture newTexture; - if (!newTexture.resize(sf::Vector2u(sf::Vector2(width, height)))) - { - return false; - } - - newTexture.update(pixels); - - ImTextureID texID = convertGLTextureHandleToImTextureID(newTexture.getNativeHandle()); - io.Fonts->SetTexID(texID); - - s_currWindowCtx->fontTexture = std::move(newTexture); - - return true; -} - -std::optional& GetFontTexture() -{ - assert(s_currWindowCtx); - return s_currWindowCtx->fontTexture; +#if IMGUI_VERSION_NUM >= 19200 + s_textureMap.clear(); +#endif } void SetActiveJoystickId(unsigned int joystickId) @@ -952,7 +1018,16 @@ void RenderDrawLists(ImDrawData* draw_data) } const ImGuiIO& io = ImGui::GetIO(); - assert(io.Fonts->TexID != (ImTextureID) nullptr); // You forgot to create and set font texture +#if IMGUI_VERSION_NUM >= 19200 + assert(draw_data->Textures); + for (auto* tex : *draw_data->Textures) + { + if (tex->Status != ImTextureStatus_OK) + { + UpdateImguiTexture(tex); + } + } +#endif // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != // framebuffer coordinates) diff --git a/imgui-SFML.h b/imgui-SFML.h index ee873f6..ef139dd 100644 --- a/imgui-SFML.h +++ b/imgui-SFML.h @@ -7,8 +7,6 @@ #include #include -#include - #include "imgui-SFML_export.h" namespace sf @@ -26,9 +24,10 @@ namespace ImGui { namespace SFML { -[[nodiscard]] IMGUI_SFML_API bool Init(sf::RenderWindow& window, bool loadDefaultFont = true); -[[nodiscard]] IMGUI_SFML_API bool Init(sf::Window& window, sf::RenderTarget& target, bool loadDefaultFont = true); -[[nodiscard]] IMGUI_SFML_API bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultFont = true); + +[[nodiscard]] IMGUI_SFML_API bool Init(sf::RenderWindow& window); +[[nodiscard]] IMGUI_SFML_API bool Init(sf::Window& window, sf::RenderTarget& target); +[[nodiscard]] IMGUI_SFML_API bool Init(sf::Window& window, const sf::Vector2f& displaySize); IMGUI_SFML_API void SetCurrentWindow(const sf::Window& window); IMGUI_SFML_API void ProcessEvent(const sf::Window& window, const sf::Event& event); @@ -45,9 +44,6 @@ IMGUI_SFML_API void Shutdown(const sf::Window& window); // Shuts down all ImGui contexts IMGUI_SFML_API void Shutdown(); -[[nodiscard]] IMGUI_SFML_API bool UpdateFontTexture(); -IMGUI_SFML_API std::optional& GetFontTexture(); - // joystick functions IMGUI_SFML_API void SetActiveJoystickId(unsigned int joystickId); IMGUI_SFML_API void SetJoystickDPadThreshold(float threshold);