From 1fe6533192e889dbec22b87d6b8e41e27d3ed9f0 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Apr 2019 16:36:14 +0200 Subject: [PATCH 1/4] Examples: Emscripten: Tweaks for size. (#2494) --- examples/.gitignore | 1 + examples/example_emscripten/Makefile | 6 ++++-- examples/example_emscripten/main.cpp | 8 ++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index 54c0a118..d56b94f0 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -25,6 +25,7 @@ project.xcworkspace xcuserdata ## Emscripten output +*.o.tmp *.out.js *.out.wasm example_emscripten/example_emscripten.* diff --git a/examples/example_emscripten/Makefile b/examples/example_emscripten/Makefile index 6c9865ff..9edfafd0 100644 --- a/examples/example_emscripten/Makefile +++ b/examples/example_emscripten/Makefile @@ -24,10 +24,12 @@ UNAME_S := $(shell uname -s) EMS = -s USE_SDL=2 -s WASM=1 EMS += -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN_TRAP_MODE=clamp EMS += -s DISABLE_EXCEPTION_CATCHING=1 -s NO_EXIT_RUNTIME=0 -EMS += -s ASSERTIONS=1 -s SAFE_HEAP=1 +EMS += -s ASSERTIONS=1 -s NO_FILESYSTEM=1 +#EMS += -s SAFE_HEAP=1 ## Adds overhead CPPFLAGS = -I../ -I../../ -CPPFLAGS += -g -Wall -Wformat -O3 +#CPPFLAGS += -g +CPPFLAGS += -Wall -Wformat -Os CPPFLAGS += $(EMS) LIBS = $(EMS) LDFLAGS = --shell-file shell_minimal.html diff --git a/examples/example_emscripten/main.cpp b/examples/example_emscripten/main.cpp index 847b505a..fc7017d5 100644 --- a/examples/example_emscripten/main.cpp +++ b/examples/example_emscripten/main.cpp @@ -14,7 +14,7 @@ #include #include -// Emscripten requires to have full control over the main loop. We're going to store our SDL book-keeping variables globally. +// Emscripten requires to have full control over the main loop. We're going to store our SDL book-keeping variables globally. // Having a single function that acts as a loop prevents us to store state in the stack of said function. So we need some location for this. SDL_Window* g_Window = NULL; SDL_GLContext g_GLContext = NULL; @@ -63,6 +63,10 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. + // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. + io.IniFilename = NULL; + // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); @@ -90,7 +94,7 @@ int main(int, char**) emscripten_set_main_loop_arg(main_loop, NULL, 0, true); } -void main_loop(void* arg) +void main_loop(void* arg) { ImGuiIO& io = ImGui::GetIO(); IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that. From 8130fd9816fcf25c13f35694655fe3dff7784bad Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Apr 2019 18:47:36 +0200 Subject: [PATCH 2/4] Examples: DirectX10/11/12, Allegro, Marmalade: Render functions early out when display size is zero (minimized). (#2496) --- docs/CHANGELOG.txt | 1 + examples/imgui_impl_allegro5.cpp | 4 ++++ examples/imgui_impl_dx10.cpp | 4 ++++ examples/imgui_impl_dx11.cpp | 4 ++++ examples/imgui_impl_dx12.cpp | 4 ++++ examples/imgui_impl_marmalade.cpp | 4 ++++ 6 files changed, 21 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b9c44824..937583c0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: - Examples: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like. - Examples: Vulkan: Added ImGui_ImplVulkan_SetMinImageCount() to change min image count at runtime. (#2071) [@nathanvoglsam] - Examples: DirectX9: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). (#2454) +- Examples: DirectX10/11/12, Allegro, Marmalade: Render functions early out when display size is zero (minimized). (#2496) - Examples: GLUT: Fixed existing FreeGLUT example to work with regular GLUT. (#2465) [@andrewwillmott] - Examples: GLUT: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h. (#2465) [@andrewwillmott] - Examples: GLUT: Made io.DeltaTime always > 0. (#2430) diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index 3b589c32..ca0444ff 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -64,6 +64,10 @@ struct ImDrawVertAllegro // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) { + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + // Backup Allegro state that will be modified ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ac394348..7bb58859 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -59,6 +59,10 @@ struct VERTEX_CONSTANT_BUFFER // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) { + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + ID3D10Device* ctx = g_pd3dDevice; // Create and grow vertex/index buffers if needed diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 060d86cd..e8d022f6 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -59,6 +59,10 @@ struct VERTEX_CONSTANT_BUFFER // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; // Create and grow vertex/index buffers if needed diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 04fe7fd0..45fb4c79 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -62,6 +62,10 @@ struct VERTEX_CONSTANT_BUFFER // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) { + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + // FIXME: I'm assuming that this only gets called once per frame! // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. g_frameIndex = g_frameIndex + 1; diff --git a/examples/imgui_impl_marmalade.cpp b/examples/imgui_impl_marmalade.cpp index f1eaa99a..1f2307b2 100644 --- a/examples/imgui_impl_marmalade.cpp +++ b/examples/imgui_impl_marmalade.cpp @@ -40,6 +40,10 @@ static ImVec2 g_RenderScale = ImVec2(1.0f,1.0f); // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data) { + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { From 311469e9d638dfa6afe3489536a049e462dc2146 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 16 Apr 2019 11:58:17 +0200 Subject: [PATCH 3/4] Internals: Columns: Some renaming, extracted code into GetColumnsID(). --- imgui.cpp | 83 +++++++++++++++++++++++++++-------------------- imgui_internal.h | 14 ++++---- imgui_widgets.cpp | 14 ++++---- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d46de350..80e7bdbc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2233,8 +2233,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.ColumnsSet) - window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + if (window->DC.CurrentColumns) + window->DC.CurrentColumns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -2597,7 +2597,7 @@ ImGuiWindow::~ImGuiWindow() IM_ASSERT(DrawList == &DrawListInst); IM_DELETE(Name); for (int i = 0; i != ColumnsStorage.Size; i++) - ColumnsStorage[i].~ImGuiColumnsSet(); + ColumnsStorage[i].~ImGuiColumns(); } ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) @@ -5443,7 +5443,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.ColumnsSet = NULL; + window->DC.CurrentColumns = NULL; window->DC.TreeDepth = 0; window->DC.TreeDepthMayJumpToParentOnPop = 0x00; window->DC.StateStorage = &window->StateStorage; @@ -5627,7 +5627,7 @@ void ImGui::End() ImGuiWindow* window = g.CurrentWindow; - if (window->DC.ColumnsSet != NULL) + if (window->DC.CurrentColumns != NULL) EndColumns(); PopClipRect(); // Inner window clip rectangle @@ -6348,8 +6348,8 @@ ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; - if (window->DC.ColumnsSet) - mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x; + if (window->DC.CurrentColumns) + mx.x = GetColumnOffset(window->DC.CurrentColumns->Current + 1) - window->WindowPadding.x; return mx; } @@ -8275,11 +8275,11 @@ void ImGui::NavUpdateWindowingList() void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsSet == NULL) + if (window->SkipItems || window->DC.CurrentColumns == NULL) return; ImGuiContext& g = *GImGui; - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) { @@ -8318,28 +8318,28 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0; + return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1; + return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1; } -static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) +static float OffsetNormToPixels(const ImGuiColumns* columns, float offset_norm) { return offset_norm * (columns->MaxX - columns->MinX); } -static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) +static float PixelsToOffsetNorm(const ImGuiColumns* columns, float offset) { return offset / (columns->MaxX - columns->MinX); } static inline float GetColumnsRectHalfWidth() { return 4.0f; } -static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) +static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. @@ -8359,7 +8359,7 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) @@ -8371,7 +8371,7 @@ float ImGui::GetColumnOffset(int column_index) return x_offset; } -static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false) +static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool before_resize = false) { if (column_index < 0) column_index = columns->Current; @@ -8387,7 +8387,7 @@ static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool b float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) @@ -8399,7 +8399,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) @@ -8420,7 +8420,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) @@ -8431,46 +8431,57 @@ void ImGui::SetColumnWidth(int column_index, float width) void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; if (column_index < 0) column_index = columns->Current; - PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false); + ImGuiColumnData* column = &columns->Columns[column_index]; + PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); } -static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) +ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) { + // We have few columns per window so for now we don't need bother much with turning this into a faster lookup. for (int n = 0; n < window->ColumnsStorage.Size; n++) if (window->ColumnsStorage[n].ID == id) return &window->ColumnsStorage[n]; - window->ColumnsStorage.push_back(ImGuiColumnsSet()); - ImGuiColumnsSet* columns = &window->ColumnsStorage.back(); + window->ColumnsStorage.push_back(ImGuiColumns()); + ImGuiColumns* columns = &window->ColumnsStorage.back(); columns->ID = id; return columns; } -void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) +ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) { - ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported - // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. PushID(0x11223347 + (str_id ? 0 : columns_count)); ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + return id; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + IM_ASSERT(columns_count >= 1); + IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported + + ImGuiID id = GetColumnsID(str_id, columns_count); + // Acquire storage for the columns set - ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); + ImGuiColumns* columns = FindOrCreateColumns(window, id); IM_ASSERT(columns->ID == id); columns->Current = 0; columns->Count = columns_count; columns->Flags = flags; - window->DC.ColumnsSet = columns; + window->DC.CurrentColumns = columns; // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x); @@ -8521,7 +8532,7 @@ void ImGui::EndColumns() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; + ImGuiColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); PopItemWidth(); @@ -8582,7 +8593,7 @@ void ImGui::EndColumns() } columns->IsBeingResized = is_being_resized; - window->DC.ColumnsSet = NULL; + window->DC.CurrentColumns = NULL; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); } @@ -8595,10 +8606,10 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags) + if (window->DC.CurrentColumns != NULL && window->DC.CurrentColumns->Count == columns_count && window->DC.CurrentColumns->Flags == flags) return; - if (window->DC.ColumnsSet != NULL) + if (window->DC.CurrentColumns != NULL) EndColumns(); if (columns_count != 1) @@ -9582,7 +9593,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { for (int n = 0; n < window->ColumnsStorage.Size; n++) { - const ImGuiColumnsSet* columns = &window->ColumnsStorage[n]; + const ImGuiColumns* columns = &window->ColumnsStorage[n]; if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) { ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX); diff --git a/imgui_internal.h b/imgui_internal.h index 7e7ffb44..240a000e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -63,7 +63,7 @@ struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawListSharedData; // Data shared between all ImDrawList instances struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColumnData; // Storage data for a single column -struct ImGuiColumnsSet; // Storage data for a columns set +struct ImGuiColumns; // Storage data for a columns set struct ImGuiContext; // Main imgui context struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box @@ -661,7 +661,7 @@ struct ImGuiColumnData ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; Flags = 0; } }; -struct ImGuiColumnsSet +struct ImGuiColumns { ImGuiID ID; ImGuiColumnsFlags Flags; @@ -675,7 +675,7 @@ struct ImGuiColumnsSet float StartMaxPosX; // Copy of CursorMaxPos ImVector Columns; - ImGuiColumnsSet() { Clear(); } + ImGuiColumns() { Clear(); } void Clear() { ID = 0; @@ -1156,7 +1156,7 @@ struct IMGUI_API ImGuiWindowTempData ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 GroupOffset; ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - ImGuiColumnsSet* ColumnsSet; // Current columns set + ImGuiColumns* CurrentColumns; // Current columns set ImGuiWindowTempData() { @@ -1187,7 +1187,7 @@ struct IMGUI_API ImGuiWindowTempData Indent = ImVec1(0.0f); GroupOffset = ImVec1(0.0f); ColumnsOffset = ImVec1(0.0f); - ColumnsSet = NULL; + CurrentColumns = NULL; } }; @@ -1250,7 +1250,7 @@ struct IMGUI_API ImGuiWindow float ItemWidthDefault; ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; - ImVector ColumnsStorage; + ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window int SettingsIdx; // Index into SettingsWindow[] (indices are always valid as we only grow the array from the back) @@ -1488,6 +1488,8 @@ namespace ImGui IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index = -1); + IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); + IMGUI_API ImGuiColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); // Tab Bars IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 82696d5a..b209f033 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1209,7 +1209,7 @@ void ImGui::Separator() } // Horizontal Separator - if (window->DC.ColumnsSet) + if (window->DC.CurrentColumns) PopClipRect(); float x1 = window->Pos.x; @@ -1221,7 +1221,7 @@ void ImGui::Separator() ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. if (!ItemAdd(bb, 0)) { - if (window->DC.ColumnsSet) + if (window->DC.CurrentColumns) PushColumnClipRect(); return; } @@ -1231,10 +1231,10 @@ void ImGui::Separator() if (g.LogEnabled) LogRenderedText(&bb.Min, "--------------------------------"); - if (window->DC.ColumnsSet) + if (window->DC.CurrentColumns) { PushColumnClipRect(); - window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; + window->DC.CurrentColumns->LineMinY = window->DC.CursorPos.y; } } @@ -5303,7 +5303,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped. + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped. PopClipRect(); ImGuiID id = window->GetID(label); @@ -5347,7 +5347,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } if (!item_add) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) PushColumnClipRect(); return false; } @@ -5392,7 +5392,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) { PushColumnClipRect(); bb.Max.x -= (GetContentRegionMax().x - max_x); From 742b5f4c68fdf05936805e2d119b7ce863b0ed9c Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 16 Apr 2019 13:07:43 +0200 Subject: [PATCH 4/4] Merged a bunch of small changes from Docking branch to reduce the difference between branches. Noticeable: horizontal alignment of CloseButton. Menu fill take account of border. Various stylistic tweaks to accomodate other changes in Docking. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 118 ++++++++++++++++++++++++++++----------------- imgui_demo.cpp | 8 +-- imgui_internal.h | 2 +- 4 files changed, 79 insertions(+), 50 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 937583c0..a91fd118 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Other Changes: - GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero. - Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood] - PlotLines, PlotHistogram: Ignore NaN values when calculating min/max bounds. (#2485) +- Window: Window close button is horizontally aligned with style.FramePadding.x. - Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert to using the ImGui::MemAlloc()/MemFree() calls directly. - Examples: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized diff --git a/imgui.cpp b/imgui.cpp index 80e7bdbc..ee5f6c73 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -914,7 +914,7 @@ CODE (The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse) Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - You can call ImGui::GetBackgroundDrawList() or ImGui::GetForegroundDrawList() and use those draw list to display - contents behind or over every other imgui windows. + contents behind or over every other imgui windows (one bg/fg drawlist per viewport). - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data. @@ -1065,7 +1065,7 @@ static float NavUpdatePageUpPageDown(int allowed_dir_flags); static inline void NavUpdateAnyRequestFlag(); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); static ImVec2 NavCalcPreferredRefPos(); -static void NavSaveLastChildNavWindow(ImGuiWindow* nav_window); +static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); // Misc @@ -3609,6 +3609,7 @@ void ImGui::NewFrame() { ImGuiWindow* window = g.Windows[i]; window->WasActive = window->Active; + window->BeginCount = 0; window->Active = false; window->WriteAccessed = false; } @@ -3791,6 +3792,7 @@ static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWin } } +// Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu) static void AddRootWindowToDrawData(ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -4916,6 +4918,13 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au window->Size = window->SizeFull; } +static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& rect, const ImVec2& padding) +{ + ImGuiContext& g = *GImGui; + ImVec2 size_for_clamping = (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size; + window->Pos = ImMin(rect.Max - padding, ImMax(window->Pos + size_for_clamping, rect.Min + padding) - size_for_clamping); +} + static void ImGui::RenderOuterBorders(ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -5002,18 +5011,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); - // Update Flags, LastFrameActive, BeginOrderXXX fields - if (first_begin_of_the_frame) - window->Flags = (ImGuiWindowFlags)flags; - else - flags = window->Flags; - - // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); - ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; - IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - window->HasCloseButton = (p_open != NULL); - // Update the Appearing flag bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0); @@ -5027,9 +5024,28 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); + // Update Flags, LastFrameActive, BeginOrderXXX fields + if (first_begin_of_the_frame) + { + window->Flags = (ImGuiWindowFlags)flags; + window->LastFrameActive = current_frame; + window->BeginOrderWithinParent = 0; + window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++); + } + else + { + flags = window->Flags; + } + + // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack + ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; + IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); + // Add to stack + // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() g.CurrentWindowStack.push_back(window); - SetCurrentWindow(window); + g.CurrentWindow = NULL; CheckStacksSize(window, true); if (flags & ImGuiWindowFlags_Popup) { @@ -5093,11 +5109,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) UpdateWindowParentAndRootLinks(window, flags, parent_window); window->Active = true; - window->BeginOrderWithinParent = 0; - window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++); - window->BeginCount = 0; + window->HasCloseButton = (p_open != NULL); window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); - window->LastFrameActive = current_frame; window->IDStack.resize(1); // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged). @@ -5143,7 +5156,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetCurrentWindow(window); // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies) - window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; + if (flags & ImGuiWindowFlags_ChildWindow) + window->WindowBorderSize = style.ChildBorderSize; + else + window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; window->WindowPadding = style.WindowPadding; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); @@ -5247,14 +5263,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Clamp position so it stays visible // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. + ImRect viewport_rect(GetViewportRect()); if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) { if (g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. { - ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); - ImVec2 size_for_clamping = ((g.IO.ConfigWindowsMoveFromTitleBarOnly) && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size; - window->Pos = ImMax(window->Pos + size_for_clamping, padding) - size_for_clamping; - window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding); + ImVec2 clamp_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); + ClampWindowRect(window, viewport_rect, clamp_padding); } } window->Pos = ImFloor(window->Pos); @@ -5297,7 +5312,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->Clear(); window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - ImRect viewport_rect(GetViewportRect()); if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else @@ -5364,7 +5378,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImRect menu_bar_rect = window->MenuBarRect(); menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. - window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); + window->DrawList->AddRectFilled(menu_bar_rect.Min+ImVec2(window_border_size,0), menu_bar_rect.Max-ImVec2(window_border_size,0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } @@ -5485,9 +5499,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Close button if (p_open != NULL) { - const float pad = style.FramePadding.y; const float rad = g.FontSize * 0.5f; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1)) + if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1)) *p_open = false; } @@ -5547,7 +5560,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y); - // We fill last item data based on Title Bar, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). + // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // This is useful to allow creating context menus on title bar only, etc. window->DC.LastItemId = window->MoveId; window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; @@ -5557,6 +5570,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId); #endif } + else + { + // Append + SetCurrentWindow(window); + } PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); @@ -7126,14 +7144,6 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } -ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow*) -{ - ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding; - ImRect r_screen = GetViewportRect(); - r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); - return r_screen; -} - // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy) @@ -7189,6 +7199,15 @@ ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& s return pos; } +ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow* window) +{ + IM_UNUSED(window); + ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding; + ImRect r_screen = GetViewportRect(); + r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); + return r_screen; +} + ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -7530,7 +7549,9 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov } } -static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window) +// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). +// This way we could find the last focused window among our children. It would be much less confusing this way? +static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window) { ImGuiWindow* parent_window = nav_window; while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) @@ -7539,7 +7560,8 @@ static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window) parent_window->NavLastChildNavWindow = nav_window; } -// Call when we are expected to land on Layer 0 after FocusWindow() +// Restore the last focused child. +// Call when we are expected to land on the Main Layer (0) after FocusWindow() static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window) { return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window; @@ -7767,7 +7789,7 @@ static void ImGui::NavUpdate() // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0 if (g.NavWindow) - NavSaveLastChildNavWindow(g.NavWindow); + NavSaveLastChildNavWindowIntoParent(g.NavWindow); if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0) g.NavWindow->NavLastChildNavWindow = NULL; @@ -8166,7 +8188,9 @@ static void ImGui::NavUpdateWindowing() // Keyboard: Press and Release ALT to toggle menu layer // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB - if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released)) + if (IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Pressed)) + g.NavWindowingToggleLayer = true; + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && g.NavWindowingToggleLayer && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released)) if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) apply_toggle_layer = true; @@ -8212,7 +8236,8 @@ static void ImGui::NavUpdateWindowing() { // Move to parent menu if necessary ImGuiWindow* new_nav_window = g.NavWindow; - while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0 + while (new_nav_window->ParentWindow + && (new_nav_window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) new_nav_window = new_nav_window->ParentWindow; @@ -8224,7 +8249,10 @@ static void ImGui::NavUpdateWindowing() } g.NavDisableHighlight = false; g.NavDisableMouseHover = true; - NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main); + + // When entering a regular menu bar with the Alt key, we always reinitialize the navigation ID. + const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main; + NavRestoreLayer(new_nav_layer); } } @@ -9515,7 +9543,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - if (show_draw_cmd_clip_rects && ImGui::IsItemHovered()) + if (show_draw_cmd_clip_rects && fg_draw_list && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; @@ -9544,7 +9572,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) (n == 0) ? "idx" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); - if (ImGui::IsItemHovered()) + if (fg_draw_list && ImGui::IsItemHovered()) { ImDrawListFlags backup_flags = fg_draw_list->Flags; fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d8707f42..9b732c3f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4267,16 +4267,16 @@ void ShowExampleAppDocuments(bool* p_open) { static ExampleAppDocuments app; + // Options + static bool opt_reorderable = true; + static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_; + if (!ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar)) { ImGui::End(); return; } - // Options - static bool opt_reorderable = true; - static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_; - // Menu if (ImGui::BeginMenuBar()) { diff --git a/imgui_internal.h b/imgui_internal.h index 240a000e..1b0fd35c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1221,7 +1221,7 @@ struct IMGUI_API ImGuiWindow bool WantCollapseToggle; bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) - bool Hidden; // Do not display (== (HiddenFramesForResize > 0) || + bool Hidden; // Do not display (== (HiddenFrames*** > 0)) bool HasCloseButton; // Set when the window has a close button (p_open != NULL) signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)