From 66c428129051b278d252de9b1ec66443e49d48da Mon Sep 17 00:00:00 2001 From: Geoffrey Tucker Date: Sat, 29 Oct 2016 15:44:08 -0700 Subject: [PATCH 001/101] Began improvements to columns API by splitting the Columns() function into BeginColumns() and EndColumns() and adding additional flags. The columns data still needs to be placed into a stack. --- imgui.cpp | 202 ++++++++++++++++++++++++++++++----------------- imgui.h | 33 +++++--- imgui_demo.cpp | 43 ++++++++++ imgui_draw.cpp | 4 +- imgui_internal.h | 6 +- 5 files changed, 199 insertions(+), 89 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 07466840b..8761f7843 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3507,7 +3507,7 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) bool ImGui::BeginPopup(const char* str_id) { - if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance + if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; @@ -9175,7 +9175,7 @@ void ImGui::EndGroup() ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls + IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls ImGuiGroupData& group_data = window->DC.GroupStack.back(); @@ -9295,6 +9295,18 @@ int ImGui::GetColumnsCount() return window->DC.ColumnsCount; } +static float OffsetNormToPixels(float offsetNorm) +{ + ImGuiWindow* window = ImGui::GetCurrentWindowRead(); + return offsetNorm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); +} + +static float PixelsToOffsetNorm(float offset) +{ + ImGuiWindow* window = ImGui::GetCurrentWindowRead(); + return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); +} + static float GetDraggedColumnOffset(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 @@ -9305,7 +9317,9 @@ static float GetDraggedColumnOffset(int column_index) IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; - x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing); + x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); + if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return (float)(int)x; } @@ -9332,16 +9346,26 @@ float ImGui::GetColumnOffset(int column_index) void ImGui::SetColumnOffset(int column_index, float offset) { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); - window->DC.ColumnsData[column_index].OffsetNorm = t; + + const bool preserveWidth = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const float width = preserveWidth ? GetColumnWidth(column_index) : 0.0f; + + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); + const float offsetNorm = PixelsToOffsetNorm(offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, t); + window->DC.StateStorage->SetFloat(column_id, offsetNorm); + window->DC.ColumnsData[column_index].OffsetNorm = offsetNorm; + + if (preserveWidth) + SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } float ImGui::GetColumnWidth(int column_index) @@ -9350,8 +9374,16 @@ float ImGui::GetColumnWidth(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); - return w; + return OffsetNormToPixels(window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); +} + +void ImGui::SetColumnWidth(int column_index, float width) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + if (column_index < 0) + column_index = window->DC.ColumnsCurrent; + + SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } static void PushColumnClipRect(int column_index) @@ -9365,56 +9397,12 @@ static void PushColumnClipRect(int column_index) ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); } -void ImGui::Columns(int columns_count, const char* id, bool border) +void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - - if (window->DC.ColumnsCount != 1) - { - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0,0)); // Advance to column 0 - PopItemWidth(); - PopClipRect(); - window->DrawList->ChannelsMerge(); - - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - } - - // Draw columns borders and handle resize at the time of "closing" a columns set - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems) - { - const float y1 = window->DC.ColumnsStartPosY; - const float y2 = window->DC.CursorPos.y; - for (int i = 1; i < window->DC.ColumnsCount; i++) - { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const ImRect column_rect(ImVec2(x-4,y1),ImVec2(x+4,y2)); - if (IsClippedEx(column_rect, &column_id, false)) - continue; - - bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - - // Draw before resize so our items positioning are in sync with the line being drawn - const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1+1.0f), ImVec2(xi, y2), col); - - if (held) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) - x = GetDraggedColumnOffset(i); - SetColumnOffset(i, x); - } - } - } + IM_ASSERT(columns_count > 1); + IM_ASSERT(window->DC.ColumnsCount == 1); // 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. @@ -9425,7 +9413,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) // Set state for first column window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = columns_count; - window->DC.ColumnsShowBorders = border; + window->DC.ColumnsFlags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range @@ -9435,26 +9423,92 @@ void ImGui::Columns(int columns_count, const char* id, bool border) window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - if (window->DC.ColumnsCount != 1) + // Cache column offsets + window->DC.ColumnsData.resize(columns_count + 1); + for (int column_index = 0; column_index < columns_count + 1; column_index++) { - // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); - for (int column_index = 0; column_index < columns_count + 1; column_index++) - { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; - const float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) - window->DC.ColumnsData[column_index].OffsetNorm = t; - } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); - PushColumnClipRect(); - PushItemWidth(GetColumnWidth() * 0.65f); - } - else - { - window->DC.ColumnsData.resize(0); + const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + KeepAliveID(column_id); + const float default_t = column_index / (float)window->DC.ColumnsCount; + float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); + window->DC.ColumnsData[column_index].OffsetNorm = t; } + window->DrawList->ChannelsSplit(window->DC.ColumnsCount); + PushColumnClipRect(); + PushItemWidth(GetColumnWidth() * 0.65f); +} + +void ImGui::EndColumns() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(window->DC.ColumnsCount > 1); + + if (window->DC.ColumnsCurrent != 0) + ItemSize(ImVec2(0, 0)); // Advance to column 0 + PopItemWidth(); + PopClipRect(); + window->DrawList->ChannelsMerge(); + + window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + + // Draw columns borders and handle resize + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + { + const float y1 = window->DC.ColumnsStartPosY; + const float y2 = window->DC.CursorPos.y; + for (int i = 1; i < window->DC.ColumnsCount; i++) + { + float x = window->Pos.x + GetColumnOffset(i); + const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + const ImRect column_rect(ImVec2(x - 4, y1), ImVec2(x + 4, y2)); + if (IsClippedEx(column_rect, &column_id, false)) + continue; + + bool hovered, held; + ButtonBehavior(column_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + + // Draw before resize so our items positioning are in sync with the line being drawn + const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + + if (held) + { + if (g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) + x = GetDraggedColumnOffset(i); + SetColumnOffset(i, x); + } + } + } + + window->DC.ColumnsSetId = 0; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsCount = 1; + window->DC.ColumnsFlags = 0; + window->DC.ColumnsData.resize(0); +} + +void ImGui::Columns(int columns_count, const char* id, bool border) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(columns_count >= 1); + + ImGuiColumnsFlags flags = 0; + flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); + + if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) + EndColumns(); + + if (columns_count != 1) + BeginColumns(id, columns_count, flags); } void ImGui::Indent(float indent_w) diff --git a/imgui.h b/imgui.h index edb1d68d5..548d9cc65 100644 --- a/imgui.h +++ b/imgui.h @@ -73,6 +73,7 @@ typedef int ImGuiKey; // a key identifier (ImGui-side enum) // e typedef int ImGuiColorEditMode; // color edit mode for ColorEdit*() // enum ImGuiColorEditMode_ typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_ typedef int ImGuiWindowFlags; // window flags for Begin*() // enum ImGuiWindowFlags_ +typedef int ImGuiColumnsFlags; // column flags for Columns() // enum ImGuiColumnsFlags_ typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ @@ -221,13 +222,16 @@ namespace ImGui // Columns // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1). - IMGUI_API void NextColumn(); // next column - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API float GetColumnWidth(int column_index = -1); // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset()) - IMGUI_API int GetColumnsCount(); // number of columns (what was passed to Columns()) + IMGUI_API void BeginColumns(const char* 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 NextColumn(); // next column, defaults to current row or next row if the current row is finished + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column + IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this + IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column + IMGUI_API int GetColumnsCount(); + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. @@ -418,7 +422,7 @@ namespace ImGui IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame + IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame IMGUI_API void EndChildFrame(); IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); @@ -506,6 +510,15 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; +// Flags for ImGui::Columns() +enum ImGuiColumnsFlags_ +{ + // Default: 0 + ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window +}; + // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { @@ -1029,8 +1042,8 @@ struct ImGuiTextEditCallbackData struct ImGuiSizeConstraintCallbackData { void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 544d6230f..3ebdb8ab7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1400,6 +1400,49 @@ void ImGui::ShowTestWindow(bool* p_open) } */ + if (ImGui::TreeNode("Advanced settings")) + { + static bool border = true; + static bool preserveWidths = true; + static bool forceWithinWindow = true; + + ImGui::Checkbox("Border", &border); + ImGui::SameLine(); + ImGui::Checkbox("Preserve widths", &preserveWidths); + ImGui::SameLine(); + ImGui::Checkbox("Force within window", &forceWithinWindow); + + ImGuiColumnsFlags flags = 0; + flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); + flags |= (preserveWidths ? 0 : ImGuiColumnsFlags_NoPreserveWidths); + flags |= (forceWithinWindow ? 0 : ImGuiColumnsFlags_NoForceWithinWindow); + + ImGui::BeginColumns("AdvancedColumns", 4, flags); + ImGui::Separator(); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Text("Flags"); ImGui::NextColumn(); + ImGui::Separator(); + const char* names[3] = { "One", "Two", "Three" }; + const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; + static int selected = -1; + for (int i = 0; i < 3; i++) + { + char label[32]; + sprintf(label, "%04d", i); + if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) + selected = i; + ImGui::NextColumn(); + ImGui::Text(names[i]); ImGui::NextColumn(); + ImGui::Text(paths[i]); ImGui::NextColumn(); + ImGui::Text("...."); ImGui::NextColumn(); + } + ImGui::EndColumns(); + ImGui::Separator(); + ImGui::TreePop(); + } + // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ade417771..99004adcf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1145,8 +1145,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); - if (!new_font_cfg.DstFont) - new_font_cfg.DstFont = Fonts.back(); + if (!new_font_cfg.DstFont) + new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); diff --git a/imgui_internal.h b/imgui_internal.h index 08f206adc..9eed7b943 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -282,7 +282,7 @@ struct ImGuiGroupData // Per column data for Columns() struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) //float IndentX; }; @@ -571,7 +571,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsStartPosY; float ColumnsCellMinY; float ColumnsCellMaxY; - bool ColumnsShowBorders; + ImGuiColumnsFlags ColumnsFlags; ImGuiID ColumnsSetId; ImVector ColumnsData; @@ -603,7 +603,7 @@ struct IMGUI_API ImGuiDrawContext ColumnsMinX = ColumnsMaxX = 0.0f; ColumnsStartPosY = 0.0f; ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsShowBorders = true; + ColumnsFlags = 0; ColumnsSetId = 0; } }; From ad3c1e68ab8dcb44a6f5602fd9f5e149323b7398 Mon Sep 17 00:00:00 2001 From: Nicolas Guillemot Date: Tue, 16 May 2017 16:43:59 -0700 Subject: [PATCH 002/101] save and restore sampler in GL 3 examples --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 3 +++ examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index dd02d8b1e..155ab2b99 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -48,6 +48,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) glActiveTexture(GL_TEXTURE0); GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -107,6 +108,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glBindSampler(0, 0); // rely on combined texture/sampler state. glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } @@ -117,6 +119,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) // Restore modified GL state glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); + glBindSampler(0, last_sampler); glActiveTexture(last_active_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 7b7dacaa4..77e33442b 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -42,6 +42,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) glActiveTexture(GL_TEXTURE0); GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); @@ -101,6 +102,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glBindSampler(0, 0); // rely on combined texture/sampler state. glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } @@ -111,6 +113,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) // Restore modified GL state glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); + glBindSampler(0, last_sampler); glActiveTexture(last_active_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); From d970957e2de0780bec50ed05c9f412df6db08dad Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 17 Aug 2017 19:36:48 +0800 Subject: [PATCH 003/101] ImFontAtlas: Draft of an api to submit custom rectangle (not exposed). Atlas default texture chunk using it. (WIP: we are still storing mouse UV outside in GImGui) --- imgui.h | 16 +++- imgui_draw.cpp | 224 +++++++++++++++++++++++++++++-------------------- 2 files changed, 145 insertions(+), 95 deletions(-) diff --git a/imgui.h b/imgui.h index 681ad9be5..19f01c85f 100644 --- a/imgui.h +++ b/imgui.h @@ -1388,10 +1388,22 @@ struct ImFontAtlas ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. - // Private + // [Private] User rectangle for packing custom texture data into the atlas. + struct CustomRect + { + unsigned int ID; // Input // User ID. <0x10000 for font mapped data (WIP/UNSUPPORTED), >=0x10000 for other texture data + unsigned short Width, Height; // Input // Desired rectangle dimension + unsigned short X, Y; // Output // Packed position in Atlas + CustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; } + bool IsPacked() const { return X != 0xFFFF; } + }; + + // [Private] Members + ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. ImVector ConfigData; // Internal data IMGUI_API bool Build(); // Build pixels data. This is automatically for you by the GetTexData*** functions. - IMGUI_API void RenderCustomTexData(int pass, void* rects); + IMGUI_API int CustomRectRegister(unsigned int id, int width, int height); + IMGUI_API void CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); }; // Font runtime data and rendering diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6f817db1b..579fe6f0f 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1059,6 +1059,42 @@ ImFontConfig::ImFontConfig() // ImFontAtlas //----------------------------------------------------------------------------- +// A work of art lies ahead! (. = white layer, X = black layer, others are blank) +// The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. +const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 90; +const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; +const int FONT_ATLAS_DEFAULT_TEX_DATA_ID = 0xF0000; +const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = +{ + "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" + "..- -X.....X- X.X - X.X -X.....X - X.....X" + "--- -XXX.XXX- X...X - X...X -X....X - X....X" + "X - X.X - X.....X - X.....X -X...X - X...X" + "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" + "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" + "X..X - X.X - X.X - X.X -XX X.X - X.X XX" + "X...X - X.X - X.X - XX X.X XX - X.X - X.X " + "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " + "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " + "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " + "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " + "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " + "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " + "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " + "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " + "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " + "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" + "X.X X..X - -X.......X- X.......X - XX XX - " + "XX X..X - - X.....X - X.....X - X.X X.X - " + " X..X - X...X - X...X - X..X X..X - " + " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " + "------------ - X - X -X.....................X- " + " ----------------------------------- X...XXXXXXXXXXXXX...X - " + " - X..X X..X - " + " - X.X X.X - " + " - XX XX - " +}; + ImFontAtlas::ImFontAtlas() { TexID = NULL; @@ -1091,6 +1127,7 @@ void ImFontAtlas::ClearInputData() Fonts[i]->ConfigDataCount = 0; } ConfigData.clear(); + CustomRects.clear(); } void ImFontAtlas::ClearTexData() @@ -1277,6 +1314,29 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed return font; } +int ImFontAtlas::CustomRectRegister(unsigned int id, int width, int height) +{ + IM_ASSERT(width > 0 && width <= 0xFFFF); + IM_ASSERT(height > 0 && height <= 0xFFFF); + CustomRect r; + r.ID = id; + r.Width = (unsigned short)width; + r.Height = (unsigned short)height; + CustomRects.push_back(r); + return CustomRects.Size - 1; // Return index +} + +void ImFontAtlas::CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) +{ + IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates + IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed + *out_uv_min = ImVec2((float)rect->X / TexWidth, (float)rect->Y / TexHeight); + *out_uv_max = ImVec2((float)(rect->X + rect->Width) / TexWidth, (float)(rect->Y + rect->Height) / TexHeight); +} + +static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc); +static void BuildRenderDefaultTexData(ImFontAtlas* atlas); + bool ImFontAtlas::Build() { IM_ASSERT(ConfigData.Size > 0); @@ -1299,7 +1359,7 @@ bool ImFontAtlas::Build() } // Start packing. We need a known width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. - // After packing is done, width shouldn't matter much, but some API/GPU have texture size limitations and increasing width can decrease height. + // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; TexHeight = 0; const int max_tex_height = 1024*32; @@ -1307,13 +1367,10 @@ bool ImFontAtlas::Build() stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, TexGlyphPadding, NULL); // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - ImVector extra_rects; - RenderCustomTexData(0, &extra_rects); - stbtt_PackSetOversampling(&spc, 1, 1); - stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rects[0], extra_rects.Size); - for (int i = 0; i < extra_rects.Size; i++) - if (extra_rects[i].was_packed) - TexHeight = ImMax(TexHeight, extra_rects[i].y + extra_rects[i].h); + // FIXME-WIP: We should register in the constructor (but cannot because our static instances may not have allocator ready by the time they initialize). This needs to be fixed because we can expose CustomRects. + if (CustomRects.empty()) + CustomRectRegister(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); + BuildPackCustomRects(this, &spc); // Initialize font information (so we can error without any cleanup) struct ImFontTempBuildData @@ -1476,100 +1533,81 @@ bool ImFontAtlas::Build() ImGui::MemFree(tmp_array); // Render into our custom data block - RenderCustomTexData(1, &extra_rects); + BuildRenderDefaultTexData(this); return true; } -void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) +static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc) { - // A work of art lies ahead! (. = white layer, X = black layer, others are blank) - // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes. - const int TEX_DATA_W = 90; - const int TEX_DATA_H = 27; - const char texture_data[TEX_DATA_W*TEX_DATA_H+1] = + ImVector& user_rects = atlas->CustomRects; + ImVector pack_rects; + pack_rects.resize(user_rects.Size); + memset(pack_rects.Data, 0, sizeof(stbrp_rect) * user_rects.Size); + for (int i = 0; i < user_rects.Size; i++) { - "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" - "..- -X.....X- X.X - X.X -X.....X - X.....X" - "--- -XXX.XXX- X...X - X...X -X....X - X....X" - "X - X.X - X.....X - X.....X -X...X - X...X" - "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" - "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" - "X..X - X.X - X.X - X.X -XX X.X - X.X XX" - "X...X - X.X - X.X - XX X.X XX - X.X - X.X " - "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " - "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " - "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " - "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " - "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " - "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " - "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " - "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " - "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " - "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" - "X.X X..X - -X.......X- X.......X - XX XX - " - "XX X..X - - X.....X - X.....X - X.X X.X - " - " X..X - X...X - X...X - X..X X..X - " - " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " - "------------ - X - X -X.....................X- " - " ----------------------------------- X...XXXXXXXXXXXXX...X - " - " - X..X X..X - " - " - X.X X.X - " - " - XX XX - " + pack_rects[i].w = user_rects[i].Width; + pack_rects[i].h = user_rects[i].Height; + } + stbtt_PackSetOversampling(spc, 1, 1); + stbrp_pack_rects((stbrp_context*)spc->pack_info, &pack_rects[0], pack_rects.Size); + for (int i = 0; i < pack_rects.Size; i++) + if (pack_rects[i].was_packed) + { + user_rects[i].X = pack_rects[i].x; + user_rects[i].Y = pack_rects[i].y; + IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); + atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); + } +} + +static void BuildRenderDefaultTexData(ImFontAtlas* atlas) +{ + ImFontAtlas::CustomRect& r = atlas->CustomRects[0]; + IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); + IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1); + IM_ASSERT(r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); + IM_ASSERT(r.IsPacked()); + IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); + + // Render/copy pixels + for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++) + for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++) + { + const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * atlas->TexWidth; + const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; + atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; + } + const ImVec2 tex_uv_scale(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); + atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * tex_uv_scale.x, (r.Y + 0.5f) * tex_uv_scale.y); + + // Setup mouse cursors + const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] = + { + // Pos ........ Size ......... Offset ...... + { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow + { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput + { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move + { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS + { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW + { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW + { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE }; - ImVector& rects = *(ImVector*)p_rects; - if (pass == 0) + for (int type = 0; type < ImGuiMouseCursor_Count_; type++) { - // Request rectangles - stbrp_rect r; - memset(&r, 0, sizeof(r)); - r.w = (TEX_DATA_W*2)+1; - r.h = TEX_DATA_H+1; - rects.push_back(r); - } - else if (pass == 1) - { - // Render/copy pixels - const stbrp_rect& r = rects[0]; - for (int y = 0, n = 0; y < TEX_DATA_H; y++) - for (int x = 0; x < TEX_DATA_W; x++, n++) - { - const int offset0 = (int)(r.x + x) + (int)(r.y + y) * TexWidth; - const int offset1 = offset0 + 1 + TEX_DATA_W; - TexPixelsAlpha8[offset0] = texture_data[n] == '.' ? 0xFF : 0x00; - TexPixelsAlpha8[offset1] = texture_data[n] == 'X' ? 0xFF : 0x00; - } - const ImVec2 tex_uv_scale(1.0f / TexWidth, 1.0f / TexHeight); - TexUvWhitePixel = ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y); - - // Setup mouse cursors - const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] = - { - // Pos ........ Size ......... Offset ...... - { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow - { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput - { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move - { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS - { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW - { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW - { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE - }; - - for (int type = 0; type < ImGuiMouseCursor_Count_; type++) - { - ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type]; - ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y); - const ImVec2 size = cursor_datas[type][1]; - cursor_data.Type = type; - cursor_data.Size = size; - cursor_data.HotOffset = cursor_datas[type][2]; - cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; - pos.x += TEX_DATA_W+1; - cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; - } + ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type]; + ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.X, (float)r.Y); + const ImVec2 size = cursor_datas[type][1]; + cursor_data.Type = type; + cursor_data.Size = size; + cursor_data.HotOffset = cursor_datas[type][2]; + cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; + cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; + pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; + cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; } } From 4075cc58e9e2ee53b69fc8a2ad8286b01c63811a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 17 Aug 2017 20:44:44 +0800 Subject: [PATCH 004/101] ImFontAtlas; Re-arranging code to simplify implementation of imgui_freetype (#618) --- imgui_draw.cpp | 33 ++++++++++++++++++++------------- imgui_internal.h | 5 +++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 579fe6f0f..96f258c00 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1334,13 +1334,12 @@ void ImFontAtlas::CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, I *out_uv_max = ImVec2((float)(rect->X + rect->Width) / TexWidth, (float)(rect->Y + rect->Height) / TexHeight); } -static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc); -static void BuildRenderDefaultTexData(ImFontAtlas* atlas); - bool ImFontAtlas::Build() { IM_ASSERT(ConfigData.Size > 0); + ImFontAtlasBuildRegisterDefaultCustomRects(this); + TexID = NULL; TexWidth = TexHeight = 0; TexUvWhitePixel = ImVec2(0, 0); @@ -1358,19 +1357,19 @@ bool ImFontAtlas::Build() total_glyphs_count += (in_range[1] - in_range[0]) + 1; } - // Start packing. We need a known width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. + // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; TexHeight = 0; + + // Start packing const int max_tex_height = 1024*32; stbtt_pack_context spc; stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, TexGlyphPadding, NULL); + stbtt_PackSetOversampling(&spc, 1, 1); // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - // FIXME-WIP: We should register in the constructor (but cannot because our static instances may not have allocator ready by the time they initialize). This needs to be fixed because we can expose CustomRects. - if (CustomRects.empty()) - CustomRectRegister(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); - BuildPackCustomRects(this, &spc); + ImFontAtlasBuildPackCustomRects(this, spc.pack_info); // Initialize font information (so we can error without any cleanup) struct ImFontTempBuildData @@ -1533,13 +1532,22 @@ bool ImFontAtlas::Build() ImGui::MemFree(tmp_array); // Render into our custom data block - BuildRenderDefaultTexData(this); + ImFontAtlasBuildRenderDefaultTexData(this); return true; } -static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc) +void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas) { + // FIXME-WIP: We should register in the constructor (but cannot because our static instances may not have allocator ready by the time they initialize). This needs to be fixed because we can expose CustomRects. + if (atlas->CustomRects.empty()) + atlas->CustomRectRegister(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); +} + +void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque) +{ + stbrp_context* pack_context = (stbrp_context*)pack_context_opaque; + ImVector& user_rects = atlas->CustomRects; ImVector pack_rects; pack_rects.resize(user_rects.Size); @@ -1549,8 +1557,7 @@ static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc) pack_rects[i].w = user_rects[i].Width; pack_rects[i].h = user_rects[i].Height; } - stbtt_PackSetOversampling(spc, 1, 1); - stbrp_pack_rects((stbrp_context*)spc->pack_info, &pack_rects[0], pack_rects.Size); + stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size); for (int i = 0; i < pack_rects.Size; i++) if (pack_rects[i].was_packed) { @@ -1561,7 +1568,7 @@ static void BuildPackCustomRects(ImFontAtlas* atlas, stbtt_pack_context* spc) } } -static void BuildRenderDefaultTexData(ImFontAtlas* atlas) +void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) { ImFontAtlas::CustomRect& r = atlas->CustomRects[0]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); diff --git a/imgui_internal.h b/imgui_internal.h index 0d8981278..310878049 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -792,6 +792,11 @@ namespace ImGui } // namespace ImGui +// ImFontAtlas +IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc); +IMGUI_API void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas); + #ifdef __clang__ #pragma clang diagnostic pop #endif From 1086c877671eabd394fbb178de88b446bfd04528 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 17 Aug 2017 21:13:14 +0800 Subject: [PATCH 005/101] ImFontAtlas: Re-arranging code to simplify implementation of imgui_freetype. (#618) --- imgui_draw.cpp | 44 +++++++++++++++++++++++++++----------------- imgui_internal.h | 3 ++- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 96f258c00..7f9ff56ec 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1477,20 +1477,9 @@ bool ImFontAtlas::Build() float ascent = unscaled_ascent * font_scale; float descent = unscaled_descent * font_scale; - if (!cfg.MergeMode) - { - dst_font->ContainerAtlas = this; - dst_font->ConfigData = &cfg; - dst_font->ConfigDataCount = 0; - dst_font->FontSize = cfg.SizePixels; - dst_font->Ascent = ascent; - dst_font->Descent = descent; - dst_font->Glyphs.resize(0); - dst_font->MetricsTotalSurface = 0; - } - dst_font->ConfigDataCount++; + ImFontAtlasBuildSetupFont(this, dst_font, &cfg, ascent, descent); float off_x = cfg.GlyphOffset.x; - float off_y = cfg.GlyphOffset.y; + float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (int i = 0; i < tmp.RangesCount; i++) @@ -1513,11 +1502,16 @@ bool ImFontAtlas::Build() dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1); ImFont::Glyph& glyph = dst_font->Glyphs.back(); glyph.Codepoint = (ImWchar)codepoint; - glyph.X0 = q.x0 + off_x; glyph.Y0 = q.y0 + off_y; glyph.X1 = q.x1 + off_x; glyph.Y1 = q.y1 + off_y; - glyph.U0 = q.s0; glyph.V0 = q.t0; glyph.U1 = q.s1; glyph.V1 = q.t1; - glyph.Y0 += (float)(int)(dst_font->Ascent + 0.5f); - glyph.Y1 += (float)(int)(dst_font->Ascent + 0.5f); + glyph.X0 = q.x0 + off_x; + glyph.Y0 = q.y0 + off_y; + glyph.X1 = q.x1 + off_x; + glyph.Y1 = q.y1 + off_y; + glyph.U0 = q.s0; + glyph.V0 = q.t0; + glyph.U1 = q.s1; + glyph.V1 = q.t1; glyph.XAdvance = (pc.xadvance + cfg.GlyphExtraSpacing.x); // Bake spacing into XAdvance + if (cfg.PixelSnapH) glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f); dst_font->MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round @@ -1544,6 +1538,22 @@ void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas) atlas->CustomRectRegister(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); } +void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) +{ + if (!font_config->MergeMode) + { + font->ContainerAtlas = atlas; + font->ConfigData = font_config; + font->ConfigDataCount = 0; + font->FontSize = font_config->SizePixels; + font->Ascent = ascent; + font->Descent = descent; + font->Glyphs.resize(0); + font->MetricsTotalSurface = 0; + } + font->ConfigDataCount++; +} + void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque) { stbrp_context* pack_context = (stbrp_context*)pack_context_opaque; diff --git a/imgui_internal.h b/imgui_internal.h index 310878049..09f696282 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -792,8 +792,9 @@ namespace ImGui } // namespace ImGui -// ImFontAtlas +// ImFontAtlas internals IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc); IMGUI_API void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas); From 8be7a60f206899ab66a280582d45505176d18945 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 17 Aug 2017 21:19:54 +0800 Subject: [PATCH 006/101] ImFontAtlas: Re-arranging code to simplify implementation of imgui_freetype. (#618) --- imgui_draw.cpp | 72 ++++++++++++++++++++++++++---------------------- imgui_internal.h | 1 + 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 7f9ff56ec..bacbd7f5d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1336,40 +1336,45 @@ void ImFontAtlas::CustomRectCalcUV(const CustomRect* rect, ImVec2* out_uv_min, I bool ImFontAtlas::Build() { - IM_ASSERT(ConfigData.Size > 0); + return ImFontAtlasBuildWithStbTruetype(this); +} - ImFontAtlasBuildRegisterDefaultCustomRects(this); +bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) +{ + IM_ASSERT(atlas->ConfigData.Size > 0); - TexID = NULL; - TexWidth = TexHeight = 0; - TexUvWhitePixel = ImVec2(0, 0); - ClearTexData(); + ImFontAtlasBuildRegisterDefaultCustomRects(atlas); + + atlas->TexID = NULL; + atlas->TexWidth = atlas->TexHeight = 0; + atlas->TexUvWhitePixel = ImVec2(0, 0); + atlas->ClearTexData(); // Count glyphs/ranges int total_glyphs_count = 0; int total_ranges_count = 0; - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; if (!cfg.GlyphRanges) - cfg.GlyphRanges = GetGlyphRangesDefault(); + cfg.GlyphRanges = atlas->GetGlyphRangesDefault(); for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, total_ranges_count++) total_glyphs_count += (in_range[1] - in_range[0]) + 1; } // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; - TexHeight = 0; + atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; + atlas->TexHeight = 0; // Start packing const int max_tex_height = 1024*32; stbtt_pack_context spc; - stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, TexGlyphPadding, NULL); + stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL); stbtt_PackSetOversampling(&spc, 1, 1); // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - ImFontAtlasBuildPackCustomRects(this, spc.pack_info); + ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info); // Initialize font information (so we can error without any cleanup) struct ImFontTempBuildData @@ -1379,12 +1384,13 @@ bool ImFontAtlas::Build() stbtt_pack_range* Ranges; int RangesCount; }; - ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)ConfigData.Size * sizeof(ImFontTempBuildData)); - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)atlas->ConfigData.Size * sizeof(ImFontTempBuildData)); + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == this)); + IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0); if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) @@ -1401,9 +1407,9 @@ bool ImFontAtlas::Build() memset(buf_ranges, 0, total_ranges_count * sizeof(stbtt_pack_range)); // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point) - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; // Setup ranges @@ -1436,23 +1442,23 @@ bool ImFontAtlas::Build() // Extend texture height for (int i = 0; i < n; i++) if (tmp.Rects[i].was_packed) - TexHeight = ImMax(TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); + atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); } IM_ASSERT(buf_rects_n == total_glyphs_count); IM_ASSERT(buf_packedchars_n == total_glyphs_count); IM_ASSERT(buf_ranges_n == total_ranges_count); // Create texture - TexHeight = ImUpperPowerOfTwo(TexHeight); - TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(TexWidth * TexHeight); - memset(TexPixelsAlpha8, 0, TexWidth * TexHeight); - spc.pixels = TexPixelsAlpha8; - spc.height = TexHeight; + atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); + memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); + spc.pixels = atlas->TexPixelsAlpha8; + spc.height = atlas->TexHeight; // Second pass: render font characters - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); @@ -1465,9 +1471,9 @@ bool ImFontAtlas::Build() buf_rects = NULL; // Third pass: setup ImFont and glyphs for runtime - for (int input_i = 0; input_i < ConfigData.Size; input_i++) + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) { - ImFontConfig& cfg = ConfigData[input_i]; + ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) @@ -1477,7 +1483,7 @@ bool ImFontAtlas::Build() float ascent = unscaled_ascent * font_scale; float descent = unscaled_descent * font_scale; - ImFontAtlasBuildSetupFont(this, dst_font, &cfg, ascent, descent); + ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); float off_x = cfg.GlyphOffset.x; float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); @@ -1497,7 +1503,7 @@ bool ImFontAtlas::Build() stbtt_aligned_quad q; float dummy_x = 0.0f, dummy_y = 0.0f; - stbtt_GetPackedQuad(range.chardata_for_range, TexWidth, TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); + stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0); dst_font->Glyphs.resize(dst_font->Glyphs.Size + 1); ImFont::Glyph& glyph = dst_font->Glyphs.back(); @@ -1514,7 +1520,7 @@ bool ImFontAtlas::Build() if (cfg.PixelSnapH) glyph.XAdvance = (float)(int)(glyph.XAdvance + 0.5f); - dst_font->MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round + dst_font->MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * atlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * atlas->TexHeight + 1.99f); // +1 to account for average padding, +0.99 to round } } cfg.DstFont->BuildLookupTable(); @@ -1526,7 +1532,7 @@ bool ImFontAtlas::Build() ImGui::MemFree(tmp_array); // Render into our custom data block - ImFontAtlasBuildRenderDefaultTexData(this); + ImFontAtlasBuildRenderDefaultTexData(atlas); return true; } diff --git a/imgui_internal.h b/imgui_internal.h index 09f696282..31ae2613c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -793,6 +793,7 @@ namespace ImGui } // namespace ImGui // ImFontAtlas internals +IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc); From 3b11e73333e5e2356a454d4c661d4776fc6770d5 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 15:17:37 +0800 Subject: [PATCH 007/101] Examples: gitignore added patterns for modern MSVC versions --- examples/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/.gitignore b/examples/.gitignore index 4a3d57c08..9516dc7f6 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -42,6 +42,8 @@ sdl_opengl3_example/x64/* *.exe *.pdb *.ilk +*.VC.db +*.VC.VC.opendb ## Ini files imgui.ini From 91d841dd5f0d5f5c7452f20f353539f2b3cb9efa Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 15:28:12 +0800 Subject: [PATCH 008/101] Added PushStyleColor(ImGuiCol idx, ImU32 col) overload. (Which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.) --- imgui.cpp | 12 ++++++++++++ imgui.h | 7 ++++--- imgui_demo.cpp | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5a935aac7..c3721cdfb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -204,6 +204,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow(), note that most uses relied on default parameters completely. - 2017/08/13 (1.51) - renamed ImGuiCol_Columns_*** to ImGuiCol_Separator_*** @@ -4712,6 +4713,17 @@ void ImGui::PopTextWrapPos() window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back(); } +// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 +void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) +{ + ImGuiContext& g = *GImGui; + ImGuiColMod backup; + backup.Col = idx; + backup.BackupValue = g.Style.Colors[idx]; + g.ColorModifiers.push_back(backup); + g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); +} + void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 19f01c85f..1c36d89f4 100644 --- a/imgui.h +++ b/imgui.h @@ -180,6 +180,7 @@ namespace ImGui // Parameters stacks (shared) IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font IMGUI_API void PopFont(); + IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); IMGUI_API void PopStyleColor(int count = 1); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); @@ -1095,8 +1096,8 @@ struct ImGuiSizeConstraintCallbackData // ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) // Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API. -// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. -// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. +// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE. +// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed. struct ImColor { ImVec4 Value; @@ -1109,8 +1110,8 @@ struct ImColor inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } inline operator ImVec4() const { return Value; } + // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers. inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } - static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); } }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 78e527f7a..70ac68133 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -285,9 +285,9 @@ void ImGui::ShowTestWindow(bool* p_open) { if (i > 0) ImGui::SameLine(); ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i/7.0f, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i/7.0f, 0.8f, 0.8f)); + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f)); ImGui::Button("Click"); ImGui::PopStyleColor(3); ImGui::PopID(); @@ -913,10 +913,10 @@ void ImGui::ShowTestWindow(bool* p_open) { if (i > 0) ImGui::SameLine(); ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i/7.0f, 0.6f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i/7.0f, 0.7f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); + ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f)); ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); if (ImGui::IsItemActive() || ImGui::IsItemHovered()) ImGui::SetTooltip("%.3f", values[i]); @@ -1271,9 +1271,9 @@ void ImGui::ShowTestWindow(bool* p_open) char num_buf[16]; const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf); float hue = n*0.05f; - ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(hue, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(hue, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(hue, 0.8f, 0.8f)); + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f)); ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f)); ImGui::PopStyleColor(3); ImGui::PopID(); From 1065a7b95b6ca4e0b69ca83fe56b4f729ad7320f Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 15:38:05 +0800 Subject: [PATCH 009/101] ImFontAtlas::AddFontDefault: Made it possible to override size (even if it isn't really recommended) --- imgui_draw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bacbd7f5d..85ef6a927 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1253,9 +1253,10 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.PixelSnapH = true; } if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px"); + if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, 13.0f, &font_cfg, GetGlyphRangesDefault()); + ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, GetGlyphRangesDefault()); return font; } From fd394e1e95474bb658c48086ac7edf0719aa7c7e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 16:39:11 +0800 Subject: [PATCH 010/101] Scrollbar: Comments. Fixed potential div-by-zero error which I can repro now, so added an assert to notify us if it's actually ever useful or not. --- imgui.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c3721cdfb..ab4ad2b80 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4490,15 +4490,17 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); - // V denote the main axis of the scrollbar + // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y; float win_size_avail_v = (horizontal ? window->SizeFull.x : window->SizeFull.y) - other_scrollbar_size_w; float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y; - // The grabbable box size generally represent the amount visible (vs the total scrollable amount) + // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) // But we maintain a minimum size in pixel to allow for the user to still aim inside. - const float grab_h_pixels = ImMin(ImMax(scrollbar_size_v * ImSaturate(win_size_avail_v / ImMax(win_size_contents_v, win_size_avail_v)), style.GrabMinSize), scrollbar_size_v); + IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. + const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f); + const float grab_h_pixels = ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v); const float grab_h_norm = grab_h_pixels / scrollbar_size_v; // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). From cf84650ee8443a56ff02d044879a83a3feeca9ff Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 16:39:43 +0800 Subject: [PATCH 011/101] GCC warnings fixes --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index ab4ad2b80..982624694 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -577,6 +577,8 @@ #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers +#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked +#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" #endif //------------------------------------------------------------------------- From af2db53780d45da88c3a1e9b1ae8f36ce67a954a Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 17:50:25 +0800 Subject: [PATCH 012/101] Added GetStyleColorVec4() --- imgui.cpp | 6 ++++++ imgui.h | 1 + 2 files changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 982624694..ca38cc8ea 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1212,6 +1212,12 @@ ImU32 ImGui::GetColorU32(const ImVec4& col) return ColorConvertFloat4ToU32(c); } +const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) +{ + ImGuiStyle& style = GImGui->Style; + return style.Colors[idx]; +} + ImU32 ImGui::GetColorU32(ImU32 col) { float style_alpha = GImGui->Style.Alpha; diff --git a/imgui.h b/imgui.h index 1c36d89f4..de4a913f4 100644 --- a/imgui.h +++ b/imgui.h @@ -186,6 +186,7 @@ namespace ImGui IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); IMGUI_API void PopStyleVar(int count = 1); + IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwhise use GetColorU32() to get style color + style alpha. IMGUI_API ImFont* GetFont(); // get current font IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API From b4eeb4aa8d5a102daf9bf8a5f6ce9b5cb1fdd33f Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 17:53:09 +0800 Subject: [PATCH 013/101] Renamed GetStyleColName() to GetStyleColorName() for consistency. Extra comments in Api Breaking Changes section. --- imgui.cpp | 5 +++-- imgui.h | 2 +- imgui_demo.cpp | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ca38cc8ea..b21228275 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -204,9 +204,10 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. - 2016/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. - - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow(), note that most uses relied on default parameters completely. + - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. - 2017/08/13 (1.51) - renamed ImGuiCol_Columns_*** to ImGuiCol_Separator_*** - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete). - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton(). @@ -4826,7 +4827,7 @@ void ImGui::PopStyleVar(int count) } } -const char* ImGui::GetStyleColName(ImGuiCol idx) +const char* ImGui::GetStyleColorName(ImGuiCol idx) { // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; switch (idx) diff --git a/imgui.h b/imgui.h index de4a913f4..5c8737c22 100644 --- a/imgui.h +++ b/imgui.h @@ -426,7 +426,7 @@ namespace ImGui IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API float GetTime(); IMGUI_API int GetFrameCount(); - IMGUI_API const char* GetStyleColName(ImGuiCol idx); + IMGUI_API const char* GetStyleColorName(ImGuiCol idx); IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 70ac68133..4b901acfc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1831,7 +1831,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) for (int i = 0; i < ImGuiCol_COUNT; i++) { const ImVec4& col = style.Colors[i]; - const char* name = ImGui::GetStyleColName(i); + const char* name = ImGui::GetStyleColorName(i); if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0) ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w); } @@ -1854,7 +1854,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::PushItemWidth(-160); for (int i = 0; i < ImGuiCol_COUNT; i++) { - const char* name = ImGui::GetStyleColName(i); + const char* name = ImGui::GetStyleColorName(i); if (!filter.PassFilter(name)) continue; ImGui::PushID(i); @@ -2028,7 +2028,7 @@ static void ShowExampleMenuFile() if (ImGui::BeginMenu("Colors")) { for (int i = 0; i < ImGuiCol_COUNT; i++) - ImGui::MenuItem(ImGui::GetStyleColName((ImGuiCol)i)); + ImGui::MenuItem(ImGui::GetStyleColorName((ImGuiCol)i)); ImGui::EndMenu(); } if (ImGui::BeginMenu("Disabled", false)) // Disabled From 19a42cb2fd864291419250e8c258a94761d620f2 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 18:44:48 +0800 Subject: [PATCH 014/101] Columns: Moved BeginColumns/EndColumns/flags from #913 to imgui_internals.h + minor shallow tweaks. Removed demo code temporarily. (#125) --- imgui.cpp | 26 ++++++++++++-------------- imgui.h | 15 ++------------- imgui_demo.cpp | 43 ------------------------------------------- imgui_internal.h | 14 +++++++++++++- 4 files changed, 27 insertions(+), 71 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8e774ab69..fbaf08013 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9928,15 +9928,13 @@ int ImGui::GetColumnsCount() return window->DC.ColumnsCount; } -static float OffsetNormToPixels(float offsetNorm) +static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm) { - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); - return offsetNorm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); } -static float PixelsToOffsetNorm(float offset) +static float PixelsToOffsetNorm(ImGuiWindow* window, float offset) { - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); } @@ -9986,18 +9984,18 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const bool preserveWidth = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); - const float width = preserveWidth ? GetColumnWidth(column_index) : 0.0f; + const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); - const float offsetNorm = PixelsToOffsetNorm(offset); + const float offset_norm = PixelsToOffsetNorm(window, offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, offsetNorm); - window->DC.ColumnsData[column_index].OffsetNorm = offsetNorm; + window->DC.StateStorage->SetFloat(column_id, offset_norm); + window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; - if (preserveWidth) + if (preserve_width) SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } @@ -10007,7 +10005,7 @@ float ImGui::GetColumnWidth(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - return OffsetNormToPixels(window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); + return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) @@ -10066,7 +10064,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl const float default_t = column_index / (float)window->DC.ColumnsCount; float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); + t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); window->DC.ColumnsData[column_index].OffsetNorm = t; } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); @@ -10098,7 +10096,7 @@ void ImGui::EndColumns() { float x = window->Pos.x + GetColumnOffset(i); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const float column_w = 4.0f; + const float column_w = 4.0f; // Width for interaction const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); if (IsClippedEx(column_rect, &column_id, false)) continue; diff --git a/imgui.h b/imgui.h index 8c6687a29..4fc0a9f98 100644 --- a/imgui.h +++ b/imgui.h @@ -231,9 +231,8 @@ namespace ImGui IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y // Columns - // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void BeginColumns(const char* 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 + // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column @@ -241,7 +240,6 @@ namespace ImGui IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. @@ -524,15 +522,6 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; -// Flags for ImGui::Columns() -enum ImGuiColumnsFlags_ -{ - // Default: 0 - ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers - ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns - ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window -}; - // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 862e55333..4b901acfc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1553,49 +1553,6 @@ void ImGui::ShowTestWindow(bool* p_open) } */ - if (ImGui::TreeNode("Advanced settings")) - { - static bool border = true; - static bool preserveWidths = true; - static bool forceWithinWindow = true; - - ImGui::Checkbox("Border", &border); - ImGui::SameLine(); - ImGui::Checkbox("Preserve widths", &preserveWidths); - ImGui::SameLine(); - ImGui::Checkbox("Force within window", &forceWithinWindow); - - ImGuiColumnsFlags flags = 0; - flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); - flags |= (preserveWidths ? 0 : ImGuiColumnsFlags_NoPreserveWidths); - flags |= (forceWithinWindow ? 0 : ImGuiColumnsFlags_NoForceWithinWindow); - - ImGui::BeginColumns("AdvancedColumns", 4, flags); - ImGui::Separator(); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Text("Flags"); ImGui::NextColumn(); - ImGui::Separator(); - const char* names[3] = { "One", "Two", "Three" }; - const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; - static int selected = -1; - for (int i = 0; i < 3; i++) - { - char label[32]; - sprintf(label, "%04d", i); - if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) - selected = i; - ImGui::NextColumn(); - ImGui::Text(names[i]); ImGui::NextColumn(); - ImGui::Text(paths[i]); ImGui::NextColumn(); - ImGui::Text("...."); ImGui::NextColumn(); - } - ImGui::EndColumns(); - ImGui::Separator(); - ImGui::TreePop(); - } - // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { diff --git a/imgui_internal.h b/imgui_internal.h index e83ebbe5d..7d7f3fa87 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -183,6 +183,14 @@ enum ImGuiSliderFlags_ ImGuiSliderFlags_Vertical = 1 << 0 }; +enum ImGuiColumnsFlags_ +{ + // Default: 0 + ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window +}; + enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ @@ -598,7 +606,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsStartPosY; float ColumnsCellMinY; float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; + ImGuiColumnsFlags ColumnsFlags; ImGuiID ColumnsSetId; ImVector ColumnsData; @@ -748,6 +756,10 @@ namespace ImGui IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API bool IsPopupOpen(ImGuiID id); + // New Columns API + IMGUI_API void BeginColumns(const char* 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 + // NB: All position are in absolute pixels coordinates (never using window coordinates internally) // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); From 3bf2af23e641909890a568850e5dac8ebf8930f8 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 18:44:54 +0800 Subject: [PATCH 015/101] Columns: Fixed EndColumns() not repositioning the cursor. (#913) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index fbaf08013..0837b93dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10126,6 +10126,8 @@ void ImGui::EndColumns() window->DC.ColumnsCount = 1; window->DC.ColumnsFlags = 0; window->DC.ColumnsData.resize(0); + window->DC.ColumnsOffsetX = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } // [2017/08: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] From a511b00226c31654b4cf99e027d6d51baf19d710 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:19:31 +0800 Subject: [PATCH 016/101] Columns: Fixed offset rounding leading to SetColumnOffset() being destructive when ImGuiColumnsFlags_NoPreserveWidths flag is not set. (#913, #125) --- imgui.cpp | 6 +++--- imgui.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0837b93dd..08d63a8f5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9952,7 +9952,7 @@ static float GetDraggedColumnOffset(int column_index) if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); - return (float)(int)x; + return x; } float ImGui::GetColumnOffset(int column_index) @@ -9972,7 +9972,7 @@ float ImGui::GetColumnOffset(int column_index) IM_ASSERT(column_index < window->DC.ColumnsData.Size); const float t = window->DC.ColumnsData[column_index].OffsetNorm; const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t); - return (float)(int)x_offset; + return x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) @@ -9988,7 +9988,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); + offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); const float offset_norm = PixelsToOffsetNorm(window, offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); diff --git a/imgui.h b/imgui.h index 4fc0a9f98..7c102f7d5 100644 --- a/imgui.h +++ b/imgui.h @@ -237,7 +237,7 @@ namespace ImGui IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); From 9307631c901aae10601dd669a98c9793064004fe Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:25:29 +0800 Subject: [PATCH 017/101] Columns: Removed unnecessary/misleading dummy ItemSize(). Was fixed already before, and fixed again in this branch by 3bf2af23e641909890a568850e5dac8ebf8930f8. (#913, #125). End() calls EndColumns() directly. --- imgui.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 08d63a8f5..fb43a4e60 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4450,7 +4450,7 @@ void ImGui::End() ImGuiWindow* window = g.CurrentWindow; if (window->DC.ColumnsCount != 1) // close columns set if any is open - Columns(1, "#CLOSECOLUMNS"); + EndColumns(); PopClipRect(); // inner window clip rectangle // Stop logging @@ -10078,8 +10078,6 @@ void ImGui::EndColumns() ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(window->DC.ColumnsCount > 1); - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0, 0)); // Advance to column 0 PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); From e70d49ba1f32b9a39550c32656468cb62f5bc964 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:30:57 +0800 Subject: [PATCH 018/101] Columns: Fixed one form of shearing during resizing columns with PreserveWidth enabled (there's another issue still). (#913, #125) --- imgui.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fb43a4e60..f32523cfe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9996,7 +9996,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; if (preserve_width) - SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); + SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } float ImGui::GetColumnWidth(int column_index) @@ -10090,6 +10090,7 @@ void ImGui::EndColumns() { const float y1 = window->DC.ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; + int dragging_column = -1; for (int i = 1; i < window->DC.ColumnsCount; i++) { float x = window->Pos.x + GetColumnOffset(i); @@ -10098,25 +10099,28 @@ void ImGui::EndColumns() const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); if (IsClippedEx(column_rect, &column_id, false)) continue; - - bool hovered, held; + + bool hovered, held; ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). + if (held) + dragging_column = i; - // Draw before resize so our items positioning are in sync with the line being drawn - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + // Draw column + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + } - if (held) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking) - x = GetDraggedColumnOffset(i); - SetColumnOffset(i, x); - } - } + // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. + if (dragging_column != -1) + { + float x = GetDraggedColumnOffset(dragging_column); + SetColumnOffset(dragging_column, x); + } } window->DC.ColumnsSetId = 0; From 7f0063f85849ae51eb3d291426cfc3e9da1b1507 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:32:18 +0800 Subject: [PATCH 019/101] Columns: Added ImGuiColumnsFlags_NoResize flag (internal). (#913, #125) --- imgui.cpp | 19 +++++++++++-------- imgui_internal.h | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f32523cfe..7c7a76369 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10100,14 +10100,17 @@ void ImGui::EndColumns() if (IsClippedEx(column_rect, &column_id, false)) continue; - bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - if (held && g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). - if (held) - dragging_column = i; + bool hovered = false, held = false; + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) + { + ButtonBehavior(column_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). + if (held) + dragging_column = i; + } // Draw column const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); diff --git a/imgui_internal.h b/imgui_internal.h index 7d7f3fa87..f73cdcc88 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -187,8 +187,9 @@ enum ImGuiColumnsFlags_ { // Default: 0 ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers - ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns - ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window + ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3 // Disable forcing columns to fit within window }; enum ImGuiSelectableFlagsPrivate_ From 1c83b073c66341ea7b22d7dd42916094c9a0fdeb Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:37:04 +0800 Subject: [PATCH 020/101] Columns: A set of column (and most importantly the right-most column) do not register its content to the parent, not affecting the window contents size. (#519, #125, #913) --- imgui.cpp | 3 +++ imgui_internal.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 7c7a76369..f20646e82 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4345,6 +4345,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = 1; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; + window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; @@ -10051,6 +10052,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; + window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); @@ -10084,6 +10086,7 @@ void ImGui::EndColumns() window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Columns don't grow parent // Draw columns borders and handle resize if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) diff --git a/imgui_internal.h b/imgui_internal.h index f73cdcc88..d47c77025 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -605,6 +605,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsMinX; float ColumnsMaxX; float ColumnsStartPosY; + float ColumnsStartMaxPosX; // Backup of CursorMaxPos float ColumnsCellMinY; float ColumnsCellMaxY; ImGuiColumnsFlags ColumnsFlags; @@ -638,6 +639,7 @@ struct IMGUI_API ImGuiDrawContext ColumnsCount = 1; ColumnsMinX = ColumnsMaxX = 0.0f; ColumnsStartPosY = 0.0f; + ColumnsStartMaxPosX = 0.0f; ColumnsCellMinY = ColumnsCellMaxY = 0.0f; ColumnsFlags = 0; ColumnsSetId = 0; From 7ff1c149b5657ee83c9146b6a467040ca0bbe921 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:40:25 +0800 Subject: [PATCH 021/101] Columns: Fixed another form of shearing made visible by the PreserveWidth option. The code was initially added in c46d5634d43c9f0296d845478c07b04f2c40d339 to fix because we've fixed in e42aaede42eb6d8a47cf104f3afd6057b13a61ee. (#913, #125) --- imgui.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f20646e82..a7ff91224 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9958,17 +9958,19 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { - ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; + /* if (g.ActiveId) { + ImGuiContext& g = *GImGui; const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); if (g.ActiveId == column_id) return GetDraggedColumnOffset(column_index); } + */ IM_ASSERT(column_index < window->DC.ColumnsData.Size); const float t = window->DC.ColumnsData[column_index].OffsetNorm; @@ -10148,6 +10150,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); + //flags |= ImGuiColumnsFlags_NoPreserveWidths | ImGuiColumnsFlags_NoForceWithinWindow; // NB: Legacy behavior if (columns_count != 1) BeginColumns(id, columns_count, flags); } From 1ebd7ec0494a1b97ee5ce06ad0ffb4d0964d7bff Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:56:11 +0800 Subject: [PATCH 022/101] Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913) --- imgui.cpp | 2 +- imgui_demo.cpp | 79 +++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a7ff91224..33b9178fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10150,7 +10150,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); - //flags |= ImGuiColumnsFlags_NoPreserveWidths | ImGuiColumnsFlags_NoForceWithinWindow; // NB: Legacy behavior + //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior if (columns_count != 1) BeginColumns(id, columns_count, flags); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4b901acfc..73a658086 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1527,32 +1527,6 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - // Scrolling columns - /* - if (ImGui::TreeNode("Scrolling")) - { - ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); - ImGui::Columns(3); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::EndChild(); - ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); - ImGui::Columns(3); - for (int i = 0; i < 10; i++) - { - ImGui::Text("%04d", i); ImGui::NextColumn(); - ImGui::Text("Foobar"); ImGui::NextColumn(); - ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::EndChild(); - ImGui::TreePop(); - } - */ - // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { @@ -1570,7 +1544,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("An extra line here."); ImGui::NextColumn(); - ImGui::Text("Sailor"); + ImGui::Text("Sailor"); ImGui::Button("Corniflower"); static float bar = 1.0f; ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); @@ -1607,14 +1581,59 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(); ImGui::Checkbox("vertical", &v_borders); ImGui::Columns(4, NULL, v_borders); - if (h_borders) ImGui::Separator(); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 4*3; i++) { + if (h_borders && ImGui::GetColumnIndex() == 0) + ImGui::Separator(); ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i); + ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset()); ImGui::NextColumn(); } ImGui::Columns(1); - if (h_borders) ImGui::Separator(); + if (h_borders) + ImGui::Separator(); + ImGui::TreePop(); + } + + // Scrolling columns + /* + if (ImGui::TreeNode("Vertical Scrolling")) + { + ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); + ImGui::Columns(3); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::EndChild(); + ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); + ImGui::Columns(3); + for (int i = 0; i < 10; i++) + { + ImGui::Text("%04d", i); ImGui::NextColumn(); + ImGui::Text("Foobar"); ImGui::NextColumn(); + ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::EndChild(); + ImGui::TreePop(); + } + */ + + if (ImGui::TreeNode("Horizontal Scrolling")) + { + ImGui::SetNextWindowContentWidth(2000); + ImGui::BeginChild("##scrollingregion", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::Columns(10); + for (int i = 0; i < 20; i++) + for (int j = 0; j < 10; j++) + { + ImGui::Text("Line %d Column %d", i, j); + ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::EndChild(); ImGui::TreePop(); } From 83e8d10fabc1b8a9cf069c64edeba53b65e6be63 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 21:08:07 +0800 Subject: [PATCH 023/101] Columns: Columns set resize based on the presence of vertical scrollbar. Not 100% sure about that but it looks like we've fixed enough bugs that this may not cause troubles anymore. (#125, #913, #893, #1138) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 33b9178fe..c677e79d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10052,7 +10052,8 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - window->ScrollbarSizes.x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; From 54bdd00df752008d01c50e9847564ef2357c5d56 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 21:32:18 +0800 Subject: [PATCH 024/101] Columns: Fix for explicit content width and scrollbar. (#519, #125) --- imgui.cpp | 4 ++-- imgui_demo.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c677e79d5..2f05901bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10050,10 +10050,10 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl window->DC.ColumnsCount = columns_count; window->DC.ColumnsFlags = flags; - const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; + const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - window->ScrollbarSizes.x; + window->DC.ColumnsMaxX = content_region_width - window->Scroll.x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 73a658086..8911bcf2a 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1623,13 +1623,13 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Horizontal Scrolling")) { - ImGui::SetNextWindowContentWidth(2000); + ImGui::SetNextWindowContentWidth(1500); ImGui::BeginChild("##scrollingregion", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Columns(10); for (int i = 0; i < 20; i++) for (int j = 0; j < 10; j++) { - ImGui::Text("Line %d Column %d", i, j); + ImGui::Text("Line %d Column %d...", i, j); ImGui::NextColumn(); } ImGui::Columns(1); From adeaf1cd72163646e523e1365f542a6dcad37791 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 23:09:43 +0800 Subject: [PATCH 025/101] Columns: Moved PushColumnClipRect() to imgui_internal.h --- imgui.cpp | 3 +-- imgui_internal.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2f05901bb..2fa316b29 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -617,7 +617,6 @@ static void LoadIniSettingsFromDisk(const char* ini_filename); static void SaveIniSettingsToDisk(const char* ini_filename); static void MarkIniSettingsDirty(); -static void PushColumnClipRect(int column_index = -1); static ImRect GetVisibleRect(); static bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); @@ -10020,7 +10019,7 @@ void ImGui::SetColumnWidth(int column_index, float width) SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } -static void PushColumnClipRect(int column_index) +void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = ImGui::GetCurrentWindow(); if (column_index < 0) diff --git a/imgui_internal.h b/imgui_internal.h index d47c77025..23a6db845 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -762,6 +762,7 @@ namespace ImGui // New Columns API IMGUI_API void BeginColumns(const char* 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); // NB: All position are in absolute pixels coordinates (never using window coordinates internally) // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. From 067127f11351fa68bdb76f6c3664f9bd40e757b9 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 23:17:59 +0800 Subject: [PATCH 026/101] Columns: Caching columns clipping rectangles (#125) --- imgui.cpp | 20 ++++++++++++++------ imgui_internal.h | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2fa316b29..e62af2fa9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8607,7 +8607,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.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) // FIXME-OPT: Avoid if vertically clipped. PopClipRect(); ImGuiID id = window->GetID(label); @@ -10021,13 +10021,11 @@ void ImGui::SetColumnWidth(int column_index, float width) void ImGui::PushColumnClipRect(int column_index) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); + ImGuiWindow* window = GetCurrentWindowRead(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; - float x1 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index) - 1.0f); - float x2 = ImFloor(0.5f + window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1.0f); - ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); + PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false); } void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) @@ -10066,11 +10064,21 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); KeepAliveID(column_id); const float default_t = column_index / (float)window->DC.ColumnsCount; - float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) + float t = window->DC.StateStorage->GetFloat(column_id, default_t); if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); window->DC.ColumnsData[column_index].OffsetNorm = t; } + + // Cache clipping rectangles + for (int column_index = 0; column_index < columns_count; column_index++) + { + float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); + float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); + window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + window->DC.ColumnsData[column_index].ClipRect.Clip(window->ClipRect); + } + window->DrawList->ChannelsSplit(window->DC.ColumnsCount); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); diff --git a/imgui_internal.h b/imgui_internal.h index 23a6db845..c3fdb7e49 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -316,6 +316,7 @@ struct ImGuiGroupData struct ImGuiColumnData { float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; //float IndentX; }; From 9b484d24cd048afa746ecb479bb7ed466db218f9 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 23:45:02 +0800 Subject: [PATCH 027/101] ImDrawList: Added GetClipRectMin(), GetClipRectMax() helpers. Comments. --- TODO.txt | 2 +- imgui.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index eac6d7473..944df651b 100644 --- a/TODO.txt +++ b/TODO.txt @@ -26,7 +26,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: expose contents size. (#1045) - window: GetWindowSize() returns (0,0) when not calculated? (#1045) !- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet. - - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y) + - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro) - drawlist: move Font, FontSize, FontTexUvWhitePixel inside ImDrawList and make it self-contained (apart from drawing settings?) - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally diff --git a/imgui.h b/imgui.h index 7c102f7d5..249183a92 100644 --- a/imgui.h +++ b/imgui.h @@ -1233,6 +1233,8 @@ struct ImDrawList IMGUI_API void PopClipRect(); IMGUI_API void PushTextureID(const ImTextureID& texture_id); IMGUI_API void PopTextureID(); + inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } + inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } // Primitives IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); From 530baee1a7f2901d86adedfa8990c726f66b154c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 21 Aug 2017 00:03:37 +0800 Subject: [PATCH 028/101] Removed tabs that slipped through the cracks --- imgui.cpp | 52 ++++++++++++++++++++++++------------------------ imgui_internal.h | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e62af2fa9..d40553f13 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10086,32 +10086,32 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl void ImGui::EndColumns() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->DC.ColumnsCount > 1); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(window->DC.ColumnsCount > 1); - PopItemWidth(); - PopClipRect(); - window->DrawList->ChannelsMerge(); + PopItemWidth(); + PopClipRect(); + window->DrawList->ChannelsMerge(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Columns don't grow parent - // Draw columns borders and handle resize - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) - { - const float y1 = window->DC.ColumnsStartPosY; - const float y2 = window->DC.CursorPos.y; + // Draw columns borders and handle resize + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + { + const float y1 = window->DC.ColumnsStartPosY; + const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < window->DC.ColumnsCount; i++) - { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + for (int i = 1; i < window->DC.ColumnsCount; i++) + { + float x = window->Pos.x + GetColumnOffset(i); + const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); const float column_w = 4.0f; // Width for interaction const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); - if (IsClippedEx(column_rect, &column_id, false)) - continue; + if (IsClippedEx(column_rect, &column_id, false)) + continue; bool hovered = false, held = false; if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) @@ -10137,13 +10137,13 @@ void ImGui::EndColumns() float x = GetDraggedColumnOffset(dragging_column); SetColumnOffset(dragging_column, x); } - } + } - window->DC.ColumnsSetId = 0; - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsFlags = 0; - window->DC.ColumnsData.resize(0); + window->DC.ColumnsSetId = 0; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsCount = 1; + window->DC.ColumnsFlags = 0; + window->DC.ColumnsData.resize(0); window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } @@ -10155,7 +10155,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) IM_ASSERT(columns_count >= 1); if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) - EndColumns(); + EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior diff --git a/imgui_internal.h b/imgui_internal.h index c3fdb7e49..99372b17b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -743,7 +743,7 @@ namespace ImGui IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void ClearActiveID(); + IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); From 543dc2817f7dfd5ecbf790d9ebe5ac930e20e885 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 21 Aug 2017 22:54:20 +0800 Subject: [PATCH 029/101] Fixed an assert when calling CloseCurrentPopup() twice in a row. --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d40553f13..59de6793a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3495,7 +3495,7 @@ void ImGui::CloseCurrentPopup() { ImGuiContext& g = *GImGui; int popup_idx = g.CurrentPopupStack.Size - 1; - if (popup_idx < 0 || popup_idx > g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) + if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) return; while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu)) popup_idx--; @@ -3549,7 +3549,6 @@ bool ImGui::BeginPopup(const char* str_id) return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_ShowBorders); } -// FIXME bool ImGui::IsPopupOpen(ImGuiID id) { ImGuiContext& g = *GImGui; From 6ee317d26d782ece9828f906a45c068d45a459b2 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 17:46:50 +0800 Subject: [PATCH 030/101] ImRect::Clip() -> ClipWith() to clarify meaning, going to undo the change in Nav branch. --- imgui.cpp | 8 ++++---- imgui_internal.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 59de6793a..0396108a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3103,7 +3103,7 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c // Clip ImRect rect_clipped(r_min, r_max); if (clip) - rect_clipped.Clip(window->ClipRect); + rect_clipped.ClipWith(window->ClipRect); // Expand for touch input const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); @@ -4390,7 +4390,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() window->WindowRectClipped = window->Rect(); - window->WindowRectClipped.Clip(window->ClipRect); + window->WindowRectClipped.ClipWith(window->ClipRect); // Pressing CTRL+C while holding on a window copy its content to the clipboard // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. @@ -8213,7 +8213,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); - rect.Clip(clip_rect); + rect.ClipWith(clip_rect); if (rect.Overlaps(clip_rect)) draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); } @@ -10075,7 +10075,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - window->DC.ColumnsData[column_index].ClipRect.Clip(window->ClipRect); + window->DC.ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); diff --git a/imgui_internal.h b/imgui_internal.h index 99372b17b..2bfef8420 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -267,7 +267,7 @@ struct IMGUI_API ImRect void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } - void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } + void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const { From d5b0d51274d59417a5a3dfcb81c58a37c04cffde Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 18:13:10 +0800 Subject: [PATCH 031/101] Minor miscellaneous merges from Navigation branch to reduce divergence a little bit --- imgui.cpp | 104 ++++++++++++++++++++++++----------------------- imgui_internal.h | 13 +++--- 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0396108a7..c76a6db7b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -615,7 +615,7 @@ static ImGuiIniData* FindWindowSettings(const char* name); static ImGuiIniData* AddWindowSettings(const char* name); static void LoadIniSettingsFromDisk(const char* ini_filename); static void SaveIniSettingsToDisk(const char* ini_filename); -static void MarkIniSettingsDirty(); +static void MarkIniSettingsDirty(ImGuiWindow* window); static ImRect GetVisibleRect(); @@ -742,6 +742,7 @@ ImGuiIO::ImGuiIO() // Most fields are initialized with zero memset(this, 0, sizeof(*this)); + // Settings DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f/60.0f; IniSavingRate = 5.0f; @@ -774,6 +775,7 @@ ImGuiIO::ImGuiIO() SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ClipboardUserData = NULL; ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; + ImeWindowHandle = NULL; // Set OS X style defaults based on __APPLE__ compile time flag #ifdef __APPLE__ @@ -1934,7 +1936,6 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); - if (!bb.Overlaps(window->ClipRect)) if (!id || *id != GImGui->ActiveId) if (clip_even_when_logged || !g.LogEnabled) @@ -2146,7 +2147,8 @@ void ImGui::NewFrame() g.RenderDrawData.CmdLists = NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; - // Update inputs state + + // Update mouse input state if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta @@ -2213,7 +2215,7 @@ void ImGui::NewFrame() { g.MovedWindow->PosFloat += g.IO.MouseDelta; if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) - MarkIniSettingsDirty(); + MarkIniSettingsDirty(g.MovedWindow); } FocusWindow(g.MovedWindow); } @@ -2291,23 +2293,20 @@ void ImGui::NewFrame() if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) { ImGuiWindow* window = g.HoveredWindow; - if (g.IO.KeyCtrl) + if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { - if (g.IO.FontAllowUserScaling) - { - // Zoom / Scale window - float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; + // Zoom / Scale window + const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + const float scale = new_font_scale / window->FontWindowScale; + window->FontWindowScale = new_font_scale; - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - window->Pos += offset; - window->PosFloat += offset; - window->Size *= scale; - window->SizeFull *= scale; - } + const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + window->Pos += offset; + window->PosFloat += offset; + window->Size *= scale; + window->SizeFull *= scale; } - else if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) { // Scroll const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5; @@ -2530,11 +2529,12 @@ static void SaveIniSettingsToDisk(const char* ini_filename) fclose(f); } -static void MarkIniSettingsDirty() +static void MarkIniSettingsDirty(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; + if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) + if (g.SettingsDirtyTimer <= 0.0f) + g.SettingsDirtyTimer = g.IO.IniSavingRate; } // FIXME: Add a more explicit sort order in the window structure. @@ -2684,6 +2684,7 @@ void ImGui::EndFrame() continue; AddWindowToSortedBuffer(g.WindowsSortBuffer, window); } + IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong g.Windows.swap(g.WindowsSortBuffer); @@ -3315,8 +3316,7 @@ bool ImGui::IsAnyItemActive() bool ImGui::IsItemVisible() { ImGuiWindow* window = GetCurrentWindowRead(); - ImRect r(window->ClipRect); - return r.Overlaps(window->DC.LastItemRect); + return window->ClipRect.Overlaps(window->DC.LastItemRect); } // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. @@ -3631,7 +3631,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); + ImGuiWindow* parent_window = ImGui::GetCurrentWindow(); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; const ImVec2 content_avail = ImGui::GetContentRegionAvail(); @@ -3654,14 +3654,14 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b char title[256]; if (name) - ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s.%08X", window->Name, name, id); + ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s.%08X", parent_window->Name, name, id); else - ImFormatString(title, IM_ARRAYSIZE(title), "%s.%08X", window->Name, id); + ImFormatString(title, IM_ARRAYSIZE(title), "%s.%08X", parent_window->Name, id); bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); - - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - ImGui::GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; + ImGuiWindow* child_window = ImGui::GetCurrentWindow(); + if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) + child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; return ret; } @@ -3697,8 +3697,8 @@ void ImGui::EndChild() ImGui::End(); - window = GetCurrentWindow(); - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + sz); + ImGuiWindow* parent_window = GetCurrentWindow(); + ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); ItemAdd(bb, NULL); } @@ -3744,7 +3744,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without it. ImVec2 safe_padding = style.DisplaySafeAreaPadding; ImRect r_outer(GetVisibleRect()); - r_outer.Reduce(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? safe_padding.y : 0.0f)); + r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f)); ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size); for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). @@ -4022,8 +4022,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) { window->Collapsed = !window->Collapsed; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + MarkIniSettingsDirty(window); FocusWindow(window); } } @@ -4097,8 +4096,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; if (window->AutoFitFramesY > 0) window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + MarkIniSettingsDirty(window); } } @@ -4232,16 +4230,14 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { // Manual auto-fit when double-clicking ApplySizeFullWithConstraint(window, size_auto_fit); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + MarkIniSettingsDirty(window); ClearActiveID(); } else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkIniSettingsDirty(); + MarkIniSettingsDirty(window); } window->Size = window->SizeFull; @@ -4407,7 +4403,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); const float border_size = window->BorderSize; - ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + ImRect clip_rect; clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); @@ -4496,7 +4493,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) else window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); - bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); + bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); @@ -5580,6 +5577,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return false; } + // Default behavior requires click+release on same spot if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) flags |= ImGuiButtonFlags_PressedOnClickRelease; @@ -6468,13 +6466,18 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } +static float GetMinimumStepAtDecimalPrecision(int decimal_precision) +{ + static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; + return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); +} + float ImGui::RoundScalar(float value, int decimal_precision) { // Round past decimal precision // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 // FIXME: Investigate better rounding methods - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); + const float min_step = GetMinimumStepAtDecimalPrecision(decimal_precision); bool negative = value < 0.0f; value = fabsf(value); float remainder = fmodf(value, min_step); @@ -6602,10 +6605,8 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } } - // Calculate slider grab positioning - float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); - // Draw + float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); if (!is_horizontal) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); @@ -7293,7 +7294,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over // Render fraction = ImSaturate(fraction); RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - bb.Reduce(ImVec2(window->BorderSize, window->BorderSize)); + bb.Expand(ImVec2(-window->BorderSize, -window->BorderSize)); const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); RenderFrame(bb.Min, fill_br, GetColorU32(ImGuiCol_PlotHistogram), false, style.FrameRounding); @@ -8570,6 +8571,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (BeginPopupEx(id, flags)) { // Display items + // FIXME-OPT: Use clipper Spacing(); for (int i = 0; i < items_count; i++) { @@ -8757,7 +8759,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. bool value_changed = false; - ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); + ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { @@ -10471,8 +10473,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); + ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("ActiveId: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 2bfef8420..d98d2cb48 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -266,7 +266,7 @@ struct IMGUI_API ImRect void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; } void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } + void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const @@ -397,8 +397,8 @@ struct ImGuiContext ImGuiIO IO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() - float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize() - float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters. + float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. + float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel float Time; @@ -407,8 +407,8 @@ struct ImGuiContext int FrameCountRendered; ImVector Windows; ImVector WindowsSortBuffer; - ImGuiWindow* CurrentWindow; // Being drawn into ImVector CurrentWindowStack; + ImGuiWindow* CurrentWindow; // Being drawn into ImGuiWindow* FocusedWindow; // Will catch keyboard inputs ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) @@ -417,9 +417,10 @@ struct ImGuiContext ImGuiID HoveredIdPreviousFrame; ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; - bool ActiveIdIsAlive; + bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame - bool ActiveIdAllowOverlap; // Set only by active widget + bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) + ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. From 50b3a14d0ab430d30c2c9c961ce305684b5f2e64 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 13:05:13 +0200 Subject: [PATCH 032/101] Merge 2545d75c3b978638329ac65cc1851f3f5998bb5b from Nav - Tidying up, removed two unnecessary window flags from being exposed in imgui.h --- imgui.cpp | 15 +++++---------- imgui.h | 4 +--- imgui_internal.h | 1 + 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c76a6db7b..6a5973fc1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1775,6 +1775,7 @@ ImGuiWindow::ImGuiWindow(const char* name) PopupId = 0; AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; + AutoFitChildAxises = 0x00; AutoPosLastDirection = -1; HiddenFrames = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; @@ -3636,18 +3637,11 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b const ImVec2 content_avail = ImGui::GetContentRegionAvail(); ImVec2 size = ImFloor(size_arg); + const int auto_fit_axises = ((size.x == 0.0f) ? 0x01 : 0x00) | ((size.y == 0.0f) ? 0x02 : 0x00); if (size.x <= 0.0f) - { - if (size.x == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitX; size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) - } if (size.y <= 0.0f) - { - if (size.y == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitY; size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); - } if (border) flags |= ImGuiWindowFlags_ShowBorders; flags |= extra_flags; @@ -3660,6 +3654,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); ImGuiWindow* child_window = ImGui::GetCurrentWindow(); + child_window->AutoFitChildAxises = auto_fit_axises; if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3690,9 +3685,9 @@ void ImGui::EndChild() { // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting. ImVec2 sz = GetWindowSize(); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f + if (window->AutoFitChildAxises & 0x01) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f sz.x = ImMax(4.0f, sz.x); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) + if (window->AutoFitChildAxises & 0x02) sz.y = ImMax(4.0f, sz.y); ImGui::End(); diff --git a/imgui.h b/imgui.h index 249183a92..5cf8b5a4b 100644 --- a/imgui.h +++ b/imgui.h @@ -512,9 +512,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) // [Internal] - ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitY = 1 << 22, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() diff --git a/imgui_internal.h b/imgui_internal.h index d98d2cb48..31effe442 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -679,6 +679,7 @@ struct IMGUI_API ImGuiWindow ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; + int AutoFitChildAxises; int AutoPosLastDirection; int HiddenFrames; ImGuiCond SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call. From 2ad2190d478dfc670bacc9376ff658ed4c5f0d59 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 10:02:46 +0200 Subject: [PATCH 033/101] Merge 20a0fde0124c08a7ead82357c9346acec0bafda6 Tidying up default clipboard handler for non Windows-OS (from Nav branch) --- imgui.cpp | 19 ++++++------------- imgui_internal.h | 3 +-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6a5973fc1..9e0512799 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2391,11 +2391,7 @@ void ImGui::Shutdown() for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } + g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); g.InputTextState.InitialText.clear(); g.InputTextState.TempTextBuffer.clear(); @@ -10297,21 +10293,18 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers static const char* GetClipboardTextFn_DefaultImpl(void*) { - return GImGui->PrivateClipboard; + ImGuiContext& g = *GImGui; + return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin(); } // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { ImGuiContext& g = *GImGui; - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } + g.PrivateClipboard.clear(); const char* text_end = text + strlen(text); - g.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1); - memcpy(g.PrivateClipboard, text, (size_t)(text_end - text)); + g.PrivateClipboard.resize((size_t)(text_end - text) + 1); + memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text)); g.PrivateClipboard[(int)(text_end - text)] = 0; } diff --git a/imgui_internal.h b/imgui_internal.h index 31effe442..416789dda 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -471,7 +471,7 @@ struct ImGuiContext float DragSpeedScaleFast; ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? int TooltipOverrideCount; - char* PrivateClipboard; // If no custom clipboard handler is defined + ImVector PrivateClipboard; // If no custom clipboard handler is defined ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor // Logging @@ -541,7 +541,6 @@ struct ImGuiContext DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); TooltipOverrideCount = 0; - PrivateClipboard = NULL; OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); ModalWindowDarkeningRatio = 0.0f; From 141339e4b756e996a7eec5948ae69e3d4f0f1e3b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 19:51:12 +0800 Subject: [PATCH 034/101] (internals) Renamed FocusedWindow to NavWindow to match terminology of navigation branch --- imgui.cpp | 36 ++++++++++++++++++------------------ imgui_internal.h | 4 ++-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9e0512799..3b8e84ef8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2317,8 +2317,8 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) - g.FocusedWindow->FocusIdxTabRequestNext = 0; + if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) + g.NavWindow->FocusIdxTabRequestNext = 0; // Mark all windows as not visible for (int i = 0; i != g.Windows.Size; i++) @@ -2330,7 +2330,7 @@ void ImGui::NewFrame() } // Closing the focused window restore focus to the first active root window in descending z-order - if (g.FocusedWindow && !g.FocusedWindow->WasActive) + if (g.NavWindow && !g.NavWindow->WasActive) for (int i = g.Windows.Size-1; i >= 0; i--) if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { @@ -2373,7 +2373,7 @@ void ImGui::Shutdown() g.WindowsSortBuffer.clear(); g.CurrentWindow = NULL; g.CurrentWindowStack.clear(); - g.FocusedWindow = NULL; + g.NavWindow = NULL; g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; g.ActiveIdWindow = NULL; @@ -2650,7 +2650,7 @@ void ImGui::EndFrame() // Click to focus window and start moving (after we're done with all our widgets) if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) { - if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear + if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear { if (g.HoveredRootWindow != NULL) { @@ -2662,7 +2662,7 @@ void ImGui::EndFrame() SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); } } - else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) + else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { // Clicking on void disable focus FocusWindow(NULL); @@ -3437,7 +3437,7 @@ static void CloseInactivePopups() // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. // Don't close our own child popup windows int n = 0; - if (g.FocusedWindow) + if (g.NavWindow) { for (n = 0; n < g.OpenPopupStack.Size; n++) { @@ -3450,7 +3450,7 @@ static void CloseInactivePopups() bool has_focus = false; for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) - has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); + has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow); if (!has_focus) break; } @@ -4260,7 +4260,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) @@ -4565,7 +4565,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) ImGuiContext& g = *GImGui; // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. - g.FocusedWindow = window; + g.NavWindow = window; // Passing NULL allow to disable keyboard focus if (!window) @@ -4876,19 +4876,19 @@ bool ImGui::IsWindowHovered() bool ImGui::IsWindowFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow; + return g.NavWindow == g.CurrentWindow; } bool ImGui::IsRootWindowFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow->RootWindow; + return g.NavWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; + return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildHovered() @@ -5547,7 +5547,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window) // An active popup disable hovering on other windows (apart from its own children) // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; - if (ImGuiWindow* focused_window = g.FocusedWindow) + if (ImGuiWindow* focused_window = g.NavWindow) if (ImGuiWindow* focused_root_window = focused_window->RootWindow) if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) return false; @@ -8882,13 +8882,13 @@ bool ImGui::BeginMenu(const char* label, bool enabled) const ImGuiID id = window->GetID(label); ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiWindow* backed_focused_window = g.FocusedWindow; + ImGuiWindow* backed_focused_window = g.NavWindow; bool pressed; bool menu_is_open = IsPopupOpen(id); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); if (menuset_is_open) - g.FocusedWindow = window; + g.NavWindow = window; // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestPopupWindowPos). ImVec2 popup_pos, pos = window->DC.CursorPos; @@ -8916,7 +8916,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); if (menuset_is_open) - g.FocusedWindow = backed_focused_window; + g.NavWindow = backed_focused_window; bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) @@ -10458,7 +10458,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Basic state")) { - ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); + ImGui::Text("FocusedWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not diff --git a/imgui_internal.h b/imgui_internal.h index 416789dda..e59a27edb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -409,7 +409,7 @@ struct ImGuiContext ImVector WindowsSortBuffer; ImVector CurrentWindowStack; ImGuiWindow* CurrentWindow; // Being drawn into - ImGuiWindow* FocusedWindow; // Will catch keyboard inputs + ImGuiWindow* NavWindow; // Nav/focused window for navigation ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) ImGuiID HoveredId; // Hovered widget @@ -500,7 +500,7 @@ struct ImGuiContext FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; CurrentWindow = NULL; - FocusedWindow = NULL; + NavWindow = NULL; HoveredWindow = NULL; HoveredRootWindow = NULL; HoveredId = 0; From 6be7d4904e1dd67810087f6986d683efe10dcbf9 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:10:02 +0800 Subject: [PATCH 035/101] Merge part of 88c1966629fff80f49bc6ffa0deb205f4856f3a3 from Nav branch. Renamed IsMouseHoveringAnyWindow() -> IsAnyWindowHovered(), IsMouseHoveringWindow() -> IsWindowHoveredRect() for consistency. Kept inline rediection function. --- imgui.cpp | 10 ++++++---- imgui.h | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3b8e84ef8..ea7d4e52b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -204,8 +204,10 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2016/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. - - 2016/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. + - 2017/08/22 (1.51) - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). + - renamed IsMouseHoveringWindow() to IsWindowHoveredRect() for consistency. Kept inline redirection function (will obsolete). + - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. + - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. - 2017/08/13 (1.51) - renamed ImGuiCol_Columns_*** to ImGuiCol_Separator_*** @@ -3108,13 +3110,13 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c return rect_for_touch.Contains(g.IO.MousePos); } -bool ImGui::IsMouseHoveringWindow() +bool ImGui::IsWindowHoveredRect() { ImGuiContext& g = *GImGui; return g.HoveredWindow == g.CurrentWindow; } -bool ImGui::IsMouseHoveringAnyWindow() +bool ImGui::IsAnyWindowHovered() { ImGuiContext& g = *GImGui; return g.HoveredWindow != NULL; diff --git a/imgui.h b/imgui.h index 5cf8b5a4b..d5be3a7b2 100644 --- a/imgui.h +++ b/imgui.h @@ -419,11 +419,13 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) IMGUI_API bool IsWindowFocused(); // is current window focused + IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) + IMGUI_API bool IsWindowHoveredRect(); // is current window hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) + IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API float GetTime(); @@ -450,10 +452,8 @@ namespace ImGui IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) - IMGUI_API bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window). disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) - IMGUI_API bool IsMouseHoveringAnyWindow(); // is mouse hovering any visible window - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold @@ -480,6 +480,8 @@ namespace ImGui // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. + static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ + static inline bool IsMouseHoveringWindow() { return IsWindowHoveredRect(); } // OBSOLETE 1.51+ static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ From 52b39af0a0fdc71a09a8e0e198ef61e94a4a6964 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:23:46 +0800 Subject: [PATCH 036/101] Style: Added obsolete redirects for ImGuiCol_Columns*** fields. (ref 648f75b2456f1e5b17be113908c0119ed9e5b071) --- imgui.cpp | 2 +- imgui.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ea7d4e52b..b4b52263d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -210,7 +210,7 @@ - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. - - 2017/08/13 (1.51) - renamed ImGuiCol_Columns_*** to ImGuiCol_Separator_*** + - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete). - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete). - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton(). - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu. diff --git a/imgui.h b/imgui.h index d5be3a7b2..84bb32e48 100644 --- a/imgui.h +++ b/imgui.h @@ -645,6 +645,11 @@ enum ImGuiCol_ ImGuiCol_TextSelectedBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive +#endif }; // Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. @@ -721,7 +726,7 @@ enum ImGuiCond_ ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file) ImGuiCond_Appearing = 1 << 3 // Set the variable if the window is appearing after being hidden/inactive (or the first time) -// Obsolete names (will be obsolete) + // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS , ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing #endif From eb2bbf6f29a1b007fe9ddfdf66457823328f7c8e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:25:27 +0800 Subject: [PATCH 037/101] Renamed IsItemHoveredRect() to IsItemRectHovered(). Renamed IsMouseHoveringWindow() to IsWindowRectHovered() - follow up to previous commit 6be7d4904e1dd67810087f6986d683efe10dcbf9 merged from Nav. --- imconfig.h | 2 +- imgui.cpp | 11 ++++++----- imgui.h | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/imconfig.h b/imconfig.h index 19911acce..e557fa065 100644 --- a/imconfig.h +++ b/imconfig.h @@ -24,7 +24,7 @@ //---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why. //#define IMGUI_DISABLE_TEST_WINDOWS -//---- Don't define obsolete functions names +//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) diff --git a/imgui.cpp b/imgui.cpp index b4b52263d..ae182d851 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -204,8 +204,9 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2017/08/22 (1.51) - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - - renamed IsMouseHoveringWindow() to IsWindowHoveredRect() for consistency. Kept inline redirection function (will obsolete). + - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). + - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). + - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame. @@ -3110,7 +3111,7 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c return rect_for_touch.Contains(g.IO.MousePos); } -bool ImGui::IsWindowHoveredRect() +bool ImGui::IsWindowRectHovered() { ImGuiContext& g = *GImGui; return g.HoveredWindow == g.CurrentWindow; @@ -3280,7 +3281,7 @@ bool ImGui::IsItemHovered() return window->DC.LastItemHoveredAndUsable; } -bool ImGui::IsItemHoveredRect() +bool ImGui::IsItemRectHovered() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.LastItemHoveredRect; @@ -3597,7 +3598,7 @@ void ImGui::EndPopup() // This is a helper to handle the most simple case of associating one named popup to one given widget. // 1. If you have many possible popups (for different "instances" of a same widget, or for wholly different widgets), you may be better off handling // this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup identifiers. -// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemHoveredRect() +// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemRectHovered() // and passing true to the OpenPopupEx(). // Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of ignoring the fact that // the item can be interacted with (because it is blocked by the active popup) may useful in some situation when e.g. large canvas as one item, content of menu diff --git a/imgui.h b/imgui.h index 84bb32e48..a6738b53c 100644 --- a/imgui.h +++ b/imgui.h @@ -409,7 +409,7 @@ namespace ImGui // Utilities IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? - IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this + IMGUI_API bool IsItemRectHovered(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) @@ -421,7 +421,7 @@ namespace ImGui IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(); // is current window focused IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowHoveredRect(); // is current window hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) + IMGUI_API bool IsWindowRectHovered(); // is current window rectnagle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) @@ -479,9 +479,10 @@ namespace ImGui // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+ static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ - static inline bool IsMouseHoveringWindow() { return IsWindowHoveredRect(); } // OBSOLETE 1.51+ + static inline bool IsMouseHoveringWindow() { return IsWindowRectHovered(); } // OBSOLETE 1.51+ static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ From 92efa00bc995d3e0b5d1c88600b9ec3d0ec3cb92 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:44:39 +0800 Subject: [PATCH 038/101] Minor miscellaneous merges from Navigation branch to reduce divergence a little bit --- imgui.cpp | 82 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae182d851..2ed147df6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3111,12 +3111,6 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c return rect_for_touch.Contains(g.IO.MousePos); } -bool ImGui::IsWindowRectHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow; -} - bool ImGui::IsAnyWindowHovered() { ImGuiContext& g = *GImGui; @@ -4876,6 +4870,12 @@ bool ImGui::IsWindowHovered() return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow); } +bool ImGui::IsWindowRectHovered() +{ + ImGuiContext& g = *GImGui; + return g.HoveredWindow == g.CurrentWindow; +} + bool ImGui::IsWindowFocused() { ImGuiContext& g = *GImGui; @@ -4921,7 +4921,7 @@ ImVec2 ImGui::GetWindowPos() static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) { - window->DC.CursorMaxPos.y += window->Scroll.y; + window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. window->Scroll.y = new_scroll_y; window->DC.CursorMaxPos.y -= window->Scroll.y; } @@ -5550,8 +5550,8 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window) // An active popup disable hovering on other windows (apart from its own children) // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; - if (ImGuiWindow* focused_window = g.NavWindow) - if (ImGuiWindow* focused_root_window = focused_window->RootWindow) + if (g.NavWindow) + if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) return false; @@ -6549,13 +6549,23 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v bool value_changed = false; if (g.ActiveId == id) { + bool set_new_value = false; + float clicked_t = 0.0f; if (g.IO.MouseDown[0]) { const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; + clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; if (!is_horizontal) clicked_t = 1.0f - clicked_t; + set_new_value = true; + } + else + { + ClearActiveID(); + } + if (set_new_value) + { float new_value; if (is_non_linear) { @@ -6593,10 +6603,6 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v value_changed = true; } } - else - { - ClearActiveID(); - } } // Draw @@ -6864,32 +6870,32 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s g.DragLastMouseDelta = ImVec2(0.f, 0.f); } + if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) + v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) { float speed = v_speed; - if (speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - speed = (v_max - v_min) * g.DragSpeedDefaultRatio; if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) speed = speed * g.DragSpeedScaleFast; if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) speed = speed * g.DragSpeedScaleSlow; - float delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; + float adjust_delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; if (fabsf(power - 1.0f) > 0.001f) { // Logarithmic curve on both side of 0.0 float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); + float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); float v1_abs = v1 >= 0.0f ? v1 : -v1; float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign } else { - v_cur += delta; + v_cur += adjust_delta; } g.DragLastMouseDelta.x = mouse_drag_delta.x; @@ -8504,7 +8510,6 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); const bool hovered = IsHovered(frame_bb, id); bool popup_open = IsPopupOpen(id); - bool popup_opened_now = false; const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); @@ -8521,22 +8526,27 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + bool popup_toggled = false; if (hovered) { SetHoveredID(id); if (g.IO.MouseClicked[0]) { ClearActiveID(); - if (IsPopupOpen(id)) - { - ClosePopup(id); - } - else - { - FocusWindow(window); - OpenPopup(label); - popup_open = popup_opened_now = true; - } + popup_toggled = true; + } + } + if (popup_toggled) + { + if (IsPopupOpen(id)) + { + ClosePopup(id); + } + else + { + FocusWindow(window); + OpenPopup(label); + popup_open = true; } } @@ -8580,7 +8590,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi value_changed = true; *current_item = i; } - if (item_selected && popup_opened_now) + if (item_selected && popup_toggled) SetScrollHere(); PopID(); } @@ -8885,13 +8895,13 @@ bool ImGui::BeginMenu(const char* label, bool enabled) const ImGuiID id = window->GetID(label); ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiWindow* backed_focused_window = g.NavWindow; bool pressed; bool menu_is_open = IsPopupOpen(id); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); + ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) - g.NavWindow = window; + g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestPopupWindowPos). ImVec2 popup_pos, pos = window->DC.CursorPos; @@ -8919,7 +8929,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); if (menuset_is_open) - g.NavWindow = backed_focused_window; + g.NavWindow = backed_nav_window; bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) @@ -8946,7 +8956,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); } - else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close + else if (menu_is_open && pressed && menuset_is_open) // Menu bar: click an open menu again to close it { want_close = true; want_open = menu_is_open = false; @@ -10461,12 +10471,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Basic state")) { - ImGui::Text("FocusedWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not ImGui::Text("ActiveId: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::TreePop(); } } From d213c0eb7e3e934e36d72294f8e916543687b5ae Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 24 Aug 2017 17:30:10 +0800 Subject: [PATCH 039/101] Style: Tweaked default border (undo half-way from original c1e1e015c4a81c68812113d85dfdedbc598ff413) (#707) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2ed147df6..2640ebc64 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -700,7 +700,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); - Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.22f); + Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.40f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); From 82c3116b4f2dc41be7bf66105a376666b8136ff9 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 24 Aug 2017 17:32:03 +0800 Subject: [PATCH 040/101] Demo: Displaying version number in test window. --- imgui_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8911bcf2a..8e20c6731 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -192,7 +192,7 @@ void ImGui::ShowTestWindow(bool* p_open) //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels - ImGui::Text("Dear ImGui says hello."); + ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION); // Menu if (ImGui::BeginMenuBar()) @@ -1575,6 +1575,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Borders")) { + // NB: Future columns API should allow automatic horizontal borders. static bool h_borders = true; static bool v_borders = true; ImGui::Checkbox("horizontal", &h_borders); From 55a6209931a145dd012e85e6673e5ef6575948c9 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Aug 2017 00:29:59 +0800 Subject: [PATCH 041/101] Version 1.51 --- imgui.cpp | 2 +- imgui.h | 4 ++-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2640ebc64..26ed18260 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 WIP +// dear imgui, v1.51 // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index a6738b53c..27a11fcfc 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.51 WIP +// dear imgui, v1.51 // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.51 WIP" +#define IMGUI_VERSION "1.51" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8e20c6731..8cdb5f2fb 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 WIP +// dear imgui, v1.51 // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8442bdd16..d01aa52d6 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 WIP +// dear imgui, v1.51 // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index e59a27edb..cee3f7333 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.51 WIP +// dear imgui, v1.51 // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! From 40f608ce9ba0530b7a504fa096f9b2a361589960 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Aug 2017 15:12:12 +0800 Subject: [PATCH 042/101] Version 1.52 WIP --- imgui.cpp | 3 +-- imgui.h | 4 ++-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 26ed18260..a6eaea45a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 +// dear imgui, v1.52 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -2151,7 +2151,6 @@ void ImGui::NewFrame() g.RenderDrawData.CmdLists = NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; - // Update mouse input state if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); diff --git a/imgui.h b/imgui.h index 27a11fcfc..8ec9a0fa7 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.51 +// dear imgui, v1.52 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.51" +#define IMGUI_VERSION "1.52 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8cdb5f2fb..6f7bd4db1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 +// dear imgui, v1.52 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index d01aa52d6..0f2345f5b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.51 +// dear imgui, v1.52 WIP // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index cee3f7333..df7357977 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.51 +// dear imgui, v1.52 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! From 37f3a718c63e14f30cfa51a3050b35eba9b02f6f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Aug 2017 16:10:14 +0800 Subject: [PATCH 043/101] Marked all fmt + va_list functions with format attribute so GCC/Clang can warn about them. Not ignoring -Wsuggest-attribute=format anymore for GCC/Clang. --- imgui.cpp | 1 - imgui.h | 84 +++++++++++++++++++++++++----------------------- imgui_demo.cpp | 4 +-- imgui_internal.h | 4 +-- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a6eaea45a..5ce1e7237 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -582,7 +582,6 @@ #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked -#pragma GCC diagnostic ignored "-Wsuggest-attribute=format" #endif //------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 8ec9a0fa7..d9fd8c83b 100644 --- a/imgui.h +++ b/imgui.h @@ -31,9 +31,11 @@ // Some compilers support applying printf-style warnings to user functions. #if defined(__clang__) || defined(__GNUC__) -#define IM_PRINTFARGS(FMT) __attribute__((format(printf, FMT, (FMT+1)))) +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) +#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else -#define IM_PRINTFARGS(FMT) +#define IM_FMTARGS(FMT) +#define IM_FMTLIST(FMT) #endif #if defined(__clang__) @@ -233,43 +235,45 @@ namespace ImGui // Columns // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); - IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column - IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column + IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column + IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f + IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); // ID scopes - // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. + // If you are creating widgets in a loop you most likely want to push a unique identifier (e.g. object pointer, loop index) so ImGui can differentiate them. // You can also use the "##foobar" syntax within widget label to distinguish them from each others. Read "A primer on the use of labels/IDs" in the FAQ for more details. - IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack! + IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the entire stack! IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); IMGUI_API void PushID(const void* ptr_id); IMGUI_API void PushID(int int_id); IMGUI_API void PopID(); - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you want to query into ImGuiStorage yourself + IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); - // Widgets - IMGUI_API void Text(const char* fmt, ...) IM_PRINTFARGS(1); - IMGUI_API void TextV(const char* fmt, va_list args); - IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_PRINTFARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args); - IMGUI_API void TextDisabled(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextDisabledV(const char* fmt, va_list args); - IMGUI_API void TextWrapped(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). - IMGUI_API void TextWrappedV(const char* fmt, va_list args); - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done to any bounded stack buffer, recommended for long chunks of text - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_PRINTFARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args); - IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses - IMGUI_API void BulletText(const char* fmt, ...) IM_PRINTFARGS(1); // shortcut for Bullet()+Text() - IMGUI_API void BulletTextV(const char* fmt, va_list args); + // Widgets: Text + IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // doesn't require null terminated string if 'text_end' is specified. no copy done, no limits, recommended for long chunks of text + IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text + IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). + IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() + IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + + // Widgets: Main IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button - IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed in text + IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding @@ -335,15 +339,15 @@ namespace ImGui // Widgets: Trees IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_PRINTFARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). - IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_PRINTFARGS(2); // " - IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args); // " - IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args); // " + IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). + IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " + IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); - IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_PRINTFARGS(3); - IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); - IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args); + IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); + IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); + IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); + IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API void TreePush(const char* str_id = NULL); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); // ~ Unindent()+PopId() @@ -369,8 +373,8 @@ namespace ImGui IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); // Tooltips - IMGUI_API void SetTooltip(const char* fmt, ...) IM_PRINTFARGS(1); // set text tooltip under mouse-cursor, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). - IMGUI_API void SetTooltipV(const char* fmt, va_list args); + IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set text tooltip under mouse-cursor, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip(). + IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of contents). IMGUI_API void EndTooltip(); @@ -401,7 +405,7 @@ namespace ImGui IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard IMGUI_API void LogFinish(); // stop logging (close file, etc.) IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard - IMGUI_API void LogText(const char* fmt, ...) IM_PRINTFARGS(1); // pass text data straight to log (without being displayed) + IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) // Clipping IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); @@ -996,8 +1000,8 @@ struct ImGuiTextBuffer bool empty() { return Buf.Size <= 1; } void clear() { Buf.clear(); Buf.push_back(0); } const char* c_str() const { return Buf.Data; } - IMGUI_API void append(const char* fmt, ...) IM_PRINTFARGS(2); - IMGUI_API void appendv(const char* fmt, va_list args); + IMGUI_API void append(const char* fmt, ...) IM_FMTARGS(2); + IMGUI_API void appendv(const char* fmt, va_list args) IM_FMTLIST(2); }; // Helper: Simple Key->value storage diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6f7bd4db1..abf89f349 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2298,7 +2298,7 @@ struct ExampleAppConsole ScrollToBottom = true; } - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) + void AddLog(const char* fmt, ...) IM_FMTARGS(2) { char buf[1024]; va_list args; @@ -2560,7 +2560,7 @@ struct ExampleAppLog void Clear() { Buf.clear(); LineOffsets.clear(); } - void AddLog(const char* fmt, ...) IM_PRINTFARGS(2) + void AddLog(const char* fmt, ...) IM_FMTARGS(2) { int old_size = Buf.size(); va_list args; diff --git a/imgui_internal.h b/imgui_internal.h index df7357977..b38101876 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -109,8 +109,8 @@ IMGUI_API char* ImStrdup(const char* str); IMGUI_API int ImStrlenW(const ImWchar* str); IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); -IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3); -IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args); +IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_FMTARGS(3); +IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) IM_FMTLIST(3); // Helpers: Math // We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined) From 92a6faca6f5a5abce8c4671fb0e55ed2e422eda2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Aug 2017 16:43:25 +0800 Subject: [PATCH 044/101] IO: io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we'll now accept negative mouse coordinates. --- examples/allegro5_example/imgui_impl_a5.cpp | 2 +- examples/opengl2_example/imgui_impl_glfw.cpp | 2 +- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 +- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 2 +- imgui.cpp | 11 ++++++----- imgui.h | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 9a04ff9c1..6f5b7b061 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -262,7 +262,7 @@ void ImGui_ImplA5_NewFrame() } else { - io.MousePos = ImVec2(-1, -1); + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); } al_get_mouse_state(&mouse); diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 435de7a81..f85fb5c4c 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -272,7 +272,7 @@ void ImGui_ImplGlfw_NewFrame() } else { - io.MousePos = ImVec2(-1,-1); + io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); } for (int i = 0; i < 3; i++) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a9a45e105..ff96b88a2 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -383,7 +383,7 @@ void ImGui_ImplGlfwGL3_NewFrame() } else { - io.MousePos = ImVec2(-1,-1); + io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); } for (int i = 0; i < 3; i++) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 04b6a9a39..a8338cecc 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -265,7 +265,7 @@ void ImGui_ImplSdl_NewFrame(SDL_Window *window) if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) else - io.MousePos = ImVec2(-1,-1); + io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 59101e938..1861edae0 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -377,7 +377,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) else - io.MousePos = ImVec2(-1, -1); + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index d43929f6a..90f783278 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -815,7 +815,7 @@ void ImGui_ImplGlfwVulkan_NewFrame() } else { - io.MousePos = ImVec2(-1,-1); + io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); } for (int i = 0; i < 3; i++) diff --git a/imgui.cpp b/imgui.cpp index 5ce1e7237..be7b018d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -204,6 +204,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). @@ -754,8 +755,8 @@ ImGuiIO::ImGuiIO() FontGlobalScale = 1.0f; FontDefault = NULL; DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MousePos = ImVec2(-1,-1); - MousePosPrev = ImVec2(-1,-1); + MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; MouseDragThreshold = 6.0f; @@ -2151,9 +2152,9 @@ void ImGui::NewFrame() g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; // Update mouse input state - if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) - g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); - if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta + // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta + const float MOUSE_INVALID = -256000.0f; + if ((g.IO.MousePos.x < MOUSE_INVALID && g.IO.MousePos.y < MOUSE_INVALID) || (g.IO.MousePosPrev.x < MOUSE_INVALID && g.IO.MousePosPrev.y < MOUSE_INVALID)) g.IO.MouseDelta = ImVec2(0.0f, 0.0f); else g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; diff --git a/imgui.h b/imgui.h index d9fd8c83b..61227e020 100644 --- a/imgui.h +++ b/imgui.h @@ -828,7 +828,7 @@ struct ImGuiIO // Input - Fill before calling NewFrame() //------------------------------------------------------------------ - ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). From a02210a455b2899f3fc01d7f57a3c6bdd77ef38a Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 00:31:17 +0800 Subject: [PATCH 045/101] Fixed compilation with IMGUI_DISABLE_OBSOLETE_FUNCTIONS defined --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index be7b018d5..9f8a0c5fc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3607,7 +3607,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a { if (!str_id) str_id = "window_context"; - if (IsMouseHoveringWindow() && IsMouseClicked(mouse_button)) + if (IsWindowRectHovered() && IsMouseClicked(mouse_button)) if (also_over_items || !IsAnyItemHovered()) OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true); return BeginPopup(str_id); @@ -3617,7 +3617,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) { if (!str_id) str_id = "void_context"; - if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) + if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button)) OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true); return BeginPopup(str_id); } From 304de0ee1b8727d13edbfff088bebdd55b888de6 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 14:11:41 +0800 Subject: [PATCH 046/101] ImFontConfig: Comments, const. --- imgui.h | 8 ++++---- imgui_draw.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/imgui.h b/imgui.h index 61227e020..e82d778b7 100644 --- a/imgui.h +++ b/imgui.h @@ -1321,14 +1321,14 @@ struct ImFontConfig { void* FontData; // // TTF/OTF data int FontDataSize; // // TTF/OTF data size - bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). Set to true + bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). int FontNo; // 0 // Index of font within TTF/OTF file - float SizePixels; // // Size in pixels for rasterizer + float SizePixels; // // Size in pixels for rasterizer. int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. - ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input - const ImWchar* GlyphRanges; // // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. + const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. // [Internal] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0f2345f5b..0eb1e5989 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1051,8 +1051,8 @@ ImFontConfig::ImFontConfig() GlyphOffset = ImVec2(0.0f, 0.0f); GlyphRanges = NULL; MergeMode = false; - DstFont = NULL; memset(Name, 0, sizeof(Name)); + DstFont = NULL; } //----------------------------------------------------------------------------- @@ -1478,15 +1478,15 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) ImFontTempBuildData& tmp = tmp_array[input_i]; ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) - float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); + const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - float ascent = unscaled_ascent * font_scale; - float descent = unscaled_descent * font_scale; + const float ascent = unscaled_ascent * font_scale; + const float descent = unscaled_descent * font_scale; ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); - float off_x = cfg.GlyphOffset.x; - float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); + const float off_x = cfg.GlyphOffset.x; + const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (int i = 0; i < tmp.RangesCount; i++) From f72ca6d22ccbe14f3ec8734136a3644c8dd9cfa8 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 14:11:56 +0800 Subject: [PATCH 047/101] ImFontConfig: Added RasterizerMultiply option to alter the brightness of individual fonts at rasterization time, which may help increasing readability for some. Added RasterizerFlags for custom rasterizer flags (aka imgui_freetype) --- imgui.h | 2 ++ imgui_draw.cpp | 29 +++++++++++++++++++++++++++++ imgui_internal.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/imgui.h b/imgui.h index e82d778b7..7d0721b04 100644 --- a/imgui.h +++ b/imgui.h @@ -1330,6 +1330,8 @@ struct ImFontConfig ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. + unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. + float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. // [Internal] char Name[32]; // Name (strictly to ease debugging) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0eb1e5989..cd8325393 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1051,6 +1051,8 @@ ImFontConfig::ImFontConfig() GlyphOffset = ImVec2(0.0f, 0.0f); GlyphRanges = NULL; MergeMode = false; + RasterizerFlags = 0x00; + RasterizerMultiply = 1.0f; memset(Name, 0, sizeof(Name)); DstFont = NULL; } @@ -1340,6 +1342,23 @@ bool ImFontAtlas::Build() return ImFontAtlasBuildWithStbTruetype(this); } +void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor) +{ + for (unsigned int i = 0; i < 256; i++) + { + unsigned int value = (unsigned int)(i * in_brighten_factor); + out_table[i] = value > 255 ? 255 : (value & 0xFF); + } +} + +void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride) +{ + unsigned char* data = pixels + x + y * stride; + for (int j = h; j > 0; j--, data += stride) + for (int i = 0; i < w; i++) + data[i] = table[data[i]]; +} + bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { IM_ASSERT(atlas->ConfigData.Size > 0); @@ -1382,6 +1401,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { stbtt_fontinfo FontInfo; stbrp_rect* Rects; + int RectsCount; stbtt_pack_range* Ranges; int RangesCount; }; @@ -1434,6 +1454,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Pack tmp.Rects = buf_rects + buf_rects_n; + tmp.RectsCount = font_glyphs_count; buf_rects_n += font_glyphs_count; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); @@ -1463,6 +1484,14 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) ImFontTempBuildData& tmp = tmp_array[input_i]; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); + if (cfg.RasterizerMultiply != 1.0f) + { + unsigned char multiply_table[256]; + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + for (const stbrp_rect* r = tmp.Rects; r != tmp.Rects + tmp.RectsCount; r++) + if (r->was_packed) + ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, spc.pixels, r->x, r->y, r->w, r->h, spc.stride_in_bytes); + } tmp.Rects = NULL; } diff --git a/imgui_internal.h b/imgui_internal.h index b38101876..40af8ca47 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -816,6 +816,8 @@ IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtl IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc); IMGUI_API void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); +IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); #ifdef __clang__ #pragma clang diagnostic pop From 5938f1ba61cd08b723e777b2739cc21456831f02 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 15:18:06 +0800 Subject: [PATCH 048/101] Added IsMousePosValid() helper. --- imgui.cpp | 16 ++++++++++++---- imgui.h | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9f8a0c5fc..384078d96 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2153,11 +2153,10 @@ void ImGui::NewFrame() // Update mouse input state // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta - const float MOUSE_INVALID = -256000.0f; - if ((g.IO.MousePos.x < MOUSE_INVALID && g.IO.MousePos.y < MOUSE_INVALID) || (g.IO.MousePosPrev.x < MOUSE_INVALID && g.IO.MousePosPrev.y < MOUSE_INVALID)) - g.IO.MouseDelta = ImVec2(0.0f, 0.0f); - else + if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; + else + g.IO.MouseDelta = ImVec2(0.0f, 0.0f); g.IO.MousePosPrev = g.IO.MousePos; for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { @@ -3228,6 +3227,15 @@ ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() return g.IO.MousePos; } +// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position +bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) +{ + if (mouse_pos == NULL) + mouse_pos = &GImGui->IO.MousePos; + const float MOUSE_INVALID = -256000.0f; + return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID; +} + ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 7d0721b04..7100fb24d 100644 --- a/imgui.h +++ b/imgui.h @@ -458,6 +458,7 @@ namespace ImGui IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. + IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold From 419b22a4871119625b441566dd4c27cbb15f20cd Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 16:35:39 +0800 Subject: [PATCH 049/101] Internals: Split some code out of NewFrame() into an Initialize() function. --- imgui.cpp | 26 +++++++++++++++----------- imgui_internal.h | 1 + 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 384078d96..bff649188 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2125,16 +2125,9 @@ void ImGui::NewFrame() IM_ASSERT(g.Style.CurveTessellationTol > 0.0f); // Invalid style setting IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f); // Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations) + // Initialize on first frame if (!g.Initialized) - { - // Initialize on first frame - g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); - IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer(); - - IM_ASSERT(g.Settings.empty()); - LoadIniSettingsFromDisk(g.IO.IniFilename); - g.Initialized = true; - } + ImGui::Initialize(); SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); @@ -2350,7 +2343,18 @@ void ImGui::NewFrame() ImGui::Begin("Debug"); } -// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. +void ImGui::Initialize() +{ + ImGuiContext& g = *GImGui; + g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); + IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer(); + + IM_ASSERT(g.Settings.empty()); + LoadIniSettingsFromDisk(g.IO.IniFilename); + g.Initialized = true; +} + +// This function is merely here to free heap allocations. void ImGui::Shutdown() { ImGuiContext& g = *GImGui; @@ -2359,7 +2363,7 @@ void ImGui::Shutdown() if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. g.IO.Fonts->Clear(); - // Cleanup of other data are conditional on actually having used ImGui. + // Cleanup of other data are conditional on actually having initialize ImGui. if (!g.Initialized) return; diff --git a/imgui_internal.h b/imgui_internal.h index 40af8ca47..7feaa176e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -741,6 +741,7 @@ namespace ImGui IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void FocusWindow(ImGuiWindow* window); + IMGUI_API void Initialize(); IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); From b295e185ffae72e2f3edea83526b0324484f9f5b Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 26 Aug 2017 16:42:40 +0800 Subject: [PATCH 050/101] Updated copyright date for 2017, updated Gallery link --- LICENSE.txt | 2 +- imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index b28ef2253..5a9b98b83 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2015 Omar Cornut and ImGui contributors +Copyright (c) 2014-2017 Omar Cornut and ImGui contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/imgui.cpp b/imgui.cpp index bff649188..ef3987ace 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5,7 +5,7 @@ // Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases -// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/772 +// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // This library is free but I need your support to sustain development and maintenance. // If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui From 0d4b08a851e8c16cbf16916124e1811e34ab875d Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 12:14:29 +0800 Subject: [PATCH 051/101] Added Go binding link --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3bfb46edf..44233311c 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,15 @@ _NB: those third-party bindings may be more or less maintained, more or less clo _Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!_ Languages: -- cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui -- ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET -- imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs -- DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui -- CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui -- pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui -- LUA: https://github.com/patrickriordan/imgui_lua_bindings -- imgui-pas: P ascal bindings for imgui https://github.com/dpethes/imgui-pas +- C - cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui +- C#/.Net - ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET +- D - DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui +- Go - go-imgui https://github.com/Armored-Dragon/go-imgui +- Lua - https://github.com/patrickriordan/imgui_lua_bindings +- Pascal - imgui-pas https://github.com/dpethes/imgui-pas +- Python - CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui +- Python - pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui +- Rust - imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs Frameworks: - Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples From 7a7327addec8cde30c13d6224a121033043874ba Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 13:19:20 +0800 Subject: [PATCH 052/101] ParseFormatPrecision() returns -1 for scientific noation 'e'/'E', RoundScalar() doesn't alter those. --- imgui.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ef3987ace..024d2aaa3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -936,6 +936,18 @@ const char* ImStristr(const char* haystack, const char* haystack_end, const char return NULL; } +static const char* ImAtoi(const char* src, int* output) +{ + int negative = 0; + if (*src == '-') { negative = 1; src++; } + if (*src == '+') { src++; } + int v = 0; + while (*src >= '0' && *src <= '9') + v = (v * 10) + (*src++ - '0'); + *output = negative ? -v : v; + return src; +} + // MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. int ImFormatString(char* buf, int buf_size, const char* fmt, ...) @@ -6462,10 +6474,12 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) fmt++; if (*fmt == '.') { - precision = atoi(fmt + 1); + fmt = ImAtoi(fmt + 1, &precision); if (precision < 0 || precision > 10) precision = default_precision; } + if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation + precision = -1; break; } return precision; @@ -6482,6 +6496,8 @@ float ImGui::RoundScalar(float value, int decimal_precision) // Round past decimal precision // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 // FIXME: Investigate better rounding methods + if (decimal_precision < 0) + return value; const float min_step = GetMinimumStepAtDecimalPrecision(decimal_precision); bool negative = value < 0.0f; value = fabsf(value); @@ -6533,7 +6549,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v const float grab_padding = 2.0f; const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); float grab_sz; - if (decimal_precision > 0) + if (decimal_precision != 0) grab_sz = ImMin(style.GrabMinSize, slider_sz); else grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit From 1f51e8f39d69e45d32e59f274b0b0760710b0603 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 14:11:11 +0800 Subject: [PATCH 053/101] Internals: Renamed some ImGuiCorner enums. --- imgui.cpp | 12 ++++++------ imgui_draw.cpp | 10 +++++----- imgui_internal.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 024d2aaa3..59acbb2b5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4276,7 +4276,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bg_color.w = bg_alpha; bg_color.w *= style.Alpha; if (bg_color.w > 0.0f) - window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BottomLeft|ImGuiCorner_BottomRight); + window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4500,9 +4500,9 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; int window_rounding_corners; if (horizontal) - window_rounding_corners = ImGuiCorner_BottomLeft | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); + window_rounding_corners = ImGuiCorner_BotLeft | (other_scrollbar ? 0 : ImGuiCorner_BotRight); else - window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BottomRight); + window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BotRight); window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); @@ -9085,7 +9085,7 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU continue; int rounding_corners_flags_cell = 0; if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImGuiCorner_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImGuiCorner_TopRight; } - if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImGuiCorner_BottomLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImGuiCorner_BottomRight; } + if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImGuiCorner_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImGuiCorner_BotRight; } rounding_corners_flags_cell &= rounding_corners_flags; window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell); } @@ -9145,8 +9145,8 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f) { float mid_x = (float)(int)((bb.Min.x + bb.Max.x) * 0.5f + 0.5f); - RenderColorRectWithAlphaCheckerboard(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col), grid_step, ImVec2(-grid_step, 0.0f), rounding, ImGuiCorner_TopRight|ImGuiCorner_BottomRight); - window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_without_alpha), rounding, ImGuiCorner_TopLeft|ImGuiCorner_BottomLeft); + RenderColorRectWithAlphaCheckerboard(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col), grid_step, ImVec2(-grid_step, 0.0f), rounding, ImGuiCorner_TopRight|ImGuiCorner_BotRight); + window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_without_alpha), rounding, ImGuiCorner_TopLeft|ImGuiCorner_BotLeft); } else { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index cd8325393..4e15ea0c0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -775,9 +775,9 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) { const int corners_top = ImGuiCorner_TopLeft | ImGuiCorner_TopRight; - const int corners_bottom = ImGuiCorner_BottomLeft | ImGuiCorner_BottomRight; - const int corners_left = ImGuiCorner_TopLeft | ImGuiCorner_BottomLeft; - const int corners_right = ImGuiCorner_TopRight | ImGuiCorner_BottomRight; + const int corners_bottom = ImGuiCorner_BotLeft | ImGuiCorner_BotRight; + const int corners_left = ImGuiCorner_TopLeft | ImGuiCorner_BotLeft; + const int corners_right = ImGuiCorner_TopRight | ImGuiCorner_BotRight; float r = rounding; r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners & corners_top) == corners_top) || ((rounding_corners & corners_bottom) == corners_bottom) ? 0.5f : 1.0f ) - 1.0f); @@ -794,8 +794,8 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int { const float r0 = (rounding_corners & ImGuiCorner_TopLeft) ? r : 0.0f; const float r1 = (rounding_corners & ImGuiCorner_TopRight) ? r : 0.0f; - const float r2 = (rounding_corners & ImGuiCorner_BottomRight) ? r : 0.0f; - const float r3 = (rounding_corners & ImGuiCorner_BottomLeft) ? r : 0.0f; + const float r2 = (rounding_corners & ImGuiCorner_BotRight) ? r : 0.0f; + const float r3 = (rounding_corners & ImGuiCorner_BotLeft) ? r : 0.0f; PathArcToFast(ImVec2(a.x+r0,a.y+r0), r0, 6, 9); PathArcToFast(ImVec2(b.x-r1,a.y+r1), r1, 9, 12); PathArcToFast(ImVec2(b.x-r2,b.y-r2), r2, 0, 3); diff --git a/imgui_internal.h b/imgui_internal.h index 7feaa176e..d0ac0cf84 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -234,8 +234,8 @@ enum ImGuiCorner { ImGuiCorner_TopLeft = 1 << 0, // 1 ImGuiCorner_TopRight = 1 << 1, // 2 - ImGuiCorner_BottomRight = 1 << 2, // 4 - ImGuiCorner_BottomLeft = 1 << 3, // 8 + ImGuiCorner_BotRight = 1 << 2, // 4 + ImGuiCorner_BotLeft = 1 << 3, // 8 ImGuiCorner_All = 0x0F }; From e1d81f4dc5c62f4bf76adb8da044a475949b4b83 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 14:12:55 +0800 Subject: [PATCH 054/101] ImDrawList: Minor tidying up. --- imgui_draw.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4e15ea0c0..aad5bbb6c 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -694,7 +694,8 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_ circle_vtx_builds = true; } - if (a_min_of_12 > a_max_of_12) return; + if (a_min_of_12 > a_max_of_12) + return; if (radius == 0.0f) { _Path.push_back(centre); @@ -779,11 +780,10 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int const int corners_left = ImGuiCorner_TopLeft | ImGuiCorner_BotLeft; const int corners_right = ImGuiCorner_TopRight | ImGuiCorner_BotRight; - float r = rounding; - r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners & corners_top) == corners_top) || ((rounding_corners & corners_bottom) == corners_bottom) ? 0.5f : 1.0f ) - 1.0f); - r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners & corners_left) == corners_left) || ((rounding_corners & corners_right) == corners_right) ? 0.5f : 1.0f ) - 1.0f); + rounding = ImMin(rounding, fabsf(b.x - a.x) * ( ((rounding_corners & corners_top) == corners_top) || ((rounding_corners & corners_bottom) == corners_bottom) ? 0.5f : 1.0f ) - 1.0f); + rounding = ImMin(rounding, fabsf(b.y - a.y) * ( ((rounding_corners & corners_left) == corners_left) || ((rounding_corners & corners_right) == corners_right) ? 0.5f : 1.0f ) - 1.0f); - if (r <= 0.0f || rounding_corners == 0) + if (rounding <= 0.0f || rounding_corners == 0) { PathLineTo(a); PathLineTo(ImVec2(b.x,a.y)); @@ -792,14 +792,14 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int } else { - const float r0 = (rounding_corners & ImGuiCorner_TopLeft) ? r : 0.0f; - const float r1 = (rounding_corners & ImGuiCorner_TopRight) ? r : 0.0f; - const float r2 = (rounding_corners & ImGuiCorner_BotRight) ? r : 0.0f; - const float r3 = (rounding_corners & ImGuiCorner_BotLeft) ? r : 0.0f; - PathArcToFast(ImVec2(a.x+r0,a.y+r0), r0, 6, 9); - PathArcToFast(ImVec2(b.x-r1,a.y+r1), r1, 9, 12); - PathArcToFast(ImVec2(b.x-r2,b.y-r2), r2, 0, 3); - PathArcToFast(ImVec2(a.x+r3,b.y-r3), r3, 3, 6); + const float rounding_tl = (rounding_corners & ImGuiCorner_TopLeft) ? rounding : 0.0f; + const float rounding_tr = (rounding_corners & ImGuiCorner_TopRight) ? rounding : 0.0f; + const float rounding_br = (rounding_corners & ImGuiCorner_BotRight) ? rounding : 0.0f; + const float rounding_bl = (rounding_corners & ImGuiCorner_BotLeft) ? rounding : 0.0f; + PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9); + PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12); + PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3); + PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6); } } From 808d631e35c3825f0ba9a4d7c0201be81ce879be Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 16:02:25 +0800 Subject: [PATCH 055/101] imDrawList: PathArcTo() returns when passed zero radius. --- imgui_draw.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index aad5bbb6c..27f3965a4 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -694,27 +694,26 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_ circle_vtx_builds = true; } - if (a_min_of_12 > a_max_of_12) - return; - if (radius == 0.0f) + if (radius == 0.0f || a_min_of_12 > a_max_of_12) { _Path.push_back(centre); + return; } - else + _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); + for (int a = a_min_of_12; a <= a_max_of_12; a++) { - _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); - for (int a = a_min_of_12; a <= a_max_of_12; a++) - { - const ImVec2& c = circle_vtx[a % circle_vtx_count]; - _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); - } + const ImVec2& c = circle_vtx[a % circle_vtx_count]; + _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); } } void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float amax, int num_segments) { if (radius == 0.0f) + { _Path.push_back(centre); + return; + } _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { @@ -786,9 +785,9 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int if (rounding <= 0.0f || rounding_corners == 0) { PathLineTo(a); - PathLineTo(ImVec2(b.x,a.y)); + PathLineTo(ImVec2(b.x, a.y)); PathLineTo(b); - PathLineTo(ImVec2(a.x,b.y)); + PathLineTo(ImVec2(a.x, b.y)); } else { From 7a9ea281bed18383b302815f3efcf9bb2a1e9b30 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 28 Aug 2017 19:27:12 +0800 Subject: [PATCH 056/101] ImSwap() helper. --- imgui.cpp | 4 ++-- imgui_internal.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 59acbb2b5..837a20038 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1252,12 +1252,12 @@ void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& float K = 0.f; if (g < b) { - const float tmp = g; g = b; b = tmp; + ImSwap(g, b); K = -1.f; } if (r < g) { - const float tmp = r; r = g; g = tmp; + ImSwap(r, g); K = -2.f / 6.f - K; } diff --git a/imgui_internal.h b/imgui_internal.h index d0ac0cf84..130733e87 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -138,6 +138,7 @@ static inline int ImClamp(int v, int mn, int mx) static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } +static inline void ImSwap(float& a, float& b) { float tmp = a; a = b; b = tmp; } static inline int ImLerp(int a, int b, float t) { return (int)(a + (b - a) * t); } static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } From f0fa17b5e064e87de6dfe9bbf6afc9af3f75120f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 15:10:03 +0800 Subject: [PATCH 057/101] ImDrawList: Minor renaming --- imgui_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 27f3965a4..b27da94bf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -707,7 +707,7 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_ } } -void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float amax, int num_segments) +void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments) { if (radius == 0.0f) { @@ -717,7 +717,7 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float amin, float _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { - const float a = amin + ((float)i / (float)num_segments) * (amax - amin); + const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); _Path.push_back(ImVec2(centre.x + cosf(a) * radius, centre.y + sinf(a) * radius)); } } From 01d4bf299ae660a4b3da548965b07d02bf9ba087 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 15:22:30 +0800 Subject: [PATCH 058/101] Added overcomplicated RenderRectFilledRangeH() to fix rounded progress bar, which will also help for range widgets and perhaps sliders grabs over rounded areas. (#1296, #76) --- imgui_draw.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ imgui_internal.h | 1 + 2 files changed, 72 insertions(+) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b27da94bf..4a090c355 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2329,6 +2329,77 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size; } +//----------------------------------------------------------------------------- +// Internals Drawing Helpers +//----------------------------------------------------------------------------- + +static inline float ImAcos01(float x) +{ + if (x <= 0.0f) return IM_PI * 0.5f; + if (x >= 1.0f) return 0.0f; + return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, enough for what we do. +} + +// FIXME: Cleanup and move code to ImDrawList. +void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding) +{ + if (x_end_norm == x_start_norm) + return; + if (x_start_norm > x_end_norm) + ImSwap(x_start_norm, x_end_norm); + + ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y); + ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y); + if (rounding == 0.0f) + { + draw_list->AddRectFilled(p0, p1, col, 0.0f); + return; + } + + rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding); + const float inv_rounding = 1.0f / rounding; + const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding); + const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding); + const float x0 = ImMax(p0.x, rect.Min.x + rounding); + if (arc0_b == arc0_e) + { + draw_list->PathLineTo(ImVec2(x0, p1.y)); + draw_list->PathLineTo(ImVec2(x0, p0.y)); + } + else if (arc0_b == 0.0f && arc0_e == IM_PI*0.5f) + { + draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL + draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR + } + else + { + draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL + draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR + } + if (p1.x > rect.Min.x + rounding) + { + const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding); + const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding); + const float x1 = ImMin(p1.x, rect.Max.x - rounding); + if (arc1_b == arc1_e) + { + draw_list->PathLineTo(ImVec2(x1, p0.y)); + draw_list->PathLineTo(ImVec2(x1, p1.y)); + } + else if (arc1_b == 0.0f && arc1_e == IM_PI*0.5f) + { + draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR + draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR + } + else + { + draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR + draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR + } + } + draw_list->PathFillConvex(col); +} + //----------------------------------------------------------------------------- // DEFAULT FONT DATA //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 130733e87..d0fdd063d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -779,6 +779,7 @@ namespace ImGui IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); + IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); From f8eef4957589f98781432ce72f517a1ffb43ae51 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 15:23:07 +0800 Subject: [PATCH 059/101] ProgressBar() fixed rendering when straddling rounded area. (#1296) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 837a20038..880b1f543 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7323,7 +7323,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); bb.Expand(ImVec2(-window->BorderSize, -window->BorderSize)); const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); - RenderFrame(bb.Min, fill_br, GetColorU32(ImGuiCol_PlotHistogram), false, style.FrameRounding); + RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); // Default displaying the fraction as percentage string, but user can override it char overlay_buf[32]; From 0ba3cadb887058ce6b86ce2a9048cf2bb1dc85b0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 15:25:05 +0800 Subject: [PATCH 060/101] RenderRectFilledRangeH() can't use cheap acosf() approximation for now. (#1296) --- imgui_draw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4a090c355..0a23ac0e5 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2337,7 +2337,8 @@ static inline float ImAcos01(float x) { if (x <= 0.0f) return IM_PI * 0.5f; if (x >= 1.0f) return 0.0f; - return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, enough for what we do. + return acosf(x); + //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do. } // FIXME: Cleanup and move code to ImDrawList. From ee42fae4683ea75f51faa156cf91304ef2d2bf3d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 16:05:12 +0800 Subject: [PATCH 061/101] Merge various minor things (supposedly harmless) from Navigation branch into Master to reduce differences. (#787) --- imgui.cpp | 20 ++++++++++---------- imgui.h | 14 +++++++------- imgui_internal.h | 9 +++++---- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 880b1f543..cb9a7fa1f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1803,9 +1803,9 @@ ImGuiWindow::ImGuiWindow(const char* name) DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); IM_PLACEMENT_NEW(DrawList) ImDrawList(); DrawList->_OwnerName = Name; + ParentWindow = NULL; RootWindow = NULL; RootNonPopupWindow = NULL; - ParentWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; @@ -1925,7 +1925,8 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) // declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; @@ -1933,7 +1934,6 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return false; // This is a sensible default, but widgets are free to override it after calling ItemAdd() - ImGuiContext& g = *GImGui; if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) @@ -2210,7 +2210,7 @@ void ImGui::NewFrame() g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; - // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. + // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) { KeepAliveID(g.MovedWindowMoveId); @@ -2221,7 +2221,7 @@ void ImGui::NewFrame() if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow->PosFloat += g.IO.MouseDelta; - if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) + if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) MarkIniSettingsDirty(g.MovedWindow); } FocusWindow(g.MovedWindow); @@ -3705,7 +3705,6 @@ void ImGui::EndChild() sz.x = ImMax(4.0f, sz.x); if (window->AutoFitChildAxises & 0x02) sz.y = ImMax(4.0f, sz.y); - ImGui::End(); ImGuiWindow* parent_window = GetCurrentWindow(); @@ -4159,10 +4158,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) { - ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, g.IO.MousePos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? - window->PosFloat = FindBestPopupWindowPos(g.IO.MousePos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); + ImVec2 ref_pos = g.IO.MousePos; + ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? + window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == -1) - window->PosFloat = g.IO.MousePos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. + window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. } // Clamp position so it stays visible @@ -4217,7 +4217,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; if (window->Collapsed) { - // Draw title bar only + // Title bar only RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); } else diff --git a/imgui.h b/imgui.h index 7100fb24d..14fd4d9d5 100644 --- a/imgui.h +++ b/imgui.h @@ -412,11 +412,11 @@ namespace ImGui IMGUI_API void PopClipRect(); // Utilities - IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? - IMGUI_API bool IsItemRectHovered(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this - IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) - IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) - IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) + IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)? + IMGUI_API bool IsItemRectHovered(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this + IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) + IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) + IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space @@ -425,7 +425,7 @@ namespace ImGui IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(); // is current window focused IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowRectHovered(); // is current window rectnagle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) + IMGUI_API bool IsWindowRectHovered(); // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) @@ -786,7 +786,7 @@ struct ImGuiIO float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). - float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. + float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. void* UserData; // = NULL // Store your own data for retrieval by callbacks. ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. diff --git a/imgui_internal.h b/imgui_internal.h index d0fdd063d..10598ac6f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -538,7 +538,7 @@ struct ImGuiContext DragCurrentValue = 0.0f; DragLastMouseDelta = ImVec2(0.0f, 0.0f); DragSpeedDefaultRatio = 1.0f / 100.0f; - DragSpeedScaleSlow = 0.01f; + DragSpeedScaleSlow = 1.0f / 100.0f; DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); TooltipOverrideCount = 0; @@ -697,9 +697,10 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; - ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. - ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. + ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) + ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. + ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing + // Navigation / Focus int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() From 1f1e63f705f90ef51c4b5205cf8c4517d1e8f6c2 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 16:06:52 +0800 Subject: [PATCH 062/101] Merge various minor things (supposedly harmless) from Navigation branch into Master to reduce differences. Some code in NewFrame() has been moved around. (#787) --- imgui.cpp | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cb9a7fa1f..ed69170f5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -751,25 +751,21 @@ ImGuiIO::ImGuiIO() IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; - Fonts = &GImDefaultFontAtlas; - FontGlobalScale = 1.0f; - FontDefault = NULL; - DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; - MouseDragThreshold = 6.0f; - for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) - MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) - KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; KeyRepeatDelay = 0.250f; KeyRepeatRate = 0.050f; UserData = NULL; + Fonts = &GImDefaultFontAtlas; + FontGlobalScale = 1.0f; + FontDefault = NULL; + FontAllowUserScaling = false; + DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); + // User functions RenderDrawListsFn = NULL; MemAllocFn = malloc; @@ -780,6 +776,13 @@ ImGuiIO::ImGuiIO() ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; ImeWindowHandle = NULL; + // Input (NB: we already have memset zero the entire structure) + MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); + MouseDragThreshold = 6.0f; + for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; + // Set OS X style defaults based on __APPLE__ compile time flag #ifdef __APPLE__ OSXBehaviors = true; @@ -1768,14 +1771,13 @@ ImGuiWindow::ImGuiWindow(const char* name) Name = ImStrdup(name); ID = ImHash(name, 0); IDStack.push_back(ID); - MoveId = GetID("#MOVE"); - Flags = 0; OrderWithinParent = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f); SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); WindowPadding = ImVec2(0.0f, 0.0f); + MoveId = GetID("#MOVE"); Scroll = ImVec2(0.0f, 0.0f); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); @@ -2156,6 +2158,20 @@ void ImGui::NewFrame() g.RenderDrawData.CmdLists = NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; + // Clear reference to active widget if the widget isn't alive anymore + g.HoveredIdPreviousFrame = g.HoveredId; + g.HoveredId = 0; + g.HoveredIdAllowOverlap = false; + if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) + ClearActiveID(); + g.ActiveIdPreviousFrame = g.ActiveId; + g.ActiveIdIsAlive = false; + g.ActiveIdIsJustActivated = false; + // Update keyboard input state + memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) + g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + // Update mouse input state // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) @@ -2190,9 +2206,6 @@ void ImGui::NewFrame() g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); } } - memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) - g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; // Calculate frame-rate for the user, as a purely luxurious feature g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; @@ -2200,16 +2213,6 @@ void ImGui::NewFrame() g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - // Clear reference to active widget if the widget isn't alive anymore - g.HoveredIdPreviousFrame = g.HoveredId; - g.HoveredId = 0; - g.HoveredIdAllowOverlap = false; - if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) - ClearActiveID(); - g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdIsAlive = false; - g.ActiveIdIsJustActivated = false; - // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) { From 358e7a194e0c5f86abdbd5ce5934561202a0cd50 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 16:13:17 +0800 Subject: [PATCH 063/101] Added GetKeyPressedAmount() (from Nav branch) to be able to measure fast repeat rate accurately. Added internal CalcTypematicPressedRepeatAmount() function. --- imgui.cpp | 26 ++++++++++++++++++++------ imgui.h | 1 + imgui_internal.h | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ed69170f5..80da34185 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3154,6 +3154,25 @@ bool ImGui::IsKeyDown(int user_key_index) return GImGui->IO.KeysDown[user_key_index]; } +int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) +{ + if (t == 0.0f) + return 1; + if (t <= repeat_delay || repeat_rate <= 0.0f) + return 0; + const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate); + return (count > 0) ? count : 0; +} + +int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) +{ + ImGuiContext& g = *GImGui; + if (key_index < 0) return false; + IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); + const float t = g.IO.KeysDownDuration[key_index]; + return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate); +} + bool ImGui::IsKeyPressed(int user_key_index, bool repeat) { ImGuiContext& g = *GImGui; @@ -3162,13 +3181,8 @@ bool ImGui::IsKeyPressed(int user_key_index, bool repeat) const float t = g.IO.KeysDownDuration[user_key_index]; if (t == 0.0f) return true; - if (repeat && t > g.IO.KeyRepeatDelay) - { - float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) - return true; - } + return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; return false; } diff --git a/imgui.h b/imgui.h index 14fd4d9d5..f40c7db97 100644 --- a/imgui.h +++ b/imgui.h @@ -452,6 +452,7 @@ namespace ImGui IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your backend/engine stored them into KeyDown[]! IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down).. + IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate IMGUI_API bool IsMouseDown(int button); // is mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. diff --git a/imgui_internal.h b/imgui_internal.h index 10598ac6f..80b2f4ded 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -764,6 +764,8 @@ namespace ImGui IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API bool IsPopupOpen(ImGuiID id); + IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); + // New Columns API IMGUI_API void BeginColumns(const char* 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 From 287a4b6b38d1f28ffcb06b8c58957034a0cd0b6f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 16:52:37 +0800 Subject: [PATCH 064/101] Merged from Navigation branch: https://github.com/ocornut/imgui/commit/5cac4926c82a41253bd3540ce1bb4f50b0cfc146 fix title bar color of window under a modal window. --- imgui.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 80da34185..766116333 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1935,7 +1935,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) if (IsClippedEx(bb, id, false)) return false; - // This is a sensible default, but widgets are free to override it after calling ItemAdd() + // Setting LastItemHoveredAndUsable for IsItemHovered(). This is a sensible default, but widgets are free to override it. if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) @@ -4008,11 +4008,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) break; for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) - if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) + if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (g.CurrentWindowStack[root_non_popup_idx]->Flags & ImGuiWindowFlags_Modal)) break; window->ParentWindow = parent_window; window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. + window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) @@ -4235,7 +4236,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (window->Collapsed) { // Title bar only - RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); + RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); } else { @@ -4296,8 +4297,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); // Title bar + const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) @@ -4387,11 +4389,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) { + // Close button if (p_open != NULL) { - const float pad = 2.0f; - const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) + const float PAD = 2.0f; + const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f; + if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad)) *p_open = false; } From c9298c26571ab244957e871482a46e7696266b89 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 17:09:44 +0800 Subject: [PATCH 065/101] Merged from Navigation branch: f71cdd13b71895c1d7f10b7eaa9d0fdc2849f626 Internal tidying up, moved code to CalcNextScrollFromScrollTargetAndClamp() so it can be reused by upcoming nav code. c816e6c74250b8946333682663dc9365e4b14e13 Fixed SetScrollX() handling of center ratio (which actually wasn't exposed publicly). (#323, #246) --- imgui.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 766116333..913bd9dde 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -609,6 +609,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window); static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); static void Scrollbar(ImGuiWindow* window, bool horizontal); +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); @@ -3894,6 +3895,24 @@ static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) window->SizeFull = new_size; } +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) +{ + ImVec2 scroll = window->Scroll; + float cr_x = window->ScrollTargetCenterRatio.x; + float cr_y = window->ScrollTargetCenterRatio.y; + if (window->ScrollTarget.x < FLT_MAX) + scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x); + if (window->ScrollTarget.y < FLT_MAX) + scroll.y = window->ScrollTarget.y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y); + scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); + if (!window->Collapsed && !window->SkipItems) + { + scroll.x = ImMin(scroll.x, ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x))); // == GetScrollMaxX for that window + scroll.y = ImMin(scroll.y, ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y))); // == GetScrollMaxY for that window + } + return scroll; +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -4208,23 +4227,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; // Apply scrolling - if (window->ScrollTarget.x < FLT_MAX) - { - window->Scroll.x = window->ScrollTarget.x; - window->ScrollTarget.x = FLT_MAX; - } - if (window->ScrollTarget.y < FLT_MAX) - { - float center_ratio = window->ScrollTargetCenterRatio.y; - window->Scroll.y = window->ScrollTarget.y - ((1.0f - center_ratio) * (window->TitleBarHeight() + window->MenuBarHeight())) - (center_ratio * (window->SizeFull.y - window->ScrollbarSizes.y)); - window->ScrollTarget.y = FLT_MAX; - } - window->Scroll = ImMax(window->Scroll, ImVec2(0.0f, 0.0f)); - if (!window->Collapsed && !window->SkipItems) - { - window->Scroll.x = ImMin(window->Scroll.x, GetScrollMaxX()); - window->Scroll.y = ImMin(window->Scroll.y, GetScrollMaxY()); - } + window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window); + window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); // Modal window darkens what is behind them if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) From aef041f94884cb30b4da59fdbab1c85f4b3b2575 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 17:09:56 +0800 Subject: [PATCH 066/101] Merged from Navigation branch --- imgui.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 913bd9dde..532c67648 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4255,24 +4255,27 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bool hovered, held; ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; + ImVec2 size_target(FLT_MAX,FLT_MAX); if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) { // Manual auto-fit when double-clicking - ApplySizeFullWithConstraint(window, size_auto_fit); - MarkIniSettingsDirty(window); + size_target = size_auto_fit; ClearActiveID(); } else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); - MarkIniSettingsDirty(window); + size_target = (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos; } + if (size_target.x != FLT_MAX && size_target.y != FLT_MAX) + { + ApplySizeFullWithConstraint(window, size_target); + MarkIniSettingsDirty(window); + } window->Size = window->SizeFull; title_bar_rect = window->TitleBarRect(); } From 550dc0999826379f0f79f7c30860df74bef8ce5d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 17:12:18 +0800 Subject: [PATCH 067/101] Merged from Navigation branch (misc) --- imgui.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 532c67648..590329cb3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2633,6 +2633,19 @@ static void AddWindowToRenderList(ImVector& out_render_list, ImGuiW } } +static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) +{ + // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. + ImGuiContext& g = *GImGui; + g.IO.MetricsActiveWindows++; + if (window->Flags & ImGuiWindowFlags_Popup) + AddWindowToRenderList(g.RenderDrawLists[1], window); + else if (window->Flags & ImGuiWindowFlags_Tooltip) + AddWindowToRenderList(g.RenderDrawLists[2], window); + else + AddWindowToRenderList(g.RenderDrawLists[0], window); +} + // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { @@ -2734,16 +2747,7 @@ void ImGui::Render() { ImGuiWindow* window = g.Windows[i]; if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - { - // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. - g.IO.MetricsActiveWindows++; - if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.RenderDrawLists[1], window); - else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.RenderDrawLists[2], window); - else - AddWindowToRenderList(g.RenderDrawLists[0], window); - } + AddWindowToRenderListSelectLayer(window); } // Flatten layers @@ -3138,7 +3142,7 @@ bool ImGui::IsAnyWindowHovered() static bool IsKeyPressedMap(ImGuiKey key, bool repeat) { const int key_index = GImGui->IO.KeyMap[key]; - return ImGui::IsKeyPressed(key_index, repeat); + return (key_index >= 0) ? ImGui::IsKeyPressed(key_index, repeat) : false; } int ImGui::GetKeyIndex(ImGuiKey imgui_key) From ddf41b039805983d9501d31a98aeccd3c6dbec30 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 17:27:19 +0800 Subject: [PATCH 068/101] Merged from Navigation branch. TAB/Alt-TAB processing now deactivate if holding Ctrl. --- imgui.cpp | 19 ++++++++----------- imgui_internal.h | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 590329cb3..56f3ee536 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1977,7 +1977,7 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) return false; } -bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) +bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop) { ImGuiContext& g = *GImGui; @@ -1986,13 +1986,10 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_ if (allow_keyboard_focus) window->FocusIdxTabCounter++; - // Process keyboard input at this point: TAB, Shift-TAB switch focus - // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) - { - // Modulo on index will be applied at the end of frame once we've got the total counter of items. - window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); - } + // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item. + // Note that we can always TAB out of a widget that doesn't allow tabbing in. + if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) + window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) return true; @@ -6715,7 +6712,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); + const bool tab_focus_requested = FocusableItemRegister(window, id); if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) { SetActiveID(id, window); @@ -7013,7 +7010,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); + const bool tab_focus_requested = FocusableItemRegister(window, id); if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) { SetActiveID(id, window); @@ -7818,7 +7815,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // NB: we are only allowed to access 'edit_state' if we are the active widget. ImGuiTextEditState& edit_state = g.InputTextState; - const bool focus_requested = FocusableItemRegister(window, g.ActiveId == id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing + const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; diff --git a/imgui_internal.h b/imgui_internal.h index 80b2f4ded..1a02473a0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -756,7 +756,7 @@ namespace ImGui IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); - IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested + IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); From 6cca4025eea4bb2eefe3f7af84a164ea9cc96335 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 17:56:53 +0800 Subject: [PATCH 069/101] Merge from Navigation branch: 6aa80197633f23bb0c7d72ac4731d6895766c613 --- imgui.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 56f3ee536..39ee504c5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2165,6 +2165,9 @@ void ImGui::NewFrame() g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; + if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) + g.ScalarAsInputTextId = 0; + // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) @@ -6480,11 +6483,6 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label g.ScalarAsInputTextId = g.ActiveId; SetHoveredID(id); } - else if (g.ActiveId != g.ScalarAsInputTextId) - { - // Release - g.ScalarAsInputTextId = 0; - } if (text_value_changed) return DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, NULL); return false; @@ -6727,9 +6725,8 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); - ItemSize(total_bb, style.FramePadding.y); - // Actual slider behavior + render grab + ItemSize(total_bb, style.FramePadding.y); const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. @@ -8983,6 +8980,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); + if (menuset_is_open) g.NavWindow = backed_nav_window; From 35e4fa7b851fb273c7e4f9bfae469072a93b6dee Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 18:21:36 +0800 Subject: [PATCH 070/101] Merged from Navigation branch (DragBehavior) --- imgui.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 39ee504c5..4004a6285 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6926,15 +6926,20 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) + float adjust_delta = 0.0f; + //if (g.ActiveIdSource == ImGuiInputSource_Mouse) { - float speed = v_speed; + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - speed = speed * g.DragSpeedScaleFast; + adjust_delta *= g.DragSpeedScaleFast; if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - speed = speed * g.DragSpeedScaleSlow; + adjust_delta *= g.DragSpeedScaleSlow; + } + adjust_delta *= v_speed; + g.DragLastMouseDelta.x = mouse_drag_delta.x; - float adjust_delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; + if (fabsf(adjust_delta) > 0.0f) + { if (fabsf(power - 1.0f) > 0.001f) { // Logarithmic curve on both side of 0.0 @@ -6949,7 +6954,6 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s { v_cur += adjust_delta; } - g.DragLastMouseDelta.x = mouse_drag_delta.x; // Clamp if (v_min < v_max) From 96d2942373c650dcd40979c60ec53a795497d648 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 18:40:14 +0800 Subject: [PATCH 071/101] InputText: Merged bits from Navigation branch (inc. g.ActiveIdIsJustActivated is only set on the toggle). --- imgui.cpp | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4004a6285..a94546e04 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1868,11 +1868,10 @@ ImGuiWindow* ImGui::GetParentWindow() void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; + g.ActiveIdIsJustActivated = (g.ActiveId != id); g.ActiveId = id; g.ActiveIdAllowOverlap = false; - g.ActiveIdIsJustActivated = true; - if (id) - g.ActiveIdIsAlive = true; + g.ActiveIdIsAlive |= (id != 0); g.ActiveIdWindow = window; } @@ -7829,6 +7828,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); + bool clear_active_id = false; + bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0; if (focus_requested || user_clicked || user_scrolled) { @@ -7874,8 +7875,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (io.MouseClicked[0]) { // Release focus when we click outside - if (g.ActiveId == id) - ClearActiveID(); + clear_active_id = true; } bool value_changed = false; @@ -7948,9 +7948,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Consume characters memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); } + } - // Handle various key-presses - bool cancel_edit = false; + bool cancel_edit = false; + if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) + { + // Handle key-presses const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl const bool is_wordmove_key_down = io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl @@ -7977,8 +7980,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) { - ClearActiveID(); - enter_pressed = true; + enter_pressed = clear_active_id = true; } else if (is_editable) { @@ -7993,7 +7995,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } - else if (IsKeyPressedMap(ImGuiKey_Escape)) { ClearActiveID(); cancel_edit = true; } + else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } @@ -8047,7 +8049,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 ImGui::MemFree(clipboard_filtered); } } + } + if (g.ActiveId == id) + { if (cancel_edit) { // Restore initial value @@ -8057,7 +8062,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 value_changed = true; } } - else + + // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. + // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage. + bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + if (apply_edit_back_to_user_buffer) { // Apply new value immediately - copy modified buffer back // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer @@ -8145,6 +8154,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } } + // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) + if (clear_active_id && g.ActiveId == id) + ClearActiveID(); + // Render // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; From 6a1ba317c7b14fd0e024d329493b165a176512c5 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 19:05:56 +0800 Subject: [PATCH 072/101] Demo: Minor coding style tweaks so bgfx copy needs less patching. --- imgui.cpp | 6 +++--- imgui_demo.cpp | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a94546e04..355108449 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7996,9 +7996,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 edit_state.OnKeyPressed((int)c); } else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) { // Cut, Copy diff --git a/imgui_demo.cpp b/imgui_demo.cpp index abf89f349..b114520ba 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1550,9 +1550,9 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); - if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); + if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); ImGui::Columns(1); ImGui::Separator(); ImGui::TreePop(); @@ -2105,9 +2105,9 @@ static void ShowExampleAppConstrainedResize(bool* p_open) "Custom: Fixed Steps (100)", }; ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); - if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine(); - if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine(); - if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200)); + if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200,200)); } ImGui::SameLine(); + if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500,500)); } ImGui::SameLine(); + if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800,200)); } for (int i = 0; i < 10; i++) ImGui::Text("Hello, sailor! Making this line long enough for the example."); } @@ -2325,8 +2325,8 @@ struct ExampleAppConsole // TODO: display items starting from the bottom if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); - if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine(); + if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine(); + if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine(); bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine(); if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true; //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } @@ -2385,7 +2385,7 @@ struct ExampleAppConsole if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this)) { char* input_end = InputBuf+strlen(InputBuf); - while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0; + while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0; if (InputBuf[0]) ExecCommand(InputBuf); strcpy(InputBuf, ""); @@ -2426,7 +2426,8 @@ struct ExampleAppConsole } else if (Stricmp(command_line, "HISTORY") == 0) { - for (int i = History.Size >= 10 ? History.Size - 10 : 0; i < History.Size; i++) + int first = History.Size - 10; + for (int i = first > 0 ? first : 0; i < History.Size; i++) AddLog("%3d: %s\n", i, History[i]); } else From 670d40642f726759b422b37784ef5f59c1cbbcb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 31 Aug 2017 13:04:40 -0700 Subject: [PATCH 073/101] Fixed C4267 conversion from size_t to int. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 355108449..ae1787283 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10386,7 +10386,7 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) ImGuiContext& g = *GImGui; g.PrivateClipboard.clear(); const char* text_end = text + strlen(text); - g.PrivateClipboard.resize((size_t)(text_end - text) + 1); + g.PrivateClipboard.resize((int)(text_end - text) + 1); memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text)); g.PrivateClipboard[(int)(text_end - text)] = 0; } From cf48e28932e5d920567c61c04b97fdc954cabb8b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2017 20:39:12 +1200 Subject: [PATCH 074/101] Backup polygon mode, draw with filled polygons, restore state, for clients running opengl with glPolygonMode. closes #798 --- examples/opengl2_example/imgui_impl_glfw.cpp | 5 ++++- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 5 ++++- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 5 ++++- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index f85fb5c4c..4fe957cba 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -44,8 +44,9 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) draw_data->ScaleClipRects(io.DisplayFramebufferScale); // We are using the OpenGL fixed pipeline to make the example code simpler to read! - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); @@ -58,6 +59,7 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound // Setup viewport, orthographic projection matrix @@ -109,6 +111,7 @@ void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); + glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index ff96b88a2..4c91961d8 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -51,6 +51,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); @@ -64,13 +65,14 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Setup viewport, orthographic projection matrix glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); @@ -127,6 +129,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); + glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index a8338cecc..cef10e729 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -35,8 +35,9 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) draw_data->ScaleClipRects(io.DisplayFramebufferScale); // We are using the OpenGL fixed pipeline to make the example code simpler to read! - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); @@ -49,6 +50,7 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound // Setup viewport, orthographic projection matrix @@ -100,6 +102,7 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); + glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 1861edae0..1829ac95a 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -45,6 +45,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); @@ -58,13 +59,14 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Setup viewport, orthographic projection matrix glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); @@ -121,6 +123,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); + glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } From 7d1f2c0dc55c1cdce6cf3580a395ca4dd9357d18 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 16:45:31 +0200 Subject: [PATCH 075/101] Examples: GL2: rename functions to include GL2 in name --- examples/opengl2_example/imgui_impl_glfw.cpp | 34 +++++++++---------- examples/opengl2_example/imgui_impl_glfw.h | 23 ++++++------- examples/opengl2_example/main.cpp | 6 ++-- .../sdl_opengl2_example/imgui_impl_sdl.cpp | 16 ++++----- examples/sdl_opengl2_example/imgui_impl_sdl.h | 12 +++---- examples/sdl_opengl2_example/main.cpp | 8 ++--- 6 files changed, 49 insertions(+), 50 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 4fe957cba..a1129d484 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -33,7 +33,7 @@ static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -126,18 +126,18 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) glfwSetClipboardString((GLFWwindow*)user_data, text); } -void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MousePressed[button] = true; } -void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. } -void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -152,14 +152,14 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) +void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) io.AddInputCharacter((unsigned short)c); } -bool ImGui_ImplGlfw_CreateDeviceObjects() +bool ImGui_ImplGlfwGL2_CreateDeviceObjects() { // Build texture atlas ImGuiIO& io = ImGui::GetIO(); @@ -185,7 +185,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects() return true; } -void ImGui_ImplGlfw_InvalidateDeviceObjects() +void ImGui_ImplGlfwGL2_InvalidateDeviceObjects() { if (g_FontTexture) { @@ -195,7 +195,7 @@ void ImGui_ImplGlfw_InvalidateDeviceObjects() } } -bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks) +bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) { g_Window = window; @@ -220,7 +220,7 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - io.RenderDrawListsFn = ImGui_ImplGlfw_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.RenderDrawListsFn = ImGui_ImplGlfwGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = g_Window; @@ -230,25 +230,25 @@ bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks) if (install_callbacks) { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlFw_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL2_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwGL2_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwGL2_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwGL2_CharCallback); } return true; } -void ImGui_ImplGlfw_Shutdown() +void ImGui_ImplGlfwGL2_Shutdown() { - ImGui_ImplGlfw_InvalidateDeviceObjects(); + ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); ImGui::Shutdown(); } -void ImGui_ImplGlfw_NewFrame() +void ImGui_ImplGlfwGL2_NewFrame() { if (!g_FontTexture) - ImGui_ImplGlfw_CreateDeviceObjects(); + ImGui_ImplGlfwGL2_CreateDeviceObjects(); ImGuiIO& io = ImGui::GetIO(); diff --git a/examples/opengl2_example/imgui_impl_glfw.h b/examples/opengl2_example/imgui_impl_glfw.h index 07dd96f04..470863af3 100644 --- a/examples/opengl2_example/imgui_impl_glfw.h +++ b/examples/opengl2_example/imgui_impl_glfw.h @@ -12,18 +12,17 @@ struct GLFWwindow; -IMGUI_API bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks); -IMGUI_API void ImGui_ImplGlfw_Shutdown(); -IMGUI_API void ImGui_ImplGlfw_NewFrame(); +IMGUI_API bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks); +IMGUI_API void ImGui_ImplGlfwGL2_Shutdown(); +IMGUI_API void ImGui_ImplGlfwGL2_NewFrame(); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplGlfw_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplGlfw_CreateDeviceObjects(); +IMGUI_API void ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwGL2_CreateDeviceObjects(); -// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) -// Provided here if you want to chain callbacks. -// You can also handle inputs yourself and use those as a reference. -IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_API void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); +// GLFW callbacks (registered by default to GLFW if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks yourself. You may also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow* window, unsigned int c); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index aa0816f91..2c5bd5694 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -22,7 +22,7 @@ int main(int, char**) glfwSwapInterval(1); // Enable vsync // Setup ImGui binding - ImGui_ImplGlfw_Init(window, true); + ImGui_ImplGlfwGL2_Init(window, true); // Load Fonts // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) @@ -42,7 +42,7 @@ int main(int, char**) while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - ImGui_ImplGlfw_NewFrame(); + ImGui_ImplGlfwGL2_NewFrame(); // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" @@ -84,7 +84,7 @@ int main(int, char**) } // Cleanup - ImGui_ImplGlfw_Shutdown(); + ImGui_ImplGlfwGL2_Shutdown(); glfwTerminate(); return 0; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index cef10e729..784d90aec 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -117,7 +117,7 @@ static void ImGui_ImplSdl_SetClipboardText(void*, const char* text) SDL_SetClipboardText(text); } -bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event) +bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { ImGuiIO& io = ImGui::GetIO(); switch (event->type) @@ -157,7 +157,7 @@ bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event) return false; } -bool ImGui_ImplSdl_CreateDeviceObjects() +bool ImGui_ImplSdlGL2_CreateDeviceObjects() { // Build texture atlas ImGuiIO& io = ImGui::GetIO(); @@ -184,7 +184,7 @@ bool ImGui_ImplSdl_CreateDeviceObjects() return true; } -void ImGui_ImplSdl_InvalidateDeviceObjects() +void ImGui_ImplSdlGL2_InvalidateDeviceObjects() { if (g_FontTexture) { @@ -194,7 +194,7 @@ void ImGui_ImplSdl_InvalidateDeviceObjects() } } -bool ImGui_ImplSdl_Init(SDL_Window* window) +bool ImGui_ImplSdlGL2_Init(SDL_Window* window) { ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. @@ -234,16 +234,16 @@ bool ImGui_ImplSdl_Init(SDL_Window* window) return true; } -void ImGui_ImplSdl_Shutdown() +void ImGui_ImplSdlGL2_Shutdown() { - ImGui_ImplSdl_InvalidateDeviceObjects(); + ImGui_ImplSdlGL2_InvalidateDeviceObjects(); ImGui::Shutdown(); } -void ImGui_ImplSdl_NewFrame(SDL_Window *window) +void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) { if (!g_FontTexture) - ImGui_ImplSdl_CreateDeviceObjects(); + ImGui_ImplSdlGL2_CreateDeviceObjects(); ImGuiIO& io = ImGui::GetIO(); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.h b/examples/sdl_opengl2_example/imgui_impl_sdl.h index a322bf2d9..65b2bd996 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.h +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.h @@ -9,11 +9,11 @@ struct SDL_Window; typedef union SDL_Event SDL_Event; -IMGUI_API bool ImGui_ImplSdl_Init(SDL_Window* window); -IMGUI_API void ImGui_ImplSdl_Shutdown(); -IMGUI_API void ImGui_ImplSdl_NewFrame(SDL_Window* window); -IMGUI_API bool ImGui_ImplSdl_ProcessEvent(SDL_Event* event); +IMGUI_API bool ImGui_ImplSdlGL2_Init(SDL_Window* window); +IMGUI_API void ImGui_ImplSdlGL2_Shutdown(); +IMGUI_API void ImGui_ImplSdlGL2_NewFrame(SDL_Window* window); +IMGUI_API bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event); // Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplSdl_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplSdl_CreateDeviceObjects(); +IMGUI_API void ImGui_ImplSdlGL2_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplSdlGL2_CreateDeviceObjects(); diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 53e428ba3..d6f31845a 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -28,7 +28,7 @@ int main(int, char**) SDL_GLContext glcontext = SDL_GL_CreateContext(window); // Setup ImGui binding - ImGui_ImplSdl_Init(window); + ImGui_ImplSdlGL2_Init(window); // Load Fonts // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) @@ -51,11 +51,11 @@ int main(int, char**) SDL_Event event; while (SDL_PollEvent(&event)) { - ImGui_ImplSdl_ProcessEvent(&event); + ImGui_ImplSdlGL2_ProcessEvent(&event); if (event.type == SDL_QUIT) done = true; } - ImGui_ImplSdl_NewFrame(window); + ImGui_ImplSdlGL2_NewFrame(window); // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" @@ -95,7 +95,7 @@ int main(int, char**) } // Cleanup - ImGui_ImplSdl_Shutdown(); + ImGui_ImplSdlGL2_Shutdown(); SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(window); SDL_Quit(); From d9016964ada251c72b0dc2186e485fdec8fb7d6b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 16:55:04 +0200 Subject: [PATCH 076/101] Examples: GL3: Comments, tweaks (#1145) --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 6 +++--- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 173b3835c..1cf35c653 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -31,8 +31,8 @@ static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_Attr static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) @@ -88,6 +88,7 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glBindVertexArray(g_VaoHandle); + glBindSampler(0, 0); // Rely on combined texture/sampler state. for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -110,7 +111,6 @@ void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glBindSampler(0, 0); // rely on combined texture/sampler state. glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 1ad750fcf..0301d31bc 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -25,8 +25,8 @@ static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_Attr static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) @@ -82,6 +82,7 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glBindVertexArray(g_VaoHandle); + glBindSampler(0, 0); // Rely on combined texture/sampler state. for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -104,7 +105,6 @@ void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glBindSampler(0, 0); // rely on combined texture/sampler state. glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } From 4abce8af58e5e45d2578ab6ec612bcc76fe168e4 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 16:58:07 +0200 Subject: [PATCH 077/101] Examples: GL2: Renaming, comments. --- examples/opengl2_example/imgui_impl_glfw.cpp | 12 ++++++------ examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index a1129d484..624085fd7 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -31,9 +31,9 @@ static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -116,12 +116,12 @@ void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } -static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) +static const char* ImGui_ImplGlfwGL2_GetClipboardText(void* user_data) { return glfwGetClipboardString((GLFWwindow*)user_data); } -static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) +static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text) { glfwSetClipboardString((GLFWwindow*)user_data, text); } @@ -221,8 +221,8 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; io.RenderDrawListsFn = ImGui_ImplGlfwGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. - io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; + io.SetClipboardTextFn = ImGui_ImplGlfwGL2_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwGL2_GetClipboardText; io.ClipboardUserData = g_Window; #ifdef _WIN32 io.ImeWindowHandle = glfwGetWin32Window(g_Window); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 784d90aec..78ce40357 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -22,8 +22,8 @@ static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) From b8ade0b94f7ea39f3b62a89e9473e18893e5644c Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 17:06:26 +0200 Subject: [PATCH 078/101] Examples: Main: Removed call to SetNextWindowSize() --- examples/allegro5_example/main.cpp | 3 +-- examples/apple_example/imguiex-ios/debug_hud.cpp | 2 +- examples/directx10_example/main.cpp | 3 +-- examples/directx11_example/main.cpp | 3 +-- examples/directx9_example/main.cpp | 3 +-- examples/marmalade_example/main.cpp | 3 +-- examples/opengl2_example/main.cpp | 3 +-- examples/opengl3_example/main.cpp | 3 +-- examples/sdl_opengl2_example/main.cpp | 3 +-- examples/sdl_opengl3_example/main.cpp | 3 +-- examples/vulkan_example/main.cpp | 3 +-- 11 files changed, 11 insertions(+), 21 deletions(-) diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index f99ff5e9e..9f8a6c359 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -72,9 +72,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp index 63bec89ba..fff26eee9 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.cpp +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -34,8 +34,8 @@ void DebugHUD_DoInterface(DebugHUD *hud) if (hud->show_example_window) { - ImGui::SetNextWindowSize(ImVec2(350, 200), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::Text("Hello from another window!"); ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 6b89ba9e8..90add0364 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -167,9 +167,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 63b220957..c8d566bfc 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -170,9 +170,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 036712c4b..f9791b733 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -121,9 +121,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index e08e306b6..57b7f0b69 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -56,9 +56,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 2c5bd5694..5674a4bcb 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -59,9 +59,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index a11bc59d1..0de9b0a0e 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -67,9 +67,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index d6f31845a..4db6f0f9c 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -72,9 +72,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 56b790659..30b14e72b 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -75,9 +75,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index a4922b092..7ed9ea12d 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -698,9 +698,8 @@ int main(int, char**) // 2. Show another simple window, this time using an explicit Begin/End pair if (show_another_window) { - ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); ImGui::Begin("Another Window", &show_another_window); - ImGui::Text("Hello"); + ImGui::Text("Hello from another window!"); ImGui::End(); } From fd684ba974fbebf7c89fc9c21a6591feafd01f87 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 17:43:56 +0200 Subject: [PATCH 079/101] Removed 2 obsolete redirection functions (obsoleted 26+ months ago). --- imgui.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/imgui.h b/imgui.h index f40c7db97..27c11307e 100644 --- a/imgui.h +++ b/imgui.h @@ -493,8 +493,6 @@ namespace ImGui static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ - static inline bool GetWindowCollapsed() { return ImGui::IsWindowCollapsed(); } // OBSOLETE 1.39+ - static inline bool IsRectClipped(const ImVec2& size) { return !IsRectVisible(size); } // OBSOLETE 1.39+ #endif } // namespace ImGui From 804ee78731c092801612453688cefc54817eef6d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 21:55:59 +0200 Subject: [PATCH 080/101] Added IsWindowAppearing(). --- imgui.cpp | 22 +++++++++++++++++----- imgui.h | 1 + imgui_internal.h | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae1787283..2a0df774f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1789,6 +1789,7 @@ ImGuiWindow::ImGuiWindow(const char* name) Accessed = false; Collapsed = false; SkipItems = false; + Appearing = false; BeginCount = 0; PopupId = 0; AutoFitFramesX = AutoFitFramesY = -1; @@ -3976,13 +3977,15 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); + window->Appearing = (!window_was_active || window_appearing_after_being_hidden); // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; if (g.SetNextWindowPosCond) { const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiCond_Appearing; + if (window->Appearing) + window->SetWindowPosAllowFlags |= ImGuiCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) { @@ -3998,7 +4001,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } if (g.SetNextWindowSizeCond) { - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowSizeAllowFlags |= ImGuiCond_Appearing; + if (window->Appearing) + window->SetWindowSizeAllowFlags |= ImGuiCond_Appearing; window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0; SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); g.SetNextWindowSizeCond = 0; @@ -4014,13 +4018,14 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } if (g.SetNextWindowCollapsedCond) { - if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowCollapsedAllowFlags |= ImGuiCond_Appearing; + if (window->Appearing) + window->SetWindowCollapsedAllowFlags |= ImGuiCond_Appearing; SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); g.SetNextWindowCollapsedCond = 0; } if (g.SetNextWindowFocus) { - ImGui::SetWindowFocus(); + SetWindowFocus(); g.SetNextWindowFocus = false; } @@ -5073,7 +5078,14 @@ void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond) bool ImGui::IsWindowCollapsed() { - return GImGui->CurrentWindow->Collapsed; + ImGuiWindow* window = GetCurrentWindowRead(); + return window->Collapsed; +} + +bool ImGui::IsWindowAppearing() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->Appearing; } void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) diff --git a/imgui.h b/imgui.h index 27c11307e..be4b74a62 100644 --- a/imgui.h +++ b/imgui.h @@ -149,6 +149,7 @@ namespace ImGui IMGUI_API float GetWindowWidth(); IMGUI_API float GetWindowHeight(); IMGUI_API bool IsWindowCollapsed(); + IMGUI_API bool IsWindowAppearing(); IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // set next window position. call before Begin() diff --git a/imgui_internal.h b/imgui_internal.h index 1a02473a0..f9d67d04b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -674,7 +674,8 @@ struct IMGUI_API ImGuiWindow bool WasActive; bool Accessed; // Set to true when any widget access the current window bool Collapsed; // Set when collapsing window to become only title-bar - bool SkipItems; // == Visible && !Collapsed + 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) int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) int AutoFitFramesX, AutoFitFramesY; @@ -701,7 +702,6 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing - // Navigation / Focus int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) From 5658675e9db5ddd065dee63dba9e785563edd026 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 21:58:58 +0200 Subject: [PATCH 081/101] Combo: Removed unnecessary ClearActiveId() call (from era where active combo stored an id, now we just use popup functionality) --- imgui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2a0df774f..6c400748c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8667,7 +8667,6 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi item_text = "*Unknown item*"; if (Selectable(item_text, item_selected)) { - ClearActiveID(); value_changed = true; *current_item = i; } From e8dbf1c7954060bd4e2700ab297fdd1a2ef0bf55 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 1 Sep 2017 22:10:13 +0200 Subject: [PATCH 082/101] Combo: Internally split into BeginCombo(), EndCombo(), toward a more flexible combo api. --- imgui.cpp | 152 ++++++++++++++++++++++++++--------------------- imgui_internal.h | 6 +- 2 files changed, 88 insertions(+), 70 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6c400748c..962e07fbd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8569,8 +8569,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa return value_changed; } -// Combo box function. -bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) +bool ImGui::BeginCombo(const char* label, const char* preview_value, float popup_opened_height) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8597,87 +8596,102 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); - if (*current_item >= 0 && *current_item < items_count) - { - const char* item_text; - if (items_getter(data, *current_item, &item_text)) - RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, item_text, NULL, NULL, ImVec2(0.0f,0.0f)); - } + if (preview_value != NULL) + RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); - bool popup_toggled = false; if (hovered) { SetHoveredID(id); if (g.IO.MouseClicked[0]) { ClearActiveID(); - popup_toggled = true; - } - } - if (popup_toggled) - { - if (IsPopupOpen(id)) - { - ClosePopup(id); - } - else - { - FocusWindow(window); - OpenPopup(label); - popup_open = true; - } - } - - bool value_changed = false; - if (IsPopupOpen(id)) - { - // Size default to hold ~7 items - if (height_in_items < 0) - height_in_items = 7; - - float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); - float popup_y1 = frame_bb.Max.y; - float popup_y2 = ImClamp(popup_y1 + popup_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); - if ((popup_y2 - popup_y1) < ImMin(popup_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) - { - // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement) - popup_y1 = ImClamp(frame_bb.Min.y - popup_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); - popup_y2 = frame_bb.Min.y; - } - ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2)); - SetNextWindowPos(popup_rect.Min); - SetNextWindowSize(popup_rect.GetSize()); - PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); - - const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); - if (BeginPopupEx(id, flags)) - { - // Display items - // FIXME-OPT: Use clipper - Spacing(); - for (int i = 0; i < items_count; i++) + if (IsPopupOpen(id)) { - PushID((void*)(intptr_t)i); - const bool item_selected = (i == *current_item); - const char* item_text; - if (!items_getter(data, i, &item_text)) - item_text = "*Unknown item*"; - if (Selectable(item_text, item_selected)) - { - value_changed = true; - *current_item = i; - } - if (item_selected && popup_toggled) - SetScrollHere(); - PopID(); + ClosePopup(id); + } + else + { + FocusWindow(window); + OpenPopup(label); } - EndPopup(); } - PopStyleVar(); } + + if (!IsPopupOpen(id)) + return false; + + float popup_y1 = frame_bb.Max.y; + float popup_y2 = ImClamp(popup_y1 + popup_opened_height, popup_y1, g.IO.DisplaySize.y - style.DisplaySafeAreaPadding.y); + if ((popup_y2 - popup_y1) < ImMin(popup_opened_height, frame_bb.Min.y - style.DisplaySafeAreaPadding.y)) + { + // Position our combo ABOVE because there's more space to fit! (FIXME: Handle in Begin() or use a shared helper. We have similar code in Begin() for popup placement) + popup_y1 = ImClamp(frame_bb.Min.y - popup_opened_height, style.DisplaySafeAreaPadding.y, frame_bb.Min.y); + popup_y2 = frame_bb.Min.y; + } + ImRect popup_rect(ImVec2(frame_bb.Min.x, popup_y1), ImVec2(frame_bb.Max.x, popup_y2)); + SetNextWindowPos(popup_rect.Min); + SetNextWindowSize(popup_rect.GetSize()); + PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + + const ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0); + if (!BeginPopupEx(id, flags)) + { + IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above + return false; + } + Spacing(); + + return true; +} + +void ImGui::EndCombo() +{ + EndPopup(); + PopStyleVar(); +} + +// Combo box function. +bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) +{ + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + const char* preview_text = NULL; + if (*current_item >= 0 && *current_item < items_count) + items_getter(data, *current_item, &preview_text); + + // Size default to hold ~7 items + if (height_in_items < 0) + height_in_items = 7; + float popup_opened_height = (g.FontSize + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + (style.FramePadding.y * 3); + + if (!BeginCombo(label, preview_text, popup_opened_height)) + return false; + + // Display items + // FIXME-OPT: Use clipper + bool value_changed = false; + for (int i = 0; i < items_count; i++) + { + PushID((void*)(intptr_t)i); + const bool item_selected = (i == *current_item); + const char* item_text; + if (!items_getter(data, i, &item_text)) + item_text = "*Unknown item*"; + if (Selectable(item_text, item_selected)) + { + value_changed = true; + *current_item = i; + } + if (item_selected && IsWindowAppearing()) + SetScrollHere(); + PopID(); + } + + EndCombo(); return value_changed; } diff --git a/imgui_internal.h b/imgui_internal.h index f9d67d04b..209c3a26a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -766,11 +766,15 @@ namespace ImGui IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); - // New Columns API + // FIXME-WIP: New Columns API IMGUI_API void BeginColumns(const char* 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); + // FIXME-WIP: New Combo API + IMGUI_API bool BeginCombo(const char* label, const char* preview_value, float popup_opened_height); + IMGUI_API void EndCombo(); + // NB: All position are in absolute pixels coordinates (never using window coordinates internally) // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); From 8fbe8709f9a3a6ec7b99c02f01b91e49bb2a0f63 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 4 Sep 2017 13:03:04 +0200 Subject: [PATCH 083/101] TODO, minor tweak --- TODO.txt | 3 +++ imgui.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index 944df651b..9c7b3a2a4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -99,6 +99,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID) - clipper: ability to force display 1 item in the list would be convenient. + - clipper: ability to run without knowing full count in advance. - splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) @@ -156,6 +157,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - text: proper alignment options in imgui_internal.h - text wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) + - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? - tree node / optimization: avoid formatting when clipped. - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling. @@ -215,6 +217,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - keyboard: full keyboard navigation and focus. (#323) - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) + - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#343) - inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71) - inputs: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). - inputs: support track pad style scrolling & slider edit. diff --git a/imgui.cpp b/imgui.cpp index 962e07fbd..40c15f642 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1956,7 +1956,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (!bb.Overlaps(window->ClipRect)) - if (!id || *id != GImGui->ActiveId) + if (!id || *id != g.ActiveId) if (clip_even_when_logged || !g.LogEnabled) return true; return false; From 89cae37b496ce14dbf3c4bcc59493dd9ff159e97 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 4 Sep 2017 13:05:20 +0200 Subject: [PATCH 084/101] Begin(): Tidying up some code, should be a no-op. --- imgui.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 40c15f642..5e61cee06 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3965,19 +3965,20 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us CheckStacksSize(window, true); IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - bool window_was_active = (window->LastFrameActive == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + // FIXME: This is currently true if we call Begin() multiple times in a row on a same window. + bool window_activated = (window->LastFrameActive != current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; - window_was_active &= (window->PopupId == popup_ref.PopupId); - window_was_active &= (window == popup_ref.Window); + window_activated |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed + window_activated |= (window != popup_ref.Window); popup_ref.Window = window; g.CurrentPopupStack.push_back(popup_ref); window->PopupId = popup_ref.PopupId; } const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); - window->Appearing = (!window_was_active || window_appearing_after_being_hidden); + window->Appearing = (window_activated || window_appearing_after_being_hidden); // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; @@ -4061,7 +4062,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us else PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); - if (!window_was_active) + if (window_activated) { // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = -1; @@ -4095,7 +4096,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) if (window->HiddenFrames > 0) window->HiddenFrames--; - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_active) + if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_activated) { window->HiddenFrames = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) @@ -4389,7 +4390,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); - window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active); + window->MenuColumns.Update(3, style.ItemSpacing.x, window_activated); if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; @@ -4397,7 +4398,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->AutoFitFramesY--; // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) - if (!window_was_active && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) + if (window_activated && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) FocusWindow(window); From a9c6a0f6ecb1395c78369bc7cf2d9754750a36be Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 4 Sep 2017 13:24:45 +0200 Subject: [PATCH 085/101] Begin(): Removed unnecessary code (at the time of 1.18 commit e9e0e36f988a12e0719b1e3b109dafac9fb4471f, CursorPos was used to compute SizeContentsFit and this was necessary) --- imgui.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5e61cee06..7d2f773f1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3984,7 +3984,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bool window_pos_set_by_api = false, window_size_set_by_api = false; if (g.SetNextWindowPosCond) { - const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that. if (window->Appearing) window->SetWindowPosAllowFlags |= ImGuiCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; @@ -3997,7 +3996,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond); } - window->DC.CursorPos = backup_cursor_pos; g.SetNextWindowPosCond = 0; } if (g.SetNextWindowSizeCond) @@ -4042,7 +4040,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { From 6400f2900a32c6f28f849ac1a2711fb9aaa2f88e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 4 Sep 2017 13:26:46 +0200 Subject: [PATCH 086/101] Begin(): renamed locals. --- imgui.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7d2f773f1..7413dc466 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3966,19 +3966,19 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // FIXME: This is currently true if we call Begin() multiple times in a row on a same window. - bool window_activated = (window->LastFrameActive != current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + bool window_just_activated_by_user = (window->LastFrameActive != current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; - window_activated |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed - window_activated |= (window != popup_ref.Window); + window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed + window_just_activated_by_user |= (window != popup_ref.Window); popup_ref.Window = window; g.CurrentPopupStack.push_back(popup_ref); window->PopupId = popup_ref.PopupId; } - const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); - window->Appearing = (window_activated || window_appearing_after_being_hidden); + const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1); + window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; @@ -4059,7 +4059,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us else PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); - if (window_activated) + if (window_just_activated_by_user) { // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = -1; @@ -4093,7 +4093,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) if (window->HiddenFrames > 0) window->HiddenFrames--; - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_activated) + if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_just_activated_by_user) { window->HiddenFrames = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) @@ -4173,7 +4173,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us bool window_pos_center = false; window_pos_center |= (window->SetWindowPosCenterWanted && window->HiddenFrames == 0); - window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_appearing_after_being_hidden); + window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize); if (window_pos_center) { // Center (any sort of window) @@ -4192,7 +4192,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } - else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_appearing_after_being_hidden) + else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) { ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); @@ -4387,7 +4387,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); - window->MenuColumns.Update(3, style.ItemSpacing.x, window_activated); + window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; @@ -4395,7 +4395,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->AutoFitFramesY--; // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) - if (window_activated && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) + if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) FocusWindow(window); From 2600b28f5d6321683078ace5ab2102d2dde8c7d4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 4 Sep 2017 13:29:57 +0200 Subject: [PATCH 087/101] Begin(): fixed calling Begin() more than once per frame setting `window_just_activated_by_user` which in turn would set Appearing to true for that frame. --- imgui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7413dc466..2b9f50dba 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3951,7 +3951,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window_is_new = true; } - const int current_frame = ImGui::GetFrameCount(); + const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); if (first_begin_of_the_frame) window->Flags = (ImGuiWindowFlags)flags; @@ -3965,8 +3965,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us CheckStacksSize(window, true); IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - // FIXME: This is currently true if we call Begin() multiple times in a row on a same window. - bool window_just_activated_by_user = (window->LastFrameActive != current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; From e1a7aa41cb827f55e621cf1974beddd51e92e25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Patejdl?= Date: Tue, 5 Sep 2017 16:31:54 +0200 Subject: [PATCH 088/101] Improved ColorPicker hue wheel color interpolation --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2b9f50dba..b33cb5c4e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9510,11 +9510,11 @@ static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 static void PaintVertsLinearGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) { ImVec2 gradient_extent = gradient_p1 - gradient_p0; - float gradient_inv_length = ImInvLength(gradient_extent, 0.0f); + float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) { float d = ImDot(vert->pos - gradient_p0, gradient_extent); - float t = ImMin(sqrtf(ImMax(d, 0.0f)) * gradient_inv_length, 1.0f); + float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t); int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t); int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t); From 790605e359843acb5eb3d2940385516536f37898 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 17:20:54 +0200 Subject: [PATCH 089/101] Minor comments + renaming internal fields --- imgui.cpp | 15 +++++++-------- imgui_internal.h | 6 +++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b33cb5c4e..51d03154a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2286,14 +2286,14 @@ void ImGui::NewFrame() mouse_earliest_button_down = i; } bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; - if (g.CaptureMouseNextFrame != -1) - g.IO.WantCaptureMouse = (g.CaptureMouseNextFrame != 0); + if (g.WantCaptureMouseNextFrame != -1) + g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); else g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); - g.IO.WantCaptureKeyboard = (g.CaptureKeyboardNextFrame != -1) ? (g.CaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); + g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != -1) ? (g.WantCaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); g.MouseCursor = ImGuiMouseCursor_Arrow; - g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = -1; + g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = -1; g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. @@ -3306,12 +3306,12 @@ void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) void ImGui::CaptureKeyboardFromApp(bool capture) { - GImGui->CaptureKeyboardNextFrame = capture ? 1 : 0; + GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0; } void ImGui::CaptureMouseFromApp(bool capture) { - GImGui->CaptureMouseNextFrame = capture ? 1 : 0; + GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0; } bool ImGui::IsItemHovered() @@ -6478,6 +6478,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label ImGuiWindow* window = GetCurrentWindow(); // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) + // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id SetActiveID(g.ScalarAsInputTextId, window); SetHoveredID(0); FocusableItemUnregister(window); @@ -6723,7 +6724,6 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c { SetActiveID(id, window); FocusWindow(window); - if (tab_focus_requested || g.IO.KeyCtrl) { start_text_input = true; @@ -7024,7 +7024,6 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f { SetActiveID(id, window); FocusWindow(window); - if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) { start_text_input = true; diff --git a/imgui_internal.h b/imgui_internal.h index 209c3a26a..bebdcb2a7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -486,8 +486,8 @@ struct ImGuiContext float FramerateSecPerFrame[120]; // calculate estimate of framerate for user int FramerateSecPerFrameIdx; float FramerateSecPerFrameAccum; - int CaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags - int CaptureKeyboardNextFrame; + int WantCaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags + int WantCaptureKeyboardNextFrame; char TempBuffer[1024*3+1]; // temporary text buffer ImGuiContext() @@ -558,7 +558,7 @@ struct ImGuiContext memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; FramerateSecPerFrameAccum = 0.0f; - CaptureMouseNextFrame = CaptureKeyboardNextFrame = -1; + WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = -1; memset(TempBuffer, 0, sizeof(TempBuffer)); } }; From 2169bf6895fd9175ef74545c2c7bebf6441f04db Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 17:25:36 +0200 Subject: [PATCH 090/101] Fixed WantTextInput from being true when an activated Drag or Slider was previously turned into an InputText(). (#1317) --- imgui.cpp | 5 +++-- imgui_internal.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 51d03154a..bb313abb6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2291,9 +2291,9 @@ void ImGui::NewFrame() else g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty()); g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != -1) ? (g.WantCaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); - g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId); + g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; g.MouseCursor = ImGuiMouseCursor_Arrow; - g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = -1; + g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. @@ -7906,6 +7906,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. // Down the line we should have a cleaner library-wide concept of Selected vs Active. g.ActiveIdAllowOverlap = !io.MouseDown[0]; + g.WantTextInputNextFrame = 1; // Edit in progress const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; diff --git a/imgui_internal.h b/imgui_internal.h index bebdcb2a7..7716357bc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -488,6 +488,7 @@ struct ImGuiContext float FramerateSecPerFrameAccum; int WantCaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags int WantCaptureKeyboardNextFrame; + int WantTextInputNextFrame; char TempBuffer[1024*3+1]; // temporary text buffer ImGuiContext() @@ -558,7 +559,7 @@ struct ImGuiContext memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; FramerateSecPerFrameAccum = 0.0f; - WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = -1; + WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; memset(TempBuffer, 0, sizeof(TempBuffer)); } }; From 9e2f202f05e92294c14629eb5856f588d1709ac1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 19:24:08 +0200 Subject: [PATCH 091/101] Demo: Not using the undesirable Begin() overload. --- imgui_demo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b114520ba..45a845d6c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2118,7 +2118,8 @@ static void ShowExampleAppConstrainedResize(bool* p_open) static void ShowExampleAppFixedOverlay(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); + if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) { ImGui::End(); return; @@ -2127,6 +2128,7 @@ static void ShowExampleAppFixedOverlay(bool* p_open) ImGui::Separator(); ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); ImGui::End(); + ImGui::PopStyleColor(); } // Demonstrate using "##" and "###" in identifiers to manipulate ID generation. From 51fcef0c21b9c05547370d02513406a196a739d6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 19:31:50 +0200 Subject: [PATCH 092/101] BeginCombo() tweaks, merged from Navigation branch. --- imgui.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bb313abb6..acca6ed0d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7020,7 +7020,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; const bool tab_focus_requested = FocusableItemRegister(window, id); - if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) + if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0]))) { SetActiveID(id, window); FocusWindow(window); @@ -8599,25 +8599,31 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, float popup if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + bool popup_toggled = false; if (hovered) { SetHoveredID(id); if (g.IO.MouseClicked[0]) { ClearActiveID(); - if (IsPopupOpen(id)) - { - ClosePopup(id); - } - else - { - FocusWindow(window); - OpenPopup(label); - } + popup_toggled = true; } } + if (popup_toggled) + { + if (popup_open) + { + ClosePopup(id); + } + else + { + FocusWindow(window); + OpenPopupEx(id, false); + } + popup_open = !popup_open; + } - if (!IsPopupOpen(id)) + if (!popup_open) return false; float popup_y1 = frame_bb.Max.y; @@ -9054,7 +9060,10 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_open = menu_is_open = false; } else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others + { want_open = true; + } + if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' want_close = true; if (want_close && IsPopupOpen(id)) From f63c03c46485c758712d0e6500137288622223d6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 20:28:36 +0200 Subject: [PATCH 093/101] Internals: moved ButtonRepeat and AllowKeyboardFocus bools/stacks to a generic ItemFlags stack. Merged from Navigation branch. --- imgui.cpp | 49 ++++++++++++++++++++++++++++++------------------ imgui.h | 4 ++-- imgui_internal.h | 20 ++++++++++++++------ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index acca6ed0d..26ad6a192 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1981,7 +1981,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop { ImGuiContext& g = *GImGui; - const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus; + const bool allow_keyboard_focus = (window->DC.ItemFlags & ImGuiItemFlags_AllowKeyboardFocus) != 0; window->FocusIdxAllCounter++; if (allow_keyboard_focus) window->FocusIdxTabCounter++; @@ -4370,13 +4370,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; window->DC.ChildWindows.resize(0); window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.ItemFlags = ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled - window->DC.AllowKeyboardFocus = true; - window->DC.ButtonRepeat = false; + window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); - window->DC.AllowKeyboardFocusStack.resize(0); - window->DC.ButtonRepeatStack.resize(0); window->DC.TextWrapPosStack.resize(0); window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = 1; @@ -4388,6 +4386,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); + if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags)) + { + window->DC.ItemFlags = parent_window->DC.ItemFlags; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); + } + if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; if (window->AutoFitFramesY > 0) @@ -4721,32 +4725,41 @@ void ImGui::PopFont() SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); } -void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) +void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocus = allow_keyboard_focus; - window->DC.AllowKeyboardFocusStack.push_back(allow_keyboard_focus); + if (enabled) + window->DC.ItemFlags |= option; + else + window->DC.ItemFlags &= ~option; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); +} + +void ImGui::PopItemFlag() +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ItemFlagsStack.pop_back(); + window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back(); +} + +void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) +{ + PushItemFlag(ImGuiItemFlags_AllowKeyboardFocus, allow_keyboard_focus); } void ImGui::PopAllowKeyboardFocus() { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocusStack.pop_back(); - window->DC.AllowKeyboardFocus = window->DC.AllowKeyboardFocusStack.empty() ? true : window->DC.AllowKeyboardFocusStack.back(); + PopItemFlag(); } void ImGui::PushButtonRepeat(bool repeat) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeat = repeat; - window->DC.ButtonRepeatStack.push_back(repeat); + PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } void ImGui::PopButtonRepeat() { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeatStack.pop_back(); - window->DC.ButtonRepeat = window->DC.ButtonRepeatStack.empty() ? false : window->DC.ButtonRepeatStack.back(); + PopItemFlag(); } void ImGui::PushTextWrapPos(float wrap_pos_x) @@ -5722,7 +5735,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (!ItemAdd(bb, &id)) return false; - if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); diff --git a/imgui.h b/imgui.h index be4b74a62..0cf364955 100644 --- a/imgui.h +++ b/imgui.h @@ -204,9 +204,9 @@ namespace ImGui IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PopTextWrapPos(); - IMGUI_API void PushAllowKeyboardFocus(bool v); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets + IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets IMGUI_API void PopAllowKeyboardFocus(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (uses io.KeyRepeatDelay/io.KeyRepeatRate for now). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. + IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. IMGUI_API void PopButtonRepeat(); // Cursor / Layout diff --git a/imgui_internal.h b/imgui_internal.h index 7716357bc..d882661f6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -48,6 +48,7 @@ typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ +typedef int ImGuiItemFlags; // enum ImGuiItemFlags_ //------------------------------------------------------------------------- // STB libraries @@ -564,6 +565,14 @@ struct ImGuiContext } }; +// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). +enum ImGuiItemFlags_ +{ + ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // default: true + ImGuiItemFlags_ButtonRepeat = 1 << 1, // default: false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. + ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus +}; + // Transient per-window data, reset at the beginning of the frame // FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered. struct IMGUI_API ImGuiDrawContext @@ -589,14 +598,12 @@ struct IMGUI_API ImGuiDrawContext ImGuiLayoutType LayoutType; // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. + ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] - bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] - bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] + ImVectorItemFlagsStack; ImVector ItemWidthStack; ImVector TextWrapPosStack; - ImVector AllowKeyboardFocusStack; - ImVector ButtonRepeatStack; ImVectorGroupStack; int StackSizesBackup[6]; // Store size of various stacks for asserting @@ -630,8 +637,7 @@ struct IMGUI_API ImGuiDrawContext StateStorage = NULL; LayoutType = ImGuiLayoutType_Vertical; ItemWidth = 0.0f; - ButtonRepeat = false; - AllowKeyboardFocus = true; + ItemFlags = ImGuiItemFlags_Default_; TextWrapPos = -1.0f; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); @@ -761,6 +767,8 @@ namespace ImGui IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); + IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); + IMGUI_API void PopItemFlag(); IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API bool IsPopupOpen(ImGuiID id); From cb2775ae54d1052a54fb6511292af6a3df245fda Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Sep 2017 20:36:36 +0200 Subject: [PATCH 094/101] Internals: ImGuiItemFlags comments --- imgui_internal.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index d882661f6..2d8b8457a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -568,8 +568,11 @@ struct ImGuiContext // Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). enum ImGuiItemFlags_ { - ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // default: true - ImGuiItemFlags_ButtonRepeat = 1 << 1, // default: false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. + ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true + ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. + //ImGuiItemFlags_Disabled = 1 << 2, // false // All widgets appears are disabled + //ImGuiItemFlags_AllowNavDefaultFocus = 1 << 3, // true + //ImGuiItemFlags_SelectableDontClosePopup = 1 << 4, // false // MenuItem/Selectable() automatically closes current Popup window ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus }; From cf6ba9dd2dda9151450c0f7a3ef0689ccbc53756 Mon Sep 17 00:00:00 2001 From: Daniel Loffgren Date: Sun, 10 Sep 2017 23:58:18 -0700 Subject: [PATCH 095/101] Don't do a bunch of OS gymnastics. alloca.h is only for glibc, everyone else uses stdlib.h --- imgui_draw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0a23ac0e5..e0d4016ff 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -21,10 +21,10 @@ #if !defined(alloca) #ifdef _WIN32 #include // alloca -#elif (defined(__FreeBSD__) || defined(FreeBSD_kernel) || defined(__DragonFly__)) && !defined(__GLIBC__) -#include // alloca. FreeBSD uses stdlib.h unless GLIBC +#elif !defined(__GLIBC__) +#include // alloca #else -#include // alloca +#include // alloca. glibc has an alloca specific header #endif #endif From 65632d268217ef8592ca478be7dc526398c1950f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Sep 2017 11:55:13 +0200 Subject: [PATCH 096/101] Fixed alloca include for SunOS (#1319) --- imgui_draw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e0d4016ff..b4b7f5648 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -21,10 +21,10 @@ #if !defined(alloca) #ifdef _WIN32 #include // alloca -#elif !defined(__GLIBC__) -#include // alloca +#elif defined(__GLIBC__) || defined(__sun) +#include // alloca #else -#include // alloca. glibc has an alloca specific header +#include // alloca #endif #endif From 54d30d758feaee651d3f791d450e204c2160ee63 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Sep 2017 13:16:27 +0200 Subject: [PATCH 097/101] Implicit "Debug" window uses a "Debug##Default" identifier to allow the user creating such window with custom flags --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 26ad6a192..42a3989fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2355,8 +2355,9 @@ void ImGui::NewFrame() CloseInactivePopups(); // Create implicit window - we will only render it if the user has added something to it. + // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); - ImGui::Begin("Debug"); + ImGui::Begin("Debug##Default"); } void ImGui::Initialize() From 2fcdeb7f1263d699b68b543f63b32f24c8dc7b73 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 14 Sep 2017 10:35:30 +0700 Subject: [PATCH 098/101] Remove commas after last item in enumeration. This brings these enums to match the rest of the code and fixes 2 warnings under clang about using C++11 extensions. --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 2d8b8457a..fcced1ac9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -220,7 +220,7 @@ enum ImGuiDataType { ImGuiDataType_Int, ImGuiDataType_Float, - ImGuiDataType_Float2, + ImGuiDataType_Float2 }; enum ImGuiDir @@ -229,7 +229,7 @@ enum ImGuiDir ImGuiDir_Left = 0, ImGuiDir_Right = 1, ImGuiDir_Up = 2, - ImGuiDir_Down = 3, + ImGuiDir_Down = 3 }; enum ImGuiCorner From 83645aa5938e9fa518cf26a1d2a027f84bf4b1a3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Sep 2017 01:28:30 +0200 Subject: [PATCH 099/101] More consistently uses "Dear ImGui" --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 44233311c..5aae9d67d 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,13 @@ Monthly donations via Patreon: One-off donations via PayPal:
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) -dear imgui (AKA ImGui), is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). +Dear ImGui, is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). -ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries. +Dear ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries. -ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. +Dear ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. -ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: +Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: - imgui.cpp - imgui.h @@ -31,26 +31,26 @@ ImGui is self-contained within a few files that you can easily copy and compile No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. -Your code passes mouse/keyboard inputs and settings to ImGui (see example applications for more details). After ImGui is setup, you can use it like in this example: +Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it like in this example: -![screenshot of sample code alongside its output with ImGui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png) +![screenshot of sample code alongside its output with dear imgui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png) -ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase. +Dear ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. _A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions are called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ -ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. +Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. Binaries/Demo ------------- -You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20170723.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20170723.zip) (Windows binaries, ImGui 1.51+ 2017/07/23, 5 executables, 808 KB) +You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: +- [imgui-demo-binaries-20170723.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20170723.zip) (Windows binaries, Dear ImGui 1.51+ 2017/07/23, 5 executables, 808 KB) Bindings -------- -_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ +_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ _Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!_ @@ -104,7 +104,7 @@ See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for so ![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) ![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png) -ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: +Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: ``` ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); @@ -142,32 +142,32 @@ Frequently Asked Question (FAQ) The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations.
What is ImTextureID and how do I display an image? -
I integrated ImGui in my engine and the text or lines are blurry.. -
I integrated ImGui in my engine and some elements are disappearing when I move windows around.. +
I integrated Dear ImGui in my engine and the text or lines are blurry.. +
I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs. -
How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? +
How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
How can I load a different font than the default?
How can I easily use icons in my application?
How can I load multiple fonts?
How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? -
How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables) -
How can I use the drawing facilities without an ImGui window? (using ImDrawList API) +
How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) +
How can I use the drawing facilities without an Dear ImGui window? (using ImDrawList API) See the FAQ in imgui.cpp for answers. -How do you use ImGui on a platform that may not have a mouse or keyboard? +How do you use Dear ImGui on a platform that may not have a mouse or keyboard? -I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. +I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. Dear ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. -Can you create elaborate/serious tools with ImGui? +Can you create elaborate/serious tools with Dear ImGui? Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). -ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. ImGui is about making things that are simple, efficient and powerful. +Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. Dear ImGui is about making things that are simple, efficient and powerful. -Is ImGui fast? +Is Dear ImGui fast? -Probably fast enough for most uses. Down to the foundation of its visual design, ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but ImGui aims to minimize it. +Probably fast enough for most uses. Down to the foundation of its visual design, Dear ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but Dear ImGui aims to minimize it. Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended). @@ -175,11 +175,11 @@ Mileage may vary but the following screenshot can give you a rough idea of the c This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint. -If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem. +If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to Dear ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem. -Can you reskin the look of ImGui? +Can you reskin the look of Dear ImGui? -You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. +You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. This is [LumixEngine](https://github.com/nem0/LumixEngine) with a minor skinning hack + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged). @@ -187,7 +187,7 @@ This is [LumixEngine](https://github.com/nem0/LumixEngine) with a minor skinning Why using C++ (as opposed to C)? -ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. +Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. There is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages. From 052999a6ab0ccc7e26981b0912140e6cc47d1374 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Sep 2017 01:31:41 +0200 Subject: [PATCH 100/101] More consistently uses "Dear ImGui" --- imgui.cpp | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 42a3989fd..f98cd6801 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2,7 +2,7 @@ // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. -// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase. +// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 @@ -17,22 +17,22 @@ - END-USER GUIDE - PROGRAMMER GUIDE (read me!) - Read first - - How to update to a newer version of ImGui - - Getting started with integrating ImGui in your code/engine + - How to update to a newer version of Dear ImGui + - Getting started with integrating Dear ImGui in your code/engine - API BREAKING CHANGES (read me when you update!) - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I help? - What is ImTextureID and how do I display an image? - - I integrated ImGui in my engine and the text or lines are blurry.. - - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + - I integrated Dear ImGui in my engine and the text or lines are blurry.. + - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs. - - How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? + - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - How can I load a different font than the default? - How can I easily use icons in my application? - How can I load multiple fonts? - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - - How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables) + - How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - ISSUES & TODO-LIST - CODE @@ -89,7 +89,7 @@ - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 - HOW TO UPDATE TO A NEWER VERSION OF IMGUI + HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h) - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. @@ -98,26 +98,26 @@ Please report any issue to the GitHub page! - Try to keep your copy of dear imgui reasonably up to date. - GETTING STARTED WITH INTEGRATING IMGUI IN YOUR CODE/ENGINE + GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - - Add the ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. + - Add the Dear ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because it is short, then switch to the one more appropriate to your use case. - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - - When using ImGui, your programming IDE if your friend: follow the declaration of variables, functions and types to find comments about them. + - When using Dear ImGui, your programming IDE if your friend: follow the declaration of variables, functions and types to find comments about them. - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic integration you don't need to worry about it all. - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory. - Every frame: - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.) - - Call ImGui::NewFrame() to begin the imgui frame + - Call ImGui::NewFrame() to begin the frame - You can use any ImGui function you want between NewFrame() and Render() - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler. (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) - All rendering information are stored into command-lists until ImGui::Render() is called. - - ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. + - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. - Refer to the examples applications in the examples/ folder for instruction on how to setup your code. - A minimal application skeleton may be: @@ -338,33 +338,33 @@ ====================================== Q: How can I help? - A: - If you are experienced enough with ImGui and with C/C++, look at the todo list and see how you want/can help! + A: - If you are experienced enough with Dear ImGui and with C/C++, look at the todo list and see how you want/can help! - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui Q: What is ImTextureID and how do I display an image? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. - ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry! + Dear ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry! It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc. At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render. Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing. (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. - ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. + Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. It is your responsibility to get textures uploaded to your GPU. - Q: I integrated ImGui in my engine and the text or lines are blurry.. + Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. - Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). Q: Can I have multiple widgets with the same label? Can I have widget without a label? - A: Yes. A primer on the use of labels/IDs in ImGui.. + A: Yes. A primer on the use of labels/IDs in Dear ImGui.. - Elements that are not clickable, such as Text() items don't need an ID. - - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget). + - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. Button("OK"); // Label = "OK", ID = hash of "OK" @@ -452,15 +452,15 @@ e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! - Q: How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? + Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console without a keyboard). Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is also generally ok, - as the bool toggles fairly rarely and you don't generally expect to interact with either ImGui or your application during the same frame when that transition occurs. - ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. + as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during the same frame when that transition occurs. + Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantCaptureKeyboard=false'. - Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) + Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for Dear ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF/OTF file you want: @@ -523,7 +523,7 @@ Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that. For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. - Q: How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables) + Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' so you don't rely on the default globals. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) From c4c042bcec31821f65f44589d2743353e76ad4db Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Sep 2017 01:32:29 +0200 Subject: [PATCH 101/101] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aae9d67d..31b101567 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Monthly donations via Patreon: One-off donations via PayPal:
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) -Dear ImGui, is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). +Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). Dear ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.