From 64d3c7884d7986b9739e79dc744ede3b92680b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 19 Oct 2015 18:12:08 -0700 Subject: [PATCH] Updated ImGui. --- 3rdparty/ocornut-imgui/imgui.cpp | 154 +++++++++++++----------- 3rdparty/ocornut-imgui/imgui.h | 6 +- 3rdparty/ocornut-imgui/imgui_demo.cpp | 15 ++- 3rdparty/ocornut-imgui/imgui_draw.cpp | 2 +- 3rdparty/ocornut-imgui/imgui_internal.h | 27 +++-- 5 files changed, 118 insertions(+), 86 deletions(-) diff --git a/3rdparty/ocornut-imgui/imgui.cpp b/3rdparty/ocornut-imgui/imgui.cpp index 80f4b6eaf..10eeaa5bc 100644 --- a/3rdparty/ocornut-imgui/imgui.cpp +++ b/3rdparty/ocornut-imgui/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.46 WIP +// ImGui library v1.47 WIP // Main code & documentation // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -665,7 +665,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); Colors[ImGuiCol_TitleBgActive] = ImVec4(0.50f, 0.50f, 1.00f, 0.55f); Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); - Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f); + Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); @@ -761,6 +761,8 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) // HELPERS //----------------------------------------------------------------------------- +#define IM_F32_TO_INT8(_VAL) ((int)((_VAL) * 255.0f + 0.5f)) + #define IM_INT_MIN (-2147483647-1) #define IM_INT_MAX (2147483647) @@ -1083,10 +1085,11 @@ ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) { - ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f)); - out |= ((ImU32)(ImSaturate(in.y)*255.f) << 8); - out |= ((ImU32)(ImSaturate(in.z)*255.f) << 16); - out |= ((ImU32)(ImSaturate(in.w)*255.f) << 24); + ImU32 out; + out = ((ImU32)IM_F32_TO_INT8(ImSaturate(in.x))); + out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.y))) << 8; + out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.z))) << 16; + out |= ((ImU32)IM_F32_TO_INT8(ImSaturate(in.w))) << 24; return out; } @@ -1524,7 +1527,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; SetWindowPosCenterWanted = false; - LastFrameDrawn = -1; + LastFrameActive = -1; ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; @@ -3495,7 +3498,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } const int current_frame = ImGui::GetFrameCount(); - const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame); + const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); if (first_begin_of_the_frame) window->Flags = (ImGuiWindowFlags)flags; else @@ -3508,23 +3511,25 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ CheckStacksSize(window, true); IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); - bool window_was_visible = (window->LastFrameDrawn == current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on + bool window_was_active = (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.OpenedPopupStack[g.CurrentPopupStack.Size]; - window_was_visible &= (window->PopupID == popup_ref.PopupID); - window_was_visible &= (window == popup_ref.Window); + window_was_active &= (window->PopupID == popup_ref.PopupID); + window_was_active &= (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); // 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 anymore :( need to look into that. - if (!window_was_visible) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; + if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_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) { @@ -3533,16 +3538,16 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } else { - ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond); + SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond); } window->DC.CursorPos = backup_cursor_pos; g.SetNextWindowPosCond = 0; } if (g.SetNextWindowSizeCond) { - if (!window_was_visible) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing; + if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowSizeAllowFlags |= ImGuiSetCond_Appearing; window_size_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0; - ImGui::SetWindowSize(g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); + SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); g.SetNextWindowSizeCond = 0; } if (g.SetNextWindowContentSizeCond) @@ -3556,8 +3561,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } if (g.SetNextWindowCollapsedCond) { - if (!window_was_visible) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; - ImGui::SetWindowCollapsed(g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); + if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowCollapsedAllowFlags |= ImGuiSetCond_Appearing; + SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); g.SetNextWindowCollapsedCond = 0; } if (g.SetNextWindowFocus) @@ -3588,7 +3593,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->BeginCount = 0; window->DrawList->Clear(); window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); - window->LastFrameDrawn = current_frame; + window->LastFrameActive = current_frame; window->IDStack.resize(1); // Setup texture, outer clipping rectangle @@ -3599,7 +3604,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ PushClipRect(GetVisibleRect()); // New windows appears in front - if (!window_was_visible) + if (!window_was_active) { window->AutoPosLastDirection = -1; @@ -3630,10 +3635,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->Collapsed = false; } - const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); - if (window->HiddenFrames > 0) - window->HiddenFrames--; - // SIZE // Save contents size from last frame for auto-fitting (unless explicitly specified) @@ -3641,7 +3642,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->SizeContents.y = (window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y); // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_visible) + if (window->HiddenFrames > 0) + window->HiddenFrames--; + if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_active) { window->HiddenFrames = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) @@ -3961,7 +3964,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); - window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_visible); + window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active); if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; @@ -4081,7 +4084,9 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) const float border_offset = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; ImRect bb = horizontal ? ImRect(window->Pos.x + border_offset, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w, window_rect.Max.y) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight() + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w); + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w); + if (!horizontal) + bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() - border_offset : 0.0f); float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; int window_rounding_corners; @@ -7087,6 +7092,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f } // Edit a string of text +// FIXME: This is rather complex partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) { ImGuiWindow* window = GetCurrentWindow(); @@ -7174,9 +7180,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { // Recycle existing cursor/selection/undo stack but clamp position // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. - edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, edit_state.CurLenW); - edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, edit_state.CurLenW); - edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, edit_state.CurLenW); + edit_state.CursorClamp(); } else { @@ -7207,6 +7211,16 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (g.ActiveId == id) { + if (!is_editable && !g.ActiveIdIsJustActivated) + { + // When read-only we always use the live data passed to the function + edit_state.Text.resize(buf_size+1); + const char* buf_end = NULL; + edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end); + edit_state.CurLenA = (int)(buf_end - buf); + edit_state.CursorClamp(); + } + edit_state.BufSizeA = buf_size; // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. @@ -7256,6 +7270,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); } + // Handle various key-presses const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0); const bool is_ctrl_only = is_ctrl_down && !is_alt_down && !is_shift_down; if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); } @@ -7264,8 +7279,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (is_multiline && IsKeyPressedMap(ImGuiKey_DownArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y + g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_DOWN| k_mask); } else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } - else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } + else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Enter)) { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; @@ -7274,16 +7289,16 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 SetActiveID(0); enter_pressed = true; } - else if (is_editable) // New line + else if (is_editable) { - unsigned int c = '\n'; + unsigned int c = '\n'; // Insert new line if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } } else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !is_ctrl_down && !is_shift_down && !is_alt_down && is_editable) { - unsigned int c = '\t'; + unsigned int c = '\t'; // Insert TAB if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } @@ -7358,7 +7373,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { // Apply new value immediately - copy modified buffer back // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer - // FIXME: We actually always render 'buf' in RenderTextScrolledClipped + // FIXME: We actually always render 'buf' when calling DrawList->AddText // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks if (is_editable) { @@ -7428,6 +7443,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } } + // Copy back to user buffer if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0) { ImFormatString(buf, buf_size, "%s", edit_state.TempTextBuffer.Data); @@ -7439,9 +7455,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (!is_multiline) RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); + // Render + const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x + style.FramePadding.x*2.0f, frame_bb.Min.y + size.y + style.FramePadding.y*2.0f); ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; - - ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x + style.FramePadding.x*2.0f, frame_bb.Min.y + size.y + style.FramePadding.y*2.0f); ImVec2 text_size(0.f, 0.f); if (g.ActiveId == id || (edit_state.Id == id && is_multiline && g.ActiveId == draw_window->GetID("#SCROLLY"))) { @@ -7453,40 +7469,44 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // - Measure text height (for scrollbar) // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) const ImWchar* text_begin = edit_state.Text.Data; - const ImWchar* text_end = text_begin + edit_state.CurLenW; ImVec2 cursor_offset, select_start_offset; { - // Count lines + find lines numbers of cursor and select_start - int matches_remaining = 0; - int matches_line_no[2] = { -1, -999 }; - const ImWchar* matches_ptr[2] = { NULL, NULL }; - matches_ptr[0] = text_begin + edit_state.StbState.cursor; matches_remaining++; + // Count lines + find lines numbers straddling 'cursor' and 'select_start' position. + const ImWchar* searches_input_ptr[2]; + searches_input_ptr[0] = text_begin + edit_state.StbState.cursor; + searches_input_ptr[1] = NULL; + int searches_remaining = 1; + int searches_result_line_number[2] = { -1, -999 }; if (edit_state.StbState.select_start != edit_state.StbState.select_end) { - matches_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); - matches_line_no[1] = -1; - matches_remaining++; + searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end); + searches_result_line_number[1] = -1; + searches_remaining++; } - matches_remaining += is_multiline ? 1 : 0; // So that we never exit the loop until all lines are counted. + // Iterate all lines to find our line numbers + // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. + searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const ImWchar* s = text_begin; s < text_end+1; s++) - if ((*s) == '\n' || s == text_end) + for (const ImWchar* s = text_begin; *s != 0; s++) + if (*s == '\n') { line_count++; - if (matches_line_no[0] == -1 && s >= matches_ptr[0]) { matches_line_no[0] = line_count; if (--matches_remaining <= 0) break; } - if (matches_line_no[1] == -1 && s >= matches_ptr[1]) { matches_line_no[1] = line_count; if (--matches_remaining <= 0) break; } + if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } + if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } } + line_count++; + if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; + if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; - // Calculate 2d position - IM_ASSERT(matches_line_no[0] != -1); - cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(matches_ptr[0], text_begin), matches_ptr[0]).x; - cursor_offset.y = matches_line_no[0] * g.FontSize; - if (matches_line_no[1] >= 0) + // Calculate 2d position by finding the beginning of the line and measuring distance + cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; + cursor_offset.y = searches_result_line_number[0] * g.FontSize; + if (searches_result_line_number[1] >= 0) { - select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(matches_ptr[1], text_begin), matches_ptr[1]).x; - select_start_offset.y = matches_line_no[1] * g.FontSize; + select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; + select_start_offset.y = searches_result_line_number[1] * g.FontSize; } // Calculate text height @@ -7525,7 +7545,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } } edit_state.CursorFollow = false; - ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f); + const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f); // Draw selection if (edit_state.StbState.select_start != edit_state.StbState.select_end) @@ -8322,6 +8342,7 @@ void ImGui::EndMenu() } // A little colored square. Return true when clicked. +// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border) { ImGuiWindow* window = GetCurrentWindow(); @@ -8342,13 +8363,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde RenderFrame(bb.Min, bb.Max, window->Color(col), outline_border, style.FrameRounding); if (hovered) - { - int ix = (int)(col.x * 255.0f + 0.5f); - int iy = (int)(col.y * 255.0f + 0.5f); - int iz = (int)(col.z * 255.0f + 0.5f); - int iw = (int)(col.w * 255.0f + 0.5f); - ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, ix, iy, iz, iw); - } + ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8(col.x), IM_F32_TO_INT8(col.y), IM_F32_TO_INT8(col.z), IM_F32_TO_INT8(col.z)); return pressed; } @@ -8390,7 +8405,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) if (edit_mode == ImGuiColorEditMode_HSV) ImGui::ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - int i[4] = { (int)(f[0] * 255.0f + 0.5f), (int)(f[1] * 255.0f + 0.5f), (int)(f[2] * 255.0f + 0.5f), (int)(f[3] * 255.0f + 0.5f) }; + int i[4] = { IM_F32_TO_INT8(f[0]), IM_F32_TO_INT8(f[1]), IM_F32_TO_INT8(f[2]), IM_F32_TO_INT8(f[3]) }; int components = alpha ? 4 : 3; bool value_changed = false; @@ -8463,6 +8478,10 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) const ImVec4 col_display(col[0], col[1], col[2], 1.0f); if (ImGui::ColorButton(col_display)) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! + + // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8(col[0]), IM_F32_TO_INT8(col[1]), IM_F32_TO_INT8(col[2]), IM_F32_TO_INT8(col[3])); if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) { @@ -8932,6 +8951,7 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) } } +// FIXME: May want to remove those helpers? void ImGui::Color(const char* prefix, const ImVec4& v) { ImGui::Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w); diff --git a/3rdparty/ocornut-imgui/imgui.h b/3rdparty/ocornut-imgui/imgui.h index 7bb0aacc5..d2c4155d9 100644 --- a/3rdparty/ocornut-imgui/imgui.h +++ b/3rdparty/ocornut-imgui/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.46 WIP +// ImGui library v1.47 WIP // Headers // See imgui.cpp file for documentation. @@ -17,7 +17,7 @@ #include // NULL, malloc, free, qsort, atoi #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.46 WIP" +#define IMGUI_VERSION "1.47 WIP" // Define assertion handler. #ifndef IM_ASSERT @@ -953,7 +953,7 @@ struct ImGuiTextEditCallbackData ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only char* Buf; // Current text // Read-write (pointed data only) int BufSize; // // Read-only - bool BufDirty; // Set if you modify Buf directly // Write + bool BufDirty; // Must set if you modify Buf directly // Write int CursorPos; // // Read-write int SelectionStart; // // Read-write (== to SelectionEnd when no selection) int SelectionEnd; // // Read-write diff --git a/3rdparty/ocornut-imgui/imgui_demo.cpp b/3rdparty/ocornut-imgui/imgui_demo.cpp index d78630ee5..1f34a048c 100644 --- a/3rdparty/ocornut-imgui/imgui_demo.cpp +++ b/3rdparty/ocornut-imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.46 WIP +// ImGui library v1.47 WIP // Demo code // Don't remove this file from your project! It is useful reference code that you can execute. @@ -423,7 +423,18 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Multi-line Text Input")) { static bool read_only = false; - static char text[1024*16] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n"; + static char text[1024*16] = + "/*\n" + " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" + " the hexadecimal encoding of one offending instruction,\n" + " more formally, the invalid operand with locked CMPXCHG8B\n" + " instruction bug, is a design flaw in the majority of\n" + " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" + " processors (all in the P5 microarchitecture).\n" + "*/\n\n" + "label:\n" + "\tlock cmpxchg8b eax\n"; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); ImGui::Checkbox("Read-only", &read_only); ImGui::PopStyleVar(); diff --git a/3rdparty/ocornut-imgui/imgui_draw.cpp b/3rdparty/ocornut-imgui/imgui_draw.cpp index 09fcf0154..9ec01ef82 100644 --- a/3rdparty/ocornut-imgui/imgui_draw.cpp +++ b/3rdparty/ocornut-imgui/imgui_draw.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.46 WIP +// ImGui library v1.47 WIP // Drawing and font code // Contains implementation for diff --git a/3rdparty/ocornut-imgui/imgui_internal.h b/3rdparty/ocornut-imgui/imgui_internal.h index 1fac43269..cc4144ecf 100644 --- a/3rdparty/ocornut-imgui/imgui_internal.h +++ b/3rdparty/ocornut-imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// ImGui library v1.46 WIP +// ImGui library v1.47 WIP // Internals // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -270,24 +270,25 @@ struct IMGUI_API ImGuiSimpleColumns // Internal state of the currently focused/edited text input box struct IMGUI_API ImGuiTextEditState { - ImGuiID Id; // widget id owning the text state - ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. - ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + ImGuiID Id; // widget id owning the text state + ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. + ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector TempTextBuffer; - int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. - int BufSizeA; // end-user buffer size + int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. + int BufSizeA; // end-user buffer size float ScrollX; ImGuiStb::STB_TexteditState StbState; float CursorAnim; bool CursorFollow; - ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback. + ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback. bool SelectedAllMouseLock; - ImGuiTextEditState() { memset(this, 0, sizeof(*this)); } - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - bool HasSelection() const { return StbState.select_start != StbState.select_end; } - void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } - void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; } + ImGuiTextEditState() { memset(this, 0, sizeof(*this)); } + void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking + void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); } + bool HasSelection() const { return StbState.select_start != StbState.select_end; } + void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } + void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; } void OnKeyPressed(int key); }; @@ -598,7 +599,7 @@ struct IMGUI_API ImGuiWindow ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. ImRect ClippedWindowRect; // = ClipRect just after setup in Begin() - int LastFrameDrawn; + int LastFrameActive; float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage;