1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-11 00:04:24 +00:00

(Breaking) added ImTextureRef struct. Changed ImDrawCmd::TextureId to TexRef.

Softly breaking. May require support from language binding generator.
Rebased and reworked completely on 2025/03/19.
This commit is contained in:
ocornut 2025-03-17 19:13:17 +01:00
parent b2f39318cb
commit 191a728ecc
7 changed files with 126 additions and 92 deletions

View file

@ -3841,12 +3841,12 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale))) if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale)))
continue; continue;
ImDrawList* draw_list = GetForegroundDrawList(viewport); ImDrawList* draw_list = GetForegroundDrawList(viewport);
ImTextureID tex_id = font_atlas->TexID; ImTextureRef tex_ref = font_atlas->TexID;
draw_list->PushTextureID(tex_id); draw_list->PushTexture(tex_ref);
draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_ref, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_ref, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); draw_list->AddImage(tex_ref, pos, pos + size * scale, uv[2], uv[3], col_border);
draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); draw_list->AddImage(tex_ref, pos, pos + size * scale, uv[0], uv[1], col_fill);
if (mouse_cursor == ImGuiMouseCursor_Wait || mouse_cursor == ImGuiMouseCursor_Progress) if (mouse_cursor == ImGuiMouseCursor_Wait || mouse_cursor == ImGuiMouseCursor_Progress)
{ {
float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI); float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI);
@ -3854,7 +3854,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max); draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max);
draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale); draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
} }
draw_list->PopTextureID(); draw_list->PopTexture();
} }
} }
@ -4925,7 +4925,7 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount) if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
{ {
draw_list->_ResetForNewFrame(); draw_list->_ResetForNewFrame();
draw_list->PushTextureID(g.IO.Fonts->TexID); draw_list->PushTexture(g.IO.Fonts->TexID);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false); draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount; viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
} }
@ -7580,7 +7580,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Setup draw list and outer clipping rectangle // Setup draw list and outer clipping rectangle
IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0); IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); window->DrawList->PushTexture(g.Font->ContainerAtlas->TexID);
PushClipRect(host_rect.Min, host_rect.Max, false); PushClipRect(host_rect.Min, host_rect.Max, false);
// Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71) // Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71)
@ -8553,7 +8553,7 @@ void ImGui::PushFont(ImFont* font)
font = GetDefaultFont(); font = GetDefaultFont();
g.FontStack.push_back(font); g.FontStack.push_back(font);
SetCurrentFont(font); SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); g.CurrentWindow->DrawList->_SetTexture(font->ContainerAtlas->TexID);
} }
void ImGui::PopFont() void ImGui::PopFont()
@ -8567,7 +8567,7 @@ void ImGui::PopFont()
g.FontStack.pop_back(); g.FontStack.pop_back();
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font); SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); g.CurrentWindow->DrawList->_SetTexture(font->ContainerAtlas->TexID);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -15500,11 +15500,11 @@ void ImGui::UpdateDebugToolFlashStyleColor()
DebugFlashStyleColorStop(); DebugFlashStyleColorStop();
} }
static const char* FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) static const char* FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureRef tex_ref)
{ {
union { void* ptr; int integer; } tex_id_opaque; union { void* ptr; int integer; } tex_id_opaque;
memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id))); memcpy(&tex_id_opaque, &tex_ref._TexID, ImMin(sizeof(void*), sizeof(tex_ref._TexID)));
if (sizeof(tex_id) >= sizeof(void*)) if (sizeof(tex_ref._TexID) >= sizeof(void*))
ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr); ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr);
else else
ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer); ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer);
@ -16245,7 +16245,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
} }
char texid_desc[20]; char texid_desc[20];
FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId); FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TexRef);
char buf[300]; char buf[300];
ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);

73
imgui.h
View file

