From 02fd666956e87d7d1662e02505df3052b6915771 Mon Sep 17 00:00:00 2001 From: Zhilkin Serg Date: Mon, 25 Nov 2024 18:34:02 +0300 Subject: [PATCH] Apply dda/imtui patch to imgui --- src/third-party/imgui/imconfig.h | 4 +- src/third-party/imgui/imgui.cpp | 69 ++++++- src/third-party/imgui/imgui.h | 30 ++- src/third-party/imgui/imgui_demo.cpp | 5 + src/third-party/imgui/imgui_draw.cpp | 111 +++++++++- src/third-party/imgui/imgui_impl_sdl2.cpp | 59 +++++- .../imgui/imgui_impl_sdlrenderer2.cpp | 22 ++ .../imgui/imgui_impl_sdlrenderer2.h | 2 + src/third-party/imgui/imgui_internal.h | 4 + src/third-party/imgui/imgui_tables.cpp | 41 +++- src/third-party/imgui/imgui_widgets.cpp | 191 ++++++++++++++++-- 11 files changed, 491 insertions(+), 47 deletions(-) diff --git a/src/third-party/imgui/imconfig.h b/src/third-party/imgui/imconfig.h index fea89dea0913b..e0404568b8604 100644 --- a/src/third-party/imgui/imconfig.h +++ b/src/third-party/imgui/imconfig.h @@ -80,7 +80,9 @@ //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. -//#define IMGUI_ENABLE_FREETYPE +#ifdef TILES +#define IMGUI_ENABLE_FREETYPE +#endif //---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT) // Only works in combination with IMGUI_ENABLE_FREETYPE. diff --git a/src/third-party/imgui/imgui.cpp b/src/third-party/imgui/imgui.cpp index 4624c45d9ee0e..27957927684e5 100644 --- a/src/third-party/imgui/imgui.cpp +++ b/src/third-party/imgui/imgui.cpp @@ -1343,6 +1343,9 @@ ImGuiStyle::ImGuiStyle() AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.). +#ifdef IMTUI + WindowBorderAscii = false; // [ImTui] Draw ASCII window border +#endif CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. @@ -1464,6 +1467,17 @@ ImGuiIO::ImGuiIO() for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; } AppAcceptingEvents = true; + PreEditText[0] = NULL; +} + +void ImGuiIO::SetPreEditText(const char *str) +{ + strcpy(PreEditText, str); +} + +void ImGuiIO::ClearPreEditText() +{ + PreEditText[0] = NULL; } // Pass in translated ASCII characters for text input. @@ -3667,7 +3681,12 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); + ImVec2 p_frame_max = p_max; +#ifdef IMTUI + p_min += ImVec2(1.0, 0.0); + p_frame_max -= ImVec2(+0.1,0.1); +#endif + window->DrawList->AddRectFilled(p_min, p_frame_max, fill_col, rounding); const float border_size = g.Style.FrameBorderSize; if (borders && border_size > 0.0f) { @@ -6282,6 +6301,9 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars); if (window->Flags & ImGuiWindowFlags_Tooltip) { +#ifdef IMTUI + size_desired += ImVec2(1.5f, 0.0f); +#endif // Tooltip always resize return size_desired; } @@ -6424,7 +6446,10 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si int ret_auto_fit_mask = 0x00; const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); - const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f; + float grip_hover_inner_size = IM_FLOOR(grip_draw_size * 0.75f); +#ifdef IMTUI + grip_hover_inner_size = ImMax(1.0f, grip_hover_inner_size); +#endif const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f; ImRect clamp_rect = visibility_rect; @@ -6698,6 +6723,11 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar } else { +#ifdef IMTUI + ImVec2 p_max_extra_padding = ImVec2(1, 1); +#else + ImVec2 p_max_extra_padding = ImVec2(0, 0); +#endif // Window background if (!(flags & ImGuiWindowFlags_NoBackground)) { @@ -6711,14 +6741,14 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar } if (override_alpha) bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT); - window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom); + window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size - p_max_extra_padding, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom); } // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) { ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); - window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop); + window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max - p_max_extra_padding, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop); } // Menu bar @@ -6726,7 +6756,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar { ImRect menu_bar_rect = window->MenuBarRect(); menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. - window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); + window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0) - p_max_extra_padding, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } @@ -6737,6 +6767,21 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar if (window->ScrollbarY) Scrollbar(ImGuiAxis_Y); +#ifdef IMTUI + // Ascii borders + if (style.WindowBorderAscii) { + window->DrawList->AddText(ImVec2(window->Pos.x - 1, window->Pos.y + window->Size.y - 1), GetColorU32(ImGuiCol_Border), "\\"); + window->DrawList->AddText(ImVec2(window->Pos.x + window->Size.x - 2, window->Pos.y + window->Size.y - 1), GetColorU32(ImGuiCol_Border), "/"); + for (int i = 0; i < window->Size.x - 2; ++i) { + window->DrawList->AddText(ImVec2(window->Pos.x + i, window->Pos.y + window->Size.y - 1), GetColorU32(ImGuiCol_Border), "-"); + } + for (int i = 1; i < window->Size.y - 1; ++i) { + window->DrawList->AddText(ImVec2(window->Pos.x - 1, window->Pos.y + i), GetColorU32(ImGuiCol_Border), "|"); + window->DrawList->AddText(ImVec2(window->Pos.x + window->Size.x - 2, window->Pos.y + i), GetColorU32(ImGuiCol_Border), "|"); + } + } +#endif + // Render resize grips (after their input handling so we don't have a frame of latency) if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize)) { @@ -6747,10 +6792,14 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar continue; const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); +#ifdef IMTUI + window->DrawList->AddText(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)) - ImVec2(1, 1), resize_grip_col[resize_grip_n], "+"); +#else window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size))); window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size))); window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); window->DrawList->PathFillConvex(col); +#endif } } @@ -6832,7 +6881,11 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl } ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); - ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y); + float clip_r_x2 = ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x); +#ifdef IMTUI + clip_r_x2 -= 2.1f; +#endif + ImRect clip_r(layout_r.Min.x, layout_r.Min.y, clip_r_x2, layout_r.Max.y); if (flags & ImGuiWindowFlags_UnsavedDocument) { ImVec2 marker_pos; @@ -7952,16 +8005,19 @@ void ImGui::SetCurrentFont(ImFont* font) // because we have a concrete need and a test bed for multiple atlas textures. void ImGui::PushFont(ImFont* font) { +#ifdef TILES ImGuiContext& g = *GImGui; if (font == NULL) font = GetDefaultFont(); g.FontStack.push_back(font); SetCurrentFont(font); g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); +#endif } void ImGui::PopFont() { +#ifdef TILES ImGuiContext& g = *GImGui; if (g.FontStack.Size <= 0) { @@ -7972,6 +8028,7 @@ void ImGui::PopFont() ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); SetCurrentFont(font); g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); +#endif } void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) diff --git a/src/third-party/imgui/imgui.h b/src/third-party/imgui/imgui.h index d6286592bb91a..8e443f95d0621 100644 --- a/src/third-party/imgui/imgui.h +++ b/src/third-party/imgui/imgui.h @@ -170,6 +170,7 @@ struct ImFontAtlas; // Runtime data for multiple fonts, bake mul struct ImFontBuilderIO; // Opaque interface to a font builder (stb_truetype or FreeType). struct ImFontConfig; // Configuration data when adding a font or merging fonts struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset) +struct ImFontGlyphToDraw; struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) @@ -283,6 +284,9 @@ typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() +typedef int (*ImGuiGetFallbackTextSize)(const char* begin, const char* end, const float scale); // Function signature for ImGui::SetTextSizeCallback() +typedef int (*ImGuiGetFallbackCharSize)(const ImWchar ch, const float scale); // Function signature for ImGui::SetCharSizeCallback() +typedef bool (*ImGuiRenderFallbackChar)(const ImWchar ch); // Function signature for ImGui::SetRenderFallbackCharCallback() // ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type] // - This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. @@ -2163,6 +2167,9 @@ struct ImGuiStyle bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). +#ifdef IMTUI + bool WindowBorderAscii; // [ImTui] Draw ASCII window border +#endif float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. ImVec4 Colors[ImGuiCol_COUNT]; @@ -2331,6 +2338,8 @@ struct ImGuiIO IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue a new characters input from a UTF-8 string + IMGUI_API void SetPreEditText(const char *str); + IMGUI_API void ClearPreEditText(); IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode. IMGUI_API void SetAppAcceptingEvents(bool accepting_events); // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen. @@ -2404,6 +2413,7 @@ struct ImGuiIO bool AppAcceptingEvents; // Only modify via SetAppAcceptingEvents() ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16() ImVector InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. + char PreEditText[255]; // Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame. // This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent(). @@ -3048,6 +3058,7 @@ struct ImDrawList ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those ImVector VtxBuffer; // Vertex buffer. + ImVector FallbackGlyphs; ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. // [Internal, used while building lists] @@ -3258,6 +3269,13 @@ struct ImFontGlyph float U0, V0, U1, V1; // Texture coordinates }; +struct ImFontGlyphToDraw +{ + char uni_str[7]; + ImVec2 pos; + ImU32 col; +}; + // Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges(). // This is essentially a tightly packed of vector of 64k booleans = 8KB storage. struct ImFontGlyphRangesBuilder @@ -3444,20 +3462,28 @@ struct ImFont float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. + ImGuiGetFallbackTextSize GetFallbackTextSizeCallback; + ImGuiGetFallbackCharSize GetFallbackCharSizeCallback; + ImGuiRenderFallbackChar RenderFallbackCharCallback; // Methods IMGUI_API ImFont(); - IMGUI_API ~ImFont(); + virtual IMGUI_API ~ImFont(); IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c); IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c); - float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } + float GetCharAdvance(ImWchar c) const; bool IsLoaded() const { return ContainerAtlas != NULL; } const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + void SetFallbackStrSizeCallback(ImGuiGetFallbackTextSize callback) { GetFallbackTextSizeCallback = callback; } + void SetFallbackCharSizeCallback(ImGuiGetFallbackCharSize callback) { GetFallbackCharSizeCallback = callback; } + void SetRenderFallbackCharCallback(ImGuiRenderFallbackChar callback) { RenderFallbackCharCallback = callback; } // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL); // utf8 IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width); + int GetFallbackCharWidth( const char* s_begin, const char* s_end, const float scale ) const; + int GetFallbackCharWidth(ImWchar c, const float scale) const; IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c); IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false); diff --git a/src/third-party/imgui/imgui_demo.cpp b/src/third-party/imgui/imgui_demo.cpp index 76a06cc7d334d..fc7a916f4445a 100644 --- a/src/third-party/imgui/imgui_demo.cpp +++ b/src/third-party/imgui/imgui_demo.cpp @@ -445,8 +445,13 @@ void ImGui::ShowDemoWindow(bool* p_open) // We specify a default position/size in case there's no data in the .ini file. // We only do it to make the demo applications a little more welcoming, but typically this isn't required. const ImGuiViewport* main_viewport = ImGui::GetMainViewport(); +#ifndef IMTUI ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); +#else + ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 1, main_viewport->WorkPos.y + 1), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(main_viewport->WorkSize.x - 1, main_viewport->WorkSize.y - 1), ImGuiCond_FirstUseEver); +#endif // Main body of the Demo window starts here. if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags)) diff --git a/src/third-party/imgui/imgui_draw.cpp b/src/third-party/imgui/imgui_draw.cpp index fa82a9419376b..8be4c859f895c 100644 --- a/src/third-party/imgui/imgui_draw.cpp +++ b/src/third-party/imgui/imgui_draw.cpp @@ -35,7 +35,7 @@ Index of this file: #ifndef IMGUI_DISABLE #include "imgui_internal.h" #ifdef IMGUI_ENABLE_FREETYPE -#include "misc/freetype/imgui_freetype.h" +#include "imgui_freetype.h" #endif #include // vsnprintf, sscanf, printf @@ -408,6 +408,7 @@ void ImDrawList::_ResetForNewFrame() CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); + FallbackGlyphs.resize(0); Flags = _Data->InitialFlags; memset(&_CmdHeader, 0, sizeof(_CmdHeader)); _VtxCurrentIdx = 0; @@ -3623,6 +3624,9 @@ ImFont::ImFont() Ascent = Descent = 0.0f; MetricsTotalSurface = 0; memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); + GetFallbackTextSizeCallback = nullptr; + GetFallbackCharSizeCallback = nullptr; + RenderFallbackCharCallback = nullptr; } ImFont::~ImFont() @@ -3837,6 +3841,18 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) return &Glyphs.Data[i]; } +float ImFont::GetCharAdvance(ImWchar c) const +{ + if((int)c < IndexAdvanceX.Size) + { + return IndexAdvanceX[(int)c]; + } + else + { + return GetFallbackCharWidth(c, 1.f); + } +} + const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) { if (c >= (size_t)IndexLookup.Size) @@ -4016,7 +4032,12 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons continue; } - const float char_width = ImFontGetCharAdvanceX(this, c) * scale; + float char_width = 0.f; + if( (int)c < IndexAdvanceX.Size ) { + char_width = IndexAdvanceX.Data[c] * scale; + } else { + char_width = GetFallbackCharWidth( prev_s, s, scale ); + } if (line_width + char_width >= max_width) { s = prev_s; @@ -4053,6 +4074,24 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im draw_list->PrimRectUV(ImVec2(x + glyph->X0 * scale, y + glyph->Y0 * scale), ImVec2(x + glyph->X1 * scale, y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } +int ImFont::GetFallbackCharWidth( const char* s_begin, const char* s_end, const float scale ) const +{ + if(GetFallbackTextSizeCallback != nullptr) { + return GetFallbackTextSizeCallback(s_begin, s_end, scale); + } else { + return FallbackAdvanceX * scale; + } +} + +int ImFont::GetFallbackCharWidth(ImWchar c, const float scale) const +{ + if(GetFallbackCharSizeCallback != nullptr) { + return GetFallbackCharSizeCallback(c, scale); + } else { + return FallbackAdvanceX * scale; + } +} + // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) { @@ -4122,6 +4161,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im while (s < text_end) { + const char* s_orig = s; if (word_wrap_enabled) { // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. @@ -4166,13 +4206,23 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im continue; float char_width = glyph->AdvanceX * scale; + if( glyph == FallbackGlyph ) { + char_width = GetFallbackCharWidth( s_orig, s, scale ); + } if (glyph->Visible) { // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w +#ifdef IMTUI + float x1 = x; + float x2 = x + 1.0f; + float y1 = y - 0.5f; + float y2 = y - 0.5f; +#else float x1 = x + glyph->X0 * scale; float x2 = x + glyph->X1 * scale; float y1 = y + glyph->Y0 * scale; float y2 = y + glyph->Y1 * scale; +#endif if (x1 <= clip_rect.z && x2 >= clip_rect.x) { // Render a character @@ -4181,6 +4231,10 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im float u2 = glyph->U1; float v2 = glyph->V1; +#ifdef IMTUI + col &= 0x00FFFFFF; + col |= (c << 24); +#else // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. if (cpu_fine_clip) { @@ -4210,10 +4264,24 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im continue; } } - +#endif // Support for untinted glyphs ImU32 glyph_col = glyph->Colored ? col_untinted : col; +#ifndef IMTUI + if(glyph == FallbackGlyph && RenderFallbackCharCallback != nullptr && RenderFallbackCharCallback(c)) + { + ImFontGlyphToDraw glyphToDraw; + size_t len = s - s_orig; + memcpy(glyphToDraw.uni_str, s_orig, len); + glyphToDraw.uni_str[len] = 0; + glyphToDraw.pos = { x1, y1 }; + glyphToDraw.col = glyph_col; + draw_list->FallbackGlyphs.push_back(glyphToDraw); + glyph = NULL; + } + else +#endif // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: { vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; @@ -4222,6 +4290,10 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; idx_write[0] = (ImDrawIdx)(vtx_index); idx_write[1] = (ImDrawIdx)(vtx_index + 1); idx_write[2] = (ImDrawIdx)(vtx_index + 2); idx_write[3] = (ImDrawIdx)(vtx_index); idx_write[4] = (ImDrawIdx)(vtx_index + 2); idx_write[5] = (ImDrawIdx)(vtx_index + 3); +#ifdef IMTUI + vtx_write[1].col = c; + vtx_write[2].col = (ImU32)char_width; +#endif vtx_write += 4; vtx_index += 4; idx_write += 6; @@ -4260,11 +4332,20 @@ void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir d { const float h = draw_list->_Data->FontSize * 1.00f; float r = h * 0.40f * scale; - ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); + ImVec2 center = pos; +#ifndef IMTUI + center += ImVec2(h * 0.50f, h * 0.50f * scale); +#endif ImVec2 a, b, c; switch (dir) { +#ifdef IMTUI + case ImGuiDir_Left: draw_list->AddText(center, col, "<"); return; + case ImGuiDir_Right: draw_list->AddText(center, col, ">"); return; + case ImGuiDir_Up: draw_list->AddText(center, col, "^"); return; + case ImGuiDir_Down: draw_list->AddText(center, col, "v"); return; +#else case ImGuiDir_Up: case ImGuiDir_Down: if (dir == ImGuiDir_Up) r = -r; @@ -4279,6 +4360,7 @@ void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir d b = ImVec2(-0.750f, +0.866f) * r; c = ImVec2(-0.750f, -0.866f) * r; break; +#endif case ImGuiDir_None: case ImGuiDir_COUNT: IM_ASSERT(0); @@ -4290,12 +4372,25 @@ void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir d void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) { // FIXME-OPT: This should be baked in font. +#ifdef IMTUI + draw_list->AddText(ImVec2(pos.x - 0.5, pos.y - 0.5), col, "B"); +#else draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); +#endif } +#ifdef IMTUI +void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz, const char * symbol) +#else void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) +#endif { float thickness = ImMax(sz / 5.0f, 1.0f); +#ifdef IMTUI + pos += ImVec2(thickness*0.25f, thickness*0.25f); + + draw_list->AddText(ImVec2(pos.x - 0.5, pos.y - 0.5), col, symbol); +#else sz -= thickness * 0.5f; pos += ImVec2(thickness * 0.25f, thickness * 0.25f); @@ -4306,6 +4401,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float draw_list->PathLineTo(ImVec2(bx, by)); draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f)); draw_list->PathStroke(col, 0, thickness); +#endif } // Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side. @@ -4313,10 +4409,17 @@ void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half { switch (direction) { +#ifdef IMTUI + case ImGuiDir_Left: draw_list->AddText(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), col, "<"); return; + case ImGuiDir_Right: draw_list->AddText(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), col, ">"); return; + case ImGuiDir_Up: draw_list->AddText(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), col, "^"); return; + case ImGuiDir_Down: draw_list->AddText(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), col, "v"); return; +#else case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; +#endif case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings } } diff --git a/src/third-party/imgui/imgui_impl_sdl2.cpp b/src/third-party/imgui/imgui_impl_sdl2.cpp index 14022159f8c44..631c322b3f7ea 100644 --- a/src/third-party/imgui/imgui_impl_sdl2.cpp +++ b/src/third-party/imgui/imgui_impl_sdl2.cpp @@ -91,6 +91,8 @@ #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_sdl2.h" +float x_scale = 1.f; +float y_scale = 1.f; // Clang warnings with -Weverything #if defined(__clang__) @@ -99,8 +101,16 @@ #endif // SDL +#if defined(_MSC_VER) && defined(USE_VCPKG) +#include +#include +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" #include +#pragma GCC diagnostic pop #include +#endif #ifdef __APPLE__ #include #endif @@ -113,7 +123,7 @@ #else #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 #endif -#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) +//#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) #if SDL_HAS_VULKAN #include #endif @@ -346,7 +356,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) return false; ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); - io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); + io.AddMousePosEvent(mouse_pos.x * x_scale, mouse_pos.y * y_scale); return true; } case SDL_MOUSEWHEEL: @@ -390,6 +400,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { if (ImGui_ImplSDL2_GetViewportForWindowID(event->text.windowID) == NULL) return false; + io.ClearPreEditText(); io.AddInputCharactersUTF8(event->text.text); return true; } @@ -404,6 +415,9 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. return true; } + case SDL_WINDOWEVENT_FOCUS_LOST: + ImGui::GetIO().ClearPreEditText(); + return true; case SDL_WINDOWEVENT: { if (ImGui_ImplSDL2_GetViewportForWindowID(event->window.windowID) == NULL) @@ -420,13 +434,40 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) bd->MouseLastLeaveFrame = 0; } if (window_event == SDL_WINDOWEVENT_LEAVE) + { bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1; + ImGui::GetIO().ClearPreEditText(); + } if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) io.AddFocusEvent(false); + ImGui::GetIO().ClearPreEditText(); return true; } + case SDL_TEXTEDITING: { + if(strlen(event->edit.text) > 0) + { + ImGui::GetIO().SetPreEditText(event->edit.text); + } + else + { + io.ClearPreEditText(); + } + break; + } +#if defined(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT) + case SDL_TEXTEDITING_EXT: { + if( event->editExt.text != nullptr && strlen(event->editExt.text) > 0) + { + ImGui::GetIO().SetPreEditText( event->editExt.text ); + } + else { + ImGui::GetIO().ClearPreEditText(); + } + break; + } +#endif case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: { @@ -591,7 +632,7 @@ void ImGui_ImplSDL2_Shutdown() IM_DELETE(bd); } -static void ImGui_ImplSDL2_UpdateMouseData() +static void ImGui_ImplSDL2_UpdateMouseData(float x_scale, float y_scale) { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); @@ -617,7 +658,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() int window_x, window_y, mouse_x_global, mouse_y_global; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetWindowPosition(bd->Window, &window_x, &window_y); - io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y)); + io.AddMousePosEvent((float)(mouse_x_global - window_x) * x_scale, (float)(mouse_y_global - window_y) * y_scale); } } } @@ -755,6 +796,8 @@ static void ImGui_ImplSDL2_UpdateGamepads() void ImGui_ImplSDL2_NewFrame() { + x_scale = 1.f; + y_scale = 1.f; ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?"); ImGuiIO& io = ImGui::GetIO(); @@ -773,9 +816,7 @@ void ImGui_ImplSDL2_NewFrame() #endif else SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); - io.DisplaySize = ImVec2((float)w, (float)h); - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); + io.DisplaySize = ImVec2((float)display_w, (float)display_h); // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) // (Accept SDL_GetPerformanceCounter() not returning a monotonically increasing value. Happens in VMs and Emscripten, see #6189, #6114, #3644) @@ -793,8 +834,8 @@ void ImGui_ImplSDL2_NewFrame() io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } - ImGui_ImplSDL2_UpdateMouseData(); - ImGui_ImplSDL2_UpdateMouseCursor(); + ImGui_ImplSDL2_UpdateMouseData(x_scale, y_scale); + //ImGui_ImplSDL2_UpdateMouseCursor(); // Update game controllers (if enabled and available) ImGui_ImplSDL2_UpdateGamepads(); diff --git a/src/third-party/imgui/imgui_impl_sdlrenderer2.cpp b/src/third-party/imgui/imgui_impl_sdlrenderer2.cpp index 27c9522697a60..93c8098d0654c 100644 --- a/src/third-party/imgui/imgui_impl_sdlrenderer2.cpp +++ b/src/third-party/imgui/imgui_impl_sdlrenderer2.cpp @@ -42,7 +42,14 @@ #endif // SDL +#if defined(_MSC_VER) && defined(USE_VCPKG) +#include +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" #include +#pragma GCC diagnostic pop +#endif #if !SDL_VERSION_ATLEAST(2,0,17) #error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function #endif @@ -112,6 +119,13 @@ void ImGui_ImplSDLRenderer2_NewFrame() ImGui_ImplSDLRenderer2_CreateDeviceObjects(); } +std::function drawFallbackGlyphCallback; + +void ImGui_ImplSDLRenderer2_SetFallbackGlyphDrawCallback(std::function func) +{ + drawFallbackGlyphCallback = func; +} + void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer) { // If there's a scale factor set by the user, use that instead @@ -206,6 +220,14 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* draw_list->VtxBuffer.Size - pcmd->VtxOffset, idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx)); } + + if(drawFallbackGlyphCallback) + { + for(const ImFontGlyphToDraw &glyphToDraw : draw_list->FallbackGlyphs) + { + drawFallbackGlyphCallback(glyphToDraw); + } + } } } platform_io.Renderer_RenderState = NULL; diff --git a/src/third-party/imgui/imgui_impl_sdlrenderer2.h b/src/third-party/imgui/imgui_impl_sdlrenderer2.h index 804ca183d14a1..1c57abe4e63a3 100644 --- a/src/third-party/imgui/imgui_impl_sdlrenderer2.h +++ b/src/third-party/imgui/imgui_impl_sdlrenderer2.h @@ -22,6 +22,7 @@ #pragma once #ifndef IMGUI_DISABLE +#include #include "imgui.h" // IMGUI_IMPL_API struct SDL_Renderer; @@ -30,6 +31,7 @@ struct SDL_Renderer; IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_SetFallbackGlyphDrawCallback(std::function func); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer); // Called by Init/NewFrame/Shutdown diff --git a/src/third-party/imgui/imgui_internal.h b/src/third-party/imgui/imgui_internal.h index 49452ab0ad22e..64c110bc74865 100644 --- a/src/third-party/imgui/imgui_internal.h +++ b/src/third-party/imgui/imgui_internal.h @@ -3375,7 +3375,11 @@ namespace ImGui // Render helpers (those functions don't access any ImGui state!) IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); +#ifdef IMTUI + IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz, const char * symbol = "X"); +#else IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); +#endif IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding); diff --git a/src/third-party/imgui/imgui_tables.cpp b/src/third-party/imgui/imgui_tables.cpp index e36e6f17289e8..96956ef610b51 100644 --- a/src/third-party/imgui/imgui_tables.cpp +++ b/src/third-party/imgui/imgui_tables.cpp @@ -1972,12 +1972,20 @@ void ImGui::TableEndRow(ImGuiTable* table) // We soft/cpu clip this so all backgrounds and borders can share the same clipping rectangle if (bg_col0 || bg_col1) { - ImRect row_rect(table->WorkRect.Min.x, bg_y1, table->WorkRect.Max.x, bg_y2); + float row_rect_x = table->WorkRect.Min.x; +#ifdef IMTUI + row_rect_x += 1.0f; +#endif + ImRect row_rect(row_rect_x, bg_y1, table->WorkRect.Max.x, bg_y2); row_rect.ClipWith(table->BgClipRect); + ImVec2 row_background_max = row_rect.Max; +#ifdef IMTUI + row_background_max.y = row_rect.Min.y; +#endif if (bg_col0 != 0 && row_rect.Min.y < row_rect.Max.y) - window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col0); + window->DrawList->AddRectFilled(row_rect.Min, row_background_max, bg_col0); if (bg_col1 != 0 && row_rect.Min.y < row_rect.Max.y) - window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col1); + window->DrawList->AddRectFilled(row_rect.Min, row_background_max, bg_col1); } // Draw cell background color @@ -1993,11 +2001,16 @@ void ImGui::TableEndRow(ImGuiTable* table) cell_bg_rect.ClipWith(table->BgClipRect); cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX); +#ifdef IMTUI + cell_bg_rect.Min.x += 1.0f; + cell_bg_rect.Max.y = cell_bg_rect.Min.y; +#endif if (cell_bg_rect.Min.y < cell_bg_rect.Max.y) window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor); } } +#ifndef IMTUI // Draw top border if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y) window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), top_border_col, border_size); @@ -2005,6 +2018,7 @@ void ImGui::TableEndRow(ImGuiTable* table) // Draw bottom border at the row unfreezing mark (always strong) if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y) window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size); +#endif } // End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle) @@ -2741,7 +2755,12 @@ void ImGui::TableDrawBorders(ImGuiTable* table) // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling. float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head; if (draw_y2 > draw_y1) +#ifdef IMTUI + for (int y = draw_y1; y < draw_y2; ++y) + inner_drawlist->AddText(ImVec2(column->MaxX - 0.1f, y), TableGetColumnBorderCol(table, order_n, column_n), "|"); +#else inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size); +#endif } } @@ -2758,10 +2777,23 @@ void ImGui::TableDrawBorders(ImGuiTable* table) const ImU32 outer_col = table->BorderColorStrong; if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) { +#ifdef IMTUI + for (int y = outer_border.Min.y; y < outer_border.Max.y; ++y) { + inner_drawlist->AddText(ImVec2(outer_border.Min.x, y), outer_col, "|"); + inner_drawlist->AddText(ImVec2(outer_border.Max.x - 2.0f, y), outer_col, "|"); + } +#else inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size); +#endif } else if (table->Flags & ImGuiTableFlags_BordersOuterV) { +#ifdef IMTUI + for (int y = outer_border.Min.y; y < outer_border.Max.y; ++y) { + inner_drawlist->AddText(ImVec2(outer_border.Min.x, y), outer_col, "|"); + inner_drawlist->AddText(ImVec2(outer_border.Max.x - 2.0f, y), outer_col, "|"); + } +#else inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size); inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size); } @@ -2769,8 +2801,10 @@ void ImGui::TableDrawBorders(ImGuiTable* table) { inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size); inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size); +#endif } } +#ifndef IMTUI if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y) { // Draw bottom-most row border between it is above outer border. @@ -2778,6 +2812,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table) if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y) inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size); } +#endif inner_drawlist->PopClipRect(); } diff --git a/src/third-party/imgui/imgui_widgets.cpp b/src/third-party/imgui/imgui_widgets.cpp index b5d66baa02af6..c52229d63ea0d 100644 --- a/src/third-party/imgui/imgui_widgets.cpp +++ b/src/third-party/imgui/imgui_widgets.cpp @@ -728,7 +728,11 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags ImVec2 pos = window->DC.CursorPos; if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y; - ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); + float size_x = label_size.x; +#ifndef IMTUI + size_x += style.FramePadding.x * 2.0f; +#endif + ImVec2 size = CalcItemSize(size_arg, size_x, label_size.y + style.FramePadding.y * 2.0f); const ImRect bb(pos, pos + size); ItemSize(size, style.FramePadding.y); @@ -741,11 +745,19 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderNavCursor(bb, id); - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); + ImVec2 final_bb_max = bb.Max; +#ifdef IMTUI + final_bb_max += ImVec2(0.5f, 0.0f); +#endif + RenderFrame(bb.Min, final_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); + ImVec2 text_min = bb.Min; +#ifndef IMTUI + text_min += style.FramePadding; +#endif + RenderTextClipped(text_min, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); // Automatically close popups //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) @@ -857,14 +869,25 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) // Render ImU32 bg_col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); + ImVec2 center = bb.GetCenter(); if (hovered) - window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col); + { + float hovered_radius = ImMax(2.0f, g.FontSize * 0.5f + 1.0f); +#ifdef IMTUI + hovered_radius = 0.1f; +#endif + window->DrawList->AddCircleFilled(center, hovered_radius,bg_col); + } RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact); ImU32 cross_col = GetColorU32(ImGuiCol_Text); ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f); float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; +#ifdef IMTUI + window->DrawList->AddText(center + ImVec2(-2.0,-cross_extent), cross_col, "[X]"); +#else window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); +#endif return pressed; } @@ -884,8 +907,16 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) // Render ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); - if (hovered || held) - window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col); + if (hovered || held) { +#ifdef IMTUI + ImVec2 hovered_center = bb.GetCenter() + ImVec2(1.0, 0); + float hovered_radius = 0.1f; +#else + ImVec2 hovered_center = bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/; + float hovered_radius = g.FontSize * 0.5f + 1.0f; +#endif + window->DrawList->AddCircleFilled(hovered_center, hovered_radius, bg_col); + } RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact); RenderArrow(window->DrawList, bb.Min, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); @@ -911,8 +942,13 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) IM_ASSERT(scrollbar_size > 0.0f); if (axis == ImGuiAxis_X) return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size); - else - return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size); + else { + float final_x2 = outer_rect.Max.x; +#ifdef IMTUI + final_x2 -= 0.1f; +#endif + return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, final_x2, inner_rect.Max.y); + } } void ImGui::Scrollbar(ImGuiAxis axis) @@ -973,7 +1009,12 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 const bool allow_interaction = (alpha >= 1.0f); ImRect bb = bb_frame; - bb.Expand(ImVec2(-ImClamp(IM_TRUNC((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_TRUNC((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); +#ifdef IMTUI + float bb_mx = 0.5f; +#else + float bb_mx = 3.0f; +#endif + bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, bb_mx))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); @@ -1185,18 +1226,31 @@ bool ImGui::Checkbox(const char* label, bool* v) if (is_visible) { RenderNavCursor(total_bb, id); - RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + ImVec2 frame_p_max = check_bb.Max; +#ifdef IMTUI + frame_p_max.x += 0.5f; +#endif + RenderFrame(check_bb.Min, frame_p_max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); if (mixed_value) { // Undocumented tristate/mixed/indeterminate checkbox (#2644) // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) +#ifdef IMTUI + const float pad = 0.5f; + RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f, "O"); +#else ImVec2 pad(ImMax(1.0f, IM_TRUNC(square_sz / 3.6f)), ImMax(1.0f, IM_TRUNC(square_sz / 3.6f))); window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); +#endif } else if (*v) { - const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f)); +#ifdef IMTUI + const float pad = 0.5f; +#else + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); +#endif RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); } } @@ -1288,11 +1342,21 @@ bool ImGui::RadioButton(const char* label, bool active) RenderNavCursor(total_bb, id); const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius); - window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment); + ImVec2 base_center = center; + float base_radius = radius; +#ifdef IMTUI + base_center += ImVec2(+0.5, -0.5); + base_radius = 0.1f; +#endif + window->DrawList->AddCircleFilled(base_center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment); if (active) { - const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f)); +#ifdef IMTUI + window->DrawList->AddText(center + ImVec2(-1, -1), GetColorU32(ImGuiCol_CheckMark), "x"); +#else + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark)); +#endif } if (style.FrameBorderSize > 0.0f) @@ -1358,7 +1422,13 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over // Render RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); +#ifdef IMTUI + bb.Expand(ImVec2(0, -0.1f)); +#endif RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), fill_n0, fill_n1, style.FrameRounding); +#ifdef IMTUI + bb.Expand(ImVec2(0, 0.1f)); +#endif // Default displaying the fraction as percentage string, but user can override it // Don't display text for indeterminate bars by default @@ -1568,7 +1638,7 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness) { // Horizontal Separator float x1 = window->DC.CursorPos.x; - float x2 = window->WorkRect.Max.x; + float x2 = window->WorkRect.Max.x - 1; // Preserve legacy behavior inside Columns() // Before Tables API happened, we relied on Separator() to span all columns of a Columns() set. @@ -1589,8 +1659,10 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness) if (ItemAdd(bb, 0)) { +#ifndef IMTUI // Draw window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator)); +#endif if (g.LogEnabled) LogRenderedText(&bb.Min, "--------------------------------\n"); @@ -1837,7 +1909,10 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF const ImVec2 label_size = CalcTextSize(label, NULL, true); const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f; const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth()); - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); + ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); +#ifdef IMTUI + bb.Min.x += 1.0f; +#endif const ImRect total_bb(bb.Min, 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, &bb)) @@ -1858,15 +1933,30 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size); RenderNavCursor(bb, id); - if (!(flags & ImGuiComboFlags_NoPreview)) - window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); + if (!(flags & ImGuiComboFlags_NoPreview)) + { + ImVec2 preview_p_max = ImVec2(value_x2, bb.Max.y); +#ifdef IMTUI + preview_p_max.x += 1.0f; + preview_p_max.y = bb.Min.y; +#endif + window->DrawList->AddRectFilled(bb.Min, preview_p_max, frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); + } if (!(flags & ImGuiComboFlags_NoArrowButton)) { ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); - window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); + ImVec2 arrow_btn_p_min = ImVec2(value_x2, bb.Min.y); + ImVec2 arrow_btn_p_max = ImVec2(bb.Max); +#ifdef IMTUI + arrow_btn_p_min.x += 1.0f; + arrow_btn_p_max.y = bb.Min.y; +#endif + window->DrawList->AddRectFilled(arrow_btn_p_min, arrow_btn_p_max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); +#ifndef IMTUI if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x) RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); +#endif } RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding); @@ -3252,7 +3342,11 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat // Render grab if (grab_bb.Max.x > grab_bb.Min.x) +#ifdef IMTUI + window->DrawList->AddText(grab_bb.Min + ImVec2(0.5*(grab_bb.Max.x - grab_bb.Min.x), -2), GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), "I"); +#else window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); +#endif // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -5240,6 +5334,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn)); rect.ClipWith(clip_rect); +#ifdef IMTUI + rect.Max.y = rect.Min.y + 0.1; +#endif if (rect.Overlaps(clip_rect)) draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); rect_pos.x = draw_pos.x - draw_scroll.x; @@ -5253,7 +5350,33 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + + if (GImGui->IO.PreEditText[0] != '\0' && !is_multiline) + { + const char *preEditTextEnd = GImGui->IO.PreEditText + strlen(GImGui->IO.PreEditText); + char wcharBuf[255] = { 0 }; + int wlen = ImTextStrFromUtf8((ImWchar*)wcharBuf, 255, GImGui->IO.PreEditText, preEditTextEnd); + char tmpBuf[255] = "\0"; + + ImVec2 drawPosStart = draw_pos - draw_scroll; + size_t tmpBufLen = ImTextStrToUtf8( tmpBuf, 255, (ImWchar*)(text_begin), (ImWchar*)(text_begin + state->Stb->cursor) ); + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, tmpBuf, tmpBuf + tmpBufLen, 0.0f, &clip_rect); + drawPosStart.x += InputTextCalcTextSize(GImGui, text_begin, (char*)(text_begin + state->Stb->cursor)).x; + ImU32 bg_color = GetColorU32( ImGuiCol_TextSelectedBg, 1.f ); + ImVec2 highlightRectMax = drawPosStart; + highlightRectMax += InputTextCalcTextSize(GImGui, wcharBuf, wcharBuf + wlen); + draw_window->DrawList->AddRectFilled( drawPosStart, highlightRectMax, bg_color ); + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, GImGui->IO.PreEditText, preEditTextEnd, 0.0f, &clip_rect); + if( buf_display_end != NULL && buf_display + tmpBufLen < buf_display_end ) + { + drawPosStart.x = highlightRectMax.x; + draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, buf_display + tmpBufLen, buf_display_end, 0.0f, &clip_rect); + } + } + else + { + draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + } } // Draw blinking cursor @@ -5263,9 +5386,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll); ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); +#ifdef IMTUI + if (cursor_is_visible) + draw_window->DrawList->AddLine(cursor_screen_rect.Min + ImVec2(0.6f, -0.5f), cursor_screen_rect.Min + ImVec2(0.6f,-0.5f), GetColorU32(ImGuiCol_Text)); +#else if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); - +#endif // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) if (!is_readonly) { @@ -9050,7 +9177,16 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut PopStyleColor(); } if (selected) - RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); + { + float offset_x = offsets->OffsetMark + stretch_w + g.FontSize * 0.40f; +#ifdef IMTUI + float offset_y = g.FontSize * 0.134f * 0.5f; + offset_x -= 1.0f; +#else + float offset_y = 1.0f; +#endif + RenderCheckMark(window->DrawList, pos + ImVec2(offset_x, offset_y), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); + } } } IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); @@ -9236,6 +9372,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); +#ifndef IMTUI // Draw separator // (it would be misleading to draw this in EndTabBar() suggesting that it may be drawn over tabs, as tab bar are appendable) const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected); @@ -9244,6 +9381,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG const float y = tab_bar->BarRect.Max.y; window->DrawList->AddRectFilled(ImVec2(tab_bar->SeparatorMinX, y - g.Style.TabBarBorderSize), ImVec2(tab_bar->SeparatorMaxX, y), col); } +#endif return true; } @@ -9985,6 +10123,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab->ContentWidth = size.x; tab->BeginOrder = tab_bar->TabsActiveCount++; +#ifdef IMTUI + if (p_open == NULL) + flags |= ImGuiTabItemFlags_NoCloseButton; +#endif + const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0; const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount); @@ -10200,7 +10343,11 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI IM_UNUSED(flags); IM_ASSERT(width > 0.0f); const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f)); - const float y1 = bb.Min.y + 1.0f; +#ifdef IMTUI + float y1 = bb.Min.y; +#else + float y1 = bb.Min.y + 1.0f; +#endif const float y2 = bb.Max.y - g.Style.TabBarBorderSize; draw_list->PathLineTo(ImVec2(bb.Min.x, y2)); draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);