Perf: allocation-free ItemSize/ItemAdd/IsMouseHoveringRect/GetColorU32/RenderArrow, @native on hot UI paths; t_drawhash output-equivalence check

This commit is contained in:
4DBug
2026-10-08 10:41:15 -05:00
parent d9a741aa0e
commit 71843392f1
8 changed files with 296 additions and 101 deletions
+1 -1
View File
@@ -1 +1 @@
[[12, "imgui.lua"], [13761, "imgui_demo.lua"], [14694, "imgui_demo_2.lua"], [17769, "imgui_demo_apps.lua"], [19028, "imgui_demo_tools.lua"], [20354, "imgui_demo_widgets.lua"], [22278, "imgui_docking.lua"], [25406, "imgui_dragdrop.lua"], [25698, "imgui_draw.lua"], [30930, "imgui_h.lua"], [33096, "imgui_impl_roblox.lua"], [33920, "imgui_impl_roblox_fonts.lua"], [40323, "imgui_internal.lua"], [43479, "imgui_tables.lua"], [47826, "imgui_tabs.lua"], [48993, "imgui_widgets.lua"], [57517, "imstb_rectpack.lua"], [57963, "imstb_textedit.lua"], [59204, "imstb_truetype.lua"], [61672, "imstd_minstdio.lua"]]
[[12, "imgui.lua"], [13795, "imgui_demo.lua"], [14728, "imgui_demo_2.lua"], [17803, "imgui_demo_apps.lua"], [19062, "imgui_demo_tools.lua"], [20388, "imgui_demo_widgets.lua"], [22312, "imgui_docking.lua"], [25440, "imgui_dragdrop.lua"], [25732, "imgui_draw.lua"], [30979, "imgui_h.lua"], [33153, "imgui_impl_roblox.lua"], [33977, "imgui_impl_roblox_fonts.lua"], [40380, "imgui_internal.lua"], [43552, "imgui_tables.lua"], [47899, "imgui_tabs.lua"], [49066, "imgui_widgets.lua"], [57600, "imstb_rectpack.lua"], [58046, "imstb_textedit.lua"], [59287, "imstb_truetype.lua"], [61755, "imstd_minstdio.lua"]]
+133 -50
View File
@@ -375,6 +375,7 @@ function ImHashStr(str, size, seed)
return ImHashStrRaw(str, size, seed)
end
@native
function ImHashStrRaw(str, size, seed)
if str == "" or size == 0 then
@@ -1541,6 +1542,7 @@ local function GetWindowForTitleDisplay(window)
end
--- @param id ImGuiID
@native
function ImGui.KeepAliveID(id)
local g = GImGui
@@ -1556,20 +1558,28 @@ end
--- @param r_min ImVec2
--- @param r_max ImVec2
--- @param clip? bool
@native
function ImGui.IsMouseHoveringRect(r_min, r_max, clip)
if clip == nil then clip = true end
local g = GImGui
local rect_clipped = ImRect(r_min, r_max)
-- [Luau] scalar version of: rect_clipped = ImRect(r_min, r_max); ClipWith(window.ClipRect); ContainsWithPad(); viewport Overlaps()
local x0, y0, x1, y1 = r_min.x, r_min.y, r_max.x, r_max.y
if clip then
rect_clipped:ClipWith(g.CurrentWindow.ClipRect)
local cr = g.CurrentWindow.ClipRect
local cmin, cmax = cr.Min, cr.Max
x0 = math.max(x0, cmin.x); y0 = math.max(y0, cmin.y)
x1 = math.min(x1, cmax.x); y1 = math.min(y1, cmax.y)
end
if not rect_clipped:ContainsWithPad(g.IO.MousePos, g.Style.TouchExtraPadding) then
local p, pad = g.IO.MousePos, g.Style.TouchExtraPadding
if not (p.x >= x0 - pad.x and p.y >= y0 - pad.y and p.x < x1 + pad.x and p.y < y1 + pad.y) then
return false
end
if (not g.MouseViewport:GetMainRect():Overlaps(rect_clipped)) then
local vp = g.MouseViewport
local vx0, vy0 = vp.Pos.x, vp.Pos.y
local vx1, vy1 = vx0 + vp.Size.x, vy0 + vp.Size.y
if not (vx0 <= x1 and vx1 >= x0 and vy0 <= y1 and vy1 >= y0) then
return false
end
@@ -1642,6 +1652,7 @@ end
--- @param id ImGuiID
--- @param nav_bb_arg? ImRect
--- @param extra_flags? ImGuiItemFlags
@native
function ImGui.ItemAdd(bb, id, nav_bb_arg, extra_flags)
if extra_flags == nil then extra_flags = 0 end
@@ -1677,7 +1688,8 @@ function ImGui.ItemAdd(bb, id, nav_bb_arg, extra_flags)
g.NextItemData.HasFlags = ImGuiNextItemDataFlags.None
g.NextItemData.ItemFlagsSet = ImGuiItemFlags.None
local is_rect_visible = bb:Overlaps(window.ClipRect)
local bmin, bmax, cr = bb.Min, bb.Max, window.ClipRect
local is_rect_visible = bmin.x <= cr.Max.x and bmax.x >= cr.Min.x and bmin.y <= cr.Max.y and bmax.y >= cr.Min.y
if not is_rect_visible then
if id == 0 or not (id == g.ActiveId or id == g.ActiveIdPreviousFrame or id == g.NavId or id == g.NavActivateId or g.ItemUnclipByLog) then
return false
@@ -1701,16 +1713,18 @@ end
--- @param size_or_bb ImVec2|ImRect
--- @param text_baseline_y? float
@native
function ImGui.ItemSize(size_or_bb, text_baseline_y)
if text_baseline_y == nil then text_baseline_y = -1.0 end
local size
if size_or_bb.Min then
local size_x, size_y
local bb_min = size_or_bb.Min
if bb_min then
--- @cast size_or_bb ImRect
size = size_or_bb:GetSize()
size_x = size_or_bb.Max.x - bb_min.x; size_y = size_or_bb.Max.y - bb_min.y
else
--- @cast size_or_bb ImVec2
size = size_or_bb
size_x = size_or_bb.x; size_y = size_or_bb.y
end
local g = GImGui
@@ -1719,45 +1733,50 @@ function ImGui.ItemSize(size_or_bb, text_baseline_y)
if window.SkipItems then
return
end
local dc = window.DC
local mathMax = math.max
local offset_to_match_baseline_y
if text_baseline_y >= 0 then
offset_to_match_baseline_y = ImMax(0, window.DC.CurrLineTextBaseOffset - text_baseline_y)
offset_to_match_baseline_y = mathMax(0, dc.CurrLineTextBaseOffset - text_baseline_y)
else
offset_to_match_baseline_y = 0
end
local cursor, prev_line, max_pos = dc.CursorPos, dc.CursorPosPrevLine, dc.CursorMaxPos
local line_y1
if window.DC.IsSameLine then
line_y1 = window.DC.CursorPosPrevLine.y
if dc.IsSameLine then
line_y1 = prev_line.y
else
line_y1 = window.DC.CursorPos.y
line_y1 = cursor.y
end
local line_height = ImMax(window.DC.CurrLineSize.y, window.DC.CursorPos.y - line_y1 + size.y + offset_to_match_baseline_y)
local line_height = mathMax(dc.CurrLineSize.y, cursor.y - line_y1 + size_y + offset_to_match_baseline_y)
local spacing_y = g.Style.ItemSpacing.y
window.DC.CursorPosPrevLine.x = window.DC.CursorPos.x + size.x
window.DC.CursorPosPrevLine.y = line_y1
window.DC.CursorPos.x = IM_TRUNC(window.Pos.x + window.DC.Indent.x + window.DC.ColumnsOffset.x)
window.DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y)
window.DC.CursorMaxPos.x = ImMax(window.DC.CursorMaxPos.x, window.DC.CursorPosPrevLine.x)
window.DC.CursorMaxPos.y = ImMax(window.DC.CursorMaxPos.y, window.DC.CursorPos.y - g.Style.ItemSpacing.y)
prev_line.x = cursor.x + size_x
prev_line.y = line_y1
cursor.x = math.floor(window.Pos.x + dc.Indent.x + dc.ColumnsOffset.x)
cursor.y = math.floor(line_y1 + line_height + spacing_y)
max_pos.x = mathMax(max_pos.x, prev_line.x)
max_pos.y = mathMax(max_pos.y, cursor.y - spacing_y)
window.DC.PrevLineSize.y = line_height
window.DC.CurrLineSize.y = 0
window.DC.PrevLineTextBaseOffset = ImMax(window.DC.CurrLineTextBaseOffset, text_baseline_y)
window.DC.CurrLineTextBaseOffset = 0
window.DC.IsSetPos = false
window.DC.IsSameLine = false
dc.PrevLineSize.y = line_height
dc.CurrLineSize.y = 0
dc.PrevLineTextBaseOffset = mathMax(dc.CurrLineTextBaseOffset, text_baseline_y)
dc.CurrLineTextBaseOffset = 0
dc.IsSetPos = false
dc.IsSameLine = false
--- Horizontal layout mode
if (window.DC.LayoutType == ImGuiLayoutType.Horizontal) then
if (dc.LayoutType == ImGuiLayoutType.Horizontal) then
ImGui.SameLine()
end
end
--- @param offset_from_start_x float?
--- @param spacing_w float?
@native
function ImGui.SameLine(offset_from_start_x, spacing_w)
if offset_from_start_x == nil then offset_from_start_x = 0.0 end
if spacing_w == nil then spacing_w = -1.0 end
@@ -1870,6 +1889,7 @@ end
--- @return ImVec2
--- @nodiscard
@native
function ImGui.GetContentRegionAvail()
local g = GImGui
local window = g.CurrentWindow
@@ -2085,6 +2105,7 @@ function ImGui.EndGroup()
end
end
@native
function ImGui.CalcItemWidth()
local g = GImGui
local window = g.CurrentWindow
@@ -2575,6 +2596,7 @@ function ImGui.ClearActiveID()
end
--- @param str_id string|int
@native
function ImGui.PushID(str_id)
local g = GImGui
local window = g.CurrentWindow
@@ -2592,6 +2614,7 @@ function ImGui.PushOverrideID(id)
window.IDStack:push_back(id)
end
@native
function ImGui.PopID()
local window = GImGui.CurrentWindow
IM_ASSERT_USER_ERROR_RET(window.IDStack.Size > 1, "Calling PopID() too many times!")
@@ -2600,6 +2623,7 @@ end
--- @param id string|int
--- @return ImGuiID
@native
function MT.ImGuiWindow:GetID(id)
local seed = self.IDStack:back()
@@ -2662,6 +2686,7 @@ function ImGui.GetIDWithSeed(a, b, c)
end
--- @param id ImGuiID
@native
function ImGui.SetHoveredID(id)
local g = GImGui
g.HoveredId = id
@@ -2763,6 +2788,7 @@ function ImGui.IsWindowContentHoverable(window, flags)
end
--- @param flags? ImGuiHoveredFlags
@native
function ImGui.IsItemHovered(flags)
if flags == nil then flags = 0 end
@@ -2862,6 +2888,7 @@ end
--- @param bb ImRect
--- @param id ImGuiID
--- @param item_flags ImGuiItemFlags
@native
function ImGui.ItemHoverable(bb, id, item_flags)
local g = GImGui
local window = g.CurrentWindow
@@ -4785,6 +4812,7 @@ end
--- @param text ImString
--- @param text_end int?
--- @return int # Exclusive upper bound
@native
function ImGui.FindRenderedTextEnd(text, text_end)
local text_display_end = 1
local text_len = #text
@@ -4803,6 +4831,7 @@ end
--- @param text_begin int?
--- @param text_end int?
--- @param hide_text_after_hash bool? # true by default
@native
function ImGui.RenderText(pos, text, text_begin, text_end, hide_text_after_hash)
if text_begin == nil then text_begin = 1 end
if hide_text_after_hash == nil then hide_text_after_hash = true end
@@ -4855,6 +4884,7 @@ end
--- @param text_size_if_known? ImVec2
--- @param align? ImVec2
--- @param clip_rect? ImRect
@native
function ImGui.RenderTextClippedEx(draw_list, pos_min, pos_max, text, text_begin, text_display_end, text_size_if_known, align, clip_rect)
if not align then align = ImVec2(0, 0) end
@@ -4910,6 +4940,7 @@ end
--- @param id ImGuiID
--- @param flags? ImGuiNavRenderCursorFlags
--- @param rounding? float
@native
function ImGui.RenderNavCursor(bb, id, flags, rounding)
if flags == nil then flags = ImGuiNavRenderCursorFlags.None end
if rounding == nil then rounding = -1.0 end
@@ -5075,6 +5106,7 @@ end
--- @param fill_col ImU32
--- @param borders? bool
--- @param rounding? float
@native
function ImGui.RenderFrame(p_min, p_max, fill_col, borders, rounding)
if borders == nil then borders = true end
if rounding == nil then rounding = 0.0 end
@@ -7959,6 +7991,7 @@ end
--- @param clip_rect_min ImVec2
--- @param clip_rect_max ImVec2
--- @param intersect_with_current_clip_rect? bool
@native
function ImGui.PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect)
local window = ImGui.GetCurrentWindow()
window.DrawList:PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect)
@@ -8519,6 +8552,7 @@ end
--- @param hide_text_after_double_hash? bool
--- @param wrap_width? float
--- @return ImVec2
@native
function ImGui.CalcTextSize(text, text_end, hide_text_after_double_hash, wrap_width)
return ImGui.CalcTextSizeEx(text, 1, text_end, hide_text_after_double_hash, wrap_width)
end
@@ -8529,6 +8563,7 @@ end
--- @param hide_text_after_double_hash? bool
--- @param wrap_width? float
--- @return ImVec2
@native
function ImGui.CalcTextSizeEx(text, text_begin, text_end, hide_text_after_double_hash, wrap_width)
if hide_text_after_double_hash == nil then hide_text_after_double_hash = false end
if wrap_width == nil then wrap_width = -1.0 end
@@ -8657,13 +8692,11 @@ end
--- @param in_col ImVec4
--- @return ImU32
local function F32ToU8Sat(v) if v < 0.0 then v = 0.0 elseif v > 1.0 then v = 1.0 end return math.floor(v * 255.0 + 0.5) end
@native
function ImGui.ColorConvertFloat4ToU32(in_col)
local out_col = 0
out_col = bit32.bor(out_col, bit32.lshift(IM_F32_TO_INT8_SAT(in_col.x), IM_COL32_R_SHIFT))
out_col = bit32.bor(out_col, bit32.lshift(IM_F32_TO_INT8_SAT(in_col.y), IM_COL32_G_SHIFT))
out_col = bit32.bor(out_col, bit32.lshift(IM_F32_TO_INT8_SAT(in_col.z), IM_COL32_B_SHIFT))
out_col = bit32.bor(out_col, bit32.lshift(IM_F32_TO_INT8_SAT(in_col.w), IM_COL32_A_SHIFT))
return out_col
return bit32.bor(F32ToU8Sat(in_col.x), bit32.lshift(F32ToU8Sat(in_col.y), 8), bit32.lshift(F32ToU8Sat(in_col.z), 16), bit32.lshift(F32ToU8Sat(in_col.w), 24))
end
--- @param r float
@@ -8746,6 +8779,7 @@ local c = ImVec4()
--- @param alpha_mul? float
--- @param col_is_u32? bool # must be truthy if `col` is `ImU32`
--- @return ImU32
@native
function ImGui.GetColorU32(col, alpha_mul, col_is_u32)
if alpha_mul == nil then alpha_mul = 1.0 end
@@ -8753,14 +8787,14 @@ function ImGui.GetColorU32(col, alpha_mul, col_is_u32)
if not col_is_u32 then
--- @cast col ImVec4|ImGuiCol
local w
if type(col) == "number" then
ImVec4_Copy(c, style.Colors[col])
c.w = c.w * style.Alpha * alpha_mul
col = style.Colors[col]
w = col.w * style.Alpha * alpha_mul
else --- @cast col ImVec4
ImVec4_Copy(c, col)
c.w = c.w * style.Alpha
w = col.w * style.Alpha
end
return ImGui.ColorConvertFloat4ToU32(c)
return bit32.bor(F32ToU8Sat(col.x), bit32.lshift(F32ToU8Sat(col.y), 8), bit32.lshift(F32ToU8Sat(col.z), 16), bit32.lshift(F32ToU8Sat(w), 24))
else
--- @cast col ImU32
alpha_mul = alpha_mul * style.Alpha
@@ -28311,6 +28345,7 @@ end
--- @return int remaining
local TEXT_SIZE_CACHE_MAX = 4096
@native
function ImFontCalcTextSizeEx(font, size, max_width, wrap_width, text, text_begin, text_end_display, text_end, out_offset, flags)
-- [Luau] cache for the common case (whole string, single pass, no wrap/limit): per baked font, text -> unscaled width, line count.
-- Advances of a baked font never change once loaded, so entries stay valid. ponytail: whole-cache reset at TEXT_SIZE_CACHE_MAX entries, LRU if dynamic text churns it
@@ -29243,6 +29278,7 @@ function MT.ImDrawList:ChannelsSetCurrent(n) self._Splitter:SetCurrentChannel(se
--- @param points ImVec2[]
--- @param points_count int
--- @param col ImU32
@native
function MT.ImDrawList:AddConvexPolyFilled(points, points_count, col)
if points_count < 3 or bit32.band(col, IM_COL32_A_MASK) == 0 then
return
@@ -29351,6 +29387,7 @@ function MT.ImDrawList:_SetTexture(tex_ref)
self:_OnChangedTexture()
end
@native
function MT.ImDrawList:PrimReserve(idx_count, vtx_count)
IM_ASSERT_PARANOID(idx_count >= 0 and vtx_count >= 0)
@@ -29387,6 +29424,7 @@ end
--- @param a ImVec2
--- @param c ImVec2
--- @param col ImU32
@native
function MT.ImDrawList:PrimRect(a, c, col)
local uv = self._Data.TexUvWhitePixel
@@ -29469,6 +29507,7 @@ end
--- @param col ImU32
--- @param thickness float
--- @param flags? ImDrawFlags
@native
function MT.ImDrawList:AddPolyline(points, points_count, col, thickness, flags)
if flags == nil then flags = 0 end
@@ -29729,6 +29768,7 @@ function MT.ImDrawList:PathRect(a, b, rounding, flags)
end
end
@native
function MT.ImDrawList:AddRectFilled(p_min, p_max, col, rounding, flags)
if not rounding then rounding = 0.0 end
if not flags then flags = 0 end
@@ -29771,6 +29811,7 @@ end
--- @param rounding float
--- @param thickness? float
--- @param flags? ImDrawFlags
@native
function MT.ImDrawList:AddRect(p_min, p_max, col, rounding, thickness, flags)
if thickness == nil then thickness = 1.0 end
if flags == nil then flags = 0 end
@@ -29946,6 +29987,7 @@ end
--- @param text_end int
--- @param wrap_width float
--- @param cpu_fine_clip_rect? ImVec4
@native
function MT.ImDrawList:AddText(font, font_size, pos, col, text, text_begin, text_end, wrap_width, cpu_fine_clip_rect)
-- Overload: AddText(pos, col, text, text_end?)
if type(font) == "table" and type(font[1]) == "number" then
@@ -30092,6 +30134,7 @@ end
--- @param a_min_sample int
--- @param a_max_sample int
--- @param a_step int
@native
function MT.ImDrawList:_PathArcToFastEx(center, radius, a_min_sample, a_max_sample, a_step)
if radius < 0.5 then
self._Path:push_back(center)
@@ -30180,6 +30223,7 @@ function MT.ImDrawList:_PathArcToFastEx(center, radius, a_min_sample, a_max_samp
IM_ASSERT_PARANOID(self._Path.Size == out_ptr - 1)
end
@native
function MT.ImDrawList:PathArcToFast(center, radius, a_min_of_12, a_max_of_12)
if radius < 0.5 then
self._Path:push_back(center)
@@ -30267,6 +30311,7 @@ end
--- @param text_end int
--- @param wrap_width? float
--- @param flags? ImDrawTextFlags
@native
function MT.ImFont:RenderText(draw_list, size, pos, col, clip_rect, text, text_begin, text_end, wrap_width, flags)
if wrap_width == nil then wrap_width = .0 end
if flags == nil then flags = 0 end
@@ -30477,31 +30522,35 @@ end
--- @param color ImU32
--- @param dir ImGuiDir
--- @param scale? float
local arrow_a, arrow_b, arrow_c = ImVec2(), ImVec2(), ImVec2() -- scratch: the path is consumed by AddTriangleFilled before returning
function ImGui.RenderArrow(draw_list, pos, color, dir, scale)
if scale == nil then scale = 1.0 end
local h = draw_list._Data.FontSize * 1.00
local r = h * 0.40 * scale
local center = pos + ImVec2(h * 0.50, h * 0.50 * scale)
local a, b, c
local cx, cy = pos.x + h * 0.50, pos.y + h * 0.50 * scale
local ax, ay, bx, by, qx, qy
if dir == ImGuiDir.Up or dir == ImGuiDir.Down then
if dir == ImGuiDir.Up then r = -r end
a = ImVec2( 0.000, 0.750) * r
b = ImVec2(-0.866, -0.750) * r
c = ImVec2( 0.866, -0.750) * r
ax, ay = 0.000 * r, 0.750 * r
bx, by = -0.866 * r, -0.750 * r
qx, qy = 0.866 * r, -0.750 * r
elseif dir == ImGuiDir.Left or dir == ImGuiDir.Right then
if dir == ImGuiDir.Left then r = -r end
a = ImVec2( 0.750, 0.000) * r
b = ImVec2(-0.750, 0.866) * r
c = ImVec2(-0.750, -0.866) * r
elseif dir == ImGuiDir.None or dir == ImGuiDir.COUNT then
ax, ay = 0.750 * r, 0.000 * r
bx, by = -0.750 * r, 0.866 * r
qx, qy = -0.750 * r, -0.866 * r
else
IM_ASSERT(false)
end
draw_list:AddTriangleFilled(center + a, center + b, center + c, color)
arrow_a.x, arrow_a.y = cx + ax, cy + ay
arrow_b.x, arrow_b.y = cx + bx, cy + by
arrow_c.x, arrow_c.y = cx + qx, cy + qy
draw_list:AddTriangleFilled(arrow_a, arrow_b, arrow_c, color)
end
--- @param draw_list ImDrawList
@@ -31151,16 +31200,21 @@ end
--- @param y? number
--- @return ImVec2
--- @nodiscard
@native
function ImVec2(x, y) return setmetatable({ x = x or 0, y = y or 0 }, IM_VEC2) end
@native
function IM_VEC2.__add(lhs, rhs) return setmetatable({ x = lhs.x + rhs.x, y = lhs.y + rhs.y }, IM_VEC2) end
@native
function IM_VEC2.__sub(lhs, rhs) return setmetatable({ x = lhs.x - rhs.x, y = lhs.y - rhs.y }, IM_VEC2) end
@native
function IM_VEC2.__mul(lhs, rhs)
if type(rhs) == "number" then return setmetatable({ x = lhs.x * rhs, y = lhs.y * rhs }, IM_VEC2) end
return setmetatable({ x = lhs.x * rhs.x, y = lhs.y * rhs.y }, IM_VEC2)
end
@native
function IM_VEC2.__div(lhs, rhs)
if type(rhs) == "number" then return setmetatable({ x = lhs.x / rhs, y = lhs.y / rhs }, IM_VEC2) end
return setmetatable({ x = lhs.x / rhs.x, y = lhs.y / rhs.y }, IM_VEC2)
@@ -31172,6 +31226,7 @@ function IM_VEC2:__tostring() return string.format("ImVec2(%g, %g)", self.x, sel
--- @param dest ImVec2
--- @param src ImVec2
@native
function ImVec2_Copy(dest, src) dest.x = src.x; dest.y = src.y end
function ImVec2_CopyV(dest, src_x, src_y) dest.x = src_x; dest.y = src_y end
@@ -31210,6 +31265,7 @@ end
--- @return ImVec4
--- @nodiscard
@native
function ImVec4(x, y, z, w) return setmetatable({ x = x or 0, y = y or 0, z = z or 0, w = w or 0 }, IM_VEC4) end
function IM_VEC4.__add(lhs, rhs) return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w) end
@@ -31221,6 +31277,7 @@ function IM_VEC4:__tostring() return string.format("ImVec4(%g, %g, %g, %g)", sel
--- @param dest ImVec4
--- @param src ImVec4
@native
function ImVec4_Copy(dest, src) dest.x = src.x; dest.y = src.y; dest.z = src.z; dest.w = src.w end
--- A compact ImVector clone
@@ -40462,6 +40519,7 @@ end
--- @overload fun(lhs: number, rhs: number): number
--- @overload fun(lhs: ImVec2, rhs: ImVec2): ImVec2
@native
function ImMin(lhs, rhs)
if type(lhs) == "number" then return mathMin(lhs, rhs) end
return ImVec2(mathMin(lhs.x, rhs.x), mathMin(lhs.y, rhs.y))
@@ -40469,6 +40527,7 @@ end
--- @overload fun(lhs: number, rhs: number): number
--- @overload fun(lhs: ImVec2, rhs: ImVec2): ImVec2
@native
function ImMax(lhs, rhs)
if type(lhs) == "number" then return mathMax(lhs, rhs) end
return ImVec2(mathMax(lhs.x, rhs.x), mathMax(lhs.y, rhs.y))
@@ -40481,6 +40540,7 @@ ImStd.ImQsort = function(base, count, cmp_func) if count > 0 then t_sort(base, c
--- @overload fun(v: number, mn: number, mx: number): number
--- @overload fun(v: ImVec2, mn: ImVec2, mx: ImVec2): ImVec2
@native
function ImClamp(v, mn, mx)
if type(v) == "number" and type(mn) == "number" and type(mx) == "number" then return mathMin(mathMax(v, mn), mx)
elseif type(v) == "table" and type(mn) == "table" and type(mx) == "table" then return ImVec2(mathMax(mn.x, mathMin(v.x, mx.x)), mathMax(mn.y, mathMin(v.y, mx.y)))
@@ -40490,6 +40550,7 @@ end
--- @overload fun(a: number, b: number, t: number): number
--- @overload fun(a: ImVec2, b: ImVec2, t: number): ImVec2
--- @overload fun(a: ImVec2, b: ImVec2, t: ImVec2): ImVec2
@native
function ImLerp(a, b, t)
if type(a) == "number" and type(b) == "number" and type(t) == "number" then return ((a) + ((b) - (a)) * (t))
elseif type(a) == "table" and type(b) == "table" and type(t) == "number" then return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t)
@@ -41004,12 +41065,14 @@ IM_RECT.__newindex = function(t, k, v) IM_ASSERT(false, "ImRect: unknown field "
--- @return ImRect
--- @nodiscard
@native
function ImRect(a, b, c, d) if c and d then return setmetatable({ Min = ImVec2(a, b), Max = ImVec2(c, d) }, IM_RECT) end return setmetatable({ Min = ImVec2(a and a.x or 0, a and a.y or 0), Max = ImVec2(b and b.x or 0, b and b.y or 0) }, IM_RECT) end
function IM_RECT:__eq(other) return self.Min == other.Min and self.Max == other.Max end
function IM_RECT:__tostring() return string.format("ImRect(Min: %g,%g, Max: %g,%g)", self.Min.x, self.Min.y, self.Max.x, self.Max.y) end
--- @param p ImRect|ImVec2
@native
function IM_RECT:Contains(p)
if p.Min then
--- @cast p ImRect
@@ -41027,6 +41090,7 @@ function IM_RECT:ContainsWithPad(p, pad)
end
--- @param r ImRect
@native
function IM_RECT:Overlaps(r)
return self.Min.x <= r.Max.x and self.Max.x >= r.Min.x and self.Min.y <= r.Max.y and self.Max.y >= r.Min.y
end
@@ -41036,6 +41100,7 @@ function IM_RECT:GetCenter() return ImVec2((self.Min.x + self.Max.x) * 0.5, (sel
function IM_RECT:GetWidth() return self.Max.x - self.Min.x end
function IM_RECT:GetHeight() return self.Max.y - self.Min.y end
--- @nodiscard
@native
function IM_RECT:GetSize() return ImVec2(self.Max.x - self.Min.x, self.Max.y - self.Min.y) end
--- @nodiscard
@@ -41048,16 +41113,19 @@ function IM_RECT:GetBL() return ImVec2(self.Min.x, self.Max.y) end
function IM_RECT:GetBR() return ImVec2(self.Max.x, self.Max.y) end
--- @param r ImRect
@native
function IM_RECT:ClipWith(r)
ImVec2_Copy(self.Min, ImMax(self.Min, r.Min)); ImVec2_Copy(self.Max, ImMin(self.Max, r.Max))
end
--- @param r ImRect
@native
function IM_RECT:ClipWithFull(r)
ImVec2_Copy(self.Min, ImClamp(self.Min, r.Min, r.Max)); ImVec2_Copy(self.Max, ImClamp(self.Max, r.Min, r.Max))
end
--- @param p ImRect|ImVec2
@native
function IM_RECT:Add(p)
if p.Min then
--- @cast p ImRect
@@ -41075,6 +41143,7 @@ function IM_RECT:Add(p)
end
--- @param amount float|ImVec2
@native
function IM_RECT:Expand(amount)
if type(amount) == "number" then
self.Min.x = self.Min.x - amount; self.Min.y = self.Min.y - amount
@@ -41091,6 +41160,7 @@ function IM_RECT:ToVec4()
end
--- @param d ImVec2
@native
function IM_RECT:Translate(d)
self.Min.x = self.Min.x + d.x; self.Min.y = self.Min.y + d.y
self.Max.x = self.Max.x + d.x; self.Max.y = self.Max.y + d.y
@@ -41115,6 +41185,7 @@ function IM_RECT:AsVec4() return ImVec4(self.Min.x, self.Min.y, self.Max.x, self
--- @param dest ImRect
--- @param src ImRect
@native
function ImRect_Copy(dest, src)
dest.Min.x = src.Min.x; dest.Min.y = src.Min.y
dest.Max.x = src.Max.x; dest.Max.y = src.Max.y
@@ -41179,6 +41250,7 @@ end
function MT.ImDrawList:PathClear() self._Path:clear() end
--- @param pos ImVec2
@native
function MT.ImDrawList:PathLineTo(pos) self._Path:push_back(pos) end
function MT.ImDrawList:PathLineToMergeDuplicate(pos)
@@ -41188,6 +41260,7 @@ function MT.ImDrawList:PathLineToMergeDuplicate(pos)
end
end
@native
function MT.ImDrawList:PathFillConvex(col)
self:AddConvexPolyFilled(self._Path.Data, self._Path.Size, col)
self._Path.Size = 0
@@ -49026,6 +49099,7 @@ local IM_U32_MAX = UINT_MAX
--- @param text string
--- @param text_end? int
--- @param flags? ImGuiTextFlags
@native
function ImGui.TextEx(text, text_end, flags)
if not flags then flags = 0 end
@@ -49136,6 +49210,7 @@ end
--- @param fmt string
--- @param ... any
@native
function ImGui.TextV(fmt, ...)
local window = ImGui.GetCurrentWindow()
if window.SkipItems then
@@ -49148,6 +49223,7 @@ end
--- @param fmt string
--- @param ... any
@native
function ImGui.Text(fmt, ...)
if select('#', ...) > 0 then
ImGui.TextV(fmt, ...)
@@ -49322,6 +49398,7 @@ end
--- @param bb ImRect
--- @param id ImGuiID
--- @param flags? ImGuiButtonFlags
@native
function ImGui.ButtonBehavior(bb, id, flags)
if flags == nil then flags = 0 end
@@ -49564,6 +49641,7 @@ end
--- @param size_arg? ImVec2
--- @param flags? ImGuiButtonFlags
--- @return bool
@native
function ImGui.ButtonEx(label, size_arg, flags)
if size_arg == nil then size_arg = ImVec2(0, 0) end
if flags == nil then flags = 0 end
@@ -50100,6 +50178,7 @@ end
--- @param v bool
--- @return bool is_pressed
--- @return bool is_checked # The updated `v` passed in
@native
function ImGui.Checkbox(label, v)
local window = ImGui.GetCurrentWindow()
if window.SkipItems then
@@ -55838,6 +55917,7 @@ end
-- Overloads: TreeNode(label) / TreeNode(str_id, fmt, ...)
--- @param label string
@native
function ImGui.TreeNode(label, fmt, ...)
if fmt ~= nil then
return ImGui.TreeNodeEx(label, 0, fmt, ...)
@@ -55959,6 +56039,7 @@ end
--- @param flags ImGuiTreeNodeFlags
--- @param label string
--- @param label_end? int
@native
function ImGui.TreeNodeBehavior(id, flags, label, label_end)
local window = ImGui.GetCurrentWindow()
if window.SkipItems then
@@ -56372,6 +56453,7 @@ end
-- Overloads: CollapsingHeader(label, flags?) -> is_open
-- CollapsingHeader(label, p_visible: bool, flags?) -> is_open, p_visible
--- @param label string
@native
function ImGui.CollapsingHeader(label, a, b)
local p_visible, flags
if type(a) == "boolean" then p_visible, flags = a, b else flags = a end
@@ -56426,6 +56508,7 @@ end
--- @param size_arg? any
--- @return bool is_pressed
--- @return bool is_selected # Updated `selected`
@native
function ImGui.Selectable(label, selected, flags, size_arg)
if selected == nil then selected = false end
if flags == nil then flags = 0 end