@ -37,7 +37,7 @@
Index of this file: Index of this file:
// [SECTION] Header mess // [SECTION] Header mess
// [SECTION] Forward declarations and basic types // [SECTION] Forward declarations and basic types
// [SECTION] Texture identifier (ImTextureID) // [SECTION] Texture identifiers (ImTextureID, ImTextureRef)
// [SECTION] Dear ImGui end-user API functions // [SECTION] Dear ImGui end-user API functions
// [SECTION] Flags & Enumerations // [SECTION] Flags & Enumerations
// [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) // [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
@ -301,10 +301,10 @@ struct ImVec4
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Texture identifier (ImTextureID) // [SECTION] Texture identifiers (ImTextureID, ImTextureRef)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type] // ImTextureID: user data for renderer backend to identify a texture [Compile-time configurable type]
// - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file. // - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file.
// - This can be whatever to you want it to be! read the FAQ about ImTextureID for details. // - This can be whatever to you want it to be! read the FAQ about ImTextureID for details.
// - You can make this a structure with various constructors if you need. You will have to implement ==/!= operators. // - You can make this a structure with various constructors if you need. You will have to implement ==/!= operators.
@ -313,6 +313,26 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
typedef ImU64 ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that) typedef ImU64 ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that)
#endif #endif
// ImTextureRef contains:
// - a texture/atlas pointer, typically when created by Dear ImGui itself.
// - OR a raw ImTextureID value (user/backend identifier), typically when created by user code to load images.
// There is no constructor to create a ImTextureID from a ImTextureData* as we don't expect this to be useful to the end-user.
IM_MSVC_RUNTIME_CHECKS_OFF
struct ImTextureRef
{
ImTextureRef() { memset(this, 0, sizeof(*this)); }
ImTextureRef(ImTextureID tex_id) { memset(this, 0, sizeof(*this)); _TexID = tex_id; }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImTextureRef(void* tex_id) { memset(this, 0, sizeof(*this)); _TexID = (ImTextureID)(size_t)tex_id; } // For legacy backends casting to ImTextureID
//inline operator intptr_t() const { return (intptr_t)_TexID; } // For legacy backends casting to ImTextureID
#endif
// Members
ImFontAtlas* _Atlas; // Texture/Atlas pointer
ImTextureID _TexID; // _OR_ Underlying user/backend texture identifier, or zero if not yet uploaded.
};
IM_MSVC_RUNTIME_CHECKS_RESTORE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Dear ImGui end-user API functions // [SECTION] Dear ImGui end-user API functions
// (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!) // (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!)
@ -567,9 +587,9 @@ namespace ImGui
// - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side. // - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
// - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function. // - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function.
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1)); IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1));
IMGUI_API void ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API void ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API bool ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
// Widgets: Combo Box (Dropdown) // Widgets: Combo Box (Dropdown)
// - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
@ -3004,11 +3024,11 @@ typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* c
// - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled, // - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
// this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices. // this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
// Backends made for <1.71. will typically ignore the VtxOffset fields. // Backends made for <1.71. will typically ignore the VtxOffset fields.
// - The ClipRect/TextureId/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for). // - The ClipRect/TexRef/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for).
struct ImDrawCmd struct ImDrawCmd
{ {
ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
ImTextureID TextureId; // 4-8 // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. ImTextureRef TexRef; // 16 // User-provided texture ID. Set by user in ImFontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices. unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices.
unsigned int IdxOffset; // 4 // Start offset in index buffer. unsigned int IdxOffset; // 4 // Start offset in index buffer.
unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
@ -3020,7 +3040,8 @@ struct ImDrawCmd
ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
// Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature) // Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature)
inline ImTextureID GetTexID() const { return TextureId; } // Since 1.92: removed ImDrawCmd::TextureId field, the getter function must be used!
inline ImTextureID GetTexID() const { return TexRef._TexID; }
}; };
// Vertex layout // Vertex layout
@ -3043,7 +3064,7 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
struct ImDrawCmdHeader struct ImDrawCmdHeader
{ {
ImVec4 ClipRect; ImVec4 ClipRect;
ImTextureID TextureId; ImTextureRef TexRef;
unsigned int VtxOffset; unsigned int VtxOffset;
}; };
@ -3128,7 +3149,7 @@ struct ImDrawList
ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back().
ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
ImVector<ImVec4> _ClipRectStack; // [Internal] ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureID> _TextureIdStack; // [Internal] ImVector<ImTextureRef> _TextureStack; // [Internal]
ImVector<ImU8> _CallbacksDataBuf; // [Internal] ImVector<ImU8> _CallbacksDataBuf; // [Internal]
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
const char* _OwnerName; // Pointer to owner window's name for debugging const char* _OwnerName; // Pointer to owner window's name for debugging
@ -3141,8 +3162,8 @@ struct ImDrawList
IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
IMGUI_API void PushClipRectFullScreen(); IMGUI_API void PushClipRectFullScreen();
IMGUI_API void PopClipRect(); IMGUI_API void PopClipRect();
IMGUI_API void PushTextureID(ImTextureID texture_id); IMGUI_API void PushTexture(ImTextureRef tex_ref);
IMGUI_API void PopTextureID(); IMGUI_API void PopTexture();
inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }
inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }
@ -3180,12 +3201,12 @@ struct ImDrawList
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
// Image primitives // Image primitives
// - Read FAQ to understand what ImTextureID is. // - Read FAQ to understand what ImTextureID/ImTextureRef are.
// - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle.
// - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture. // - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture.
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImage(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE);
IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImageQuad(ImTextureRef tex_ref, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE);
IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); IMGUI_API void AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0);
// Stateful path API, add points then finish with PathFillConvex() or PathStroke() // Stateful path API, add points then finish with PathFillConvex() or PathStroke()
// - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. // - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
@ -3241,6 +3262,10 @@ struct ImDrawList
inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index
// Obsolete names // Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//IMGUI_API void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.x
//IMGUI_API void PopTextureID() { PopTexture(); } // RENAMED in 1.92.x
#endif
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024) //inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024) //inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0) { PathEllipticalArcTo(center, ImVec2(radius_x, radius_y), rot, a_min, a_max, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024) //inline void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0) { PathEllipticalArcTo(center, ImVec2(radius_x, radius_y), rot, a_min, a_max, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
@ -3253,9 +3278,9 @@ struct ImDrawList
IMGUI_API void _PopUnusedDrawCmd(); IMGUI_API void _PopUnusedDrawCmd();
IMGUI_API void _TryMergeDrawCmds(); IMGUI_API void _TryMergeDrawCmds();
IMGUI_API void _OnChangedClipRect(); IMGUI_API void _OnChangedClipRect();
IMGUI_API void _OnChangedTextureID(); IMGUI_API void _OnChangedTexture();
IMGUI_API void _OnChangedVtxOffset(); IMGUI_API void _OnChangedVtxOffset();
IMGUI_API void _SetTextureID(ImTextureID texture_id); IMGUI_API void _SetTexture(ImTextureRef tex_ref);
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments); IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
@ -3412,7 +3437,11 @@ struct ImFontAtlas
IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't build texture but effectively we should check TexID != 0 except that would be backend dependent... bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't build texture but effectively we should check TexID != 0 except that would be backend dependent...
void SetTexID(ImTextureID id) { TexID = id; } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void SetTexID(ImTextureID id){ TexID._Atlas = this; TexID._TexID = id; } // FIXME-NEWATLAS: Called by legacy backends.
void SetTexID(ImTextureRef id) { TexID = id; } // FIXME-NEWATLAS: Called by legacy backends.
#endif
//------------------------------------------- //-------------------------------------------
// Glyph Ranges // Glyph Ranges
@ -3456,7 +3485,7 @@ struct ImFontAtlas
// Input // Input
ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. ImTextureRef TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false). int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false).
void* UserData; // Store your own atlas related user-data (if e.g. you have multiple font atlas). void* UserData; // Store your own atlas related user-data (if e.g. you have multiple font atlas).
@ -3654,7 +3683,7 @@ struct ImGuiPlatformImeData
namespace ImGui namespace ImGui
{ {
// OBSOLETED in 1.91.9 (from February 2025) // OBSOLETED in 1.91.9 (from February 2025)
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); // <-- 'border_col' was removed in favor of ImGuiCol_ImageBorder. If you use 'tint_col', use ImageWithBg() instead. IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); // <-- 'border_col' was removed in favor of ImGuiCol_ImageBorder. If you use 'tint_col', use ImageWithBg() instead.
// OBSOLETED in 1.91.0 (from July 2024) // OBSOLETED in 1.91.0 (from July 2024)
static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); }
static inline void PopButtonRepeat() { PopItemFlag(); } static inline void PopButtonRepeat() { PopItemFlag(); }

