Update imgui.

This commit is contained in:
Mr_Goldberg 2021-06-13 00:07:16 -04:00
parent 02195f5636
commit 7350397f9d
No known key found for this signature in database
GPG Key ID: 8597D87419DEF278
19 changed files with 496 additions and 233 deletions

View File

@ -42,7 +42,8 @@
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//---- Include imgui_user.h at the end of imgui.h as a convenience //---- Include imgui_user.h at the end of imgui.h as a convenience

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (main code and documentation) // (main code and documentation)
// Help: // Help:
@ -304,9 +304,9 @@ CODE
} }
else else
{ {
// The texture for the draw call is specified by pcmd->TextureId. // The texture for the draw call is specified by pcmd->GetTexID().
// The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization. // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
MyEngineBindTexture((MyTexture*)pcmd->TextureId); MyEngineBindTexture((MyTexture*)pcmd->GetTexID());
// We are using scissoring to clip some objects. All low-level graphics API should support it. // We are using scissoring to clip some objects. All low-level graphics API should support it.
// - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
@ -376,6 +376,9 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID().
- if you are using official backends from the source tree: you have nothing to do.
- if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().
- 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags. - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
- ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft - ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft
- ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight - ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight
@ -1698,7 +1701,7 @@ int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
} }
// Based on stb_to_utf8() from github.com/nothings/stb/ // Based on stb_to_utf8() from github.com/nothings/stb/
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) static inline int ImTextCharToUtf8_inline(char* buf, int buf_size, unsigned int c)
{ {
if (c < 0x80) if (c < 0x80)
{ {
@ -1733,6 +1736,13 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
return 0; return 0;
} }
const char* ImTextCharToUtf8(char out_buf[5], unsigned int c)
{
int count = ImTextCharToUtf8_inline(out_buf, 5, c);
out_buf[count] = 0;
return out_buf;
}
// Not optimal but we very rarely use this function. // Not optimal but we very rarely use this function.
int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
{ {
@ -1749,20 +1759,20 @@ static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
return 3; return 3;
} }
int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
{ {
char* buf_out = buf; char* buf_p = out_buf;
const char* buf_end = buf + buf_size; const char* buf_end = out_buf + out_buf_size;
while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
{ {
unsigned int c = (unsigned int)(*in_text++); unsigned int c = (unsigned int)(*in_text++);
if (c < 0x80) if (c < 0x80)
*buf_out++ = (char)c; *buf_p++ = (char)c;
else else
buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c); buf_p += ImTextCharToUtf8_inline(buf_p, (int)(buf_end - buf_p - 1), c);
} }
*buf_out = 0; *buf_p = 0;
return (int)(buf_out - buf); return (int)(buf_p - out_buf);
} }
int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
@ -3923,7 +3933,8 @@ void ImGui::NewFrame()
g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame));
g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)g.FramerateSecPerFrameCount)) : FLT_MAX;
UpdateViewportsNewFrame(); UpdateViewportsNewFrame();
@ -4060,6 +4071,9 @@ void ImGui::NewFrame()
for (int i = 0; i < g.TablesLastTimeActive.Size; i++) for (int i = 0; i < g.TablesLastTimeActive.Size; i++)
if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time) if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
TableGcCompactTransientBuffers(g.Tables.GetByIndex(i)); TableGcCompactTransientBuffers(g.Tables.GetByIndex(i));
for (int i = 0; i < g.TablesTempDataStack.Size; i++)
if (g.TablesTempDataStack[i].LastTimeActive >= 0.0f && g.TablesTempDataStack[i].LastTimeActive < memory_compact_start_time)
TableGcCompactTransientBuffers(&g.TablesTempDataStack[i]);
if (g.GcCompactAll) if (g.GcCompactAll)
GcCompactTransientMiscBuffers(); GcCompactTransientMiscBuffers();
g.GcCompactAll = false; g.GcCompactAll = false;
@ -4099,20 +4113,20 @@ void ImGui::UpdateDebugToolItemPicker()
if (g.DebugItemPickerActive) if (g.DebugItemPickerActive)
{ {
const ImGuiID hovered_id = g.HoveredIdPreviousFrame; const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); SetMouseCursor(ImGuiMouseCursor_Hand);
if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) if (IsKeyPressedMap(ImGuiKey_Escape))
g.DebugItemPickerActive = false; g.DebugItemPickerActive = false;
if (ImGui::IsMouseClicked(0) && hovered_id) if (IsMouseClicked(0) && hovered_id)
{ {
g.DebugItemPickerBreakId = hovered_id; g.DebugItemPickerBreakId = hovered_id;
g.DebugItemPickerActive = false; g.DebugItemPickerActive = false;
} }
ImGui::SetNextWindowBgAlpha(0.60f); SetNextWindowBgAlpha(0.60f);
ImGui::BeginTooltip(); BeginTooltip();
ImGui::Text("HoveredId: 0x%08X", hovered_id); Text("HoveredId: 0x%08X", hovered_id);
ImGui::Text("Press ESC to abort picking."); Text("Press ESC to abort picking.");
ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!");
ImGui::EndTooltip(); EndTooltip();
} }
} }
@ -4134,10 +4148,8 @@ void ImGui::Initialize(ImGuiContext* context)
g.SettingsHandlers.push_back(ini_handler); g.SettingsHandlers.push_back(ini_handler);
} }
#ifdef IMGUI_HAS_TABLE
// Add .ini handle for ImGuiTable type // Add .ini handle for ImGuiTable type
TableSettingsInstallHandler(context); TableSettingsInstallHandler(context);
#endif // #ifdef IMGUI_HAS_TABLE
// Create default viewport // Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
@ -4204,7 +4216,9 @@ void ImGui::Shutdown(ImGuiContext* context)
g.ShrinkWidthBuffer.clear(); g.ShrinkWidthBuffer.clear();
g.Tables.Clear(); g.Tables.Clear();
g.CurrentTableStack.clear(); for (int i = 0; i < g.TablesTempDataStack.Size; i++)
g.TablesTempDataStack[i].~ImGuiTableTempData();
g.TablesTempDataStack.clear();
g.DrawChannelsTempMergeBuffer.clear(); g.DrawChannelsTempMergeBuffer.clear();
g.ClipboardHandlerData.clear(); g.ClipboardHandlerData.clear();
@ -7206,13 +7220,11 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
while (g.CurrentWindowStack.Size > 0) while (g.CurrentWindowStack.Size > 0)
{ {
#ifdef IMGUI_HAS_TABLE
while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow)) while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
{ {
if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name); if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
EndTable(); EndTable();
} }
#endif
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window != NULL); IM_ASSERT(window != NULL);
while (g.CurrentTabBar != NULL) //-V1044 while (g.CurrentTabBar != NULL) //-V1044
@ -8517,7 +8529,7 @@ ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& s
} }
// Note that this is used for popups, which can overlap the non work-area of individual viewports. // Note that this is used for popups, which can overlap the non work-area of individual viewports.
ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window) ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_UNUSED(window); IM_UNUSED(window);
@ -8531,7 +8543,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImRect r_outer = GetWindowAllowedExtentRect(window); ImRect r_outer = GetPopupAllowedExtentRect(window);
if (window->Flags & ImGuiWindowFlags_ChildMenu) if (window->Flags & ImGuiWindowFlags_ChildMenu)
{ {
// Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds. // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds.
@ -9659,8 +9671,13 @@ static void ImGui::NavUpdateWindowing()
NavInitWindow(apply_focus_window, false); NavInitWindow(apply_focus_window, false);
// If the window has ONLY a menu layer (no main layer), select it directly // If the window has ONLY a menu layer (no main layer), select it directly
// FIXME-NAV: This should be done in NavInit.. or in FocusWindow.. // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame,
if (apply_focus_window->DC.NavLayersActiveMask == (1 << ImGuiNavLayer_Menu)) // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since
// the target window as already been previewed once.
// FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases,
// we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask*
// won't be valid.
if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
g.NavLayer = ImGuiNavLayer_Menu; g.NavLayer = ImGuiNavLayer_Menu;
} }
if (apply_focus_window) if (apply_focus_window)
@ -10900,6 +10917,10 @@ static void MetricsHelpMarker(const char* desc)
} }
} }
#ifndef IMGUI_DISABLE_DEMO_WINDOWS
namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }
#endif
void ImGui::ShowMetricsWindow(bool* p_open) void ImGui::ShowMetricsWindow(bool* p_open)
{ {
if (!Begin("Dear ImGui Metrics/Debugger", p_open)) if (!Begin("Dear ImGui Metrics/Debugger", p_open))
@ -11002,10 +11023,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count); cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
if (cfg->ShowTablesRects && g.NavWindow != NULL) if (cfg->ShowTablesRects && g.NavWindow != NULL)
{ {
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
{ {
ImGuiTable* table = g.Tables.GetByIndex(table_n); ImGuiTable* table = g.Tables.TryGetMapData(table_n);
if (table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow)) if (table == NULL || table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))
continue; continue;
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name); BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
@ -11087,22 +11108,36 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
// Details for TabBars // Details for TabBars
if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetAliveCount()))
{ {
for (int n = 0; n < g.TabBars.GetSize(); n++) for (int n = 0; n < g.TabBars.GetMapSize(); n++)
DebugNodeTabBar(g.TabBars.GetByIndex(n), "TabBar"); if (ImGuiTabBar* tab_bar = g.TabBars.TryGetMapData(n))
{
PushID(tab_bar);
DebugNodeTabBar(tab_bar, "TabBar");
PopID();
}
TreePop(); TreePop();
} }
// Details for Tables // Details for Tables
#ifdef IMGUI_HAS_TABLE if (TreeNode("Tables", "Tables (%d)", g.Tables.GetAliveCount()))
if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize()))
{ {
for (int n = 0; n < g.Tables.GetSize(); n++) for (int n = 0; n < g.Tables.GetMapSize(); n++)
DebugNodeTable(g.Tables.GetByIndex(n)); if (ImGuiTable* table = g.Tables.TryGetMapData(n))
DebugNodeTable(table);
TreePop(); TreePop();
} }
#endif // #ifdef IMGUI_HAS_TABLE
// Details for Fonts
#ifndef IMGUI_DISABLE_DEMO_WINDOWS
ImFontAtlas* atlas = g.IO.Fonts;
if (TreeNode("Fonts", "Fonts (%d)", atlas->Fonts.Size))
{
ShowFontAtlas(atlas);
TreePop();
}
#endif
// Details for Docking // Details for Docking
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
@ -11142,14 +11177,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
TreePop(); TreePop();
} }
#ifdef IMGUI_HAS_TABLE
if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
{ {
for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
DebugNodeTableSettings(settings); DebugNodeTableSettings(settings);
TreePop(); TreePop();
} }
#endif // #ifdef IMGUI_HAS_TABLE
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
#endif // #ifdef IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK
@ -11223,14 +11256,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
} }
#ifdef IMGUI_HAS_TABLE
// Overlay: Display Tables Rectangles // Overlay: Display Tables Rectangles
if (cfg->ShowTablesRects) if (cfg->ShowTablesRects)
{ {
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
{ {
ImGuiTable* table = g.Tables.GetByIndex(table_n); ImGuiTable* table = g.Tables.TryGetMapData(table_n);
if (table->LastFrameActive < g.FrameCount - 1) if (table == NULL || table->LastFrameActive < g.FrameCount - 1)
continue; continue;
ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow); ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
if (cfg->ShowTablesRectsType >= TRT_ColumnsRect) if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
@ -11250,7 +11282,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
} }
} }
#endif // #ifdef IMGUI_HAS_TABLE
#ifdef IMGUI_HAS_DOCK #ifdef IMGUI_HAS_DOCK
// Overlay: Display Docking info // Overlay: Display Docking info
@ -11262,6 +11293,25 @@ void ImGui::ShowMetricsWindow(bool* p_open)
End(); End();
} }
// [DEBUG] List fonts in a font atlas and display its texture
void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
{
for (int i = 0; i < atlas->Fonts.Size; i++)
{
ImFont* font = atlas->Fonts[i];
PushID(font);
DebugNodeFont(font);
PopID();
}
if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
{
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
TreePop();
}
}
// [DEBUG] Display contents of Columns // [DEBUG] Display contents of Columns
void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
{ {
@ -11396,6 +11446,102 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
out_draw_list->Flags = backup_flags; out_draw_list->Flags = backup_flags;
} }
// [DEBUG] Display details for a single font, called by ShowStyleEditor().
void ImGui::DebugNodeFont(ImFont* font)
{
bool opened = TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
SameLine();
if (SmallButton("Set as default"))
GetIO().FontDefault = font;
if (!opened)
return;
// Display preview text
PushFont(font);
Text("The quick brown fox jumps over the lazy dog");
PopFont();
// Display details
SetNextItemWidth(GetFontSize() * 8);
DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");
SameLine(); MetricsHelpMarker(
"Note than the default embedded font is NOT meant to be scaled.\n\n"
"Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
"You may oversample them to get some flexibility with scaling. "
"You can also render at multiple sizes and select which one to use at runtime.\n\n"
"(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
char c_str[5];
Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface);
Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
if (font->ConfigData)
if (const ImFontConfig* cfg = &font->ConfigData[config_i])
BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
// Display all glyphs of the fonts in separate pages of 256 characters
if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
{
ImDrawList* draw_list = GetWindowDrawList();
const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
const float cell_size = font->FontSize * 1;
const float cell_spacing = GetStyle().ItemSpacing.y;
for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
{
// Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)
// This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT
// is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)
if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
{
base += 4096 - 256;
continue;
}
int count = 0;
for (unsigned int n = 0; n < 256; n++)
if (font->FindGlyphNoFallback((ImWchar)(base + n)))
count++;
if (count <= 0)
continue;
if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
continue;
// Draw a 16x16 grid of glyphs
ImVec2 base_pos = GetCursorScreenPos();
for (unsigned int n = 0; n < 256; n++)
{
// We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions
// available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.
ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
if (glyph)
font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
if (glyph && IsMouseHoveringRect(cell_p1, cell_p2))
{
BeginTooltip();
Text("Codepoint: U+%04X", base + n);
Separator();
Text("Visible: %d", glyph->Visible);
Text("AdvanceX: %.1f", glyph->AdvanceX);
Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
EndTooltip();
}
}
Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
TreePop();
}
TreePop();
}
TreePop();
}
// [DEBUG] Display contents of ImGuiStorage // [DEBUG] Display contents of ImGuiStorage
void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label) void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
{ {
@ -11420,7 +11566,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
IM_UNUSED(p); IM_UNUSED(p);
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
bool open = TreeNode(tab_bar, "%s", buf); bool open = TreeNode(label, "%s", buf);
if (!is_active) { PopStyleColor(); } if (!is_active) { PopStyleColor(); }
if (is_active && IsItemHovered()) if (is_active && IsItemHovered())
{ {
@ -11546,9 +11692,11 @@ void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* la
#else #else
void ImGui::ShowMetricsWindow(bool*) {} void ImGui::ShowMetricsWindow(bool*) {}
void ImGui::ShowFontAtlas(ImFontAtlas*) {}
void ImGui::DebugNodeColumns(ImGuiOldColumns*) {} void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {} void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {}
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {} void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
void ImGui::DebugNodeFont(ImFont*) {}
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {} void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (headers) // (headers)
// Help: // Help:
@ -60,8 +60,8 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.83 WIP" #define IMGUI_VERSION "1.84 WIP"
#define IMGUI_VERSION_NUM 18209 #define IMGUI_VERSION_NUM 18304
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
@ -89,12 +89,12 @@ Index of this file:
#endif #endif
// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__clang__) #if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__)
#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1)))
#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
#elif !defined(IMGUI_USE_STB_SPRINTF) && defined(__GNUC__) && defined(__MINGW32__)
#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1)))
#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) #define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0)))
#elif !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__))
#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1)))
#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
#else #else
#define IM_FMTARGS(FMT) #define IM_FMTARGS(FMT)
#define IM_FMTLIST(FMT) #define IM_FMTLIST(FMT)
@ -1864,7 +1864,7 @@ struct ImGuiIO
bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving! bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events). bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
float Framerate; // Application framerate estimate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames. float Framerate; // Rough estimate of application framerate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames.
int MetricsRenderVertices; // Vertices output during last call to Render() int MetricsRenderVertices; // Vertices output during last call to Render()
int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
int MetricsRenderWindows; // Number of visible windows int MetricsRenderWindows; // Number of visible windows
@ -2243,6 +2243,9 @@ struct ImDrawCmd
void* UserCallbackData; // 4-8 // The draw callback code can access this. void* UserCallbackData; // 4-8 // The draw callback code can access this.
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)
inline ImTextureID GetTexID() const { return TextureId; }
}; };
// Vertex index, default to 16-bit // Vertex index, default to 16-bit

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (drawing and font code) // (drawing and font code)
/* /*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@ -63,7 +63,9 @@ Index of this file:
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) #pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
#pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer) #pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6). #pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
#endif
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -130,10 +132,11 @@ struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
struct ImGuiTable; // Storage for a table struct ImGuiTable; // Storage for a table
struct ImGuiTableColumn; // Storage for one column of a table struct ImGuiTableColumn; // Storage for one column of a table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiWindow; // Storage for one window struct ImGuiWindow; // Storage for one window
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame) struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
@ -321,12 +324,13 @@ static inline bool ImCharIsBlankA(char c) { return c == ' ' || c =
static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
// Helpers: UTF-8 <> wchar conversions // Helpers: UTF-8 <> wchar conversions
IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf
IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count IMGUI_API int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count
IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
// Helpers: ImVec2/ImVec4 operators // Helpers: ImVec2/ImVec4 operators
// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.) // We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
@ -608,20 +612,30 @@ struct IMGUI_API ImPool
ImVector<T> Buf; // Contiguous data ImVector<T> Buf; // Contiguous data
ImGuiStorage Map; // ID->Index ImGuiStorage Map; // ID->Index
ImPoolIdx FreeIdx; // Next free idx to use ImPoolIdx FreeIdx; // Next free idx to use
ImPoolIdx AliveCount; // Number of active/alive items (for display purpose)
ImPool() { FreeIdx = 0; } ImPool() { FreeIdx = AliveCount = 0; }
~ImPool() { Clear(); } ~ImPool() { Clear(); }
T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; } T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; }
T* GetByIndex(ImPoolIdx n) { return &Buf[n]; } T* GetByIndex(ImPoolIdx n) { return &Buf[n]; }
ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); } ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); }
T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); } T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); }
bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); } bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); }
void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = 0; } void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = AliveCount = 0; }
T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); return &Buf[idx]; } T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); AliveCount++; return &Buf[idx]; }
void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); } void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); }
void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); } void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); AliveCount--; }
void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); } void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); }
int GetSize() const { return Buf.Size; }
// To iterate a ImPool: for (int n = 0; n < pool.GetMapSize(); n++) if (T* t = pool.TryGetMapData(n)) { ... }
// Can be avoided if you know .Remove() has never been called on the pool, or AliveCount == GetMapSize()
int GetAliveCount() const { return AliveCount; } // Number of active/alive items in the pool (for display purpose)
int GetBufSize() const { return Buf.Size; }
int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere
T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
int GetSize() { return GetMapSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18304)
#endif
}; };
// Helper: ImChunkStream<> // Helper: ImChunkStream<>
@ -1028,7 +1042,7 @@ struct IMGUI_API ImGuiInputTextState
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool Edited; // edited this frame bool Edited; // edited this frame
ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback ImGuiInputTextFlags Flags; // copy of InputText() flags
ImGuiInputTextCallback UserCallback; // " ImGuiInputTextCallback UserCallback; // "
void* UserCallbackData; // " void* UserCallbackData; // "
@ -1516,8 +1530,9 @@ struct ImGuiContext
// Table // Table
ImGuiTable* CurrentTable; ImGuiTable* CurrentTable;
int CurrentTableStackIdx;
ImPool<ImGuiTable> Tables; ImPool<ImGuiTable> Tables;
ImVector<ImGuiPtrOrIndex> CurrentTableStack; ImVector<ImGuiTableTempData> TablesTempDataStack;
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC) ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer; ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
@ -1584,6 +1599,7 @@ struct ImGuiContext
// Misc // Misc
float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds.
int FramerateSecPerFrameIdx; int FramerateSecPerFrameIdx;
int FramerateSecPerFrameCount;
float FramerateSecPerFrameAccum; float FramerateSecPerFrameAccum;
int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags
int WantCaptureKeyboardNextFrame; int WantCaptureKeyboardNextFrame;
@ -1694,6 +1710,7 @@ struct ImGuiContext
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
CurrentTable = NULL; CurrentTable = NULL;
CurrentTableStackIdx = -1;
CurrentTabBar = NULL; CurrentTabBar = NULL;
LastValidMousePos = ImVec2(0.0f, 0.0f); LastValidMousePos = ImVec2(0.0f, 0.0f);
@ -1730,7 +1747,7 @@ struct ImGuiContext
DebugItemPickerBreakId = 0; DebugItemPickerBreakId = 0;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = 0; FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
FramerateSecPerFrameAccum = 0.0f; FramerateSecPerFrameAccum = 0.0f;
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
memset(TempBuffer, 0, sizeof(TempBuffer)); memset(TempBuffer, 0, sizeof(TempBuffer));
@ -1945,7 +1962,7 @@ enum ImGuiTabItemFlagsPrivate_
ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button
}; };
// Storage for one active tab item (sizeof() 28~32 bytes) // Storage for one active tab item (sizeof() 40 bytes)
struct ImGuiTabItem struct ImGuiTabItem
{ {
ImGuiID ID; ImGuiID ID;
@ -1955,12 +1972,12 @@ struct ImGuiTabItem
float Offset; // Position relative to beginning of tab float Offset; // Position relative to beginning of tab
float Width; // Width currently displayed float Width; // Width currently displayed
float ContentWidth; // Width of label, stored during BeginTabItem() call float ContentWidth; // Width of label, stored during BeginTabItem() call
ImS16 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
ImS16 IndexDuringLayout; // Index only used during TabBarLayout() ImS16 IndexDuringLayout; // Index only used during TabBarLayout()
bool WantClose; // Marked as closed by SetTabItemClosed() bool WantClose; // Marked as closed by SetTabItemClosed()
ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = BeginOrder = IndexDuringLayout = -1; } ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
}; };
// Storage for a tab bar (sizeof() 152 bytes) // Storage for a tab bar (sizeof() 152 bytes)
@ -2002,7 +2019,7 @@ struct ImGuiTabBar
int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); } int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); }
const char* GetTabName(const ImGuiTabItem* tab) const const char* GetTabName(const ImGuiTabItem* tab) const
{ {
IM_ASSERT(tab->NameOffset != -1 && (int)tab->NameOffset < TabsNames.Buf.Size); IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < TabsNames.Buf.Size);
return TabsNames.Buf.Data + tab->NameOffset; return TabsNames.Buf.Data + tab->NameOffset;
} }
}; };
@ -2011,8 +2028,6 @@ struct ImGuiTabBar
// [SECTION] Table support // [SECTION] Table support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef IMGUI_HAS_TABLE
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color. #define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64. #define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels() #define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels()
@ -2089,12 +2104,13 @@ struct ImGuiTableCellData
ImGuiTableColumnIdx Column; // Column number ImGuiTableColumnIdx Column; // Column number
}; };
// FIXME-TABLE: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData // FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
struct ImGuiTable struct ImGuiTable
{ {
ImGuiID ID; ImGuiID ID;
ImGuiTableFlags Flags; ImGuiTableFlags Flags;
void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[]
ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[]
ImSpan<ImGuiTableColumn> Columns; // Point within RawData[] ImSpan<ImGuiTableColumn> Columns; // Point within RawData[]
ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1)
ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row. ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row.
@ -2146,22 +2162,11 @@ struct ImGuiTable
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect. ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window. ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground() ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
ImGuiWindow* OuterWindow; // Parent window for the table ImGuiWindow* OuterWindow; // Parent window for the table
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table) ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would work be good.
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
ImGuiTableColumnIdx SortSpecsCount; ImGuiTableColumnIdx SortSpecsCount;
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
@ -2208,6 +2213,32 @@ struct ImGuiTable
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); } IMGUI_API ~ImGuiTable() { IM_FREE(RawData); }
}; };
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// FIXME-TABLE: more transient data could be stored here: DrawSplitter, incoming RowData?
struct ImGuiTableTempData
{
int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImDrawListSplitter DrawSplitter;
ImGuiTableColumnSortSpecs SortSpecsSingle;
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
};
// sizeof() ~ 12 // sizeof() ~ 12
struct ImGuiTableColumnSettings struct ImGuiTableColumnSettings
{ {
@ -2246,8 +2277,6 @@ struct ImGuiTableSettings
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); } ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
}; };
#endif // #ifdef IMGUI_HAS_TABLE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImGui internal API // [SECTION] ImGui internal API
// No guarantee of forward compatibility here! // No guarantee of forward compatibility here!
@ -2269,7 +2298,6 @@ namespace ImGui
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window);
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
@ -2377,11 +2405,15 @@ namespace ImGui
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
// Combos
IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);
// Gamepad/Keyboard Navigation // Gamepad/Keyboard Navigation
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
IMGUI_API bool NavMoveRequestButNoResultYet(); IMGUI_API bool NavMoveRequestButNoResultYet();
@ -2470,6 +2502,7 @@ namespace ImGui
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
IMGUI_API void TableRemove(ImGuiTable* table); IMGUI_API void TableRemove(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table); IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
IMGUI_API void TableGcCompactSettings(); IMGUI_API void TableGcCompactSettings();
// Tables: Settings // Tables: Settings
@ -2596,9 +2629,11 @@ namespace ImGui
inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); }
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
IMGUI_API void DebugNodeFont(ImFont* font);
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
IMGUI_API void DebugNodeTable(ImGuiTable* table); IMGUI_API void DebugNodeTable(ImGuiTable* table);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (tables and columns code) // (tables and columns code)
/* /*
@ -343,6 +343,16 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (instance_no > 0) if (instance_no > 0)
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
// Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table);
g.CurrentTableStackIdx++;
if (g.CurrentTableStackIdx + 1 > g.TablesTempDataStack.Size)
g.TablesTempDataStack.resize(g.CurrentTableStackIdx + 1, ImGuiTableTempData());
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempDataStack[g.CurrentTableStackIdx];
temp_data->TableIndex = table_idx;
table->DrawSplitter = &table->TempData->DrawSplitter;
table->DrawSplitter->Clear();
// Fix flags // Fix flags
table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0; table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0;
flags = TableFixFlags(flags, outer_window); flags = TableFixFlags(flags, outer_window);
@ -356,7 +366,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->ColumnsCount = columns_count; table->ColumnsCount = columns_count;
table->IsLayoutLocked = false; table->IsLayoutLocked = false;
table->InnerWidth = inner_width; table->InnerWidth = inner_width;
table->UserOuterSize = outer_size; temp_data->UserOuterSize = outer_size;
// When not using a child window, WorkRect.Max will grow as we append contents. // When not using a child window, WorkRect.Max will grow as we append contents.
if (use_child_window) if (use_child_window)
@ -405,14 +415,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->HostIndentX = inner_window->DC.Indent.x; table->HostIndentX = inner_window->DC.Indent.x;
table->HostClipRect = inner_window->ClipRect; table->HostClipRect = inner_window->ClipRect;
table->HostSkipItems = inner_window->SkipItems; table->HostSkipItems = inner_window->SkipItems;
table->HostBackupWorkRect = inner_window->WorkRect; temp_data->HostBackupWorkRect = inner_window->WorkRect;
table->HostBackupParentWorkRect = inner_window->ParentWorkRect; temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
table->HostBackupPrevLineSize = inner_window->DC.PrevLineSize; temp_data->HostBackupPrevLineSize = inner_window->DC.PrevLineSize;
table->HostBackupCurrLineSize = inner_window->DC.CurrLineSize; temp_data->HostBackupCurrLineSize = inner_window->DC.CurrLineSize;
table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos; temp_data->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
table->HostBackupItemWidth = outer_window->DC.ItemWidth; temp_data->HostBackupItemWidth = outer_window->DC.ItemWidth;
table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
// Padding and Spacing // Padding and Spacing
@ -455,8 +465,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
// Make table current // Make table current
const int table_idx = g.Tables.GetIndex(table);
g.CurrentTableStack.push_back(ImGuiPtrOrIndex(table_idx));
g.CurrentTable = table; g.CurrentTable = table;
outer_window->DC.CurrentTableIdx = table_idx; outer_window->DC.CurrentTableIdx = table_idx;
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
@ -469,6 +477,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (table_idx >= g.TablesLastTimeActive.Size) if (table_idx >= g.TablesLastTimeActive.Size)
g.TablesLastTimeActive.resize(table_idx + 1, -1.0f); g.TablesLastTimeActive.resize(table_idx + 1, -1.0f);
g.TablesLastTimeActive[table_idx] = (float)g.Time; g.TablesLastTimeActive[table_idx] = (float)g.Time;
temp_data->LastTimeActive = (float)g.Time;
table->MemoryCompacted = false; table->MemoryCompacted = false;
// Setup memory buffer (clear data if columns count changed) // Setup memory buffer (clear data if columns count changed)
@ -1117,7 +1126,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Initial state // Initial state
ImGuiWindow* inner_window = table->InnerWindow; ImGuiWindow* inner_window = table->InnerWindow;
if (table->Flags & ImGuiTableFlags_NoClip) if (table->Flags & ImGuiTableFlags_NoClip)
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
else else
inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false);
} }
@ -1205,6 +1214,7 @@ void ImGui::EndTable()
const ImGuiTableFlags flags = table->Flags; const ImGuiTableFlags flags = table->Flags;
ImGuiWindow* inner_window = table->InnerWindow; ImGuiWindow* inner_window = table->InnerWindow;
ImGuiWindow* outer_window = table->OuterWindow; ImGuiWindow* outer_window = table->OuterWindow;
ImGuiTableTempData* temp_data = table->TempData;
IM_ASSERT(inner_window == g.CurrentWindow); IM_ASSERT(inner_window == g.CurrentWindow);
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
@ -1217,9 +1227,9 @@ void ImGui::EndTable()
TableOpenContextMenu((int)table->HoveredColumnBody); TableOpenContextMenu((int)table->HoveredColumnBody);
// Finalize table height // Finalize table height
inner_window->DC.PrevLineSize = table->HostBackupPrevLineSize; inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
inner_window->DC.CurrLineSize = table->HostBackupCurrLineSize; inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
inner_window->DC.CursorMaxPos = table->HostBackupCursorMaxPos; inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
const float inner_content_max_y = table->RowPosY2; const float inner_content_max_y = table->RowPosY2;
IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y);
if (inner_window != outer_window) if (inner_window != outer_window)
@ -1266,10 +1276,11 @@ void ImGui::EndTable()
#endif #endif
// Flatten channels and merge draw calls // Flatten channels and merge draw calls
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0); ImDrawListSplitter* splitter = table->DrawSplitter;
splitter->SetCurrentChannel(inner_window->DrawList, 0);
if ((table->Flags & ImGuiTableFlags_NoClip) == 0) if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
TableMergeDrawChannels(table); TableMergeDrawChannels(table);
table->DrawSplitter.Merge(inner_window->DrawList); splitter->Merge(inner_window->DrawList);
// Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
@ -1311,18 +1322,18 @@ void ImGui::EndTable()
// Pop from id stack // Pop from id stack
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!"); IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
PopID(); PopID();
// Restore window data that we modified // Restore window data that we modified
const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos;
inner_window->WorkRect = table->HostBackupWorkRect; inner_window->WorkRect = temp_data->HostBackupWorkRect;
inner_window->ParentWorkRect = table->HostBackupParentWorkRect; inner_window->ParentWorkRect = temp_data->HostBackupParentWorkRect;
inner_window->SkipItems = table->HostSkipItems; inner_window->SkipItems = table->HostSkipItems;
outer_window->DC.CursorPos = table->OuterRect.Min; outer_window->DC.CursorPos = table->OuterRect.Min;
outer_window->DC.ItemWidth = table->HostBackupItemWidth; outer_window->DC.ItemWidth = temp_data->HostBackupItemWidth;
outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize; outer_window->DC.ItemWidthStack.Size = temp_data->HostBackupItemWidthStackSize;
outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset; outer_window->DC.ColumnsOffset = temp_data->HostBackupColumnsOffset;
// Layout in outer window // Layout in outer window
// (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding
@ -1345,20 +1356,20 @@ void ImGui::EndTable()
IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0); IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0);
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth);
} }
else if (table->UserOuterSize.x <= 0.0f) else if (temp_data->UserOuterSize.x <= 0.0f)
{ {
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f; const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f;
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - table->UserOuterSize.x); outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
} }
else else
{ {
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x);
} }
if (table->UserOuterSize.y <= 0.0f) if (temp_data->UserOuterSize.y <= 0.0f)
{ {
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f;
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - table->UserOuterSize.y); outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y));
} }
else else
@ -1374,8 +1385,15 @@ void ImGui::EndTable()
// Clear or restore current table, if any // Clear or restore current table, if any
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
g.CurrentTableStack.pop_back(); IM_ASSERT(g.CurrentTableStackIdx >= 0);
g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL; g.CurrentTableStackIdx--;
temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL;
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
if (g.CurrentTable)
{
g.CurrentTable->TempData = temp_data;
g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter;
}
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
} }
@ -1748,7 +1766,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here. // always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
if ((table->Flags & ImGuiTableFlags_NoClip) == 0) if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4(); window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4();
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0); table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
} }
// Draw row background // Draw row background
@ -1820,7 +1838,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent);
} }
if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) if (!(table->RowFlags & ImGuiTableRowFlags_Headers))
@ -1935,14 +1953,14 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
if (table->Flags & ImGuiTableFlags_NoClip) if (table->Flags & ImGuiTableFlags_NoClip)
{ {
// FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed. // FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
//IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP); //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP);
} }
else else
{ {
// FIXME-TABLE: Could avoid this if draw channel is dummy channel? // FIXME-TABLE: Could avoid this if draw channel is dummy channel?
SetWindowClipRectBeforeSetChannel(window, column->ClipRect); SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
} }
// Logging // Logging
@ -2190,7 +2208,7 @@ void ImGui::TablePushBackgroundChannel()
// Optimization: avoid SetCurrentChannel() + PushClipRect() // Optimization: avoid SetCurrentChannel() + PushClipRect()
table->HostBackupInnerClipRect = window->ClipRect; table->HostBackupInnerClipRect = window->ClipRect;
SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd); SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd);
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent); table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
} }
void ImGui::TablePopBackgroundChannel() void ImGui::TablePopBackgroundChannel()
@ -2202,7 +2220,7 @@ void ImGui::TablePopBackgroundChannel()
// Optimization: avoid PopClipRect() + SetCurrentChannel() // Optimization: avoid PopClipRect() + SetCurrentChannel()
SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect); SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
} }
// Allocate draw channels. Called by TableUpdateLayout() // Allocate draw channels. Called by TableUpdateLayout()
@ -2228,7 +2246,7 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
const int channels_for_bg = 1 + 1 * freeze_row_multiplier; const int channels_for_bg = 1 + 1 * freeze_row_multiplier;
const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0; const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0;
const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy;
table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total); table->DrawSplitter->Split(table->InnerWindow->DrawList, channels_total);
table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1); table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1);
table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN; table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN;
table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN); table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN);
@ -2292,7 +2310,7 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
void ImGui::TableMergeDrawChannels(ImGuiTable* table) void ImGui::TableMergeDrawChannels(ImGuiTable* table)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImDrawListSplitter* splitter = &table->DrawSplitter; ImDrawListSplitter* splitter = table->DrawSplitter;
const bool has_freeze_v = (table->FreezeRowsCount > 0); const bool has_freeze_v = (table->FreezeRowsCount > 0);
const bool has_freeze_h = (table->FreezeColumnsCount > 0); const bool has_freeze_h = (table->FreezeColumnsCount > 0);
IM_ASSERT(splitter->_Current == 0); IM_ASSERT(splitter->_Current == 0);
@ -2463,7 +2481,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
return; return;
ImDrawList* inner_drawlist = inner_window->DrawList; ImDrawList* inner_drawlist = inner_window->DrawList;
table->DrawSplitter.SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0); table->DrawSplitter->SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0);
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
// Draw inner border and resizing feedback // Draw inner border and resizing feedback
@ -2723,8 +2741,9 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
TableSortSpecsSanitize(table); TableSortSpecsSanitize(table);
// Write output // Write output
table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount); ImGuiTableTempData* temp_data = table->TempData;
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; temp_data->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &temp_data->SortSpecsSingle : temp_data->SortSpecsMulti.Data;
if (sort_specs != NULL) if (sort_specs != NULL)
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
@ -3279,8 +3298,9 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Tables.GetSize(); i++) for (int i = 0; i != g.Tables.GetMapSize(); i++)
g.Tables.GetByIndex(i)->SettingsOffset = -1; if (ImGuiTable* table = g.Tables.TryGetMapData(i))
table->SettingsOffset = -1;
g.SettingsTables.clear(); g.SettingsTables.clear();
} }
@ -3288,12 +3308,12 @@ static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandle
static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Tables.GetSize(); i++) for (int i = 0; i != g.Tables.GetMapSize(); i++)
{ if (ImGuiTable* table = g.Tables.TryGetMapData(i))
ImGuiTable* table = g.Tables.GetByIndex(i); {
table->IsSettingsRequestLoad = true; table->IsSettingsRequestLoad = true;
table->SettingsOffset = -1; table->SettingsOffset = -1;
} }
} }
static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
@ -3422,8 +3442,6 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
//IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID); //IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(table->MemoryCompacted == false); IM_ASSERT(table->MemoryCompacted == false);
table->DrawSplitter.ClearFreeMemory();
table->SortSpecsMulti.clear();
table->SortSpecs.Specs = NULL; table->SortSpecs.Specs = NULL;
table->IsSortSpecsDirty = true; table->IsSortSpecsDirty = true;
table->ColumnsNames.clear(); table->ColumnsNames.clear();
@ -3433,6 +3451,13 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f; g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f;
} }
void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
{
temp_data->DrawSplitter.ClearFreeMemory();
temp_data->SortSpecsMulti.clear();
temp_data->LastTimeActive = -1.0f;
}
// Compact and remove unused settings data (currently only used by TestEngine) // Compact and remove unused settings data (currently only used by TestEngine)
void ImGui::TableGcCompactSettings() void ImGui::TableGcCompactSettings()
{ {

View File

@ -1,4 +1,4 @@
// dear imgui, v1.83 WIP // dear imgui, v1.84 WIP
// (widgets code) // (widgets code)
/* /*
@ -1537,7 +1537,9 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// [SECTION] Widgets: ComboBox // [SECTION] Widgets: ComboBox
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// - CalcMaxPopupHeightFromItemCount() [Internal]
// - BeginCombo() // - BeginCombo()
// - BeginComboPopup() [Internal]
// - EndCombo() // - EndCombo()
// - Combo() // - Combo()
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -1552,79 +1554,91 @@ static float CalcMaxPopupHeightFromItemCount(int items_count)
bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
{ {
// Always consume the SetNextWindowSizeConstraint() call in our early return paths
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;
g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags;
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
if (window->SkipItems) if (window->SkipItems)
return false; return false;
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float expected_w = CalcItemWidth(); const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb)) if (!ItemAdd(total_bb, id, &bb))
return false; return false;
// Open on click
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); bool pressed = ButtonBehavior(bb, id, &hovered, &held);
bool popup_open = IsPopupOpen(id, ImGuiPopupFlags_None); const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
if ((pressed || g.NavActivateId == id) && !popup_open)
{
OpenPopupEx(popup_id, ImGuiPopupFlags_None);
popup_open = true;
}
// Render shape
const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size); const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
RenderNavHighlight(frame_bb, id); RenderNavHighlight(bb, id);
if (!(flags & ImGuiComboFlags_NoPreview)) if (!(flags & ImGuiComboFlags_NoPreview))
window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
if (!(flags & ImGuiComboFlags_NoArrowButton)) if (!(flags & ImGuiComboFlags_NoArrowButton))
{ {
ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text); ImU32 text_col = GetColorU32(ImGuiCol_Text);
window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x) if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x)
RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
} }
RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
// Render preview and label
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
{ {
ImVec2 preview_pos = frame_bb.Min + style.FramePadding;
if (g.LogEnabled) if (g.LogEnabled)
LogSetNextTextDecoration("{", "}"); LogSetNextTextDecoration("{", "}");
RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f)); RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
} }
if (label_size.x > 0) if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);
if ((pressed || g.NavActivateId == id) && !popup_open)
{
if (window->DC.NavLayerCurrent == 0)
window->NavLastIds[0] = id;
OpenPopupEx(id, ImGuiPopupFlags_None);
popup_open = true;
}
if (!popup_open) if (!popup_open)
return false; return false;
if (has_window_size_constraint) g.NextWindowData.Flags = backup_next_window_data_flags;
return BeginComboPopup(popup_id, bb, flags);
}
bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags)
{
ImGuiContext& g = *GImGui;
if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None))
{
g.NextWindowData.ClearFlags();
return false;
}
// Set popup size
float w = bb.GetWidth();
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
{ {
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
} }
else else
{ {
if ((flags & ImGuiComboFlags_HeightMask_) == 0) if ((flags & ImGuiComboFlags_HeightMask_) == 0)
flags |= ImGuiComboFlags_HeightRegular; flags |= ImGuiComboFlags_HeightRegular;
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
int popup_max_height_in_items = -1; int popup_max_height_in_items = -1;
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
@ -1632,30 +1646,27 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
} }
// This is essentially a specialized version of BeginPopupEx()
char name[16]; char name[16];
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
// Position the window given a custom constraint (peak into expected window size so we can position it) // Set position given a custom constraint (peak into expected window size so we can position it)
// This might be easier to express with an hypothetical SetNextWindowPosConstraints() function. // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?
// FIXME: This might be moved to Begin() or at least around the same spot where Tooltips and other Popups are calling FindBestWindowPosForPopupEx()?
if (ImGuiWindow* popup_window = FindWindowByName(name)) if (ImGuiWindow* popup_window = FindWindowByName(name))
if (popup_window->WasActive) if (popup_window->WasActive)
{ {
// Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us. // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us.
ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window); ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window);
if (flags & ImGuiComboFlags_PopupAlignLeft) popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down; // Left = "Below, Toward Left", Down = "Below, Toward Right (default)"
popup_window->AutoPosLastDirection = ImGuiDir_Left; // "Below, Toward Left" ImRect r_outer = GetPopupAllowedExtentRect(popup_window);
else ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox);
popup_window->AutoPosLastDirection = ImGuiDir_Down; // "Below, Toward Right (default)"
ImRect r_outer = GetWindowAllowedExtentRect(popup_window);
ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
SetNextWindowPos(pos); SetNextWindowPos(pos);
} }
// We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx()
ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text
// Horizontally align ourselves with the framed text
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y));
bool ret = Begin(name, NULL, window_flags); bool ret = Begin(name, NULL, window_flags);
PopStyleVar(); PopStyleVar();
if (!ret) if (!ret)
@ -3579,12 +3590,12 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t
namespace ImStb namespace ImStb
{ {
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; } static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; }
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; } static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { return obj->TextW[idx]; }
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; } static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx) static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
{ {
const ImWchar* text = obj->TextW.Data; const ImWchar* text = obj->TextW.Data;
const ImWchar* text_remaining = NULL; const ImWchar* text_remaining = NULL;
@ -3597,19 +3608,20 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
r->num_chars = (int)(text_remaining - (text + line_start_idx)); r->num_chars = (int)(text_remaining - (text + line_start_idx));
} }
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; } static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
#ifdef __APPLE__ // FIXME: Move setting to IO structure #ifdef __APPLE__ // FIXME: Move setting to IO structure
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; } static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#else #else
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#endif #endif
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
{ {
ImWchar* dst = obj->TextW.Data + pos; ImWchar* dst = obj->TextW.Data + pos;
@ -3625,9 +3637,9 @@ static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
*dst = '\0'; *dst = '\0';
} }
static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len) static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len)
{ {
const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0; const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
const int text_len = obj->CurLenW; const int text_len = obj->CurLenW;
IM_ASSERT(pos <= text_len); IM_ASSERT(pos <= text_len);
@ -3681,7 +3693,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im
// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling // stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling
// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?) // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
static void stb_textedit_replace(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len) static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len)
{ {
stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len); stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW); ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
@ -4067,7 +4079,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
backup_current_text_length = state->CurLenA; backup_current_text_length = state->CurLenA;
state->Edited = false; state->Edited = false;
state->BufCapacityA = buf_size; state->BufCapacityA = buf_size;
state->UserFlags = flags; state->Flags = flags;
state->UserCallback = callback; state->UserCallback = callback;
state->UserCallbackData = callback_user_data; state->UserCallbackData = callback_user_data;
@ -4420,7 +4432,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
// Clear temporary user storage // Clear temporary user storage
state->UserFlags = 0; state->Flags = ImGuiInputTextFlags_None;
state->UserCallback = NULL; state->UserCallback = NULL;
state->UserCallbackData = NULL; state->UserCallbackData = NULL;
} }
@ -6297,7 +6309,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v
// Plot/Graph widgets are not very good. // Plot/Graph widgets are not very good.
// Consider writing your own, or using a third-party one, see: // Consider writing your own, or using a third-party one, see:
// - ImPlot https://github.com/epezent/implot // - ImPlot https://github.com/epezent/implot
// - others https://github.com/ocornut/imgui/wiki/Useful-Widgets // - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size) int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
@ -6882,11 +6894,11 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{ {
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
// Note that in this situation we render neither the shortcut neither the selected tick mark // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
float w = label_size.x; float w = label_size.x;
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); pressed = Selectable(label, selected, flags, ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
} }
@ -7762,7 +7774,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
tab->Flags = flags; tab->Flags = flags;
// Append name with zero-terminator // Append name with zero-terminator
tab->NameOffset = (ImS16)tab_bar->TabsNames.size(); tab->NameOffset = (ImS32)tab_bar->TabsNames.size();
tab_bar->TabsNames.append(label, label + strlen(label) + 1); tab_bar->TabsNames.append(label, label + strlen(label) + 1);
// Update selected tab // Update selected tab

View File

@ -7,12 +7,15 @@
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. // 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer. // 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
@ -143,6 +146,11 @@ using namespace gl;
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif #endif
// Desktop GL use extension detection
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#endif
// OpenGL Data // OpenGL Data
static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings. static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings.
@ -151,6 +159,7 @@ static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location
static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
static bool g_HasClipOrigin = false;
// Functions // Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
@ -230,6 +239,19 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
GLint current_texture; GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support
g_HasClipOrigin = (g_GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++)
{
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (extension != NULL && strcmp(extension, "GL_ARB_clip_control") == 0)
g_HasClipOrigin = true;
}
#endif
return true; return true;
} }
@ -266,7 +288,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
#if defined(GL_CLIP_ORIGIN) #if defined(GL_CLIP_ORIGIN)
bool clip_origin_lower_left = true; bool clip_origin_lower_left = true;
if (g_GlVersion >= 450) if (g_HasClipOrigin)
{ {
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin); GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT) if (current_clip_origin == GL_UPPER_LEFT)
@ -408,7 +430,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
// Bind texture, Draw // Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (g_GlVersion >= 320) if (g_GlVersion >= 320)
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);

View File

@ -7,7 +7,8 @@
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -5,12 +5,14 @@
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer. // 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData(). // 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
@ -236,7 +238,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw // Bind texture, Draw
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->TextureId; ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
} }

View File

@ -5,7 +5,8 @@
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -5,12 +5,14 @@
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. // 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). // 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. // 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
@ -246,7 +248,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw // Bind texture, Draw
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
} }

View File

@ -5,7 +5,8 @@
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -9,12 +9,14 @@
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. // This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer. // 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. // 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning. // 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
@ -237,7 +239,9 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
if (r.right > r.left && r.bottom > r.top) if (r.right > r.left && r.bottom > r.top)
{ {
ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId); D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {};
texture_handle.ptr = (UINT64)(intptr_t)pcmd->GetTexID();
ctx->SetGraphicsRootDescriptorTable(1, texture_handle);
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
} }

View File

@ -9,7 +9,8 @@
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. // This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -5,12 +5,14 @@
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states. // 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857). // 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file. // 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
@ -226,7 +228,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
else else
{ {
const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId; const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
g_pd3dDevice->SetTexture(0, texture); g_pd3dDevice->SetTexture(0, texture);
g_pd3dDevice->SetScissorRect(&r); g_pd3dDevice->SetScissorRect(&r);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3); g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);

View File

@ -5,7 +5,8 @@
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -7,7 +7,8 @@
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs

View File

@ -7,7 +7,8 @@
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs