Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_demo.cpp
This commit is contained in:
ocornut 2023-09-04 14:59:59 +02:00
commit a1b60fc1f5
10 changed files with 314 additions and 290 deletions

View File

@ -42,10 +42,14 @@ HOW TO UPDATE?
Breaking changes: Breaking changes:
- Clipper: Renamed IncludeRangeByIndices(), also called ForceDisplayRangeByIndices()
before 1.89.6, to IncludeItemsByIndex(). Kept inline redirection function. (#6424, #3841)
Other changes: Other changes:
- Tables: Made it possible to use SameLine(0,0) after TableNextColumn() or - Tables: Made it possible to use SameLine(0,0) after TableNextColumn() or
TableSetColumnIndex() in order to reuse line height from previous cell. (#3740) TableSetColumnIndex() in order to reuse line pos/height from previous cell. (#3740)
- Tables: Made it possible to change style.CellPadding.y between rows. (#3740)
- Nav, TreeNode: Pressing Left with ImGuiTreeNodeFlags_NavLeftJumpsBackHere now goes - Nav, TreeNode: Pressing Left with ImGuiTreeNodeFlags_NavLeftJumpsBackHere now goes
through proper navigation logic: honor scrolling and selection. (#1079, #1131) through proper navigation logic: honor scrolling and selection. (#1079, #1131)
- Sliders: Fixed an integer overflow and div-by-zero in SliderInt() when - Sliders: Fixed an integer overflow and div-by-zero in SliderInt() when
@ -55,8 +59,14 @@ Other changes:
setting large values. (#6749) setting large values. (#6749)
- InputFloat, SliderFloat, DragFloat: always turn both '.' and ',' into the current decimal - InputFloat, SliderFloat, DragFloat: always turn both '.' and ',' into the current decimal
point character when using Decimal/Scientific character filter. (#6719, #2278) [@adamsepp] point character when using Decimal/Scientific character filter. (#6719, #2278) [@adamsepp]
- ColorEdit, ColorPicker: Manipulating options popup don't mark item as edited. (#6722)
(Note that they may still be marked as Active/Hovered.)
- Clipper: Added IncludeItemByIndex() helper to include a single item. (#6424, #3841)
- Clipper: Fixed a bug if attempt to force-include a range which matches an already
included range, clipper would end earlier. (#3841)
- ImDrawData: Fixed an issue where TotalVtxCount/TotalIdxCount does not match the sum - ImDrawData: Fixed an issue where TotalVtxCount/TotalIdxCount does not match the sum
of individual ImDrawList's buffer sizes when a dimming/modal background is rendered. (#6716) of individual ImDrawList's buffer sizes when a dimming/modal background is rendered. (#6716)
- ImDrawList: Automatically calling ChannelsMerge() if not done after a split.
- ImDrawList: Fixed OOB access in _CalcCircleAutoSegmentCount when passing excessively - ImDrawList: Fixed OOB access in _CalcCircleAutoSegmentCount when passing excessively
large radius to AddCircle(). (#6657, #5317) [@EggsyCRO, @jdpatdiscord] large radius to AddCircle(). (#6657, #5317) [@EggsyCRO, @jdpatdiscord]
- IO: Exposed io.PlatformLocaleDecimalPoint to configure decimal point ('.' or ',') for - IO: Exposed io.PlatformLocaleDecimalPoint to configure decimal point ('.' or ',') for
@ -68,10 +78,15 @@ Other changes:
- Misc: Made multiple calls to Render() during the same frame early out faster. - Misc: Made multiple calls to Render() during the same frame early out faster.
- Debug Tools: Metrics: Fixed "Drawlists" section and per-viewport equivalent - Debug Tools: Metrics: Fixed "Drawlists" section and per-viewport equivalent
appearing empty (regression in 1.89.8). appearing empty (regression in 1.89.8).
- Demo: Demonstrate out-of-order rendering using ImDrawListSplitter. - Demo: Reorganized "Examples" menu.
- Demo: Tables: Demonstrate using SameLine() between cells. (#3740)
- Demo: Tables: Demonstrate altering CellPadding.y between rows. (#3740)
- Demo: Custom Rendering: Demonstrate out-of-order rendering using ImDrawListSplitter.
- Backends: SDL2,SDL3: added ImGui_ImplSDL2_InitForOther()/ImGui_ImplSDL3_InitForOther() - Backends: SDL2,SDL3: added ImGui_ImplSDL2_InitForOther()/ImGui_ImplSDL3_InitForOther()
for consistency (matching GLFW backend) and as most initialization paths don't actually for consistency (matching GLFW backend) and as most initialization paths don't actually
need to care about rendering backend. need to care about rendering backend.
- Examples: Emscripten+WebGPU: Fixed WGPUInstance creation process + use preferred
framebuffer format. (#6640, #6748) [@smileorigin]
Docking+Viewports Branch: Docking+Viewports Branch:

View File

@ -39,9 +39,11 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
### Usage ### Usage
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project. See [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started). **The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project.
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. See the [Integration](#integration) section of this document for details. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. **Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide and [Integration](#integration) section of this document for more details.
After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop: After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop:
```cpp ```cpp
@ -114,9 +116,11 @@ The demo applications are not DPI aware so expect some blurriness on a 4K screen
### Integration ### Integration
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so. On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
See [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started). Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) it should in theory takes you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!** Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide it should in theory takes you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
Officially maintained backends/bindings (in repository): Officially maintained backends/bindings (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU. - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU.

View File

@ -17,6 +17,7 @@
// Global WebGPU required states // Global WebGPU required states
static WGPUDevice wgpu_device = nullptr; static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr; static WGPUSurface wgpu_surface = nullptr;
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
static WGPUSwapChain wgpu_swap_chain = nullptr; static WGPUSwapChain wgpu_swap_chain = nullptr;
static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_width = 0;
static int wgpu_swap_chain_height = 0; static int wgpu_swap_chain_height = 0;
@ -71,7 +72,7 @@ int main(int, char**)
// Setup Platform/Renderer backends // Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true); ImGui_ImplGlfw_InitForOther(window, true);
ImGui_ImplWGPU_Init(wgpu_device, 3, WGPUTextureFormat_RGBA8Unorm, WGPUTextureFormat_Undefined); ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined);
// Load Fonts // Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
@ -118,9 +119,11 @@ static bool InitWGPU()
wgpu::SurfaceDescriptor surface_desc = {}; wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc; surface_desc.nextInChain = &html_surface_desc;
// Use 'null' instance wgpu::Instance instance = wgpuCreateInstance(nullptr);
wgpu::Instance instance = {}; wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu_surface = instance.CreateSurface(&surface_desc).Release(); wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
wgpu_surface = surface.Release();
return true; return true;
} }
@ -144,7 +147,7 @@ static void MainLoopStep(void* window)
wgpu_swap_chain_height = height; wgpu_swap_chain_height = height;
WGPUSwapChainDescriptor swap_chain_desc = {}; WGPUSwapChainDescriptor swap_chain_desc = {};
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm; swap_chain_desc.format = wgpu_preferred_fmt;
swap_chain_desc.width = width; swap_chain_desc.width = width;
swap_chain_desc.height = height; swap_chain_desc.height = height;
swap_chain_desc.presentMode = WGPUPresentMode_Fifo; swap_chain_desc.presentMode = WGPUPresentMode_Fifo;

200
imgui.cpp
View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (main code and documentation) // (main code and documentation)
// Help: // Help:
@ -433,6 +433,7 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates. - likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2023/08/25 (1.89.9) - Clipper: Renamed IncludeRangeByIndices() (also called ForceDisplayRangeByIndices() before 1.89.6) to IncludeItemsByIndex(). Kept inline redirection function. Sorry!
- 2023/07/12 (1.89.8) - ImDrawData: CmdLists now owned, changed from ImDrawList** to ImVector<ImDrawList*>. Majority of users shouldn't be affected, but you cannot compare to NULL nor reassign manually anymore. Instead use AddDrawList(). (#6406, #4879, #1878) - 2023/07/12 (1.89.8) - ImDrawData: CmdLists now owned, changed from ImDrawList** to ImVector<ImDrawList*>. Majority of users shouldn't be affected, but you cannot compare to NULL nor reassign manually anymore. Instead use AddDrawList(). (#6406, #4879, #1878)
- 2023/06/28 (1.89.7) - overlapping items: obsoleted 'SetItemAllowOverlap()' (called after item) in favor of calling 'SetNextItemAllowOverlap()' (called before item). 'SetItemAllowOverlap()' didn't and couldn't work reliably since 1.89 (2022-11-15). - 2023/06/28 (1.89.7) - overlapping items: obsoleted 'SetItemAllowOverlap()' (called after item) in favor of calling 'SetNextItemAllowOverlap()' (called before item). 'SetItemAllowOverlap()' didn't and couldn't work reliably since 1.89 (2022-11-15).
- 2023/06/28 (1.89.7) - overlapping items: renamed 'ImGuiTreeNodeFlags_AllowItemOverlap' to 'ImGuiTreeNodeFlags_AllowOverlap', 'ImGuiSelectableFlags_AllowItemOverlap' to 'ImGuiSelectableFlags_AllowOverlap'. Kept redirecting enums (will obsolete). - 2023/06/28 (1.89.7) - overlapping items: renamed 'ImGuiTreeNodeFlags_AllowItemOverlap' to 'ImGuiTreeNodeFlags_AllowOverlap', 'ImGuiSelectableFlags_AllowItemOverlap' to 'ImGuiSelectableFlags_AllowOverlap'. Kept redirecting enums (will obsolete).
@ -1188,7 +1189,7 @@ ImGuiStyle::ImGuiStyle()
FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
CellPadding = ImVec2(4,2); // Padding within a table cell CellPadding = ImVec2(4,2); // Padding within a table cell. CellPadding.y may be altered between different rows.
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
@ -2609,16 +2610,15 @@ void ImGuiTextFilter::Build()
input_range.split(',', &Filters); input_range.split(',', &Filters);
CountGrep = 0; CountGrep = 0;
for (int i = 0; i != Filters.Size; i++) for (ImGuiTextRange& f : Filters)
{ {
ImGuiTextRange& f = Filters[i];
while (f.b < f.e && ImCharIsBlankA(f.b[0])) while (f.b < f.e && ImCharIsBlankA(f.b[0]))
f.b++; f.b++;
while (f.e > f.b && ImCharIsBlankA(f.e[-1])) while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
f.e--; f.e--;
if (f.empty()) if (f.empty())
continue; continue;
if (Filters[i].b[0] != '-') if (f.b[0] != '-')
CountGrep += 1; CountGrep += 1;
} }
} }
@ -2631,9 +2631,8 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
if (text == NULL) if (text == NULL)
text = ""; text = "";
for (int i = 0; i != Filters.Size; i++) for (const ImGuiTextRange& f : Filters)
{ {
const ImGuiTextRange& f = Filters[i];
if (f.empty()) if (f.empty())
continue; continue;
if (f.b[0] == '-') if (f.b[0] == '-')
@ -2921,7 +2920,7 @@ void ImGuiListClipper::End()
ItemsCount = -1; ItemsCount = -1;
} }
void ImGuiListClipper::IncludeRangeByIndices(int item_begin, int item_end) void ImGuiListClipper::IncludeItemsByIndex(int item_begin, int item_end)
{ {
ImGuiListClipperData* data = (ImGuiListClipperData*)TempData; ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
IM_ASSERT(DisplayStart < 0); // Only allowed after Begin() and if there has not been a specified range yet. IM_ASSERT(DisplayStart < 0); // Only allowed after Begin() and if there has not been a specified range yet.
@ -3022,26 +3021,28 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
// - Very important: when a starting position is after our maximum item, we set Min to (ItemsCount - 1). This allows us to handle most forms of wrapping. // - Very important: when a starting position is after our maximum item, we set Min to (ItemsCount - 1). This allows us to handle most forms of wrapping.
// - Due to how Selectable extra padding they tend to be "unaligned" with exact unit in the item list, // - Due to how Selectable extra padding they tend to be "unaligned" with exact unit in the item list,
// which with the flooring/ceiling tend to lead to 2 items instead of one being submitted. // which with the flooring/ceiling tend to lead to 2 items instead of one being submitted.
for (int i = 0; i < data->Ranges.Size; i++) for (ImGuiListClipperRange& range : data->Ranges)
if (data->Ranges[i].PosToIndexConvert) if (range.PosToIndexConvert)
{ {
int m1 = (int)(((double)data->Ranges[i].Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight); int m1 = (int)(((double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight);
int m2 = (int)((((double)data->Ranges[i].Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f); int m2 = (int)((((double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f);
data->Ranges[i].Min = ImClamp(already_submitted + m1 + data->Ranges[i].PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1); range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1);
data->Ranges[i].Max = ImClamp(already_submitted + m2 + data->Ranges[i].PosToIndexOffsetMax, data->Ranges[i].Min + 1, clipper->ItemsCount); range.Max = ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount);
data->Ranges[i].PosToIndexConvert = false; range.PosToIndexConvert = false;
} }
ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo); ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
} }
// Step 0+ (if item height is given in advance) or 1+: Display the next range in line. // Step 0+ (if item height is given in advance) or 1+: Display the next range in line.
if (data->StepNo < data->Ranges.Size) while (data->StepNo < data->Ranges.Size)
{ {
clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted); clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount); clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
if (clipper->DisplayStart > already_submitted) //-V1051 if (clipper->DisplayStart > already_submitted) //-V1051
ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart); ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart);
data->StepNo++; data->StepNo++;
if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size)
continue;
return true; return true;
} }
@ -3548,13 +3549,12 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas; ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas;
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
{ {
// We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor. // We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor.
ImVec2 offset, size, uv[4]; ImVec2 offset, size, uv[4];
if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
continue; continue;
ImGuiViewportP* viewport = g.Viewports[n];
const ImVec2 pos = base_pos - offset; const ImVec2 pos = base_pos - offset;
const float scale = base_scale * viewport->DpiScale; const float scale = base_scale * viewport->DpiScale;
if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale))) if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale)))
@ -3790,9 +3790,9 @@ void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
IM_ASSERT(hook_id != 0); IM_ASSERT(hook_id != 0);
for (int n = 0; n < g.Hooks.Size; n++) for (ImGuiContextHook& hook : g.Hooks)
if (g.Hooks[n].HookId == hook_id) if (hook.HookId == hook_id)
g.Hooks[n].Type = ImGuiContextHookType_PendingRemoval_; hook.Type = ImGuiContextHookType_PendingRemoval_;
} }
// Call context hooks (used by e.g. test engine) // Call context hooks (used by e.g. test engine)
@ -3800,9 +3800,9 @@ void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int n = 0; n < g.Hooks.Size; n++) for (ImGuiContextHook& hook : g.Hooks)
if (g.Hooks[n].Type == hook_type) if (hook.Type == hook_type)
g.Hooks[n].Callback(&g, &g.Hooks[n]); hook.Callback(&g, &hook);
} }
@ -4029,6 +4029,8 @@ void ImGui::MarkItemEdited(ImGuiID id)
// This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit(). // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data. // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.LockMarkEdited > 0)
return;
if (g.ActiveId == id || g.ActiveId == 0) if (g.ActiveId == id || g.ActiveId == 0)
{ {
g.ActiveIdHasBeenEditedThisFrame = true; g.ActiveIdHasBeenEditedThisFrame = true;
@ -4739,8 +4741,8 @@ void ImGui::NewFrame()
SetCurrentFont(GetDefaultFont()); SetCurrentFont(GetDefaultFont());
IM_ASSERT(g.Font->IsLoaded()); IM_ASSERT(g.Font->IsLoaded());
ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
virtual_space.Add(g.Viewports[n]->GetMainRect()); virtual_space.Add(viewport->GetMainRect());
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4(); g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError); g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
@ -4755,9 +4757,8 @@ void ImGui::NewFrame()
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
// Mark rendering data as invalid to prevent user who may have a handle on it to use it. // Mark rendering data as invalid to prevent user who may have a handle on it to use it.
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
{ {
ImGuiViewportP* viewport = g.Viewports[n];
viewport->DrawData = NULL; viewport->DrawData = NULL;
viewport->DrawDataP.Valid = false; viewport->DrawDataP.Valid = false;
} }
@ -4910,9 +4911,8 @@ void ImGui::NewFrame()
// Mark all windows as not visible and compact unused memory. // Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (int i = 0; i != g.Windows.Size; i++) for (ImGuiWindow* window : g.Windows)
{ {
ImGuiWindow* window = g.Windows[i];
window->WasActive = window->Active; window->WasActive = window->Active;
window->Active = false; window->Active = false;
window->WriteAccessed = false; window->WriteAccessed = false;
@ -4928,9 +4928,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.TablesTempData.Size; i++) for (ImGuiTableTempData& table_temp_data : g.TablesTempData)
if (g.TablesTempData[i].LastTimeActive >= 0.0f && g.TablesTempData[i].LastTimeActive < memory_compact_start_time) if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
TableGcCompactTransientBuffers(&g.TablesTempData[i]); TableGcCompactTransientBuffers(&table_temp_data);
if (g.GcCompactAll) if (g.GcCompactAll)
GcCompactTransientMiscBuffers(); GcCompactTransientMiscBuffers();
g.GcCompactAll = false; g.GcCompactAll = false;
@ -5016,12 +5016,9 @@ static void AddWindowToDrawData(ImGuiWindow* window, int layer)
if (window->DrawList->_Splitter._Count > 1) if (window->DrawList->_Splitter._Count > 1)
window->DrawList->ChannelsMerge(); // Merge if user forgot to merge back. Also required in Docking branch for ImGuiWindowFlags_DockNodeHost windows. window->DrawList->ChannelsMerge(); // Merge if user forgot to merge back. Also required in Docking branch for ImGuiWindowFlags_DockNodeHost windows.
ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList); ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
for (int i = 0; i < window->DC.ChildWindows.Size; i++) for (ImGuiWindow* child : window->DC.ChildWindows)
{
ImGuiWindow* child = window->DC.ChildWindows[i];
if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active
AddWindowToDrawData(child, layer); AddWindowToDrawData(child, layer);
}
} }
static inline int GetWindowDisplayLayer(ImGuiWindow* window) static inline int GetWindowDisplayLayer(ImGuiWindow* window)
@ -5306,9 +5303,8 @@ void ImGui::EndFrame()
// We cannot do that on FocusWindow() because children may not exist yet // We cannot do that on FocusWindow() because children may not exist yet
g.WindowsTempSortBuffer.resize(0); g.WindowsTempSortBuffer.resize(0);
g.WindowsTempSortBuffer.reserve(g.Windows.Size); g.WindowsTempSortBuffer.reserve(g.Windows.Size);
for (int i = 0; i != g.Windows.Size; i++) for (ImGuiWindow* window : g.Windows)
{ {
ImGuiWindow* window = g.Windows[i];
if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
continue; continue;
AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window); AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window);
@ -5362,9 +5358,8 @@ void ImGui::Render()
ImGuiWindow* windows_to_render_top_most[2]; ImGuiWindow* windows_to_render_top_most[2];
windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindowDockTree : NULL; windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindowDockTree : NULL;
windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL); windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
for (int n = 0; n != g.Windows.Size; n++) for (ImGuiWindow* window : g.Windows)
{ {
ImGuiWindow* window = g.Windows[n];
IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
AddRootWindowToDrawData(window); AddRootWindowToDrawData(window);
@ -5379,9 +5374,8 @@ void ImGui::Render()
// Setup ImDrawData structures for end-user // Setup ImDrawData structures for end-user
g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0; g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0;
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
{ {
ImGuiViewportP* viewport = g.Viewports[n];
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder); FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
// Add foreground ImDrawList (for each active viewport) // Add foreground ImDrawList (for each active viewport)
@ -5391,8 +5385,8 @@ void ImGui::Render()
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch). // We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
ImDrawData* draw_data = &viewport->DrawDataP; ImDrawData* draw_data = &viewport->DrawDataP;
IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount); IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
for (int draw_list_n = 0; draw_list_n < draw_data->CmdLists.Size; draw_list_n++) for (ImDrawList* draw_list : draw_data->CmdLists)
draw_data->CmdLists[draw_list_n]->_PopUnusedDrawCmd(); draw_list->_PopUnusedDrawCmd();
g.IO.MetricsRenderVertices += draw_data->TotalVtxCount; g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
g.IO.MetricsRenderIndices += draw_data->TotalIdxCount; g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
@ -6572,9 +6566,9 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
return NULL; return NULL;
// Find a modal that has common parent with specified window. Specified window should be positioned behind that modal. // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal.
for (int i = 0; i < g.OpenPopupStack.Size; i++) for (ImGuiPopupData& popup_data : g.OpenPopupStack)
{ {
ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window; ImGuiWindow* popup_window = popup_data.Window;
if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal)) if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
continue; continue;
if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows. if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
@ -10239,9 +10233,6 @@ ImVec2 ImGui::GetCursorScreenPos()
return window->DC.CursorPos; return window->DC.CursorPos;
} }
// 2022/08/05: Setting cursor position also extend boundaries (via modifying CursorMaxPos) used to compute window size, group size etc.
// I believe this was is a judicious choice but it's probably being relied upon (it has been the case since 1.31 and 1.50)
// It would be sane if we requested user to use SetCursorPos() + Dummy(ImVec2(0,0)) to extend CursorMaxPos...
void ImGui::SetCursorScreenPos(const ImVec2& pos) void ImGui::SetCursorScreenPos(const ImVec2& pos)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -12371,7 +12362,7 @@ void ImGui::NavUpdateCreateMoveRequest()
scoring_rect.TranslateY(scoring_rect_offset_y); scoring_rect.TranslateY(scoring_rect_offset_y);
if (g.NavMoveSubmitted) if (g.NavMoveSubmitted)
NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer], g.NavMoveDir, g.NavMoveFlags); NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer], g.NavMoveDir, g.NavMoveFlags);
IM_ASSERT(!scoring_rect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allow us to remove extraneous ImFabs() calls in NavScoreItem(). IM_ASSERT(!scoring_rect.IsInverted()); // Ensure we have a non-inverted bounding box here will allow us to remove extraneous ImFabs() calls in NavScoreItem().
//GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG] //GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG]
//if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG] //if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG]
} }
@ -13647,9 +13638,9 @@ ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiID type_hash = ImHashStr(type_name); const ImGuiID type_hash = ImHashStr(type_name);
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
if (g.SettingsHandlers[handler_n].TypeHash == type_hash) if (handler.TypeHash == type_hash)
return &g.SettingsHandlers[handler_n]; return &handler;
return NULL; return NULL;
} }
@ -13658,9 +13649,9 @@ void ImGui::ClearIniSettings()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.SettingsIniData.clear(); g.SettingsIniData.clear();
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
if (g.SettingsHandlers[handler_n].ClearAllFn) if (handler.ClearAllFn != NULL)
g.SettingsHandlers[handler_n].ClearAllFn(&g, &g.SettingsHandlers[handler_n]); handler.ClearAllFn(&g, &handler);
} }
void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
@ -13695,9 +13686,9 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
// Call pre-read handlers // Call pre-read handlers
// Some types will clear their data (e.g. dock information) some types will allow merge/override (window) // Some types will clear their data (e.g. dock information) some types will allow merge/override (window)
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
if (g.SettingsHandlers[handler_n].ReadInitFn) if (handler.ReadInitFn != NULL)
g.SettingsHandlers[handler_n].ReadInitFn(&g, &g.SettingsHandlers[handler_n]); handler.ReadInitFn(&g, &handler);
void* entry_data = NULL; void* entry_data = NULL;
ImGuiSettingsHandler* entry_handler = NULL; ImGuiSettingsHandler* entry_handler = NULL;
@ -13741,9 +13732,9 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
memcpy(buf, ini_data, ini_size); memcpy(buf, ini_data, ini_size);
// Call post-read handlers // Call post-read handlers
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
if (g.SettingsHandlers[handler_n].ApplyAllFn) if (handler.ApplyAllFn != NULL)
g.SettingsHandlers[handler_n].ApplyAllFn(&g, &g.SettingsHandlers[handler_n]); handler.ApplyAllFn(&g, &handler);
} }
void ImGui::SaveIniSettingsToDisk(const char* ini_filename) void ImGui::SaveIniSettingsToDisk(const char* ini_filename)
@ -13769,11 +13760,8 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
g.SettingsDirtyTimer = 0.0f; g.SettingsDirtyTimer = 0.0f;
g.SettingsIniData.Buf.resize(0); g.SettingsIniData.Buf.resize(0);
g.SettingsIniData.Buf.push_back(0); g.SettingsIniData.Buf.push_back(0);
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
{ handler.WriteAllFn(&g, &handler, &g.SettingsIniData);
ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n];
handler->WriteAllFn(&g, handler, &g.SettingsIniData);
}
if (out_size) if (out_size)
*out_size = (size_t)g.SettingsIniData.size(); *out_size = (size_t)g.SettingsIniData.size();
return g.SettingsIniData.c_str(); return g.SettingsIniData.c_str();
@ -13842,8 +13830,8 @@ void ImGui::ClearWindowSettings(const char* name)
static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Windows.Size; i++) for (ImGuiWindow* window : g.Windows)
g.Windows[i]->SettingsOffset = -1; window->SettingsOffset = -1;
g.SettingsWindows.clear(); g.SettingsWindows.clear();
} }
@ -13894,9 +13882,8 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
// Gather data from windows that were active during this session // Gather data from windows that were active during this session
// (if a window wasn't opened in this session we preserve its settings) // (if a window wasn't opened in this session we preserve its settings)
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Windows.Size; i++) for (ImGuiWindow* window : g.Windows)
{ {
ImGuiWindow* window = g.Windows[i];
if (window->Flags & ImGuiWindowFlags_NoSavedSettings) if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
continue; continue;
@ -19090,10 +19077,9 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP*
ImVec2 scale = bb.GetSize() / viewport->Size; ImVec2 scale = bb.GetSize() / viewport->Size;
ImVec2 off = bb.Min - viewport->Pos * scale; ImVec2 off = bb.Min - viewport->Pos * scale;
float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f; float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f;
window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f)); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
for (int i = 0; i != g.Windows.Size; i++) for (ImGuiWindow* thumb_window : g.Windows)
{ {
ImGuiWindow* thumb_window = g.Windows[i];
if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow)) if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
continue; continue;
if (thumb_window->Viewport != viewport) if (thumb_window->Viewport != viewport)
@ -19122,13 +19108,12 @@ static void RenderViewportsThumbnails()
// We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports. // We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports.
float SCALE = 1.0f / 8.0f; float SCALE = 1.0f / 8.0f;
ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
bb_full.Add(g.Viewports[n]->GetMainRect()); bb_full.Add(viewport->GetMainRect());
ImVec2 p = window->DC.CursorPos; ImVec2 p = window->DC.CursorPos;
ImVec2 off = p - bb_full.Min * SCALE; ImVec2 off = p - bb_full.Min * SCALE;
for (int n = 0; n < g.Viewports.Size; n++) for (ImGuiViewportP* viewport : g.Viewports)
{ {
ImGuiViewportP* viewport = g.Viewports[n];
ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE); ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb); ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
} }
@ -19243,9 +19228,8 @@ static void MetricsHelpMarker(const char* desc)
// [DEBUG] List fonts in a font atlas and display its texture // [DEBUG] List fonts in a font atlas and display its texture
void ImGui::ShowFontAtlas(ImFontAtlas* atlas) void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
{ {
for (int i = 0; i < atlas->Fonts.Size; i++) for (ImFont* font : atlas->Fonts)
{ {
ImFont* font = atlas->Fonts[i];
PushID(font); PushID(font);
DebugNodeFont(font); DebugNodeFont(font);
PopID(); PopID();
@ -19446,9 +19430,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// Here we display windows in their submitted order/hierarchy, however note that the Begin stack doesn't constitute a Parent<>Child relationship! // Here we display windows in their submitted order/hierarchy, however note that the Begin stack doesn't constitute a Parent<>Child relationship!
ImVector<ImGuiWindow*>& temp_buffer = g.WindowsTempSortBuffer; ImVector<ImGuiWindow*>& temp_buffer = g.WindowsTempSortBuffer;
temp_buffer.resize(0); temp_buffer.resize(0);
for (int i = 0; i < g.Windows.Size; i++) for (ImGuiWindow* window : g.Windows)
if (g.Windows[i]->LastFrameActive + 1 >= g.FrameCount) if (window->LastFrameActive + 1 >= g.FrameCount)
temp_buffer.push_back(g.Windows[i]); temp_buffer.push_back(window);
struct Func { static int IMGUI_CDECL WindowComparerByBeginOrder(const void* lhs, const void* rhs) { return ((int)(*(const ImGuiWindow* const *)lhs)->BeginOrderWithinContext - (*(const ImGuiWindow* const*)rhs)->BeginOrderWithinContext); } }; struct Func { static int IMGUI_CDECL WindowComparerByBeginOrder(const void* lhs, const void* rhs) { return ((int)(*(const ImGuiWindow* const *)lhs)->BeginOrderWithinContext - (*(const ImGuiWindow* const*)rhs)->BeginOrderWithinContext); } };
ImQsort(temp_buffer.Data, (size_t)temp_buffer.Size, sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder); ImQsort(temp_buffer.Data, (size_t)temp_buffer.Size, sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder);
DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL); DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL);
@ -19460,22 +19444,21 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// DrawLists // DrawLists
int drawlist_count = 0; int drawlist_count = 0;
for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++) for (ImGuiViewportP* viewport : g.Viewports)
drawlist_count += g.Viewports[viewport_i]->DrawDataP.CmdLists.Size; drawlist_count += viewport->DrawDataP.CmdLists.Size;
if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count)) if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count))
{ {
Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh); Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes); Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++) for (ImGuiViewportP* viewport : g.Viewports)
{ {
ImGuiViewportP* viewport = g.Viewports[viewport_i];
bool viewport_has_drawlist = false; bool viewport_has_drawlist = false;
for (int draw_list_i = 0; draw_list_i < viewport->DrawDataP.CmdLists.Size; draw_list_i++) for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
{ {
if (!viewport_has_drawlist) if (!viewport_has_drawlist)
Text("Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID); Text("Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID);
viewport_has_drawlist = true; viewport_has_drawlist = true;
DebugNodeDrawList(NULL, viewport, viewport->DrawDataP.CmdLists[draw_list_i], "DrawList"); DebugNodeDrawList(NULL, viewport, draw_list, "DrawList");
} }
} }
TreePop(); TreePop();
@ -19519,22 +19502,21 @@ void ImGui::ShowMetricsWindow(bool* p_open)
viewport->Window ? viewport->Window->Name : "N/A"); viewport->Window ? viewport->Window->Name : "N/A");
TreePop(); TreePop();
} }
for (int i = 0; i < g.Viewports.Size; i++) for (ImGuiViewportP* viewport : g.Viewports)
DebugNodeViewport(g.Viewports[i]); DebugNodeViewport(viewport);
TreePop(); TreePop();
} }
// Details for Popups // Details for Popups
if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
{ {
for (int i = 0; i < g.OpenPopupStack.Size; i++) for (const ImGuiPopupData& popup_data : g.OpenPopupStack)
{ {
// As it's difficult to interact with tree nodes while popups are open, we display everything inline. // As it's difficult to interact with tree nodes while popups are open, we display everything inline.
const ImGuiPopupData* popup_data = &g.OpenPopupStack[i]; ImGuiWindow* window = popup_data.Window;
ImGuiWindow* window = popup_data->Window;
BulletText("PopupID: %08x, Window: '%s' (%s%s), BackupNavWindow '%s', ParentWindow '%s'", BulletText("PopupID: %08x, Window: '%s' (%s%s), BackupNavWindow '%s', ParentWindow '%s'",
popup_data->PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? "Child;" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? "Menu;" : "", popup_data.PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? "Child;" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? "Menu;" : "",
popup_data->BackupNavWindow ? popup_data->BackupNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL"); popup_data.BackupNavWindow ? popup_data.BackupNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL");
} }
TreePop(); TreePop();
} }
@ -19615,8 +19597,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer); Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size)) if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
{ {
for (int n = 0; n < g.SettingsHandlers.Size; n++) for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
BulletText("\"%s\"", g.SettingsHandlers[n].TypeName); BulletText("\"%s\"", handler.TypeName);
TreePop(); TreePop();
} }
if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size())) if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
@ -19805,9 +19787,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// Overlay: Display windows Rectangles and Begin Order // Overlay: Display windows Rectangles and Begin Order
if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder) if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
{ {
for (int n = 0; n < g.Windows.Size; n++) for (ImGuiWindow* window : g.Windows)
{ {
ImGuiWindow* window = g.Windows[n];
if (!window->WasActive) if (!window->WasActive)
continue; continue;
ImDrawList* draw_list = GetForegroundDrawList(window); ImDrawList* draw_list = GetForegroundDrawList(window);
@ -19883,8 +19864,8 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
return; return;
BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
for (int column_n = 0; column_n < columns->Columns.Size; column_n++) for (ImGuiOldColumnData& column : columns->Columns)
BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm)); BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column), column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm));
TreePop(); TreePop();
} }
@ -20205,11 +20186,8 @@ void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
{ {
if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
return; return;
for (int n = 0; n < storage->Data.Size; n++) for (const ImGuiStorage::ImGuiStoragePair& p : storage->Data)
{
const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n];
BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer.
}
TreePop(); TreePop();
} }
@ -20280,8 +20258,8 @@ void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
(flags & ImGuiViewportFlags_NoAutoMerge) ? " NoAutoMerge" : "", (flags & ImGuiViewportFlags_NoAutoMerge) ? " NoAutoMerge" : "",
(flags & ImGuiViewportFlags_TopMost) ? " TopMost" : "", (flags & ImGuiViewportFlags_TopMost) ? " TopMost" : "",
(flags & ImGuiViewportFlags_CanHostOtherWindows) ? " CanHostOtherWindows" : ""); (flags & ImGuiViewportFlags_CanHostOtherWindows) ? " CanHostOtherWindows" : "");
for (int draw_list_i = 0; draw_list_i < viewport->DrawDataP.CmdLists.Size; draw_list_i++) for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists)
DebugNodeDrawList(NULL, viewport, viewport->DrawDataP.CmdLists[draw_list_i], "DrawList"); DebugNodeDrawList(NULL, viewport, draw_list, "DrawList");
TreePop(); TreePop();
} }
} }
@ -20345,8 +20323,8 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
{ {
for (int n = 0; n < window->ColumnsStorage.Size; n++) for (ImGuiOldColumns& columns : window->ColumnsStorage)
DebugNodeColumns(&window->ColumnsStorage[n]); DebugNodeColumns(&columns);
TreePop(); TreePop();
} }
DebugNodeStorage(&window->StateStorage, "Storage"); DebugNodeStorage(&window->StateStorage, "Storage");