View file

@ -1778,7 +1778,7 @@ static void DemoWindowWidgetsImages()
// - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
// - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
// - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
ImTextureID my_tex_id = io.Fonts->TexID; ImTextureRef my_tex_id = io.Fonts->TexID;
float my_tex_w = (float)io.Fonts->TexWidth; float my_tex_w = (float)io.Fonts->TexWidth;
float my_tex_h = (float)io.Fonts->TexHeight; float my_tex_h = (float)io.Fonts->TexHeight;
{ {

View file

@ -423,8 +423,8 @@ void ImDrawList::_ResetForNewFrame()
{ {
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory. // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
IM_STATIC_ASSERT(offsetof(ImDrawCmd, ClipRect) == 0); IM_STATIC_ASSERT(offsetof(ImDrawCmd, ClipRect) == 0);
IM_STATIC_ASSERT(offsetof(ImDrawCmd, TextureId) == sizeof(ImVec4)); IM_STATIC_ASSERT(offsetof(ImDrawCmd, TexRef) == sizeof(ImVec4));
IM_STATIC_ASSERT(offsetof(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID)); IM_STATIC_ASSERT(offsetof(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureRef));
if (_Splitter._Count > 1) if (_Splitter._Count > 1)
_Splitter.Merge(this); _Splitter.Merge(this);
@ -437,7 +437,7 @@ void ImDrawList::_ResetForNewFrame()
_VtxWritePtr = NULL; _VtxWritePtr = NULL;
_IdxWritePtr = NULL; _IdxWritePtr = NULL;
_ClipRectStack.resize(0); _ClipRectStack.resize(0);
_TextureIdStack.resize(0); _TextureStack.resize(0);
_CallbacksDataBuf.resize(0); _CallbacksDataBuf.resize(0);
_Path.resize(0); _Path.resize(0);
_Splitter.Clear(); _Splitter.Clear();
@ -455,7 +455,7 @@ void ImDrawList::_ClearFreeMemory()
_VtxWritePtr = NULL; _VtxWritePtr = NULL;
_IdxWritePtr = NULL; _IdxWritePtr = NULL;
_ClipRectStack.clear(); _ClipRectStack.clear();
_TextureIdStack.clear(); _TextureStack.clear();
_CallbacksDataBuf.clear(); _CallbacksDataBuf.clear();
_Path.clear(); _Path.clear();
_Splitter.ClearFreeMemory(); _Splitter.ClearFreeMemory();
@ -475,7 +475,7 @@ void ImDrawList::AddDrawCmd()
{ {
ImDrawCmd draw_cmd; ImDrawCmd draw_cmd;
draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy() draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy()
draw_cmd.TextureId = _CmdHeader.TextureId; draw_cmd.TexRef = _CmdHeader.TexRef;
draw_cmd.VtxOffset = _CmdHeader.VtxOffset; draw_cmd.VtxOffset = _CmdHeader.VtxOffset;
draw_cmd.IdxOffset = IdxBuffer.Size; draw_cmd.IdxOffset = IdxBuffer.Size;
@ -530,10 +530,10 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t use
AddDrawCmd(); // Force a new command after us (see comment below) AddDrawCmd(); // Force a new command after us (see comment below)
} }
// Compare ClipRect, TextureId and VtxOffset with a single memcmp() // Compare ClipRect, TexRef and VtxOffset with a single memcmp()
#define ImDrawCmd_HeaderSize (offsetof(ImDrawCmd, VtxOffset) + sizeof(unsigned int)) #define ImDrawCmd_HeaderSize (offsetof(ImDrawCmd, VtxOffset) + sizeof(unsigned int))
#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TexRef, VtxOffset
#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TexRef, VtxOffset
#define ImDrawCmd_AreSequentialIdxOffset(CMD_0, CMD_1) (CMD_0->IdxOffset + CMD_0->ElemCount == CMD_1->IdxOffset) #define ImDrawCmd_AreSequentialIdxOffset(CMD_0, CMD_1) (CMD_0->IdxOffset + CMD_0->ElemCount == CMD_1->IdxOffset)
// Try to merge two last draw commands // Try to merge two last draw commands
@ -573,12 +573,16 @@ void ImDrawList::_OnChangedClipRect()
curr_cmd->ClipRect = _CmdHeader.ClipRect; curr_cmd->ClipRect = _CmdHeader.ClipRect;
} }
void ImDrawList::_OnChangedTextureID() // Operators for easy compare
static inline bool operator==(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID == rhs._TexID && lhs._Atlas == rhs._Atlas; }
static inline bool operator!=(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID != rhs._TexID || lhs._Atlas != rhs._Atlas; }
void ImDrawList::_OnChangedTexture()
{ {
// If current command is used with different settings we need to add a new command // If current command is used with different settings we need to add a new command
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId) if (curr_cmd->ElemCount != 0 && curr_cmd->TexRef != _CmdHeader.TexRef)
{ {
AddDrawCmd(); AddDrawCmd();
return; return;
@ -592,7 +596,7 @@ void ImDrawList::_OnChangedTextureID()
CmdBuffer.pop_back(); CmdBuffer.pop_back();
return; return;
} }
curr_cmd->TextureId = _CmdHeader.TextureId; curr_cmd->TexRef = _CmdHeader.TexRef;
} }
void ImDrawList::_OnChangedVtxOffset() void ImDrawList::_OnChangedVtxOffset()
@ -653,27 +657,27 @@ void ImDrawList::PopClipRect()
_OnChangedClipRect(); _OnChangedClipRect();
} }
void ImDrawList::PushTextureID(ImTextureID texture_id) void ImDrawList::PushTexture(ImTextureRef tex_ref)
{ {
_TextureIdStack.push_back(texture_id); _TextureStack.push_back(tex_ref);
_CmdHeader.TextureId = texture_id; _CmdHeader.TexRef = tex_ref;
_OnChangedTextureID(); _OnChangedTexture();
} }
void ImDrawList::PopTextureID() void ImDrawList::PopTexture()
{ {
_TextureIdStack.pop_back(); _TextureStack.pop_back();
_CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1]; _CmdHeader.TexRef = (_TextureStack.Size == 0) ? ImTextureRef() : _TextureStack.Data[_TextureStack.Size - 1];
_OnChangedTextureID(); _OnChangedTexture();
} }
// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID(). // This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID().
void ImDrawList::_SetTextureID(ImTextureID texture_id) void ImDrawList::_SetTexture(ImTextureRef tex_ref)
{ {
if (_CmdHeader.TextureId == texture_id) if (_CmdHeader.TexRef == tex_ref)
return; return;
_CmdHeader.TextureId = texture_id; _CmdHeader.TexRef = tex_ref;
_OnChangedTextureID(); _OnChangedTexture();
} }
// Reserve space for a number of vertices and indices. // Reserve space for a number of vertices and indices.
@ -1686,7 +1690,7 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32
if (font_size == 0.0f) if (font_size == 0.0f)
font_size = _Data->FontSize; font_size = _Data->FontSize;
IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TexRef); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
ImVec4 clip_rect = _CmdHeader.ClipRect; ImVec4 clip_rect = _CmdHeader.ClipRect;
if (cpu_fine_clip_rect) if (cpu_fine_clip_rect)
@ -1704,39 +1708,39 @@ void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, c
AddText(_Data->Font, _Data->FontSize, pos, col, text_begin, text_end); AddText(_Data->Font, _Data->FontSize, pos, col, text_begin, text_end);
} }
void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) void ImDrawList::AddImage(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id) if (push_texture_id)
PushTextureID(user_texture_id); PushTexture(tex_ref);
PrimReserve(6, 4); PrimReserve(6, 4);
PrimRectUV(p_min, p_max, uv_min, uv_max, col); PrimRectUV(p_min, p_max, uv_min, uv_max, col);
if (push_texture_id) if (push_texture_id)
PopTextureID(); PopTexture();
} }
void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col) void ImDrawList::AddImageQuad(ImTextureRef tex_ref, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id) if (push_texture_id)
PushTextureID(user_texture_id); PushTexture(tex_ref);
PrimReserve(6, 4); PrimReserve(6, 4);
PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col); PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col);
if (push_texture_id) if (push_texture_id)
PopTextureID(); PopTexture();
} }
void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags) void ImDrawList::AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
@ -1744,13 +1748,13 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
flags = FixRectCornerFlags(flags); flags = FixRectCornerFlags(flags);
if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{ {
AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col); AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col);
return; return;
} }
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id) if (push_texture_id)
PushTextureID(user_texture_id); PushTexture(tex_ref);
int vert_start_idx = VtxBuffer.Size; int vert_start_idx = VtxBuffer.Size;
PathRect(p_min, p_max, rounding, flags); PathRect(p_min, p_max, rounding, flags);
@ -1759,7 +1763,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true); ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true);
if (push_texture_id) if (push_texture_id)
PopTextureID(); PopTexture();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2187,7 +2191,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
// If current command is used with different settings we need to add a new command // If current command is used with different settings we need to add a new command
ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
if (curr_cmd->ElemCount == 0) if (curr_cmd->ElemCount == 0)
ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TexRef, VtxOffset
else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
draw_list->AddDrawCmd(); draw_list->AddDrawCmd();
@ -2213,7 +2217,7 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
if (curr_cmd == NULL) if (curr_cmd == NULL)
draw_list->AddDrawCmd(); draw_list->AddDrawCmd();
else if (curr_cmd->ElemCount == 0) else if (curr_cmd->ElemCount == 0)
ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TexRef, VtxOffset
else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
draw_list->AddDrawCmd(); draw_list->AddDrawCmd();
} }
@ -2483,6 +2487,7 @@ ImFontAtlas::ImFontAtlas()
{ {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
TexGlyphPadding = 1; TexGlyphPadding = 1;
TexID._Atlas = this;
PackIdMouseCursors = PackIdLines = -1; PackIdMouseCursors = PackIdLines = -1;
} }
@ -2882,7 +2887,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
ImFontAtlasBuildInit(atlas); ImFontAtlasBuildInit(atlas);
// Clear atlas // Clear atlas
atlas->TexID = (ImTextureID)NULL; atlas->TexID._TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0; atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);

