docking: fix docked bg + dock-host moving; per-function @native to fit Roblox codegen limit

This commit is contained in:
4DBug
2026-10-08 05:51:40 -05:00
parent 2381a232ee
commit c563739688
6 changed files with 85 additions and 9 deletions
+1 -1
View File
@@ -1 +1 @@
[[13, "imgui.lua"], [12966, "imgui_demo.lua"], [13859, "imgui_demo_2.lua"], [16747, "imgui_docking.lua"], [19875, "imgui_dragdrop.lua"], [20167, "imgui_draw.lua"], [25162, "imgui_h.lua"], [27316, "imgui_impl_roblox.lua"], [28072, "imgui_impl_roblox_fonts.lua"], [28850, "imgui_internal.lua"], [31999, "imgui_tables.lua"], [32046, "imgui_tabs.lua"], [33213, "imgui_widgets.lua"], [41303, "imstb_rectpack.lua"], [41749, "imstb_textedit.lua"], [42990, "imstb_truetype.lua"], [45458, "imstd_minstdio.lua"]] [[12, "imgui.lua"], [12965, "imgui_demo.lua"], [13858, "imgui_demo_2.lua"], [16746, "imgui_docking.lua"], [19874, "imgui_dragdrop.lua"], [20166, "imgui_draw.lua"], [25161, "imgui_h.lua"], [27315, "imgui_impl_roblox.lua"], [28080, "imgui_impl_roblox_fonts.lua"], [28858, "imgui_internal.lua"], [32007, "imgui_tables.lua"], [32054, "imgui_tabs.lua"], [33221, "imgui_widgets.lua"], [41311, "imstb_rectpack.lua"], [41757, "imstb_textedit.lua"], [42998, "imstb_truetype.lua"], [45466, "imstd_minstdio.lua"]]
+12 -4
View File
@@ -1,4 +1,3 @@
--!native
--!optimize 2 --!optimize 2
-- GENERATED by tools/bundle.py from imgui/*.lua - do not edit -- GENERATED by tools/bundle.py from imgui/*.lua - do not edit
@@ -4458,7 +4457,7 @@ end
local function GetWindowBgColorIdx(window) local function GetWindowBgColorIdx(window)
if bit32.band(window.Flags, bit32.bor(ImGuiWindowFlags.Tooltip, ImGuiWindowFlags.Popup)) ~= 0 then if bit32.band(window.Flags, bit32.bor(ImGuiWindowFlags.Tooltip, ImGuiWindowFlags.Popup)) ~= 0 then
return ImGuiCol.PopupBg return ImGuiCol.PopupBg
elseif bit32.band(window.Flags, ImGuiWindowFlags.ChildWindow) ~= 0 then elseif bit32.band(window.Flags, ImGuiWindowFlags.ChildWindow) ~= 0 and not window.DockIsActive then
return ImGuiCol.ChildBg return ImGuiCol.ChildBg
else else
return ImGuiCol.WindowBg return ImGuiCol.WindowBg
@@ -6058,9 +6057,9 @@ function ImGui.UpdateMouseMovingWindowNewFrame()
if g.MovingWindow then if g.MovingWindow then
ImGui.KeepAliveID(g.ActiveId) ImGui.KeepAliveID(g.ActiveId)
IM_ASSERT(g.MovingWindow and g.MovingWindow.RootWindow) IM_ASSERT(g.MovingWindow and g.MovingWindow.RootWindowDockTree)
local moving_window = g.MovingWindow.RootWindow local moving_window = g.MovingWindow.RootWindowDockTree
local window_disappeared = (not moving_window.WasActive and not moving_window.Active) local window_disappeared = (not moving_window.WasActive and not moving_window.Active)
if g.IO.MouseDown[0] and ImGui.IsMousePosValid(g.IO.MousePos) and not window_disappeared then if g.IO.MouseDown[0] and ImGui.IsMousePosValid(g.IO.MousePos) and not window_disappeared then
@@ -27512,6 +27511,7 @@ local TILE_SIZE -- Vector2, set below
-- Blends one pixel (r, g, b, a are 0..255). One u32 read/write, one division in the general case. -- Blends one pixel (r, g, b, a are 0..255). One u32 read/write, one division in the general case.
-- FillSpan below inlines the same math with per-span constants - keep the two in sync. -- FillSpan below inlines the same math with per-span constants - keep the two in sync.
@native
local function BlendPixel(o, r, g, b, a) local function BlendPixel(o, r, g, b, a)
if a >= 255 then if a >= 255 then
writeu32(buf, o, floor(r + 0.5) + floor(g + 0.5) * 256 + floor(b + 0.5) * 65536 + 4278190080) writeu32(buf, o, floor(r + 0.5) + floor(g + 0.5) * 256 + floor(b + 0.5) * 65536 + 4278190080)
@@ -27539,6 +27539,7 @@ local function BlendPixel(o, r, g, b, a)
end end
-- Fills pixels [x0, x1) of row y with one colour -- Fills pixels [x0, x1) of row y with one colour
@native
local function FillSpan(y, x0, x1, r, g, b, a) local function FillSpan(y, x0, x1, r, g, b, a)
if a <= 0 then return end if a <= 0 then return end
local o0 = (y * buf_w + x0) * 4 local o0 = (y * buf_w + x0) * 4
@@ -27578,11 +27579,13 @@ local function FillSpan(y, x0, x1, r, g, b, a)
end end
end end
@native
local function UnpackColor(col) local function UnpackColor(col)
return col % 256, floor(col / 256) % 256, floor(col / 65536) % 256, floor(col / 16777216) % 256 return col % 256, floor(col / 256) % 256, floor(col / 65536) % 256, floor(col / 16777216) % 256
end end
-- Nearest texel at (u, v) as r, g, b, a (0..255) -- Nearest texel at (u, v) as r, g, b, a (0..255)
@native
local function SampleTexture(t, u, v) local function SampleTexture(t, u, v)
local tw, th = t.Width, t.Height local tw, th = t.Width, t.Height
local tx, ty = floor(u * tw), floor(v * th) local tx, ty = floor(u * tw), floor(v * th)
@@ -27594,6 +27597,7 @@ local function SampleTexture(t, u, v)
end end
-- Axis aligned, single colour quad (rects, glyphs, images). Pixel centers inside [x0, x1) x [y0, y1) are drawn. -- Axis aligned, single colour quad (rects, glyphs, images). Pixel centers inside [x0, x1) x [y0, y1) are drawn.
@native
local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, cy1) local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, cy1)
local r, g, b, a = UnpackColor(col) local r, g, b, a = UnpackColor(col)
if a == 0 then return end if a == 0 then return end
@@ -27651,6 +27655,7 @@ local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, c
end end
-- Generic triangle: per-vertex colour + uv, top-left fill rule, clipped to [cx0, cx1) x [cy0, cy1) -- Generic triangle: per-vertex colour + uv, top-left fill rule, clipped to [cx0, cx1) x [cy0, cy1)
@native
local function DrawTriangle(va, vb, vc, t, cx0, cy0, cx1, cy1, ox, oy) local function DrawTriangle(va, vb, vc, t, cx0, cy0, cx1, cy1, ox, oy)
local x0, y0 = va[1][1] - ox, va[1][2] - oy local x0, y0 = va[1][1] - ox, va[1][2] - oy
local x1, y1 = vb[1][1] - ox, vb[1][2] - oy local x1, y1 = vb[1][1] - ox, vb[1][2] - oy
@@ -27727,6 +27732,7 @@ end
-- Quads emitted by PrimRect/PrimRectUV/RenderText use indices (a, b, c, a, c, d) with a=TL, b=TR, c=BR, d=BL. -- Quads emitted by PrimRect/PrimRectUV/RenderText use indices (a, b, c, a, c, d) with a=TL, b=TR, c=BR, d=BL.
-- When such a quad is axis aligned with one colour it is drawn with the much cheaper DrawRect. -- When such a quad is axis aligned with one colour it is drawn with the much cheaper DrawRect.
@native
local function TryDrawRect(va, vb, vc, vd, t, cx0, cy0, cx1, cy1, ox, oy) local function TryDrawRect(va, vb, vc, vd, t, cx0, cy0, cx1, cy1, ox, oy)
local pa, pb, pc, pd = va[1], vb[1], vc[1], vd[1] local pa, pb, pc, pd = va[1], vb[1], vc[1], vd[1]
if not (pa[2] == pb[2] and pb[1] == pc[1] and pc[2] == pd[2] and pd[1] == pa[1] and pa[1] < pb[1] and pa[2] < pd[2]) then return false end if not (pa[2] == pb[2] and pb[1] == pc[1] and pc[2] == pd[2] and pd[1] == pa[1] and pa[1] < pb[1] and pa[2] < pd[2]) then return false end
@@ -27750,6 +27756,7 @@ local P1, P2 = 2147483647, 2147483629 -- two independent 31 bit hashes per tile
local pr_a, pr_b, pr_c, pr_d, pr_t = {}, {}, {}, {}, {} -- vertices (pr_d == false -> triangle), texture local pr_a, pr_b, pr_c, pr_d, pr_t = {}, {}, {}, {}, {} -- vertices (pr_d == false -> triangle), texture
local pr_cx0, pr_cy0, pr_cx1, pr_cy1 = {}, {}, {}, {} -- clip (screen pixels) local pr_cx0, pr_cy0, pr_cx1, pr_cy1 = {}, {}, {}, {} -- clip (screen pixels)
@native
local function HashVertex(h1, h2, v) local function HashVertex(h1, h2, v)
local p, u, c = v[1], v[2], v[3] local p, u, c = v[1], v[2], v[3]
local x, y = p[1], p[2] local x, y = p[1], p[2]
@@ -27788,6 +27795,7 @@ local function DestroyTiles(bd)
bd.Tiles = {} bd.Tiles = {}
end end
@native
function ImGui_ImplRoblox_RenderDrawData(draw_data) function ImGui_ImplRoblox_RenderDrawData(draw_data)
local bd = ImGui_ImplRoblox_GetBackendData() local bd = ImGui_ImplRoblox_GetBackendData()
+9
View File
@@ -197,6 +197,7 @@ local TILE_SIZE -- Vector2, set below
-- Blends one pixel (r, g, b, a are 0..255). One u32 read/write, one division in the general case. -- Blends one pixel (r, g, b, a are 0..255). One u32 read/write, one division in the general case.
-- FillSpan below inlines the same math with per-span constants - keep the two in sync. -- FillSpan below inlines the same math with per-span constants - keep the two in sync.
@native
local function BlendPixel(o, r, g, b, a) local function BlendPixel(o, r, g, b, a)
if a >= 255 then if a >= 255 then
writeu32(buf, o, floor(r + 0.5) + floor(g + 0.5) * 256 + floor(b + 0.5) * 65536 + 4278190080) writeu32(buf, o, floor(r + 0.5) + floor(g + 0.5) * 256 + floor(b + 0.5) * 65536 + 4278190080)
@@ -224,6 +225,7 @@ local function BlendPixel(o, r, g, b, a)
end end
-- Fills pixels [x0, x1) of row y with one colour -- Fills pixels [x0, x1) of row y with one colour
@native
local function FillSpan(y, x0, x1, r, g, b, a) local function FillSpan(y, x0, x1, r, g, b, a)
if a <= 0 then return end if a <= 0 then return end
local o0 = (y * buf_w + x0) * 4 local o0 = (y * buf_w + x0) * 4
@@ -263,11 +265,13 @@ local function FillSpan(y, x0, x1, r, g, b, a)
end end
end end
@native
local function UnpackColor(col) local function UnpackColor(col)
return col % 256, floor(col / 256) % 256, floor(col / 65536) % 256, floor(col / 16777216) % 256 return col % 256, floor(col / 256) % 256, floor(col / 65536) % 256, floor(col / 16777216) % 256
end end
-- Nearest texel at (u, v) as r, g, b, a (0..255) -- Nearest texel at (u, v) as r, g, b, a (0..255)
@native
local function SampleTexture(t, u, v) local function SampleTexture(t, u, v)
local tw, th = t.Width, t.Height local tw, th = t.Width, t.Height
local tx, ty = floor(u * tw), floor(v * th) local tx, ty = floor(u * tw), floor(v * th)
@@ -279,6 +283,7 @@ local function SampleTexture(t, u, v)
end end
-- Axis aligned, single colour quad (rects, glyphs, images). Pixel centers inside [x0, x1) x [y0, y1) are drawn. -- Axis aligned, single colour quad (rects, glyphs, images). Pixel centers inside [x0, x1) x [y0, y1) are drawn.
@native
local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, cy1) local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, cy1)
local r, g, b, a = UnpackColor(col) local r, g, b, a = UnpackColor(col)
if a == 0 then return end if a == 0 then return end
@@ -336,6 +341,7 @@ local function DrawRect(x0, y0, x1, y1, u0, v0, u1, v1, col, t, cx0, cy0, cx1, c
end end
-- Generic triangle: per-vertex colour + uv, top-left fill rule, clipped to [cx0, cx1) x [cy0, cy1) -- Generic triangle: per-vertex colour + uv, top-left fill rule, clipped to [cx0, cx1) x [cy0, cy1)
@native
local function DrawTriangle(va, vb, vc, t, cx0, cy0, cx1, cy1, ox, oy) local function DrawTriangle(va, vb, vc, t, cx0, cy0, cx1, cy1, ox, oy)
local x0, y0 = va[1][1] - ox, va[1][2] - oy local x0, y0 = va[1][1] - ox, va[1][2] - oy
local x1, y1 = vb[1][1] - ox, vb[1][2] - oy local x1, y1 = vb[1][1] - ox, vb[1][2] - oy
@@ -412,6 +418,7 @@ end
-- Quads emitted by PrimRect/PrimRectUV/RenderText use indices (a, b, c, a, c, d) with a=TL, b=TR, c=BR, d=BL. -- Quads emitted by PrimRect/PrimRectUV/RenderText use indices (a, b, c, a, c, d) with a=TL, b=TR, c=BR, d=BL.
-- When such a quad is axis aligned with one colour it is drawn with the much cheaper DrawRect. -- When such a quad is axis aligned with one colour it is drawn with the much cheaper DrawRect.
@native
local function TryDrawRect(va, vb, vc, vd, t, cx0, cy0, cx1, cy1, ox, oy) local function TryDrawRect(va, vb, vc, vd, t, cx0, cy0, cx1, cy1, ox, oy)
local pa, pb, pc, pd = va[1], vb[1], vc[1], vd[1] local pa, pb, pc, pd = va[1], vb[1], vc[1], vd[1]
if not (pa[2] == pb[2] and pb[1] == pc[1] and pc[2] == pd[2] and pd[1] == pa[1] and pa[1] < pb[1] and pa[2] < pd[2]) then return false end if not (pa[2] == pb[2] and pb[1] == pc[1] and pc[2] == pd[2] and pd[1] == pa[1] and pa[1] < pb[1] and pa[2] < pd[2]) then return false end
@@ -435,6 +442,7 @@ local P1, P2 = 2147483647, 2147483629 -- two independent 31 bit hashes per tile
local pr_a, pr_b, pr_c, pr_d, pr_t = {}, {}, {}, {}, {} -- vertices (pr_d == false -> triangle), texture local pr_a, pr_b, pr_c, pr_d, pr_t = {}, {}, {}, {}, {} -- vertices (pr_d == false -> triangle), texture
local pr_cx0, pr_cy0, pr_cx1, pr_cy1 = {}, {}, {}, {} -- clip (screen pixels) local pr_cx0, pr_cy0, pr_cx1, pr_cy1 = {}, {}, {}, {} -- clip (screen pixels)
@native
local function HashVertex(h1, h2, v) local function HashVertex(h1, h2, v)
local p, u, c = v[1], v[2], v[3] local p, u, c = v[1], v[2], v[3]
local x, y = p[1], p[2] local x, y = p[1], p[2]
@@ -473,6 +481,7 @@ local function DestroyTiles(bd)
bd.Tiles = {} bd.Tiles = {}
end end
@native
function ImGui_ImplRoblox_RenderDrawData(draw_data) function ImGui_ImplRoblox_RenderDrawData(draw_data)
local bd = ImGui_ImplRoblox_GetBackendData() local bd = ImGui_ImplRoblox_GetBackendData()
+3 -3
View File
@@ -4446,7 +4446,7 @@ end
local function GetWindowBgColorIdx(window) local function GetWindowBgColorIdx(window)
if bit32.band(window.Flags, bit32.bor(ImGuiWindowFlags.Tooltip, ImGuiWindowFlags.Popup)) ~= 0 then if bit32.band(window.Flags, bit32.bor(ImGuiWindowFlags.Tooltip, ImGuiWindowFlags.Popup)) ~= 0 then
return ImGuiCol.PopupBg return ImGuiCol.PopupBg
elseif bit32.band(window.Flags, ImGuiWindowFlags.ChildWindow) ~= 0 then elseif bit32.band(window.Flags, ImGuiWindowFlags.ChildWindow) ~= 0 and not window.DockIsActive then
return ImGuiCol.ChildBg return ImGuiCol.ChildBg
else else
return ImGuiCol.WindowBg return ImGuiCol.WindowBg
@@ -6046,9 +6046,9 @@ function ImGui.UpdateMouseMovingWindowNewFrame()
if g.MovingWindow then if g.MovingWindow then
ImGui.KeepAliveID(g.ActiveId) ImGui.KeepAliveID(g.ActiveId)
IM_ASSERT(g.MovingWindow and g.MovingWindow.RootWindow) IM_ASSERT(g.MovingWindow and g.MovingWindow.RootWindowDockTree)
local moving_window = g.MovingWindow.RootWindow local moving_window = g.MovingWindow.RootWindowDockTree
local window_disappeared = (not moving_window.WasActive and not moving_window.Active) local window_disappeared = (not moving_window.WasActive and not moving_window.Active)
if g.IO.MouseDown[0] and ImGui.IsMousePosValid(g.IO.MousePos) and not window_disappeared then if g.IO.MouseDown[0] and ImGui.IsMousePosValid(g.IO.MousePos) and not window_disappeared then
+1 -1
View File
@@ -20,7 +20,7 @@ for src in FILES.values():
names.update(re.findall(r"^function ([A-Za-z_]\w*)\s*\(", src, re.M)) names.update(re.findall(r"^function ([A-Za-z_]\w*)\s*\(", src, re.M))
names.update(re.findall(r"^([A-Za-z_]\w*)\s*=[^=]", src, re.M)) names.update(re.findall(r"^([A-Za-z_]\w*)\s*=[^=]", src, re.M))
out = ["--!native", "--!optimize 2", "-- GENERATED by tools/bundle.py from imgui/*.lua - do not edit", "", out = ["--!optimize 2", "-- GENERATED by tools/bundle.py from imgui/*.lua - do not edit", "",
"local __FILES, __LOADED = {}, {}", "local __FILES, __LOADED = {}, {}",
"function IM_INCLUDE(name)", "function IM_INCLUDE(name)",
" local r = __LOADED[name]", " local r = __LOADED[name]",
+59
View File
@@ -0,0 +1,59 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local G = require(ReplicatedStorage:WaitForChild("ImGui"))
local ImGui, ImVec2 = G.ImGui, G.ImVec2
ImGui.CreateContext()
local io = ImGui.GetIO()
io.ConfigFlags = bit32.bor(io.ConfigFlags, G.ImGuiConfigFlags.DockingEnable)
G.ImGui_ImplRoblox.Init()
local frame, last_down, host0 = 0, false, nil
local function lerp(a, b, t) return a + (b - a) * t end
local function script(f)
if f < 6 then return 600, 108, false end
if f == 6 then return 600, 108, true end
if f <= 20 then local t = (f - 6) / 14 return lerp(600, 250, t), lerp(108, 190, t), true end
if f <= 27 then return 250, 190, true end
if f <= 40 then return 250, 190, false end
-- now grab empty space of the shared tab bar (right of the tabs) and move
if f == 41 then return 380, 108, false end
if f == 42 then return 380, 108, true end
if f <= 56 then local t = (f - 42) / 14 return lerp(380, 600, t), lerp(108, 300, t), true end
return 600, 300, false
end
RunService.Stepped:Connect(function()
frame += 1
G.ImGui_ImplRoblox.NewFrame()
local x, y, down = script(frame)
io:AddMousePosEvent(x, y)
if down ~= last_down then io:AddMouseButtonEvent(0, down); last_down = down end
ImGui.NewFrame()
for i, n in ipairs({"A", "B"}) do
ImGui.SetNextWindowPos(ImVec2(100 + (i - 1) * 400, 100), G.ImGuiCond.FirstUseEver)
ImGui.SetNextWindowSize(ImVec2(300, 200), G.ImGuiCond.FirstUseEver)
if ImGui.Begin(n) then ImGui.Text("window " .. n) end
ImGui.End()
end
local a = ImGui.FindWindowByName("A")
if frame == 40 then
assert(a.DockNode and a.DockNode.Windows.Size == 2, "docked")
host0 = {Pos = {x = a.DockNode.HostWindow.Pos.x, y = a.DockNode.HostWindow.Pos.y}}
print("host before", host0.Pos.x, host0.Pos.y)
end
if frame == 70 then
local h = a.DockNode.HostWindow
print("host after", h.Pos.x, h.Pos.y)
assert(math.abs(h.Pos.x - host0.Pos.x) > 100 or math.abs(h.Pos.y - host0.Pos.y) > 50, "dock host must move")
-- background: host draw list must contain a filled rect covering the node body
end
ImGui.Render()
G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
if frame == 70 then
local want = ImGui.GetColorU32(G.ImGuiCol.WindowBg)
local found = false
for _, l in ImGui.GetDrawData().CmdLists:iter() do
for i = 1, l.VtxBuffer.Size do if l.VtxBuffer.Data[i][3] == want then found = true break end end
end
assert(found, "docked windows must draw a WindowBg background")
print("MOVE OK")
end
end)