WIP (Breaking) added ImTextureRef struct.

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 8d8b125832
commit 889b03b320
7 changed files with 115 additions and 81 deletions

View file

@ -3887,12 +3887,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)))
continue;
ImDrawList* draw_list = GetForegroundDrawList(viewport);
ImTextureID tex_id = font_atlas->TexID;
draw_list->PushTextureID(tex_id);
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_id, 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_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
ImTextureRef tex_ref = font_atlas->TexID;
draw_list->PushTexture(tex_ref);
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_ref, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_ref, pos, pos + size * scale, uv[2], uv[3], col_border);
draw_list->AddImage(tex_ref, pos, pos + size * scale, uv[0], uv[1], col_fill);
if (mouse_cursor == ImGuiMouseCursor_Wait || mouse_cursor == ImGuiMouseCursor_Progress)
{
float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI);
@ -3900,7 +3900,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->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
}
draw_list->PopTextureID();
draw_list->PopTexture();
}
}
@ -5013,7 +5013,7 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
{
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);
viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
}
@ -8062,7 +8062,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Setup draw list and outer clipping rectangle
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);
// Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71)
@ -8449,7 +8449,7 @@ void ImGui::PushFont(ImFont* font)
font = GetDefaultFont();
g.FontStack.push_back(font);
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
g.CurrentWindow->DrawList->_SetTextureRef(font->ContainerAtlas->TexID);
}
void ImGui::PopFont()
@ -8463,7 +8463,7 @@ void ImGui::PopFont()
g.FontStack.pop_back();
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
g.CurrentWindow->DrawList->_SetTextureRef(font->ContainerAtlas->TexID);
}
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
@ -21112,11 +21112,11 @@ void ImGui::UpdateDebugToolFlashStyleColor()
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;
memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id)));
if (sizeof(tex_id) >= sizeof(void*))
memcpy(&tex_id_opaque, &tex_ref._TexID, ImMin(sizeof(void*), sizeof(tex_ref._TexID)));
if (sizeof(tex_ref._TexID) >= sizeof(void*))
ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr);
else
ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer);
@ -22026,7 +22026,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
}
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];
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);

71
imgui.h
View file

@ -39,7 +39,7 @@
Index of this file:
// [SECTION] Header mess
// [SECTION] Forward declarations and basic types
// [SECTION] Texture identifier (ImTextureID)
// [SECTION] Texture identifiers (ImTextureID, ImTextureRef)
// [SECTION] Dear ImGui end-user API functions
// [SECTION] Flags & Enumerations
// [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
@ -306,18 +306,38 @@ struct ImVec4
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.
// - 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.
// - (note: before v1.91.4 (2024/10/08) the default type for ImTextureID was void*. Use intermediary intptr_t cast and read FAQ if you have casting warnings)
#ifndef ImTextureID
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
// 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
// (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!)
@ -574,9 +594,9 @@ namespace ImGui
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
// - 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.
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 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 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 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(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, 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)
// - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
@ -3109,7 +3129,7 @@ typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* c
struct ImDrawCmd
{
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 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[].
@ -3121,7 +3141,8 @@ struct ImDrawCmd
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)
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
@ -3144,7 +3165,7 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
struct ImDrawCmdHeader
{
ImVec4 ClipRect;
ImTextureID TextureId;
ImTextureRef TexRef;
unsigned int VtxOffset;
};
@ -3229,7 +3250,7 @@ struct ImDrawList
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!)
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureID> _TextureIdStack; // [Internal]
ImVector<ImTextureRef> _TextureStack; // [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
const char* _OwnerName; // Pointer to owner window's name for debugging
@ -3242,8 +3263,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 PushClipRectFullScreen();
IMGUI_API void PopClipRect();
IMGUI_API void PushTextureID(ImTextureID texture_id);
IMGUI_API void PopTextureID();
IMGUI_API void PushTexture(ImTextureRef tex_ref);
IMGUI_API void PopTexture();
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); }
@ -3281,12 +3302,12 @@ struct ImDrawList
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
// 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.
// - "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 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 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 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(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(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()
// - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
@ -3342,6 +3363,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
// 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 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)
@ -3356,7 +3381,7 @@ struct ImDrawList
IMGUI_API void _OnChangedClipRect();
IMGUI_API void _OnChangedTextureID();
IMGUI_API void _OnChangedVtxOffset();
IMGUI_API void _SetTextureID(ImTextureID texture_id);
IMGUI_API void _SetTextureRef(ImTextureRef tex_ref);
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 _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
@ -3513,7 +3538,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 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...
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
@ -3557,7 +3586,7 @@ struct ImFontAtlas
// Input
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 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).
@ -3890,7 +3919,7 @@ struct ImGuiPlatformImeData
namespace ImGui
{
// 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.
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.
// OBSOLETED in 1.91.0 (from July 2024)
static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); }
static inline void PopButtonRepeat() { PopItemFlag(); }

View file

