diff --git a/3rdparty/ocornut-imgui/imgui.cpp b/3rdparty/ocornut-imgui/imgui.cpp index 161b3e44..11cdcd11 100644 --- a/3rdparty/ocornut-imgui/imgui.cpp +++ b/3rdparty/ocornut-imgui/imgui.cpp @@ -148,6 +148,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/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. @@ -508,6 +509,7 @@ - keyboard: full keyboard navigation and focus. - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - input: rework IO system to be able to pass actual ordered/timestamped events. + - input: allow to decide and pass explicit double-clicks (e.g. for windows by the CS_DBLCLKS style). - input: support track pad style scrolling & slider edit. - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? @@ -610,7 +612,7 @@ static void ClosePopupToLevel(int remaining); static void ClosePopup(ImGuiID id); static bool IsPopupOpen(ImGuiID id); static ImGuiWindow* GetFrontMostModalRootWindow(); -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiWindowFlags flags, int* last_dir, const ImRect& r_inner); +static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid); static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data); static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); @@ -1534,6 +1536,7 @@ ImGuiWindow::ImGuiWindow(const char* name) ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); ScrollbarX = ScrollbarY = false; ScrollbarSizes = ImVec2(0.0f, 0.0f); + BorderSize = 0.0f; Active = WasActive = false; Accessed = false; Collapsed = false; @@ -3413,7 +3416,7 @@ static void CheckStacksSize(ImGuiWindow* window, bool write) IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); } -static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiWindowFlags flags, int* last_dir, const ImRect& r_inner) +static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner) { const ImGuiStyle& style = GImGui->Style; @@ -3423,7 +3426,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, 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)); 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++) // Right, down, up, left. Favor last used direction. + for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). { const int dir = (n == -1) ? *last_dir : n; ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y); @@ -3433,12 +3436,8 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : base_pos_clamped.x, dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : base_pos_clamped.y); } - // Fallback + // Fallback, try to keep within display *last_dir = -1; - if (flags & ImGuiWindowFlags_Tooltip) // For tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. - return base_pos + ImVec2(2,2); - - // Otherwise try to keep within display ImVec2 pos = base_pos; pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); @@ -3802,19 +3801,21 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); else rect_to_avoid = ImRect(parent_window->Pos.x + style.ItemSpacing.x, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - style.ItemSpacing.x - parent_window->ScrollbarSizes.x, FLT_MAX); // We want some overlap to convey the relative depth of each popup (here hard-coded to 4) - window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); + 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) { 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, flags, &window->AutoPosLastDirection, rect_to_avoid); + window->PosFloat = FindBestPopupWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } // 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, flags, &window->AutoPosLastDirection, rect_to_avoid); + window->PosFloat = FindBestPopupWindowPos(g.IO.MousePos, 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. } // User moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. @@ -3931,6 +3932,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); + window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background if (bg_alpha > 0.0f) @@ -3970,11 +3972,10 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // (after the input handling so we don't have a frame of latency) if (!(flags & ImGuiWindowFlags_NoResize)) { - const float border_size = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; const ImVec2 br = window->Rect().GetBR(); - window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -border_size)); - window->DrawList->PathLineTo(br + ImVec2(-border_size, -resize_corner_size)); - window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - border_size, br.y - window_rounding - border_size), window_rounding, 0, 3); + window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -window->BorderSize)); + window->DrawList->PathLineTo(br + ImVec2(-window->BorderSize, -resize_corner_size)); + window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - window->BorderSize, br.y - window_rounding - window->BorderSize), window_rounding, 0, 3); window->DrawList->PathFill(resize_col); } @@ -4064,7 +4065,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // 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 = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; + const float border_size = window->BorderSize; ImRect clip_rect; clip_rect.Min.x = title_bar_rect.Min.x + 0.5f + ImMax(border_size, window->WindowPadding.x*0.5f); clip_rect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + 0.5f + border_size; @@ -4137,7 +4138,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX); float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f; const ImRect window_rect = window->Rect(); - const float border_size = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; + const float border_size = window->BorderSize; ImRect bb = horizontal ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); @@ -4270,8 +4271,8 @@ static void PushMultiItemsWidths(int components, float w_full) const ImGuiStyle& style = GImGui->Style; if (w_full <= 0.0f) w_full = ImGui::CalcItemWidth(); - const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); + const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); window->DC.ItemWidthStack.push_back(w_item_last); for (int i = 0; i < components-1; i++) window->DC.ItemWidthStack.push_back(w_item_one); @@ -4292,9 +4293,8 @@ float ImGui::CalcItemWidth() if (w < 0.0f) { // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well. - ImGuiState& g = *GImGui; float width_to_right_edge = ImGui::GetContentRegionAvail().x; - w = ImMax(1.0f, width_to_right_edge + w - g.Style.FramePadding.x * 2.0f); + w = ImMax(1.0f, width_to_right_edge + w); } w = (float)(int)w; return w; @@ -5155,8 +5155,8 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2, label_size.y + style.FramePadding.y*2)); - const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2 + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size); + const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2)); + const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, NULL)) return; @@ -5264,7 +5264,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + const ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 pos = window->DC.CursorPos; if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) @@ -5354,7 +5354,7 @@ static bool CloseWindowButton(bool* p_opened) } if (p_opened != NULL && pressed) - *p_opened = !*p_opened; + *p_opened = false; return pressed; } @@ -5957,7 +5957,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label char buf[32]; DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf)); - bool value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize() - g.Style.FramePadding*2.0f, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); + bool value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); if (g.ScalarAsInputTextId == 0) { // First frame @@ -6158,7 +6158,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet because we may turn into a text edit box below @@ -6249,7 +6249,6 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float char value_buf[64]; char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImGuiAlign_Center); - if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); @@ -6456,7 +6455,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); @@ -6663,7 +6662,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const ImVec2 label_size = CalcTextSize(label, NULL, true); if (graph_size.x == 0.0f) - graph_size.x = CalcItemWidth() + (style.FramePadding.x * 2); + graph_size.x = CalcItemWidth(); if (graph_size.y == 0.0f) graph_size.y = label_size.y + (style.FramePadding.y * 2); @@ -6804,15 +6803,16 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over const ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; - const ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth() + style.FramePadding.x*2.0f, g.FontSize + style.FramePadding.y*2.0f)); + ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f)); ItemSize(bb, style.FramePadding.y); if (!ItemAdd(bb, NULL)) return; // Render fraction = ImSaturate(fraction); - const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + bb.Reduce(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); // Default displaying the fraction as percentage string, but user can override it @@ -7215,9 +7215,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); - ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f); + const ImVec2 label_size = CalcTextSize(label, NULL, true); + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f)); ImGuiWindow* draw_window = window; @@ -7768,15 +7768,13 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data ImGuiState& g = *GImGui; const ImGuiStyle& style = g.Style; - const float w = CalcItemWidth(); - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImVec2 label_size = CalcTextSize(label, NULL, true); ImGui::BeginGroup(); ImGui::PushID(label); - const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding * 2; + const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding*2.0f; if (step_ptr) - ImGui::PushItemWidth(ImMax(1.0f, w - (button_sz.x + style.ItemInnerSpacing.x)*2)); + ImGui::PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); char buf[64]; DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); @@ -7986,7 +7984,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, &id)) @@ -8088,7 +8086,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl PopClipRect(); ImGuiID id = window->GetID(label); - ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrentLineTextBaseOffset; @@ -8172,10 +8170,10 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) const ImGuiStyle& style = ImGui::GetStyle(); const ImGuiID id = ImGui::GetID(label); - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + 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() + style.FramePadding.x * 2.0f, ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); 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)); @@ -8330,8 +8328,7 @@ bool ImGui::BeginMenuBar() ImGui::BeginGroup(); // Save position ImGui::PushID("##menubar"); ImRect rect = window->MenuBarRect(); - float border_size = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; - PushClipRect(ImVec2(rect.Min.x+0.5f, rect.Min.y-0.5f+border_size), ImVec2(rect.Max.x+0.5f, rect.Max.y-0.5f), false); + PushClipRect(ImVec2(rect.Min.x+0.5f, rect.Min.y-0.5f+window->BorderSize), ImVec2(rect.Max.x+0.5f, rect.Max.y-0.5f), false); window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.MenuBarAppending = true; @@ -8524,7 +8521,6 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3; float f[4] = { col[0], col[1], col[2], col[3] }; - if (edit_mode == ImGuiColorEditMode_HSV) ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); @@ -8544,8 +8540,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) { // RGB/HSV 0..255 Sliders const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x); - const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); + const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); const bool hide_prefix = (w_item_one <= CalcTextSize("M:999").x); const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; @@ -8580,18 +8576,19 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) else ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", i[0], i[1], i[2]); ImGui::PushItemWidth(w_slider_all - style.ItemInnerSpacing.x); - value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); + if (ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) + { + value_changed |= true; + char* p = buf; + while (*p == '#' || ImCharIsSpace(*p)) + p++; + i[0] = i[1] = i[2] = i[3] = 0; + if (alpha) + sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) + else + sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); + } ImGui::PopItemWidth(); - char* p = buf; - while (*p == '#' || ImCharIsSpace(*p)) - p++; - - // Treat at unsigned (%X is unsigned) - i[0] = i[1] = i[2] = i[3] = 0; - if (alpha) - sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); - else - sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); } break; } @@ -8612,14 +8609,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) const char* button_titles[3] = { "RGB", "HSV", "HEX" }; if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups)) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! - ImGui::SameLine(); - } - else - { - ImGui::SameLine(0, style.ItemInnerSpacing.x); } - ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); + const char* label_display_end = FindTextDisplayEnd(label); + if (label != label_display_end) + { + ImGui::SameLine(0, (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) ? -1.0f : style.ItemInnerSpacing.x); + ImGui::TextUnformatted(label, label_display_end); + } // Convert back for (int n = 0; n < 4; n++) diff --git a/3rdparty/ocornut-imgui/imgui.h b/3rdparty/ocornut-imgui/imgui.h index b29b8314..0e0c62e9 100644 --- a/3rdparty/ocornut-imgui/imgui.h +++ b/3rdparty/ocornut-imgui/imgui.h @@ -18,17 +18,18 @@ #define IMGUI_VERSION "1.48 WIP" +// Define attributes of all API symbols declarations, e.g. for DLL under Windows. +#ifndef IMGUI_API +#define IMGUI_API +#endif + // Define assertion handler. #ifndef IM_ASSERT #include #define IM_ASSERT(_EXPR, ...) assert(_EXPR) #endif -// Define attributes of all API symbols declarations, e.g. for DLL under Windows. -#ifndef IMGUI_API -#define IMGUI_API -#endif - +// 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)))) #else @@ -36,39 +37,50 @@ #endif // Forward declarations -struct ImDrawCmd; -struct ImDrawList; -struct ImDrawData; -struct ImFont; -struct ImFontAtlas; -struct ImColor; -struct ImGuiIO; -struct ImGuiStorage; -struct ImGuiStyle; +struct ImDrawChannel; // Temporary storage for outputting drawing commands out of order, used by ImDrawList::ChannelsSplit() +struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) +struct ImDrawData; // All draw command lists required to render the frame +struct ImDrawList; // A single draw command list (generally one per window) +struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) +struct ImFont; // Runtime data for a single font within a parent ImFontAtlas +struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF font loader +struct ImFontConfig; // Configuration data when adding a font or merging fonts +struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 +struct ImGuiIO; // Main configuration and I/O between your application and ImGui +struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro +struct ImGuiStorage; // Simple custom key value storage +struct ImGuiStyle; // Runtime data for styling/colors +struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +struct ImGuiTextBuffer; // Text buffer for logging/accumulating text +struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom callbacks (advanced) +struct ImGuiListClipper; // Helper to manually clip large list of items +// Enumerations (declared as int for compatibility and to not pollute the top of this file) typedef unsigned int ImU32; typedef unsigned short ImWchar; // character for keyboard input/display typedef void* ImTextureID; // user data to refer to a texture (e.g. store your texture handle/id) typedef ImU32 ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) -typedef int ImGuiCol; // enum ImGuiCol_ -typedef int ImGuiStyleVar; // enum ImGuiStyleVar_ -typedef int ImGuiKey; // enum ImGuiKey_ -typedef int ImGuiAlign; // enum ImGuiAlign_ -typedef int ImGuiColorEditMode; // enum ImGuiColorEditMode_ -typedef int ImGuiMouseCursor; // enum ImGuiMouseCursor_ -typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_ -typedef int ImGuiSetCond; // enum ImGuiSetCond_ -typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_ -typedef int ImGuiSelectableFlags; // enum ImGuiSelectableFlags_ -struct ImGuiTextEditCallbackData; // for advanced uses of InputText() +typedef int ImGuiCol; // a color identifier for styling // enum ImGuiCol_ +typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_ +typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_ +typedef int ImGuiAlign; // alignment // enum ImGuiAlign_ +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 ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ +typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_ +typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); +// Others helpers at bottom of the file: +// class ImVector<> // Lightweight std::vector like class. +// IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times) + struct ImVec2 { float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } - #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif @@ -79,25 +91,11 @@ struct ImVec4 float x, y, z, w; ImVec4() { x = y = z = w = 0.0f; } ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } - #ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec4. IM_VEC4_CLASS_EXTRA #endif }; -// Helpers at bottom of the file: -// - class ImVector<> // Lightweight std::vector like class. -// - IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times) -// - struct ImGuiTextFilter // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" -// - struct ImGuiTextBuffer // Text buffer for logging/accumulating text -// - struct ImGuiStorage // Custom key value storage (if you need to alter open/close states manually) -// - struct ImGuiTextEditCallbackData // Shared state of ImGui::InputText() when using custom callbacks -// - struct ImGuiListClipper // Helper to manually clip large list of items. -// - struct ImColor // Helper functions to created packed 32-bit RGBA color values -// - struct ImDrawList // Draw command list -// - struct ImFontAtlas // Bake multiple fonts into a single texture, TTF font loader, bake glyphs into bitmap -// - struct ImFont // Single font - // ImGui end-user API // In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) namespace ImGui @@ -839,7 +837,7 @@ public: inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } }; -// Helper: execute a block of code once a frame only +// Helper: execute a block of code at maximum once a frame // Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. // Usage: // IMGUI_ONCE_UPON_A_FRAME @@ -921,30 +919,30 @@ struct ImGuiStorage Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } }; - ImVector Data; + ImVector Data; // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Set***() functions find pair, insertion on demand if missing. // - Sorted insertion is costly but should amortize. A typical frame shouldn't need to insert any new pair. - IMGUI_API void Clear(); - IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; - IMGUI_API void SetInt(ImGuiID key, int val); - IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; - IMGUI_API void SetFloat(ImGuiID key, float val); - IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL - IMGUI_API void SetVoidPtr(ImGuiID key, void* val); + IMGUI_API void Clear(); + IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; + IMGUI_API void SetInt(ImGuiID key, int val); + IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; + IMGUI_API void SetFloat(ImGuiID key, float val); + IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL + IMGUI_API void SetVoidPtr(ImGuiID key, void* val); // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. // - A typical use case where this is convenient: // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; // - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application. - IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); - IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0); - IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); + IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); + IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0); + IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); // Use on your own storage if you know only integer are being stored (open/close all tree nodes) - IMGUI_API void SetAllInt(int val); + IMGUI_API void SetAllInt(int val); }; // Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used. @@ -1030,15 +1028,20 @@ struct ImGuiListClipper // Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. //----------------------------------------------------------------------------- +// Helpers macros to generate 32-bits encoded colors +#define IM_COL32(R,G,B,A) (((ImU32)(A)<<24) | ((ImU32)(B)<<16) | ((ImU32)(G)<<8) | ((ImU32)(R))) +#define IM_COL32_WHITE (0xFFFFFFFF) +#define IM_COL32_BLACK (0xFF000000) +#define IM_COL32_BLACK_TRANS (0x00000000) // Transparent black + // Draw callbacks for advanced uses. // NB- You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering (you can poke into the draw list for that) -// Draw callback are useful for example if you want to render a complex 3D scene inside a UI element. +// Draw callback may be useful for example, if you want to render a complex 3D scene inside a UI element, change your GPU render state, etc. // The expected behavior from your rendering loop is: // if (cmd.UserCallback != NULL) // cmd.UserCallback(parent_list, cmd); // else // RenderTriangles() -// It is up to you to decide if your rendering loop or the callback should be responsible for backup/restoring rendering state. typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); // Typically, 1 command = 1 gpu draw call (unless command is a callback) @@ -1068,9 +1071,9 @@ struct ImDrawVert ImU32 col; }; #else -// You can change the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h +// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h // The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. -// The type has to be described by the #define (you can either declare the struct or use a typedef) +// The type has to be described within the macro (you can either declare the struct or use a typedef) IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; #endif @@ -1088,7 +1091,6 @@ struct ImDrawChannel // If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. // All positions are in screen coordinates (0,0=top-left, 1 pixel per unit). Primitives are always added to the list and not culled (culling is done at render time and at a higher-level by ImGui:: functions). -// Note that this only gives you access to rendering polygons. If your intent is to create custom widgets and the publicly exposed functions/data aren't sufficient, you can add code in imgui_user.inl struct ImDrawList { // This is what you have to render @@ -1110,7 +1112,7 @@ struct ImDrawList ImDrawList() { _OwnerName = NULL; Clear(); } ~ImDrawList() { ClearFreeMemory(); } - IMGUI_API void PushClipRect(const ImVec4& clip_rect); // Scissoring. The values are x1, y1, x2, y2. Only apply to rendering. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) + IMGUI_API void PushClipRect(const ImVec4& clip_rect); // Scissoring. Note that the values are (x1,y1,x2,y2) and NOT (x1,y1,w,h). This is passed down to your render function but not used for CPU-side clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRectFullScreen(); IMGUI_API void PopClipRect(); IMGUI_API void PushTextureID(const ImTextureID& texture_id); diff --git a/3rdparty/ocornut-imgui/imgui_draw.cpp b/3rdparty/ocornut-imgui/imgui_draw.cpp index d85fa1d1..bd7b2532 100644 --- a/3rdparty/ocornut-imgui/imgui_draw.cpp +++ b/3rdparty/ocornut-imgui/imgui_draw.cpp @@ -346,6 +346,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) _IdxWritePtr = IdxBuffer.Data + idx_buffer_size; } +// Fully unrolled with inline call to keep our debug builds decently fast. void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel); diff --git a/3rdparty/ocornut-imgui/imgui_internal.h b/3rdparty/ocornut-imgui/imgui_internal.h index a646a740..b100111a 100644 --- a/3rdparty/ocornut-imgui/imgui_internal.h +++ b/3rdparty/ocornut-imgui/imgui_internal.h @@ -598,7 +598,8 @@ struct IMGUI_API ImGuiWindow ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered bool ScrollbarX, ScrollbarY; - ImVec2 ScrollbarSizes; // + ImVec2 ScrollbarSizes; + float BorderSize; bool Active; // Set to true on Begin() bool WasActive; bool Accessed; // Set to true when any widget access the current window