mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into docking
# Conflicts: # backends/imgui_impl_dx12.cpp # backends/imgui_impl_dx9.cpp # imgui.cpp # imgui.h
This commit is contained in:
		| @@ -692,6 +692,9 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags | ||||
|     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); | ||||
|     RenderNavHighlight(bb, id); | ||||
|     RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); | ||||
|  | ||||
|     if (g.LogEnabled) | ||||
|         LogSetNextTextDecoration("[", "]"); | ||||
|     RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); | ||||
|  | ||||
|     // Automatically close popups | ||||
| @@ -1104,10 +1107,11 @@ bool ImGui::Checkbox(const char* label, bool* v) | ||||
|         RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); | ||||
|     } | ||||
|  | ||||
|     ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); | ||||
|     if (g.LogEnabled) | ||||
|         LogRenderedText(&total_bb.Min, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); | ||||
|         LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); | ||||
|     if (label_size.x > 0.0f) | ||||
|         RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), label); | ||||
|         RenderText(label_pos, label); | ||||
|  | ||||
|     IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); | ||||
|     return pressed; | ||||
| @@ -1205,10 +1209,11 @@ bool ImGui::RadioButton(const char* label, bool active) | ||||
|         window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); | ||||
|     } | ||||
|  | ||||
|     ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); | ||||
|     if (g.LogEnabled) | ||||
|         LogRenderedText(&total_bb.Min, active ? "(x)" : "( )"); | ||||
|         LogRenderedText(&label_pos, active ? "(x)" : "( )"); | ||||
|     if (label_size.x > 0.0f) | ||||
|         RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), label); | ||||
|         RenderText(label_pos, label); | ||||
|  | ||||
|     IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); | ||||
|     return pressed; | ||||
| @@ -1392,7 +1397,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) | ||||
|             // Draw | ||||
|             window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator)); | ||||
|             if (g.LogEnabled) | ||||
|                 LogRenderedText(&bb.Min, "--------------------------------"); | ||||
|                 LogRenderedText(&bb.Min, "--------------------------------\n"); | ||||
|  | ||||
|         } | ||||
|         if (columns) | ||||
|         { | ||||
| @@ -1583,7 +1589,12 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF | ||||
|     } | ||||
|     RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); | ||||
|     if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) | ||||
|         RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f)); | ||||
|     { | ||||
|         ImVec2 preview_pos = frame_bb.Min + style.FramePadding; | ||||
|         if (g.LogEnabled) | ||||
|             LogSetNextTextDecoration("{", "}"); | ||||
|         RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), 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); | ||||
|  | ||||
| @@ -2333,6 +2344,8 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, | ||||
|     // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. | ||||
|     char value_buf[64]; | ||||
|     const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); | ||||
|     if (g.LogEnabled) | ||||
|         LogSetNextTextDecoration("{", "}"); | ||||
|     RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); | ||||
|  | ||||
|     if (label_size.x > 0.0f) | ||||
| @@ -2596,7 +2609,7 @@ template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> | ||||
| TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) | ||||
| { | ||||
|     if (v_min == v_max) | ||||
|         return (TYPE)0.0f; | ||||
|         return v_min; | ||||
|     const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); | ||||
|  | ||||
|     TYPE result; | ||||
| @@ -2945,6 +2958,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat | ||||
|     // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. | ||||
|     char value_buf[64]; | ||||
|     const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); | ||||
|     if (g.LogEnabled) | ||||
|         LogSetNextTextDecoration("{", "}"); | ||||
|     RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); | ||||
|  | ||||
|     if (label_size.x > 0.0f) | ||||
| @@ -3860,9 +3875,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|         PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); | ||||
|         PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); | ||||
|         PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); | ||||
|         PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); | ||||
|         bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding); | ||||
|         PopStyleVar(3); | ||||
|         bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove); | ||||
|         PopStyleVar(2); | ||||
|         PopStyleColor(); | ||||
|         if (!child_visible) | ||||
|         { | ||||
| @@ -3872,6 +3886,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|         } | ||||
|         draw_window = g.CurrentWindow; // Child window | ||||
|         draw_window->DC.NavLayerActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it. | ||||
|         draw_window->DC.CursorPos += style.FramePadding; | ||||
|         inner_size.x -= draw_window->ScrollbarSizes.x; | ||||
|     } | ||||
|     else | ||||
| @@ -4032,7 +4047,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|  | ||||
|         // Edit in progress | ||||
|         const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; | ||||
|         const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize * 0.5f)); | ||||
|         const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); | ||||
|  | ||||
|         const bool is_osx = io.ConfigMacOSXBehaviors; | ||||
|         if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0])) | ||||
| @@ -4481,10 +4496,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|             if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) | ||||
|             { | ||||
|                 const float scroll_increment_x = inner_size.x * 0.25f; | ||||
|                 const float visible_width = inner_size.x - style.FramePadding.x; | ||||
|                 if (cursor_offset.x < state->ScrollX) | ||||
|                     state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); | ||||
|                 else if (cursor_offset.x - inner_size.x >= state->ScrollX) | ||||
|                     state->ScrollX = IM_FLOOR(cursor_offset.x - inner_size.x + scroll_increment_x); | ||||
|                 else if (cursor_offset.x - visible_width >= state->ScrollX) | ||||
|                     state->ScrollX = IM_FLOOR(cursor_offset.x - visible_width + scroll_increment_x); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
| @@ -4592,14 +4608,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|  | ||||
|     if (is_multiline) | ||||
|     { | ||||
|         Dummy(text_size); | ||||
|         Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); | ||||
|         EndChild(); | ||||
|         EndGroup(); | ||||
|     } | ||||
|  | ||||
|     // Log as text | ||||
|     if (g.LogEnabled && (!is_password || is_displaying_hint)) | ||||
|     { | ||||
|         LogSetNextTextDecoration("{", "}"); | ||||
|         LogRenderedText(&draw_pos, buf_display, buf_display_end); | ||||
|     } | ||||
|  | ||||
|     if (label_size.x > 0) | ||||
|         RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); | ||||
| @@ -5806,19 +5825,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l | ||||
|             text_pos.x -= text_offset_x; | ||||
|         if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) | ||||
|             frame_bb.Max.x -= g.FontSize + style.FramePadding.x; | ||||
|  | ||||
|         if (g.LogEnabled) | ||||
|         { | ||||
|             // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. | ||||
|             const char log_prefix[] = "\n##"; | ||||
|             const char log_suffix[] = "##"; | ||||
|             LogRenderedText(&text_pos, log_prefix, log_prefix + 3); | ||||
|             RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); | ||||
|             LogRenderedText(&text_pos, log_suffix, log_suffix + 2); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); | ||||
|         } | ||||
|             LogSetNextTextDecoration("###", "###"); | ||||
|         RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
| @@ -5834,7 +5844,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l | ||||
|         else if (!is_leaf) | ||||
|             RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); | ||||
|         if (g.LogEnabled) | ||||
|             LogRenderedText(&text_pos, ">"); | ||||
|             LogSetNextTextDecoration(">", NULL); | ||||
|         RenderText(text_pos, label, label_end, false); | ||||
|     } | ||||
|  | ||||
| @@ -5985,7 +5995,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl | ||||
|     ItemSize(size, 0.0f); | ||||
|  | ||||
|     // Fill horizontal space | ||||
|     // We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitely right-aligned sizes not visibly match other widgets. | ||||
|     // We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitly right-aligned sizes not visibly match other widgets. | ||||
|     const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0; | ||||
|     const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x; | ||||
|     const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; | ||||
| @@ -6124,18 +6134,14 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags | ||||
| //------------------------------------------------------------------------- | ||||
| // [SECTION] Widgets: ListBox | ||||
| //------------------------------------------------------------------------- | ||||
| // - BeginListBox() | ||||
| // - EndListBox() | ||||
| // - ListBox() | ||||
| // - ListBoxHeader() | ||||
| // - ListBoxFooter() | ||||
| //------------------------------------------------------------------------- | ||||
| // FIXME: This is an old API. We should redesign some of it, rename ListBoxHeader->BeginListBox, ListBoxFooter->EndListBox | ||||
| // and promote using them over existing ListBox() functions, similarly to change with combo boxes. | ||||
| //------------------------------------------------------------------------- | ||||
|  | ||||
| // FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature. | ||||
| // Helper to calculate the size of a listbox and display a label on the right. | ||||
| // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an non-visible label e.g. "##empty" | ||||
| bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) | ||||
| // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" | ||||
| // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height). | ||||
| bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = GetCurrentWindow(); | ||||
| @@ -6146,12 +6152,12 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) | ||||
|     const ImGuiID id = GetID(label); | ||||
|     const ImVec2 label_size = CalcTextSize(label, NULL, true); | ||||
|  | ||||
|     // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. | ||||
|     ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); | ||||
|     // Size default to hold ~7.25 items. | ||||
|     // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. | ||||
|     ImVec2 size = ImFloor(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f)); | ||||
|     ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); | ||||
|     ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); | ||||
|     ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); | ||||
|     window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy. | ||||
|     g.NextItemData.ClearFlags(); | ||||
|  | ||||
|     if (!IsRectVisible(bb.Min, bb.Max)) | ||||
| @@ -6161,50 +6167,41 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // FIXME-OPT: We could omit the BeginGroup() if label_size.x but would need to omit the EndGroup() as well. | ||||
|     BeginGroup(); | ||||
|     if (label_size.x > 0) | ||||
|         RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); | ||||
|     if (label_size.x > 0.0f) | ||||
|     { | ||||
|         ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); | ||||
|         RenderText(label_pos, label); | ||||
|         window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); | ||||
|     } | ||||
|  | ||||
|     BeginChildFrame(id, frame_bb.GetSize()); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature. | ||||
| #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS | ||||
| // OBSOLETED in 1.81 (from February 2021) | ||||
| bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items) | ||||
| { | ||||
|     // Size default to hold ~7.25 items. | ||||
|     // We add +25% worth of item height to allow the user to see at a glance if there are more items up/down, without looking at the scrollbar. | ||||
|     // We don't add this extra bit if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size. | ||||
|     // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution. | ||||
|     if (height_in_items < 0) | ||||
|         height_in_items = ImMin(items_count, 7); | ||||
|     const ImGuiStyle& style = GetStyle(); | ||||
|     float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25f) : (height_in_items + 0.00f); | ||||
|  | ||||
|     // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). | ||||
|     // If height_in_items == -1, default height is maximum 7. | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f; | ||||
|     ImVec2 size; | ||||
|     size.x = 0.0f; | ||||
|     size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f); | ||||
|     return ListBoxHeader(label, size); | ||||
|     size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f; | ||||
|     return BeginListBox(label, size); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature. | ||||
| void ImGui::ListBoxFooter() | ||||
| void ImGui::EndListBox() | ||||
| { | ||||
|     ImGuiWindow * window = GetCurrentWindow(); | ||||
|     IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched ListBoxHeader/ListBoxFooter calls. Did you test the return value of ListBoxHeader()?"); | ||||
|     ImGuiWindow* parent_window = window->ParentWindow; | ||||
|     const ImRect bb = parent_window->DC.LastItemRect; | ||||
|     const ImGuiStyle& style = GetStyle(); | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
|     IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?"); | ||||
|  | ||||
|     EndChildFrame(); | ||||
|  | ||||
|     // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect) | ||||
|     // We call SameLine() to restore DC.CurrentLine* data | ||||
|     SameLine(); | ||||
|     parent_window->DC.CursorPos = bb.Min; | ||||
|     ItemSize(bb, style.FramePadding.y); | ||||
|     EndGroup(); | ||||
|     EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label | ||||
| } | ||||
|  | ||||
| bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) | ||||
| @@ -6213,25 +6210,35 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* const item | ||||
|     return value_changed; | ||||
| } | ||||
|  | ||||
| // This is merely a helper around BeginListBox(), EndListBox(). | ||||
| // Considering using those directly to submit custom data or store selection differently. | ||||
| bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items) | ||||
| { | ||||
|     if (!ListBoxHeader(label, items_count, height_in_items)) | ||||
|     ImGuiContext& g = *GImGui; | ||||
|  | ||||
|     // Calculate size from "height_in_items" | ||||
|     if (height_in_items < 0) | ||||
|         height_in_items = ImMin(items_count, 7); | ||||
|     float height_in_items_f = height_in_items + 0.25f; | ||||
|     ImVec2 size(0.0f, ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f)); | ||||
|  | ||||
|     if (!BeginListBox(label, size)) | ||||
|         return false; | ||||
|  | ||||
|     // 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. | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     // Assume all items have even height (= 1 line of text). If you need items of different height, | ||||
|     // you can create a custom version of ListBox() in your code without using the clipper. | ||||
|     bool value_changed = false; | ||||
|     ImGuiListClipper clipper; | ||||
|     clipper.Begin(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++) | ||||
|         { | ||||
|             const bool item_selected = (i == *current_item); | ||||
|             const char* item_text; | ||||
|             if (!items_getter(data, i, &item_text)) | ||||
|                 item_text = "*Unknown item*"; | ||||
|  | ||||
|             PushID(i); | ||||
|             const bool item_selected = (i == *current_item); | ||||
|             if (Selectable(item_text, item_selected)) | ||||
|             { | ||||
|                 *current_item = i; | ||||
| @@ -6241,7 +6248,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v | ||||
|                 SetItemDefaultFocus(); | ||||
|             PopID(); | ||||
|         } | ||||
|     ListBoxFooter(); | ||||
|     EndListBox(); | ||||
|     if (value_changed) | ||||
|         MarkItemEdited(g.CurrentWindow->DC.LastItemId); | ||||
|  | ||||
| @@ -6523,7 +6530,7 @@ bool ImGui::BeginMenuBar() | ||||
|     clip_rect.ClipWith(window->OuterRectClipped); | ||||
|     PushClipRect(clip_rect.Min, clip_rect.Max, false); | ||||
|  | ||||
|     // We overwrite CursorMaxPos because BeginGroup sets it to CursorPos (essentially the .EmitItem hack in EndMenuBar() would need something analoguous here, maybe a BeginGroupEx() with flags). | ||||
|     // We overwrite CursorMaxPos because BeginGroup sets it to CursorPos (essentially the .EmitItem hack in EndMenuBar() would need something analogous here, maybe a BeginGroupEx() with flags). | ||||
|     window->DC.CursorPos = window->DC.CursorMaxPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y); | ||||
|     window->DC.LayoutType = ImGuiLayoutType_Horizontal; | ||||
|     window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; | ||||
| @@ -6780,7 +6787,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) | ||||
|  | ||||
|     if (menu_is_open) | ||||
|     { | ||||
|         SetNextWindowPos(popup_pos, ImGuiCond_Always); | ||||
|         SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos. | ||||
|         menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) | ||||
|     } | ||||
|     else | ||||
|   | ||||
		Reference in New Issue
	
	Block a user