16
imgui.h
View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (headers) // (headers)
// Help: // Help:
@ -25,8 +25,8 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.89.9 WIP" #define IMGUI_VERSION "1.89.9"
#define IMGUI_VERSION_NUM 18983 #define IMGUI_VERSION_NUM 18990
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@ -1977,7 +1977,7 @@ struct ImGuiStyle
float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines.
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
ImVec2 CellPadding; // Padding within a table cell ImVec2 CellPadding; // Padding within a table cell. CellPadding.y may be altered between different rows.
ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
@ -2518,12 +2518,14 @@ struct ImGuiListClipper
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
// Call IncludeRangeByIndices() *BEFORE* first call to Step() if you need a range of items to not be clipped, regardless of their visibility. // Call IncludeItemByIndex() or IncludeItemsByIndex() *BEFORE* first call to Step() if you need a range of items to not be clipped, regardless of their visibility.
// (Due to alignment / padding of certain items it is possible that an extra item may be included on either end of the display range). // (Due to alignment / padding of certain items it is possible that an extra item may be included on either end of the display range).
IMGUI_API void IncludeRangeByIndices(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped. inline void IncludeItemByIndex(int item_index) { IncludeItemsByIndex(item_index, item_index + 1); }
IMGUI_API void IncludeItemsByIndex(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeRangeByIndices(item_begin, item_end); } // [renamed in 1.89.6] inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9]
inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6]
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] //inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
#endif #endif
}; };

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (demo code) // (demo code)
// Help: // Help:
@ -188,20 +188,20 @@ Index of this file:
#if !defined(IMGUI_DISABLE_DEMO_WINDOWS) #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
// Forward Declarations // Forward Declarations
static void ShowExampleAppDockSpace(bool* p_open);
static void ShowExampleAppDocuments(bool* p_open);
static void ShowExampleAppMainMenuBar(); static void ShowExampleAppMainMenuBar();
static void ShowExampleAppConsole(bool* p_open); static void ShowExampleAppConsole(bool* p_open);
static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleAppDockSpace(bool* p_open);
static void ShowExampleAppDocuments(bool* p_open);
static void ShowExampleAppLog(bool* p_open); static void ShowExampleAppLog(bool* p_open);
static void ShowExampleAppLayout(bool* p_open); static void ShowExampleAppLayout(bool* p_open);
static void ShowExampleAppPropertyEditor(bool* p_open); static void ShowExampleAppPropertyEditor(bool* p_open);
static void ShowExampleAppLongText(bool* p_open); static void ShowExampleAppSimpleOverlay(bool* p_open);
static void ShowExampleAppAutoResize(bool* p_open); static void ShowExampleAppAutoResize(bool* p_open);
static void ShowExampleAppConstrainedResize(bool* p_open); static void ShowExampleAppConstrainedResize(bool* p_open);
static void ShowExampleAppSimpleOverlay(bool* p_open);
static void ShowExampleAppFullscreen(bool* p_open); static void ShowExampleAppFullscreen(bool* p_open);
static void ShowExampleAppLongText(bool* p_open);
static void ShowExampleAppWindowTitles(bool* p_open); static void ShowExampleAppWindowTitles(bool* p_open);
static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleMenuFile(); static void ShowExampleMenuFile();
// We split the contents of the big ShowDemoWindow() function into smaller functions // We split the contents of the big ShowDemoWindow() function into smaller functions
@ -267,61 +267,61 @@ void* GImGuiDemoMarkerCallbackUserData = NULL;
void ImGui::ShowDemoWindow(bool* p_open) void ImGui::ShowDemoWindow(bool* p_open)
{ {
// Exceptionally add an extra assert here for people confused about initial Dear ImGui setup // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
// Most functions would normally just crash if the context is missing. // Most functions would normally just assert/crash if the context is missing.
IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!"); IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
// Examples Apps (accessible from the "Examples" menu) // Examples Apps (accessible from the "Examples" menu)
static bool show_app_main_menu_bar = false; static bool show_app_main_menu_bar = false;
static bool show_app_console = false;
static bool show_app_custom_rendering = false;
static bool show_app_dockspace = false; static bool show_app_dockspace = false;
static bool show_app_documents = false; static bool show_app_documents = false;
static bool show_app_console = false;
static bool show_app_log = false; static bool show_app_log = false;
static bool show_app_layout = false; static bool show_app_layout = false;
static bool show_app_property_editor = false; static bool show_app_property_editor = false;
static bool show_app_long_text = false; static bool show_app_simple_overlay = false;
static bool show_app_auto_resize = false; static bool show_app_auto_resize = false;
static bool show_app_constrained_resize = false; static bool show_app_constrained_resize = false;
static bool show_app_simple_overlay = false;
static bool show_app_fullscreen = false; static bool show_app_fullscreen = false;
static bool show_app_long_text = false;
static bool show_app_window_titles = false; static bool show_app_window_titles = false;
static bool show_app_custom_rendering = false;
if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
if (show_app_dockspace) ShowExampleAppDockSpace(&show_app_dockspace); // Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function) if (show_app_dockspace) ShowExampleAppDockSpace(&show_app_dockspace); // Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function)
if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace() if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace()
if (show_app_console) ShowExampleAppConsole(&show_app_console); if (show_app_console) ShowExampleAppConsole(&show_app_console);
if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
if (show_app_log) ShowExampleAppLog(&show_app_log); if (show_app_log) ShowExampleAppLog(&show_app_log);
if (show_app_layout) ShowExampleAppLayout(&show_app_layout); if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
if (show_app_fullscreen) ShowExampleAppFullscreen(&show_app_fullscreen); if (show_app_fullscreen) ShowExampleAppFullscreen(&show_app_fullscreen);
if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
// Dear ImGui Tools/Apps (accessible from the "Tools" menu) // Dear ImGui Tools (accessible from the "Tools" menu)
static bool show_app_metrics = false; static bool show_tool_metrics = false;
static bool show_app_debug_log = false; static bool show_tool_debug_log = false;
static bool show_app_stack_tool = false; static bool show_tool_stack_tool = false;
static bool show_app_about = false; static bool show_tool_style_editor = false;
static bool show_app_style_editor = false; static bool show_tool_about = false;
if (show_app_metrics) if (show_tool_metrics)
ImGui::ShowMetricsWindow(&show_app_metrics); ImGui::ShowMetricsWindow(&show_tool_metrics);
if (show_app_debug_log) if (show_tool_debug_log)
ImGui::ShowDebugLogWindow(&show_app_debug_log); ImGui::ShowDebugLogWindow(&show_tool_debug_log);
if (show_app_stack_tool) if (show_tool_stack_tool)
ImGui::ShowStackToolWindow(&show_app_stack_tool); ImGui::ShowStackToolWindow(&show_tool_stack_tool);
if (show_app_about) if (show_tool_style_editor)
ImGui::ShowAboutWindow(&show_app_about);
if (show_app_style_editor)
{ {
ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor); ImGui::Begin("Dear ImGui Style Editor", &show_tool_style_editor);
ImGui::ShowStyleEditor(); ImGui::ShowStyleEditor();
ImGui::End(); ImGui::End();
} }
if (show_tool_about)
ImGui::ShowAboutWindow(&show_tool_about);
// Demonstrate the various window flags. Typically you would just use the default! // Demonstrate the various window flags. Typically you would just use the default!
static bool no_titlebar = false; static bool no_titlebar = false;
@ -384,19 +384,24 @@ void ImGui::ShowDemoWindow(bool* p_open)
{ {
IMGUI_DEMO_MARKER("Menu/Examples"); IMGUI_DEMO_MARKER("Menu/Examples");
ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar); ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
ImGui::SeparatorText("Mini apps");
ImGui::MenuItem("Console", NULL, &show_app_console); ImGui::MenuItem("Console", NULL, &show_app_console);
ImGui::MenuItem("Log", NULL, &show_app_log);
ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen);
ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
ImGui::MenuItem("Dockspace", NULL, &show_app_dockspace); ImGui::MenuItem("Dockspace", NULL, &show_app_dockspace);
ImGui::MenuItem("Documents", NULL, &show_app_documents); ImGui::MenuItem("Documents", NULL, &show_app_documents);
ImGui::MenuItem("Log", NULL, &show_app_log);
ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
ImGui::SeparatorText("Concepts");
ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen);
ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
ImGui::EndMenu(); ImGui::EndMenu();
} }
//if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar! //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
@ -408,11 +413,11 @@ void ImGui::ShowDemoWindow(bool* p_open)
#else #else
const bool has_debug_tools = false; const bool has_debug_tools = false;
#endif #endif
ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics, has_debug_tools); ImGui::MenuItem("Metrics/Debugger", NULL, &show_tool_metrics, has_debug_tools);
ImGui::MenuItem("Debug Log", NULL, &show_app_debug_log, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools);
ImGui::MenuItem("Stack Tool", NULL, &show_app_stack_tool, has_debug_tools); ImGui::MenuItem("Stack Tool", NULL, &show_tool_stack_tool, has_debug_tools);
ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor);
ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about); ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about);
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
@ -3854,6 +3859,14 @@ struct MyItem
// very often by the sorting algorithm it would be a little wasteful. // very often by the sorting algorithm it would be a little wasteful.
static const ImGuiTableSortSpecs* s_current_sort_specs; static const ImGuiTableSortSpecs* s_current_sort_specs;
static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, MyItem* items, int items_count)
{
s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function.
if (items_count > 1)
qsort(items, (size_t)items_count, sizeof(items[0]), MyItem::CompareWithSortSpecs);
s_current_sort_specs = NULL;
}
// Compare function to be used by qsort() // Compare function to be used by qsort()
static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs) static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
{ {
@ -4851,7 +4864,7 @@ static void ShowDemoWindowTables()
HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row."); HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row.");
if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders)) if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders))
{ {
for (int row = 0; row < 10; row++) for (int row = 0; row < 8; row++)
{ {
float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row); float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row);
ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height); ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height);
@ -4882,6 +4895,23 @@ static void ShowDemoWindowTables()
ImGui::EndTable(); ImGui::EndTable();
} }
HelpMarker("Showcase altering CellPadding.y between rows. Note that CellPadding.x is locked for the entire table.");
if (ImGui::BeginTable("table_changing_cellpadding_y", 1, ImGuiTableFlags_Borders))
{
ImGuiStyle& style = ImGui::GetStyle();
for (int row = 0; row < 8; row++)
{
if ((row % 3) == 2)
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(style.CellPadding.x, 20.0f));
ImGui::TableNextRow(ImGuiTableRowFlags_None);
ImGui::TableNextColumn();
ImGui::Text("CellPadding.y = %.2f", style.CellPadding.y);
if ((row % 3) == 2)
ImGui::PopStyleVar();;
}
ImGui::EndTable();
}
ImGui::TreePop(); ImGui::TreePop();
} }
@ -5373,14 +5403,11 @@ static void ShowDemoWindowTables()
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
// Sort our data if sort specs have been changed! // Sort our data if sort specs have been changed!
if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs()) if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
if (sorts_specs->SpecsDirty) if (sort_specs->SpecsDirty)
{ {
MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
if (items.Size > 1) sort_specs->SpecsDirty = false;
qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
MyItem::s_current_sort_specs = NULL;
sorts_specs->SpecsDirty = false;
} }
// Demonstrate using clipper for large vertical lists // Demonstrate using clipper for large vertical lists
@ -5588,15 +5615,13 @@ static void ShowDemoWindowTables()
ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
// Sort our data if sort specs have been changed! // Sort our data if sort specs have been changed!
ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs(); ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
if (sorts_specs && sorts_specs->SpecsDirty) if (sort_specs && sort_specs->SpecsDirty)
items_need_sort = true; items_need_sort = true;
if (sorts_specs && items_need_sort && items.Size > 1) if (sort_specs && items_need_sort && items.Size > 1)
{ {
MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs); sort_specs->SpecsDirty = false;
MyItem::s_current_sort_specs = NULL;
sorts_specs->SpecsDirty = false;
} }
items_need_sort = false; items_need_sort = false;
@ -6325,9 +6350,8 @@ void ImGui::ShowFontSelector(const char* label)
ImFont* font_current = ImGui::GetFont(); ImFont* font_current = ImGui::GetFont();
if (ImGui::BeginCombo(label, font_current->GetDebugName())) if (ImGui::BeginCombo(label, font_current->GetDebugName()))
{ {
for (int n = 0; n < io.Fonts->Fonts.Size; n++) for (ImFont* font : io.Fonts->Fonts)
{ {
ImFont* font = io.Fonts->Fonts[n];
ImGui::PushID((void*)font); ImGui::PushID((void*)font);
if (ImGui::Selectable(font->GetDebugName(), font == font_current)) if (ImGui::Selectable(font->GetDebugName(), font == font_current))
io.FontDefault = font; io.FontDefault = font;
@ -6938,9 +6962,8 @@ struct ExampleAppConsole
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
if (copy_to_clipboard) if (copy_to_clipboard)
ImGui::LogToClipboard(); ImGui::LogToClipboard();
for (int i = 0; i < Items.Size; i++) for (const char* item : Items)
{ {
const char* item = Items[i];
if (!Filter.PassFilter(item)) if (!Filter.PassFilter(item))
continue; continue;
@ -7429,6 +7452,7 @@ static void ShowPlaceholderObject(const char* prefix, int uid)
} }
// Demonstrate create a simple property editor. // Demonstrate create a simple property editor.
// This demo is a bit lackluster nowadays, would be nice to improve.
static void ShowExampleAppPropertyEditor(bool* p_open) static void ShowExampleAppPropertyEditor(bool* p_open)
{ {
ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
@ -7437,23 +7461,24 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
ImGui::End(); ImGui::End();
return; return;
} }
IMGUI_DEMO_MARKER("Examples/Property Editor");
IMGUI_DEMO_MARKER("Examples/Property Editor");
HelpMarker( HelpMarker(
"This example shows how you may implement a property editor using two columns.\n" "This example shows how you may implement a property editor using two columns.\n"
"All objects/fields data are dummies here.\n" "All objects/fields data are dummies here.\n");
"Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
"your cursor horizontally instead of using the Columns() API.");
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
if (ImGui::BeginTable("split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable)) if (ImGui::BeginTable("##split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY))
{ {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("Object");
ImGui::TableSetupColumn("Contents");
ImGui::TableHeadersRow();
// Iterate placeholder objects (all the same data) // Iterate placeholder objects (all the same data)
for (int obj_i = 0; obj_i < 4; obj_i++) for (int obj_i = 0; obj_i < 4; obj_i++)
{
ShowPlaceholderObject("Object", obj_i); ShowPlaceholderObject("Object", obj_i);
//ImGui::Separator();
}
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -8255,12 +8280,11 @@ struct ExampleAppDocuments
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag. // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app) static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
{ {
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
{ {
MyDocument* doc = &app.Documents[doc_n]; if (!doc.Open && doc.OpenPrev)
if (!doc->Open && doc->OpenPrev) ImGui::SetTabItemClosed(doc.Name);
ImGui::SetTabItemClosed(doc->Name); doc.OpenPrev = doc.Open;
doc->OpenPrev = doc->Open;
} }
} }
@ -8299,23 +8323,19 @@ void ShowExampleAppDocuments(bool* p_open)
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
{ {
int open_count = 0; int open_count = 0;
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
open_count += app.Documents[doc_n].Open ? 1 : 0; open_count += doc.Open ? 1 : 0;
if (ImGui::BeginMenu("Open", open_count < app.Documents.Size)) if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
{ {
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
{ if (!doc.Open && ImGui::MenuItem(doc.Name))
MyDocument* doc = &app.Documents[doc_n]; doc.DoOpen();
if (!doc->Open)
if (ImGui::MenuItem(doc->Name))
doc->DoOpen();
}
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0)) if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
app.Documents[doc_n].DoQueueClose(); doc.DoQueueClose();
if (ImGui::MenuItem("Exit", "Ctrl+F4") && p_open) if (ImGui::MenuItem("Exit", "Ctrl+F4") && p_open)
*p_open = false; *p_open = false;
ImGui::EndMenu(); ImGui::EndMenu();
@ -8326,13 +8346,13 @@ void ShowExampleAppDocuments(bool* p_open)
// [Debug] List documents with one checkbox for each // [Debug] List documents with one checkbox for each
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
{ {
MyDocument* doc = &app.Documents[doc_n]; MyDocument& doc = app.Documents[doc_n];
if (doc_n > 0) if (doc_n > 0)
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushID(doc); ImGui::PushID(&doc);
if (ImGui::Checkbox(doc->Name, &doc->Open)) if (ImGui::Checkbox(doc.Name, &doc.Open))
if (!doc->Open) if (!doc.Open)
doc->DoForceClose(); doc.DoForceClose();
ImGui::PopID(); ImGui::PopID();
} }
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -8368,26 +8388,25 @@ void ShowExampleAppDocuments(bool* p_open)
//if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway.. //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
// Submit Tabs // Submit Tabs
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
{ {
MyDocument* doc = &app.Documents[doc_n]; if (!doc.Open)
if (!doc->Open)
continue; continue;
ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0); ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags); bool visible = ImGui::BeginTabItem(doc.Name, &doc.Open, tab_flags);
// Cancel attempt to close when unsaved add to save queue so we can display a popup. // Cancel attempt to close when unsaved add to save queue so we can display a popup.
if (!doc->Open && doc->Dirty) if (!doc.Open && doc.Dirty)
{ {
doc->Open = true; doc.Open = true;
doc->DoQueueClose(); doc.DoQueueClose();
} }
MyDocument::DisplayContextMenu(doc); MyDocument::DisplayContextMenu(&doc);
if (visible) if (visible)
{ {
MyDocument::DisplayContents(doc); MyDocument::DisplayContents(&doc);
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
} }
@ -8448,14 +8467,11 @@ void ShowExampleAppDocuments(bool* p_open)
if (close_queue.empty()) if (close_queue.empty())
{ {
// Close queue is locked once we started a popup // Close queue is locked once we started a popup
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++) for (MyDocument& doc : app.Documents)
if (doc.WantClose)
{ {
MyDocument* doc = &app.Documents[doc_n]; doc.WantClose = false;
if (doc->WantClose) close_queue.push_back(&doc);
{
doc->WantClose = false;
close_queue.push_back(doc);
}
} }
} }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (drawing and font code) // (drawing and font code)
/* /*
@ -1355,10 +1355,12 @@ static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags)
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags) void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
{ {
if (rounding >= 0.5f)
{
flags = FixRectCornerFlags(flags); flags = FixRectCornerFlags(flags);
rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
}
if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
{ {
PathLineTo(a); PathLineTo(a);
@ -1896,15 +1898,9 @@ void ImDrawData::DeIndexAllBuffers()
// or if there is a difference between your window resolution and framebuffer resolution. // or if there is a difference between your window resolution and framebuffer resolution.
void ImDrawData::ScaleClipRects(const ImVec2& fb_scale) void ImDrawData::ScaleClipRects(const ImVec2& fb_scale)
{ {
for (int i = 0; i < CmdListsCount; i++) for (ImDrawList* draw_list : CmdLists)
{ for (ImDrawCmd& cmd : draw_list->CmdBuffer)
ImDrawList* cmd_list = CmdLists[i]; cmd.ClipRect = ImVec4(cmd.ClipRect.x * fb_scale.x, cmd.ClipRect.y * fb_scale.y, cmd.ClipRect.z * fb_scale.x, cmd.ClipRect.w * fb_scale.y);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];
cmd->ClipRect = ImVec4(cmd->ClipRect.x * fb_scale.x, cmd->ClipRect.y * fb_scale.y, cmd->ClipRect.z * fb_scale.x, cmd->ClipRect.w * fb_scale.y);
}
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2045,19 +2041,19 @@ ImFontAtlas::~ImFontAtlas()
void ImFontAtlas::ClearInputData() void ImFontAtlas::ClearInputData()
{ {
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
for (int i = 0; i < ConfigData.Size; i++) for (ImFontConfig& font_cfg : ConfigData)
if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas) if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas)
{ {
IM_FREE(ConfigData[i].FontData); IM_FREE(font_cfg.FontData);
ConfigData[i].FontData = NULL; font_cfg.FontData = NULL;
} }
// When clearing this we lose access to the font name and other information used to build the font. // When clearing this we lose access to the font name and other information used to build the font.
for (int i = 0; i < Fonts.Size; i++) for (ImFont* font : Fonts)
if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size) if (font->ConfigData >= ConfigData.Data && font->ConfigData < ConfigData.Data + ConfigData.Size)
{ {
Fonts[i]->ConfigData = NULL; font->ConfigData = NULL;
Fonts[i]->ConfigDataCount = 0; font->ConfigDataCount = 0;
} }
ConfigData.clear(); ConfigData.clear();
CustomRects.clear(); CustomRects.clear();
@ -2862,9 +2858,9 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
} }
// Build all fonts lookup tables // Build all fonts lookup tables
for (int i = 0; i < atlas->Fonts.Size; i++) for (ImFont* font : atlas->Fonts)
if (atlas->Fonts[i]->DirtyLookupTables) if (font->DirtyLookupTables)
atlas->Fonts[i]->BuildLookupTable(); font->BuildLookupTable();
atlas->TexReady = true; atlas->TexReady = true;
} }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -895,7 +895,7 @@ enum ImGuiComboFlagsPrivate_
enum ImGuiSliderFlagsPrivate_ enum ImGuiSliderFlagsPrivate_
{ {
ImGuiSliderFlags_Vertical = 1 << 20, // Should this slider be orientated vertically? ImGuiSliderFlags_Vertical = 1 << 20, // Should this slider be orientated vertically?
ImGuiSliderFlags_ReadOnly = 1 << 21, ImGuiSliderFlags_ReadOnly = 1 << 21, // Consider using g.NextItemData.ItemFlags |= ImGuiItemFlags_ReadOnly instead.
}; };
// Extend ImGuiSelectableFlags_ // Extend ImGuiSelectableFlags_
@ -2209,6 +2209,7 @@ struct ImGuiContext
float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled() float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
short DisabledStackSize; short DisabledStackSize;
short LockMarkEdited;
short TooltipOverrideCount; short TooltipOverrideCount;
ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
@ -2417,6 +2418,7 @@ struct ImGuiContext
ScrollbarClickDeltaToGrabCenter = 0.0f; ScrollbarClickDeltaToGrabCenter = 0.0f;
DisabledAlphaBackup = 0.0f; DisabledAlphaBackup = 0.0f;
DisabledStackSize = 0; DisabledStackSize = 0;
LockMarkEdited = 0;
TooltipOverrideCount = 0; TooltipOverrideCount = 0;
PlatformImeData.InputPos = ImVec2(0.0f, 0.0f); PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
@ -2855,6 +2857,7 @@ struct IMGUI_API ImGuiTable
float RowPosY1; float RowPosY1;
float RowPosY2; float RowPosY2;
float RowMinHeight; // Height submitted to TableNextRow() float RowMinHeight; // Height submitted to TableNextRow()
float RowCellPaddingY; // Top and bottom padding. Reloaded during row change.
float RowTextBaseline; float RowTextBaseline;
float RowIndentOffsetX; float RowIndentOffsetX;
ImGuiTableRowFlags RowFlags : 16; // Current row flags, see ImGuiTableRowFlags_ ImGuiTableRowFlags RowFlags : 16; // Current row flags, see ImGuiTableRowFlags_
@ -2868,9 +2871,8 @@ struct IMGUI_API ImGuiTable
float HostIndentX; float HostIndentX;
float MinColumnWidth; float MinColumnWidth;
float OuterPaddingX; float OuterPaddingX;
float CellPaddingX; // Padding from each borders float CellPaddingX; // Padding from each borders. Locked in BeginTable()/Layout.
float CellPaddingY; float CellSpacingX1; // Spacing between non-bordered cells. Locked in BeginTable()/Layout.
float CellSpacingX1; // Spacing between non-bordered cells
float CellSpacingX2; float CellSpacingX2;
float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
float ColumnsGivenWidth; // Sum of current column width float ColumnsGivenWidth; // Sum of current column width

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (tables and columns code) // (tables and columns code)
/* /*
@ -452,7 +452,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border; table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border;
table->CellSpacingX2 = inner_spacing_explicit; table->CellSpacingX2 = inner_spacing_explicit;
table->CellPaddingX = inner_padding_explicit; table->CellPaddingX = inner_padding_explicit;
table->CellPaddingY = g.Style.CellPadding.y;
const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f; const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f;
@ -469,6 +468,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
table->RowCellPaddingY = 0.0f;
table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; table->FreezeColumnsRequest = table->FreezeColumnsCount = 0;
table->IsUnfrozenRows = true; table->IsUnfrozenRows = true;
@ -1745,19 +1745,20 @@ void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height)
table->LastRowFlags = table->RowFlags; table->LastRowFlags = table->RowFlags;
table->RowFlags = row_flags; table->RowFlags = row_flags;
table->RowCellPaddingY = g.Style.CellPadding.y;
table->RowMinHeight = row_min_height; table->RowMinHeight = row_min_height;
TableBeginRow(table); TableBeginRow(table);
// We honor min_row_height requested by user, but cannot guarantee per-row maximum height, // We honor min_row_height requested by user, but cannot guarantee per-row maximum height,
// because that would essentially require a unique clipping rectangle per-cell. // because that would essentially require a unique clipping rectangle per-cell.
table->RowPosY2 += table->CellPaddingY * 2.0f; table->RowPosY2 += table->RowCellPaddingY * 2.0f;
table->RowPosY2 = ImMax(table->RowPosY2, table->RowPosY1 + row_min_height); table->RowPosY2 = ImMax(table->RowPosY2, table->RowPosY1 + row_min_height);
// Disable output until user calls TableNextColumn() // Disable output until user calls TableNextColumn()
table->InnerWindow->SkipItems = true; table->InnerWindow->SkipItems = true;
} }
// [Internal] Called by TableNextRow() // [Internal] Only called by TableNextRow()
void ImGui::TableBeginRow(ImGuiTable* table) void ImGui::TableBeginRow(ImGuiTable* table)
{ {
ImGuiWindow* window = table->InnerWindow; ImGuiWindow* window = table->InnerWindow;
@ -1778,7 +1779,9 @@ void ImGui::TableBeginRow(ImGuiTable* table)
table->RowPosY1 = table->RowPosY2 = next_y1; table->RowPosY1 = table->RowPosY2 = next_y1;
table->RowTextBaseline = 0.0f; table->RowTextBaseline = 0.0f;
table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent
window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + table->RowCellPaddingY); // This allows users to call SameLine() to share LineSize between columns.
window->DC.PrevLineSize = window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); // This allows users to call SameLine() to share LineSize between columns, and to call it from first column too. window->DC.PrevLineSize = window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); // This allows users to call SameLine() to share LineSize between columns, and to call it from first column too.
window->DC.IsSameLine = window->DC.IsSetPos = false; window->DC.IsSameLine = window->DC.IsSetPos = false;
window->DC.CursorMaxPos.y = next_y1; window->DC.CursorMaxPos.y = next_y1;
@ -2013,10 +2016,10 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
start_x += table->RowIndentOffsetX; // ~~ += window.DC.Indent.x - table->HostIndentX, except we locked it for the row. start_x += table->RowIndentOffsetX; // ~~ += window.DC.Indent.x - table->HostIndentX, except we locked it for the row.
window->DC.CursorPos.x = start_x; window->DC.CursorPos.x = start_x;
window->DC.CursorPos.y = table->RowPosY1 + table->CellPaddingY; window->DC.CursorPos.y = table->RowPosY1 + table->RowCellPaddingY;
window->DC.CursorMaxPos.x = window->DC.CursorPos.x; window->DC.CursorMaxPos.x = window->DC.CursorPos.x;
window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT
window->DC.CursorPosPrevLine = window->DC.CursorPos; // This allows users to call SameLine() to share LineSize between columns. window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x; // PrevLine.y is preserved. This allows users to call SameLine() to share LineSize between columns.
window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; window->DC.CurrLineTextBaseOffset = table->RowTextBaseline;
window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent; window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent;
@ -2071,7 +2074,7 @@ void ImGui::TableEndCell(ImGuiTable* table)
p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
if (column->IsEnabled) if (column->IsEnabled)
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY); table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->RowCellPaddingY);
column->ItemWidth = window->DC.ItemWidth; column->ItemWidth = window->DC.ItemWidth;
// Propagate text baseline for the entire row // Propagate text baseline for the entire row
@ -2673,8 +2676,9 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set) // Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set)
// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since // When 'sort_specs->SpecsDirty == true' you should sort your data. It will be true when sorting specs have
// last call, or the first time. // changed since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting,
// else you may wastefully sort your data every frame!
// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! // Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
{ {
@ -2952,7 +2956,7 @@ void ImGui::TableHeader(const char* label)
// If we already got a row height, there's use that. // If we already got a row height, there's use that.
// FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect? // FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect?
ImRect cell_r = TableGetCellBgRect(table, column_n); ImRect cell_r = TableGetCellBgRect(table, column_n);
float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f); float label_height = ImMax(label_size.y, table->RowMinHeight - table->RowCellPaddingY * 2.0f);
// Calculate ideal size for sort order arrow // Calculate ideal size for sort order arrow
float w_arrow = 0.0f; float w_arrow = 0.0f;

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.9 WIP // dear imgui, v1.89.9
// (widgets code) // (widgets code)
/* /*
@ -2904,6 +2904,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
} }
} }
if (set_new_value)
if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
set_new_value = false;
if (set_new_value) if (set_new_value)
{ {
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
@ -2949,11 +2953,6 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
// Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
// Those are the things we can do easily outside the SliderBehaviorT<> template, saves code generation.
ImGuiContext& g = *GImGui;
if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false;
switch (data_type) switch (data_type)
{ {
case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
@ -5891,6 +5890,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context")) if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
return; return;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.LockMarkEdited++;
ImGuiColorEditFlags opts = g.ColorEditOptions; ImGuiColorEditFlags opts = g.ColorEditOptions;
if (allow_opt_inputs) if (allow_opt_inputs)
{ {
@ -5933,6 +5933,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
g.ColorEditOptions = opts; g.ColorEditOptions = opts;
EndPopup(); EndPopup();
g.LockMarkEdited--;
} }
void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags) void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
@ -5942,6 +5943,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context")) if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
return; return;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.LockMarkEdited++;
if (allow_opt_picker) if (allow_opt_picker)
{ {
ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
@ -5971,6 +5973,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar); CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
} }
EndPopup(); EndPopup();
g.LockMarkEdited--;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -6570,6 +6573,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(bb.Min, bb.Max, col, false, 0.0f); RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
} }
if (g.NavId == id)
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
if (span_all_columns && window->DC.CurrentColumns) if (span_all_columns && window->DC.CurrentColumns)