Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 80 additions & 39 deletions imgui-SFML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,6 @@ struct WindowContext
const sf::Window* window;
ImGuiContext* imContext{ImGui::CreateContext()};

std::optional<sf::Texture> 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};
Expand Down Expand Up @@ -291,17 +288,18 @@ 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<WindowContext>(&window)).get();
ImGui::SetCurrentContext(s_currWindowCtx->imContext);
Expand All @@ -313,6 +311,7 @@ bool Init(sf::Window& window, const sf::Vector2f& displaySize, bool loadDefaultF
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
io.BackendPlatformName = "imgui_impl_sfml";

s_currWindowCtx->joystickId = getConnectedJoystickId();
Expand All @@ -338,13 +337,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;
}

Expand Down Expand Up @@ -550,8 +542,7 @@ 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)
assert(io.Fonts->Fonts.Size > 0); // You forgot to create and set up font atlas

// gamepad navigation
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) && s_currWindowCtx->joystickId != NULL_JOYSTICK_ID)
Expand Down Expand Up @@ -588,6 +579,14 @@ void Render()
void Shutdown(const sf::Window& window)
{
const bool needReplacement = (s_currWindowCtx->window->getNativeHandle() == window.getNativeHandle());

for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
{
if (tex->RefCount == 1)
{
DestroyTexture(tex);
}
}

// remove window's context
auto found = std::find_if(s_windowContexts.begin(),
Expand Down Expand Up @@ -619,43 +618,83 @@ void Shutdown(const sf::Window& window)

void Shutdown()
{
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
{
if (tex->RefCount == 1)
{
DestroyTexture(tex);
}
}

s_currWindowCtx = nullptr;
ImGui::SetCurrentContext(nullptr);

s_windowContexts.clear();
}

bool UpdateFontTexture()
void UpdateTexture(ImTextureData* tex)
{
assert(s_currWindowCtx);
if (tex->Status == ImTextureStatus_WantCreate)
{
assert(tex->Format == ImTextureFormat_RGBA32);
assert(tex->BytesPerPixel == 4);

ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels = nullptr;
int width = 0;
int height = 0;
auto* texture = new sf::Texture();
texture->create(tex->Width, tex->Height);
texture->setSmooth(true);
texture->setRepeated(false);

io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
const uint8_t* src = (uint8_t*)tex->GetPixels();
int pitch = tex->GetPitch();
std::vector<uint8_t> contiguous(tex->Width * tex->Height * 4);

sf::Texture newTexture;
if (!newTexture.resize(sf::Vector2u(sf::Vector2(width, height))))
{
return false;
for (int y = 0; y < tex->Height; ++y)
memcpy(&contiguous[y * tex->Width * 4], src + y * pitch, tex->Width * 4);

texture->update(contiguous.data());

tex->BackendUserData = texture;
tex->SetTexID(convertGLTextureHandleToImTextureID(texture->getNativeHandle()));
tex->SetStatus(ImTextureStatus_OK);
}
else if (tex->Status == ImTextureStatus_WantUpdates)
{
assert(tex->BackendUserData != nullptr);

newTexture.update(pixels);
auto* texture = static_cast<sf::Texture*>(tex->BackendUserData);
int pitch = tex->GetPitch();

ImTextureID texID = convertGLTextureHandleToImTextureID(newTexture.getNativeHandle());
io.Fonts->SetTexID(texID);
std::vector<uint8_t> block;
for (ImTextureRect& r : tex->Updates)
{
block.clear();
block.resize(r.w * r.h * 4);

s_currWindowCtx->fontTexture = std::move(newTexture);
const uint8_t* src = (uint8_t*)tex->GetPixelsAt(r.x, r.y);

return true;
for (int y = 0; y < r.h; ++y)
memcpy(&block[y * r.w * 4], src + y * pitch, r.w * 4);

texture->update(block.data(), r.w, r.h, r.x, r.y);
}

tex->SetStatus(ImTextureStatus_OK);
}
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
{
DestroyTexture(tex);
}
}

std::optional<sf::Texture>& GetFontTexture()
void DestroyTexture(ImTextureData* tex)
{
assert(s_currWindowCtx);
return s_currWindowCtx->fontTexture;
assert(tex->BackendUserData != nullptr);
auto* texture = static_cast<sf::Texture*>(tex->BackendUserData);
delete texture;
tex->BackendUserData = nullptr;
tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
}

void SetActiveJoystickId(unsigned int joystickId)
Expand Down Expand Up @@ -946,14 +985,17 @@ void SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
// Rendering callback
void RenderDrawLists(ImDrawData* draw_data)
{
ImGui::GetDrawData();
if (draw_data->Textures != nullptr)
for (ImTextureData* tex : *draw_data->Textures)
if (tex->Status != ImTextureStatus_OK)
UpdateTexture(tex);

if (draw_data->CmdListsCount == 0)
{
return;
}

const ImGuiIO& io = ImGui::GetIO();
assert(io.Fonts->TexID != (ImTextureID) nullptr); // You forgot to create and set font texture

// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates !=
// framebuffer coordinates)
Expand All @@ -963,7 +1005,6 @@ void RenderDrawLists(ImDrawData* draw_data)
return;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);

// Backup GL state
// Backup GL state
GLint last_texture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
Expand Down Expand Up @@ -1040,7 +1081,7 @@ void RenderDrawLists(ImDrawData* draw_data)
(int)(clip_rect.w - clip_rect.y));

// Bind texture, Draw
const GLuint textureHandle = convertImTextureIDToGLTextureHandle(pcmd->GetTexID());
const GLuint textureHandle = convertImTextureIDToGLTextureHandle(pcmd->TexRef.GetTexID());
glBindTexture(GL_TEXTURE_2D, textureHandle);
glDrawElements(GL_TRIANGLES,
(GLsizei)pcmd->ElemCount,
Expand Down
12 changes: 7 additions & 5 deletions imgui-SFML.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ class Texture;
class Window;
} // namespace sf

struct ImTextureData;

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);
Expand All @@ -45,8 +47,8 @@ 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<sf::Texture>& GetFontTexture();
IMGUI_SFML_API void UpdateTexture(ImTextureData* tex);
IMGUI_SFML_API void DestroyTexture(ImTextureData* tex);

// joystick functions
IMGUI_SFML_API void SetActiveJoystickId(unsigned int joystickId);
Expand Down