View file

@ -3454,7 +3454,7 @@ namespace ImGui
// Widgets // Widgets
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);

View file

@ -1103,9 +1103,9 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
return held; return held;
} }
// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -1123,28 +1123,28 @@ void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, c
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize); window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize);
if (bg_col.w > 0.0f) if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col)); window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
} }
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1) void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
{ {
ImageWithBg(user_texture_id, image_size, uv0, uv1); ImageWithBg(tex_ref, image_size, uv0, uv1);
} }
// 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238) // 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f
PushStyleColor(ImGuiCol_Border, border_col); PushStyleColor(ImGuiCol_Border, border_col);
ImageWithBg(user_texture_id, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col); ImageWithBg(tex_ref, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col);
PopStyleColor(); PopStyleColor();
PopStyleVar(); PopStyleVar();
} }
#endif #endif
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags) bool ImGui::ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -1166,21 +1166,21 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2&
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding)); RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
if (bg_col.w > 0.0f) if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col)); window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
return pressed; return pressed;
} }
// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button. // - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design? // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) bool ImGui::ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems) if (window->SkipItems)
return false; return false;
return ImageButtonEx(window->GetID(str_id), user_texture_id, image_size, uv0, uv1, bg_col, tint_col); return ImageButtonEx(window->GetID(str_id), tex_ref, image_size, uv0, uv1, bg_col, tint_col);
} }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS

View file

@ -448,7 +448,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontAtlasBuildInit(atlas); ImFontAtlasBuildInit(atlas);
// Clear atlas // Clear atlas
atlas->TexID = 0; atlas->TexID._TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0; atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);