Fix: long TextUnformatted (>2000 bytes) rendered each visible line to the end of the text (RenderText end was nil, upstream passes line_end); PushFont() saved the new font instead of the current one, so PopFont() never restored it (font preview leaked into all later text); t_fixes covers both

This commit is contained in:
4DBug
2026-10-15 10:54:56 -05:00
parent dad1a0c0f1
commit a1aa5cbb2d
5 changed files with 28 additions and 8 deletions
+2 -2
View File
@@ -5512,7 +5512,7 @@ function ImGui.PushFont(font, font_size_base)
assert(font ~= nil)
assert(font_size_base >= 0.0)
g.FontStack:push_back(ImFontStackData(font, g.FontSizeBase, g.FontSize))
g.FontStack:push_back(ImFontStackData(g.Font, g.FontSizeBase, g.FontSize))
if font_size_base == 0.0 then
font_size_base = g.FontSizeBase -- Keep current font size
@@ -63145,7 +63145,7 @@ function ImGui.TextEx(text, text_end, flags)
local line_size = ImGui.CalcTextSizeEx(text, line, line_end)
text_size.x = ImMax(text_size.x, line_size.x)
ImGui.RenderText(pos, text, line, nil, false)
ImGui.RenderText(pos, text, line, line_end, false)
line = line_end + 1
line_rect.Min.y = line_rect.Min.y + line_height
line_rect.Max.y = line_rect.Max.y + line_height
+2 -2
View File
@@ -5649,7 +5649,7 @@ function ImGui.PushFont(font, font_size_base)
assert(font ~= nil)
assert(font_size_base >= 0.0)
g.FontStack:push_back(ImFontStackData(font, g.FontSizeBase, g.FontSize))
g.FontStack:push_back(ImFontStackData(g.Font, g.FontSizeBase, g.FontSize))
if font_size_base == 0.0 then
font_size_base = g.FontSizeBase -- Keep current font size
@@ -55771,7 +55771,7 @@ function ImGui.TextEx(text, text_end, flags)
local line_size = ImGui.CalcTextSizeEx(text, line, line_end)
text_size.x = ImMax(text_size.x, line_size.x)
ImGui.RenderText(pos, text, line, nil, false)
ImGui.RenderText(pos, text, line, line_end, false)
line = line_end + 1
line_rect.Min.y = line_rect.Min.y + line_height
line_rect.Max.y = line_rect.Max.y + line_height
+1 -1
View File
@@ -5467,7 +5467,7 @@ function ImGui.PushFont(font, font_size_base)
IM_ASSERT(font ~= nil)
IM_ASSERT(font_size_base >= 0.0)
g.FontStack:push_back(ImFontStackData(font, g.FontSizeBase, g.FontSize))
g.FontStack:push_back(ImFontStackData(g.Font, g.FontSizeBase, g.FontSize))
if font_size_base == 0.0 then
font_size_base = g.FontSizeBase -- Keep current font size
+1 -1
View File
@@ -170,7 +170,7 @@ function ImGui.TextEx(text, text_end, flags)
local line_size = ImGui.CalcTextSizeEx(text, line, line_end)
text_size.x = ImMax(text_size.x, line_size.x)
ImGui.RenderText(pos, text, line, nil, false)
ImGui.RenderText(pos, text, line, line_end, false)
line = line_end + 1
line_rect.Min.y = line_rect.Min.y + line_height
line_rect.Max.y = line_rect.Max.y + line_height
+22 -2
View File
@@ -1,9 +1,12 @@
-- Regressions vs upstream: clipboard paste filter (InputTextEx), ImParseFormatTrimDecorations (Ctrl+click temp input), ShrinkWidths tie order,
-- CalcItemSize by value, PushClipRectFullScreen (drop target outside clip rect), InputTextMultiline line index (render/scroll/edit), Shortcut() default
-- CalcItemSize by value, PushClipRectFullScreen (drop target outside clip rect), long TextUnformatted, PushFont/PopFont, InputTextMultiline line index (render/scroll/edit), Shortcut() default
-- args, IsWindowAppearing() on frame 1 (FrameCount starts at 0), ColorButton -> ColorEdit4 drag and drop
local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui"))
local ImGui, ImVec2 = G.ImGui, G.ImVec2
ImGui.CreateContext(); G.ImGui_ImplRoblox.Init()
ImGui.CreateContext()
ImGui.GetIO().Fonts:AddFontDefault()
local font2 = ImGui.GetIO().Fonts:AddFontDefault() -- second font for the PushFont/PopFont check
G.ImGui_ImplRoblox.Init()
local io = ImGui.GetIO()
local failed = {}
local function check(ok, msg) if not ok then table.insert(failed, msg); print("FAIL " .. msg) end end
@@ -18,6 +21,10 @@ check(w[3] == 100 and w[2] == 100 and w[1] == 99 and w[0] == 99, ("ShrinkWidths
check(G.ImFloor(-1.5) == -2 and G.ImFloor(-0.2) == -1 and G.ImFloor(2.7) == 2, "ImFloor negative")
local long_text = {}
for i = 1, 300 do long_text[i] = string.format("line %04d", i) end
long_text = table.concat(long_text, "\n") -- 2999 bytes
local function edit_text()
local st = ImGui.GetCurrentContext().InputTextState
return G.ImGui._ByteArrayToString(st.TextA.Data, 1, st.TextLen + 1)
@@ -110,6 +117,19 @@ game:GetService("RunService").Stepped:Connect(function()
ImGui.ColorButton("cb", cb_col); rects.cb = rect()
ImGui.ColorEdit4("##ce", ce_col); rects.ce = rect()
ImGui.End()
-- TextUnformatted() > 2000 bytes (coarse-clipped long text path): each visible line renders only up to its '\n'
ImGui.SetNextWindowPos(ImVec2(320, 220)); ImGui.SetNextWindowSize(ImVec2(300, 150))
ImGui.Begin("L")
local dl = ImGui.GetWindowDrawList()
local v0 = dl.VtxBuffer.Size
ImGui.TextUnformatted(long_text)
local nv = dl.VtxBuffer.Size - v0
if f == 3 then check(nv > 0 and nv <= 14 * 9 * 4, "long TextUnformatted vertices " .. nv) end
-- PushFont() saves the CURRENT font: PopFont() must restore it
local font1 = ImGui.GetFont()
check(font2 ~= font1, "font2 is the default font"); ImGui.PushFont(font2, 0.0); ImGui.PopFont()
if f == 3 then check(ImGui.GetFont() == font1, "PopFont() did not restore the previous font") end
ImGui.End()
ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
if f == 8 then check(edit_text() == "abc\u{e9}", "paste: '" .. edit_text() .. "'") end
if f == 13 then check(edit_text() == "45", "SliderFloat temp input: '" .. edit_text() .. "'") end