[upstream_utils] Update imgui and implot (#8762)

Not updating GLFW yet due to a likely future move to SDL.
This commit is contained in:
Peter Johnson
2026-04-12 12:19:32 -07:00
committed by GitHub
parent d76486d885
commit 476b9641c1
47 changed files with 27710 additions and 12792 deletions

View File

@@ -177,53 +177,35 @@ void gui::SetCurrentContext(Context* context) {
gContext = context;
}
ImFont* Context::FontMaker::GetFont() const {
if (!font) {
auto& io = ImGui::GetIO();
ImFontConfig cfg;
std::snprintf(cfg.Name, sizeof(cfg.Name), "%s", name.c_str());
font = func(io, 0, &cfg);
// Merge font awesome solid
ImFontConfig icons_cfg;
icons_cfg.MergeMode = true;
icons_cfg.PixelSnapH = true;
ImGui::AddFontFontAwesomeSolid(io, 0, &icons_cfg);
}
return font;
}
static void UpdateFontScale() {
// Scale based on OS window content scaling
float windowScale = 1.0;
#ifndef __APPLE__
glfwGetWindowContentScale(gContext->window, &windowScale, nullptr);
#endif
// map to closest font size: 0 = 0.5x, 1 = 0.75x, 2 = 1.0x, 3 = 1.25x,
// 4 = 1.5x, 5 = 1.75x, 6 = 2x
int fontScale =
gContext->userScale + static_cast<int>((windowScale - 1.0) * 4);
if (fontScale < 0) {
fontScale = 0;
}
if (gContext->fontScale != fontScale) {
gContext->reloadFonts = true;
gContext->fontScale = fontScale;
}
}
// the range is based on 13px being the "nominal" 100% size and going from
// ~0.5x (7px) to ~2.0x (25px)
static void ReloadFonts() {
auto& io = ImGui::GetIO();
io.Fonts->Clear();
gContext->fonts.clear();
float size = 7.0f + gContext->fontScale * 3.0f;
for (auto&& makeFont : gContext->makeFonts) {
if (makeFont.func) {
ImFontConfig cfg;
std::snprintf(cfg.Name, sizeof(cfg.Name), "%s", makeFont.name.c_str());
bool isDefault = makeFont.name == gContext->defaultFontName;
if (!makeFont.defaultOnly || isDefault) {
ImFont* font = makeFont.func(io, size, &cfg);
if (isDefault) {
// Merge font awesome solid into default font
static const ImWchar icons_ranges[] = {ICON_MIN_FA, ICON_MAX_16_FA,
0};
ImFontConfig icons_cfg;
icons_cfg.MergeMode = true;
icons_cfg.PixelSnapH = true;
ImGui::AddFontFontAwesomeSolid(io, size, &icons_cfg, icons_ranges);
ImGui::GetIO().FontDefault = font;
}
gContext->fonts.emplace_back(font);
}
}
float fontScale = gContext->userScale / 100.0 * windowScale;
if (fontScale < 0.5) {
fontScale = 0.5;
}
ImGui::GetStyle().FontSizeBase = 13;
ImGui::GetStyle().FontScaleDpi = fontScale;
}
bool gui::Initialize(const char* title, int width, int height,
@@ -382,8 +364,6 @@ bool gui::Initialize(const char* title, int width, int height,
// Load Fonts
UpdateFontScale();
ReloadFonts();
gContext->reloadFonts = false; // init renderer will do this
if (!PlatformInitRenderer()) {
return false;
@@ -401,10 +381,6 @@ void gui::Main() {
glfwPollEvents();
gContext->isPlatformRendering = true;
UpdateFontScale();
if (gContext->reloadFonts) {
ReloadFonts();
// PlatformRenderFrame() will clear reloadFonts flag
}
PlatformRenderFrame();
gContext->isPlatformRendering = false;
@@ -527,22 +503,12 @@ bool gui::AddIcon(const unsigned char* data, int len) {
return true;
}
int gui::AddFont(
const char* name,
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
makeFont) {
if (makeFont) {
gContext->makeFonts.emplace_back(name, false, std::move(makeFont));
}
return gContext->makeFonts.size() - 1;
}
void gui::AddDefaultFont(
const char* name,
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
makeFont) {
if (makeFont) {
gContext->makeFonts.emplace_back(name, true, std::move(makeFont));
gContext->makeFonts.emplace_back(name, std::move(makeFont));
}
}
@@ -708,19 +674,20 @@ void gui::EmitViewMenu() {
if (ImGui::BeginMenu("Font")) {
for (auto&& makeFont : gContext->makeFonts) {
bool selected = gContext->defaultFontName == makeFont.name;
if (ImGui::MenuItem(makeFont.name.c_str(), nullptr, &selected)) {
gContext->defaultFontName = makeFont.name;
gContext->reloadFonts = true;
auto& name = makeFont.GetName();
bool selected = gContext->defaultFontName == name;
if (ImGui::MenuItem(name.c_str(), nullptr, &selected)) {
ImGui::GetIO().FontDefault = makeFont.GetFont();
gContext->defaultFontName = name;
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Zoom")) {
for (int i = 0; i < kFontScaledLevels && (25 * (i + 2)) <= 200; ++i) {
for (int i = 50; i <= 200; i += 25) {
char label[20];
std::snprintf(label, sizeof(label), "%d%%", 25 * (i + 2));
std::snprintf(label, sizeof(label), "%d%%", i);
bool selected = gContext->userScale == i;
if (ImGui::MenuItem(label, nullptr, &selected)) {
gContext->userScale = i;
@@ -764,12 +731,12 @@ bool gui::UpdateTextureFromImage(ImTextureID* texture, int width, int height,
int height2 = 0;
unsigned char* imgData =
stbi_load_from_memory(data, len, &width2, &height2, nullptr, 4);
if (!data) {
if (!imgData) {
return false;
}
if (width2 == width && height2 == height) {
UpdateTexture(texture, kPixelRGBA, width2, height2, imgData);
UpdateTexture(*texture, kPixelRGBA, width2, height2, imgData);
} else {
*texture = CreateTexture(kPixelRGBA, width2, height2, imgData);
}

View File

@@ -133,11 +133,6 @@ bool gui::PlatformInitRenderer() {
}
void gui::PlatformRenderFrame() {
if (gContext->reloadFonts) {
ImGui_ImplDX11_InvalidateDeviceObjects();
ImGui_ImplDX11_CreateDeviceObjects();
gContext->reloadFonts = false;
}
ImGui_ImplDX11_NewFrame();
CommonRenderFrame();
@@ -181,7 +176,7 @@ static inline DXGI_FORMAT DXPixelFormat(PixelFormat format) {
ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
const unsigned char* data) {
if (!gPlatformValid) {
return nullptr;
return ImTextureID_Invalid;
}
// Create texture
@@ -216,7 +211,7 @@ ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
&srv);
pTexture->Release();
return srv;
return reinterpret_cast<uintptr_t>(srv);
}
void gui::UpdateTexture(ImTextureID texture, PixelFormat, int width, int height,
@@ -234,7 +229,7 @@ void gui::UpdateTexture(ImTextureID texture, PixelFormat, int width, int height,
box.bottom = height;
ID3D11Resource* resource = nullptr;
static_cast<ID3D11ShaderResourceView*>(texture)->GetResource(&resource);
reinterpret_cast<ID3D11ShaderResourceView*>(texture)->GetResource(&resource);
if (resource) {
gPlatformContext->pd3dDeviceContext->UpdateSubresource(
@@ -249,7 +244,7 @@ void gui::DeleteTexture(ImTextureID texture) {
return;
}
if (texture) {
static_cast<ID3D11ShaderResourceView*>(texture)->Release();
reinterpret_cast<ID3D11ShaderResourceView*>(texture)->Release();
}
}

View File

@@ -148,24 +148,8 @@ inline bool AddIcon(std::string_view data) {
}
/**
* Adds a font to the GUI. The passed function is called during
* initialization as many times as necessary to create a range of sizes.
*
* @param name font name
* @param makeFont font creation / loader function
* @return Font index for later use with GetFont()
*/
int AddFont(
const char* name,
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
makeFont);
/**
* Adds a default font option. This is the font used for menus, etc. If the
* font is selected by the user as the default font, the passed function is
* called during initialization as many times as necessary to create a range of
* sizes. If not selected, the font is not loaded (to always load a font,
* use AddFont() instead).
* Adds a default font option. This is the font used for menus, etc. If not
* selected, the font is not loaded.
*
* @param name font name
* @param makeFont font creation / loader function
@@ -175,15 +159,6 @@ void AddDefaultFont(
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
makeFont);
/**
* Gets a font added with AddFont() with the appropriate font size for
* the current scaling of the GUI.
*
* @param font font index returned by AddFont()
* @return Font pointer
*/
ImFont* GetFont(int font);
enum Style { kStyleClassic = 0, kStyleDark, kStyleLight, kStyleDeepDark };
/**
@@ -339,7 +314,7 @@ class Texture {
m_format{oth.m_format},
m_width{oth.m_width},
m_height{oth.m_height} {
oth.m_texture = 0; // NOLINT
oth.m_texture = ImTextureID_Invalid;
}
Texture& operator=(const Texture&) = delete;
@@ -348,7 +323,7 @@ class Texture {
DeleteTexture(m_texture);
}
m_texture = oth.m_texture;
oth.m_texture = 0; // NOLINT
oth.m_texture = ImTextureID_Invalid;
m_format = oth.m_format;
m_width = oth.m_width;
m_height = oth.m_height;
@@ -364,13 +339,18 @@ class Texture {
/**
* Evaluates to true if the texture is valid.
*/
explicit operator bool() const { return m_texture; }
explicit operator bool() const { return m_texture != ImTextureID_Invalid; }
/**
* Implicit conversion to ImTextureID.
*/
operator ImTextureID() const { return m_texture; } // NOLINT
/**
* Implicit conversion to ImTextureRef.
*/
operator ImTextureRef() const { return ImTextureRef{m_texture}; } // NOLINT
/**
* Gets the texture pixel format.
*
@@ -452,7 +432,7 @@ class Texture {
}
private:
ImTextureID m_texture = nullptr;
ImTextureID m_texture = ImTextureID_Invalid;
PixelFormat m_format = kPixelRGBA;
int m_width = 0;
int m_height = 0;

View File

@@ -22,14 +22,12 @@ struct SavedSettings {
bool maximized = false;
int xPos = -1;
int yPos = -1;
int userScale = 2;
int userScale = 100;
int style = 0;
int fps = 120;
std::string defaultFontName = "Proggy Dotted";
};
constexpr int kFontScaledLevels = 9;
struct Context : public SavedSettings {
std::atomic_bool exit{false};
@@ -45,17 +43,20 @@ struct Context : public SavedSettings {
std::function<void(bool exiting)> saveSettings;
std::vector<std::function<void()>> initializers;
std::vector<std::function<void(float scale)>> windowScalers;
struct FontMaker {
class FontMaker {
public:
FontMaker(
std::string name, bool defaultOnly,
std::string name,
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
func)
: name{std::move(name)},
defaultOnly{defaultOnly},
func{std::move(func)} {}
: name{std::move(name)}, func{std::move(func)} {}
const std::string& GetName() const { return name; }
ImFont* GetFont() const;
private:
std::string name;
bool defaultOnly;
mutable ImFont* font = nullptr;
std::function<ImFont*(ImGuiIO& io, float size, const ImFontConfig* cfg)>
func;
};
@@ -65,15 +66,10 @@ struct Context : public SavedSettings {
std::vector<std::function<void()>> earlyExecutors;
std::vector<std::function<void()>> lateExecutors;
int fontScale = 2; // updated by main loop
std::vector<ImFont*> fonts;
std::vector<GLFWimage> icons;
std::string iniPath = "imgui.ini";
bool resetOnExit = false;
bool reloadFonts = false; // reload fonts in next PlatformRenderFrame()
};
extern Context* gContext;

View File

@@ -84,12 +84,6 @@ void gui::PlatformRenderFrame() {
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder pushDebugGroup:@"WPI GUI"];
if (gContext->reloadFonts) {
ImGui_ImplMetal_DestroyFontsTexture();
ImGui_ImplMetal_CreateFontsTexture(gPlatformContext->layer.device);
gContext->reloadFonts = false;
}
// Start the Dear ImGui frame
ImGui_ImplMetal_NewFrame(renderPassDescriptor);
@@ -125,7 +119,7 @@ static inline MTLPixelFormat MetalPixelFormat(PixelFormat format) {
ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
const unsigned char* data) {
if (!gPlatformValid) return nullptr;
if (!gPlatformValid) return ImTextureID_Invalid;
MTLPixelFormat fmt = MetalPixelFormat(format);
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:fmt width:width height:height mipmapped:NO];
@@ -138,19 +132,19 @@ ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
id <MTLTexture> texture = [gPlatformContext->layer.device newTextureWithDescriptor:textureDescriptor];
[texture replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 withBytes:data bytesPerRow:width * 4];
return (__bridge_retained void *)texture;
return (ImTextureID)(intptr_t)(__bridge_retained void *)texture;
}
void gui::UpdateTexture(ImTextureID texture, PixelFormat, int width,
int height, const unsigned char* data) {
if (!texture) return;
id <MTLTexture> mtlTexture = (__bridge id <MTLTexture>)texture;
id <MTLTexture> mtlTexture = (__bridge id <MTLTexture>)(void*)(intptr_t)texture;
[mtlTexture replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 withBytes:data bytesPerRow:width * 4];
}
void gui::DeleteTexture(ImTextureID texture) {
if (!gPlatformValid || !texture) return;
id <MTLTexture> mtlTexture = (__bridge_transfer id <MTLTexture>)texture;
id <MTLTexture> mtlTexture = (__bridge_transfer id <MTLTexture>)(void*)(intptr_t)texture;
(void)mtlTexture;
}

View File

@@ -51,11 +51,6 @@ bool gui::PlatformInitRenderer() {
}
void gui::PlatformRenderFrame() {
if (gContext->reloadFonts) {
ImGui_ImplOpenGL2_DestroyFontsTexture();
ImGui_ImplOpenGL2_CreateFontsTexture();
gContext->reloadFonts = false;
}
ImGui_ImplOpenGL2_NewFrame();
CommonRenderFrame();
@@ -92,7 +87,7 @@ static inline GLenum GLPixelFormat(PixelFormat format) {
ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
const unsigned char* data) {
if (!gPlatformValid) {
return nullptr;
return ImTextureID_Invalid;
}
// Create a OpenGL texture identifier
@@ -109,12 +104,12 @@ ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GLPixelFormat(format), GL_UNSIGNED_BYTE, data);
return reinterpret_cast<ImTextureID>(static_cast<uintptr_t>(texture));
return texture;
}
void gui::UpdateTexture(ImTextureID texture, PixelFormat format, int width,
int height, const unsigned char* data) {
GLuint glTexture = static_cast<GLuint>(reinterpret_cast<uintptr_t>(texture));
GLuint glTexture = texture;
if (glTexture == 0) {
return;
}
@@ -127,7 +122,7 @@ void gui::DeleteTexture(ImTextureID texture) {
if (!gPlatformValid) {
return;
}
GLuint glTexture = static_cast<GLuint>(reinterpret_cast<uintptr_t>(texture));
GLuint glTexture = texture;
if (glTexture != 0) {
glDeleteTextures(1, &glTexture);
}

View File

@@ -76,11 +76,6 @@ bool gui::PlatformInitRenderer() {
}
void gui::PlatformRenderFrame() {
if (gContext->reloadFonts) {
ImGui_ImplOpenGL3_DestroyFontsTexture();
ImGui_ImplOpenGL3_CreateFontsTexture();
gContext->reloadFonts = false;
}
ImGui_ImplOpenGL3_NewFrame();
CommonRenderFrame();
@@ -117,7 +112,7 @@ static inline GLenum GLPixelFormat(PixelFormat format) {
ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
const unsigned char* data) {
if (!gPlatformValid) {
return nullptr;
return ImTextureID_Invalid;
}
// Create a OpenGL texture identifier
@@ -134,12 +129,12 @@ ImTextureID gui::CreateTexture(PixelFormat format, int width, int height,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GLPixelFormat(format), GL_UNSIGNED_BYTE, data);
return reinterpret_cast<ImTextureID>(static_cast<uintptr_t>(texture));
return texture;
}
void gui::UpdateTexture(ImTextureID texture, PixelFormat format, int width,
int height, const unsigned char* data) {
GLuint glTexture = static_cast<GLuint>(reinterpret_cast<uintptr_t>(texture));
GLuint glTexture = static_cast<GLuint>(texture);
if (glTexture == 0) {
return;
}
@@ -152,7 +147,7 @@ void gui::DeleteTexture(ImTextureID texture) {
if (!gPlatformValid) {
return;
}
GLuint glTexture = static_cast<GLuint>(reinterpret_cast<uintptr_t>(texture));
GLuint glTexture = static_cast<GLuint>(texture);
if (glTexture != 0) {
glDeleteTextures(1, &glTexture);
}