@ -1809,7 +1809,7 @@ static void DemoWindowWidgetsImages()
// - 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/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_h = (float)io.Fonts->TexHeight;
{

View file

@ -426,8 +426,8 @@ void ImDrawList::_ResetForNewFrame()
{
// 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, TextureId) == sizeof(ImVec4));
IM_STATIC_ASSERT(offsetof(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
IM_STATIC_ASSERT(offsetof(ImDrawCmd, TexRef) == sizeof(ImVec4));
IM_STATIC_ASSERT(offsetof(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureRef));
if (_Splitter._Count > 1)
_Splitter.Merge(this);
@ -440,7 +440,7 @@ void ImDrawList::_ResetForNewFrame()
_VtxWritePtr = NULL;
_IdxWritePtr = NULL;
_ClipRectStack.resize(0);
_TextureIdStack.resize(0);
_TextureStack.resize(0);
_CallbacksDataBuf.resize(0);
_Path.resize(0);
_Splitter.Clear();
@ -458,7 +458,7 @@ void ImDrawList::_ClearFreeMemory()
_VtxWritePtr = NULL;
_IdxWritePtr = NULL;
_ClipRectStack.clear();
_TextureIdStack.clear();
_TextureStack.clear();
_CallbacksDataBuf.clear();
_Path.clear();
_Splitter.ClearFreeMemory();
@ -478,7 +478,7 @@ void ImDrawList::AddDrawCmd()
{
ImDrawCmd draw_cmd;
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.IdxOffset = IdxBuffer.Size;
@ -576,12 +576,16 @@ void ImDrawList::_OnChangedClipRect()
curr_cmd->ClipRect = _CmdHeader.ClipRect;
}
// 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::_OnChangedTextureID()
{
// If current command is used with different settings we need to add a new command
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
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();
return;
@ -595,7 +599,7 @@ void ImDrawList::_OnChangedTextureID()
CmdBuffer.pop_back();
return;
}
curr_cmd->TextureId = _CmdHeader.TextureId;
curr_cmd->TexRef = _CmdHeader.TexRef;
}
void ImDrawList::_OnChangedVtxOffset()
@ -656,26 +660,26 @@ void ImDrawList::PopClipRect()
_OnChangedClipRect();
}
void ImDrawList::PushTextureID(ImTextureID texture_id)
void ImDrawList::PushTexture(ImTextureRef tex_ref)
{
_TextureIdStack.push_back(texture_id);
_CmdHeader.TextureId = texture_id;
_TextureStack.push_back(tex_ref);
_CmdHeader.TexRef = tex_ref;
_OnChangedTextureID();
}
void ImDrawList::PopTextureID()
void ImDrawList::PopTexture()
{
_TextureIdStack.pop_back();
_CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1];
_TextureStack.pop_back();
_CmdHeader.TexRef = (_TextureStack.Size == 0) ? ImTextureRef() : _TextureStack.Data[_TextureStack.Size - 1];
_OnChangedTextureID();
}
// 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::_SetTextureRef(ImTextureRef tex_ref)
{
if (_CmdHeader.TextureId == texture_id)
if (_CmdHeader.TexRef == tex_ref)
return;
_CmdHeader.TextureId = texture_id;
_CmdHeader.TexRef = tex_ref;
_OnChangedTextureID();
}
@ -1689,7 +1693,7 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32
if (font_size == 0.0f)
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;
if (cpu_fine_clip_rect)
@ -1707,39 +1711,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);
}
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)
return;
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id)
PushTextureID(user_texture_id);
PushTexture(tex_ref);
PrimReserve(6, 4);
PrimRectUV(p_min, p_max, uv_min, uv_max, col);
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)
return;
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id)
PushTextureID(user_texture_id);
PushTexture(tex_ref);
PrimReserve(6, 4);
PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col);
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)
return;
@ -1747,13 +1751,13 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
flags = FixRectCornerFlags(flags);
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;
}
const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
const bool push_texture_id = tex_ref != _CmdHeader.TexRef;
if (push_texture_id)
PushTextureID(user_texture_id);
PushTexture(tex_ref);
int vert_start_idx = VtxBuffer.Size;
PathRect(p_min, p_max, rounding, flags);
@ -1762,7 +1766,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);
if (push_texture_id)
PopTextureID();
PopTexture();
}
//-----------------------------------------------------------------------------
@ -2486,6 +2490,7 @@ ImFontAtlas::ImFontAtlas()
{
memset(this, 0, sizeof(*this));
TexGlyphPadding = 1;
TexID._Atlas = this;
PackIdMouseCursors = PackIdLines = -1;
}
@ -2885,7 +2890,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
ImFontAtlasBuildInit(atlas);
// Clear atlas
atlas->TexID = (ImTextureID)NULL;
atlas->TexID._TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);

View file

@ -3740,7 +3740,7 @@ namespace ImGui
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags 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 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 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);

View file

@ -1069,9 +1069,9 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
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.
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;
ImGuiWindow* window = GetCurrentWindow();
@ -1089,28 +1089,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);
if (bg_col.w > 0.0f)
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)
#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;
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);
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();
PopStyleVar();
}
#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;
ImGuiWindow* window = GetCurrentWindow();
@ -1132,21 +1132,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));
if (bg_col.w > 0.0f)
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;
}
// - 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?
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;
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
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

View file

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