Perf: ColorEdit4 layout-only fast path for fully clipped rows, cached drag/slider value text, @native on color/group widgets; t_widget_cost + t_colors_hash
This commit is contained in:
@@ -1 +1 @@
|
||||
[[12, "imgui.lua"], [13799, "imgui_demo.lua"], [14732, "imgui_demo_2.lua"], [17807, "imgui_demo_apps.lua"], [19066, "imgui_demo_tools.lua"], [20392, "imgui_demo_widgets.lua"], [22316, "imgui_docking.lua"], [25444, "imgui_dragdrop.lua"], [25736, "imgui_draw.lua"], [30974, "imgui_h.lua"], [33172, "imgui_impl_roblox.lua"], [34298, "imgui_impl_roblox_fonts.lua"], [40701, "imgui_internal.lua"], [43873, "imgui_tables.lua"], [48220, "imgui_tabs.lua"], [49387, "imgui_widgets.lua"], [57921, "imstb_rectpack.lua"], [58367, "imstb_textedit.lua"], [59608, "imstb_truetype.lua"], [62076, "imstd_minstdio.lua"]]
|
||||
[[12, "imgui.lua"], [13808, "imgui_demo.lua"], [14741, "imgui_demo_2.lua"], [17816, "imgui_demo_apps.lua"], [19075, "imgui_demo_tools.lua"], [20401, "imgui_demo_widgets.lua"], [22325, "imgui_docking.lua"], [25453, "imgui_dragdrop.lua"], [25745, "imgui_draw.lua"], [30983, "imgui_h.lua"], [33181, "imgui_impl_roblox.lua"], [34307, "imgui_impl_roblox_fonts.lua"], [40710, "imgui_internal.lua"], [43882, "imgui_tables.lua"], [48229, "imgui_tabs.lua"], [49396, "imgui_widgets.lua"], [57971, "imstb_rectpack.lua"], [58417, "imstb_textedit.lua"], [59658, "imstb_truetype.lua"], [62126, "imstd_minstdio.lua"]]
|
||||
+53
-2
@@ -2004,6 +2004,7 @@ end
|
||||
-- Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
|
||||
-- Groups are currently a mishmash of functionalities which should perhaps be clarified and separated.
|
||||
-- FIXME-OPT: Could we safely early out on ->SkipItems?
|
||||
@native
|
||||
function ImGui.BeginGroup()
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -2035,6 +2036,7 @@ function ImGui.BeginGroup()
|
||||
end
|
||||
end
|
||||
|
||||
@native
|
||||
function ImGui.EndGroup()
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -3909,6 +3911,7 @@ end
|
||||
--- @param button ImGuiMouseButton
|
||||
--- @param flags ImGuiInputFlags
|
||||
--- @param owner_id? ImGuiID
|
||||
@native
|
||||
function ImGui.IsMouseClickedEx(button, flags, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
|
||||
@@ -5126,6 +5129,7 @@ end
|
||||
--- @param p_min ImVec2
|
||||
--- @param p_max ImVec2
|
||||
--- @param rounding float
|
||||
@native
|
||||
function ImGui.RenderFrameBorder(p_min, p_max, rounding)
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -7986,6 +7990,7 @@ function ImGui.GetCurrentWindowRead()
|
||||
end
|
||||
|
||||
--- @return ImGuiWindow
|
||||
@native
|
||||
function ImGui.GetCurrentWindow()
|
||||
local g = GImGui
|
||||
g.CurrentWindow.WriteAccessed = true
|
||||
@@ -8707,6 +8712,7 @@ end
|
||||
--- @param g float
|
||||
--- @param b float
|
||||
--- @return float, float, float
|
||||
@native
|
||||
function ImGui.ColorConvertRGBtoHSV(r, g, b)
|
||||
local K = 0.0
|
||||
if g < b then
|
||||
@@ -8729,6 +8735,7 @@ end
|
||||
--- @param s float
|
||||
--- @param v float
|
||||
--- @return float, float, float
|
||||
@native
|
||||
function ImGui.ColorConvertHSVtoRGB(h, s, v)
|
||||
if s == 0.0 then
|
||||
-- gray
|
||||
@@ -10009,6 +10016,7 @@ end
|
||||
|
||||
--- @param popup_flags ImGuiPopupFlags
|
||||
--- @param id ImGuiID
|
||||
@native
|
||||
function ImGui.IsPopupOpenRequestForItem(popup_flags, id)
|
||||
local g = GImGui
|
||||
local mouse_button = ImGui.GetMouseButtonFromPopupFlags(popup_flags)
|
||||
@@ -10023,6 +10031,7 @@ end
|
||||
|
||||
--- @param str_id? string
|
||||
--- @param popup_flags? ImGuiPopupFlags
|
||||
@native
|
||||
function ImGui.OpenPopupOnItemClick(str_id, popup_flags)
|
||||
if popup_flags == nil then popup_flags = 0 end
|
||||
|
||||
@@ -52376,6 +52385,7 @@ end
|
||||
--- @param max number
|
||||
--- @param format string
|
||||
--- @param flags ImGuiSliderFlags
|
||||
@native
|
||||
function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags)
|
||||
IM_ASSERT((flags == 1 or bit32.band(flags, ImGuiSliderFlags.InvalidMask_) == 0), "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.")
|
||||
|
||||
@@ -52444,6 +52454,22 @@ end
|
||||
--- @param max number
|
||||
--- @param format string
|
||||
--- @param flags ImGuiSliderFlags
|
||||
-- [Luau] memo of string.format(format, value) for drag/slider value text (same values are redrawn every frame).
|
||||
-- ponytail: whole-memo reset at 4096 entries, LRU if values churn
|
||||
local fmt_memo, fmt_memo_n = {}, 0
|
||||
local DRAG_TEXT_ALIGN = ImVec2(0.5, 0.5)
|
||||
function FormatCached(format, v)
|
||||
local m = fmt_memo[format]
|
||||
if m == nil then m = {}; fmt_memo[format] = m end
|
||||
local r = m[v]
|
||||
if r == nil then
|
||||
if fmt_memo_n >= 4096 then table.clear(fmt_memo); m = {}; fmt_memo[format] = m; fmt_memo_n = 0 end
|
||||
r = ImFormatString(format, v); m[v] = r; fmt_memo_n += 1
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
@native
|
||||
function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, flags)
|
||||
if v_speed == nil then v_speed = 1.0 end
|
||||
if flags == nil then flags = 0 end
|
||||
@@ -52537,7 +52563,7 @@ function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, fla
|
||||
-- TODO: ImGui.DataTypeFormatString() should be used here instead of ImFormatString()
|
||||
|
||||
-- Display value using user-provided display format so user can add prefix/suffix/decorations to the value
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, ImFormatString(format, data), nil, nil, ImVec2(0.5, 0.5))
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN)
|
||||
|
||||
if label_size.x > 0.0 then
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
@@ -52570,6 +52596,7 @@ end
|
||||
--- @param v_max? int
|
||||
--- @param format? string
|
||||
--- @param flags? ImGuiSliderFlags
|
||||
@native
|
||||
function ImGui.DragInt(label, v, v_speed, v_min, v_max, format, flags)
|
||||
if v_speed == nil then v_speed = 1.0 end
|
||||
if v_min == nil then v_min = 0 end
|
||||
@@ -53159,7 +53186,7 @@ function ImGui.SliderScalar(label, data_type, data, min, max, format, flags)
|
||||
-- if g.LogEnabled then
|
||||
-- ImGui.LogSetNextTextDecoration("{", "}")
|
||||
-- end
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, ImFormatString(format, data), nil, nil, ImVec2(0.5, 0.5))
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN)
|
||||
|
||||
if label_size.x > 0.0 then
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
@@ -55231,6 +55258,7 @@ local fmt_table_float = {
|
||||
--- @param label string
|
||||
--- @param col float[]
|
||||
--- @param flags ImGuiColorEditFlags
|
||||
@native
|
||||
function ImGui.ColorEdit4(label, col, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
@@ -55245,6 +55273,27 @@ function ImGui.ColorEdit4(label, col, flags)
|
||||
local w_full = ImGui.CalcItemWidth()
|
||||
g.NextItemData:ClearFlags()
|
||||
|
||||
-- [Luau] Fast path for a row that is entirely clipped (e.g. long lists such as Style Editor > Colors): nothing
|
||||
-- inside would draw, be hovered or receive input, so only reproduce the layout (same group size, baseline and
|
||||
-- last item rect as the full path). Not taken while anything could depend on the inner items: an active item
|
||||
-- or popup, keyboard navigation, logging, or the ID debug hook.
|
||||
if label_display_end == 1 and bit32.band(flags, bit32.bor(ImGuiColorEditFlags.NoInputs, ImGuiColorEditFlags.NoSmallPreview)) == 0
|
||||
and g.ActiveId == 0 and g.OpenPopupStack.Size == 0 and not g.NavCursorVisible and not g.NavAnyRequest
|
||||
and not g.LogEnabled and g.DebugHookIdInfoId == 0 then
|
||||
local w_button = square_sz + style.ItemInnerSpacing.x
|
||||
local w = ImMax(w_full - w_button, 1.0) + w_button
|
||||
local p = window.DC.CursorPos
|
||||
local cr = window.ClipRect
|
||||
if p.y + square_sz < cr.Min.y or p.y > cr.Max.y or p.x + w < cr.Min.x or p.x > cr.Max.x then
|
||||
ImGui.BeginGroup()
|
||||
local bb = ImRect(p.x, p.y, p.x + w, p.y + square_sz)
|
||||
ImGui.ItemSize(ImVec2(w, square_sz), style.FramePadding.y)
|
||||
ImGui.ItemAdd(bb, 0)
|
||||
ImGui.EndGroup()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
ImGui.BeginGroup()
|
||||
ImGui.PushID(label)
|
||||
local set_current_color_edit_id = (g.ColorEditCurrentID == 0)
|
||||
@@ -55956,6 +56005,7 @@ end
|
||||
--- @param col ImVec4
|
||||
--- @param flags? ImGuiColorEditFlags
|
||||
--- @param size_arg? ImVec2
|
||||
@native
|
||||
function ImGui.ColorButton(desc_id, col, flags, size_arg)
|
||||
if flags == nil then flags = 0 end
|
||||
if size_arg == nil then size_arg = ImVec2(0, 0) end
|
||||
@@ -62370,6 +62420,7 @@ return {
|
||||
FLT_MIN = FLT_MIN,
|
||||
FONT_ATLAS_DEFAULT_TEX_DATA_H = FONT_ATLAS_DEFAULT_TEX_DATA_H,
|
||||
FONT_ATLAS_DEFAULT_TEX_DATA_W = FONT_ATLAS_DEFAULT_TEX_DATA_W,
|
||||
FormatCached = FormatCached,
|
||||
GetDefaultFontDataProggyClean = GetDefaultFontDataProggyClean,
|
||||
GetDefaultFontDataProggyForever = GetDefaultFontDataProggyForever,
|
||||
GetMinimumStepAtDecimalPrecision = GetMinimumStepAtDecimalPrecision,
|
||||
|
||||
@@ -1993,6 +1993,7 @@ end
|
||||
-- Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
|
||||
-- Groups are currently a mishmash of functionalities which should perhaps be clarified and separated.
|
||||
-- FIXME-OPT: Could we safely early out on ->SkipItems?
|
||||
@native
|
||||
function ImGui.BeginGroup()
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -2024,6 +2025,7 @@ function ImGui.BeginGroup()
|
||||
end
|
||||
end
|
||||
|
||||
@native
|
||||
function ImGui.EndGroup()
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -3898,6 +3900,7 @@ end
|
||||
--- @param button ImGuiMouseButton
|
||||
--- @param flags ImGuiInputFlags
|
||||
--- @param owner_id? ImGuiID
|
||||
@native
|
||||
function ImGui.IsMouseClickedEx(button, flags, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
|
||||
@@ -5115,6 +5118,7 @@ end
|
||||
--- @param p_min ImVec2
|
||||
--- @param p_max ImVec2
|
||||
--- @param rounding float
|
||||
@native
|
||||
function ImGui.RenderFrameBorder(p_min, p_max, rounding)
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
@@ -7975,6 +7979,7 @@ function ImGui.GetCurrentWindowRead()
|
||||
end
|
||||
|
||||
--- @return ImGuiWindow
|
||||
@native
|
||||
function ImGui.GetCurrentWindow()
|
||||
local g = GImGui
|
||||
g.CurrentWindow.WriteAccessed = true
|
||||
@@ -8696,6 +8701,7 @@ end
|
||||
--- @param g float
|
||||
--- @param b float
|
||||
--- @return float, float, float
|
||||
@native
|
||||
function ImGui.ColorConvertRGBtoHSV(r, g, b)
|
||||
local K = 0.0
|
||||
if g < b then
|
||||
@@ -8718,6 +8724,7 @@ end
|
||||
--- @param s float
|
||||
--- @param v float
|
||||
--- @return float, float, float
|
||||
@native
|
||||
function ImGui.ColorConvertHSVtoRGB(h, s, v)
|
||||
if s == 0.0 then
|
||||
-- gray
|
||||
@@ -9998,6 +10005,7 @@ end
|
||||
|
||||
--- @param popup_flags ImGuiPopupFlags
|
||||
--- @param id ImGuiID
|
||||
@native
|
||||
function ImGui.IsPopupOpenRequestForItem(popup_flags, id)
|
||||
local g = GImGui
|
||||
local mouse_button = ImGui.GetMouseButtonFromPopupFlags(popup_flags)
|
||||
@@ -10012,6 +10020,7 @@ end
|
||||
|
||||
--- @param str_id? string
|
||||
--- @param popup_flags? ImGuiPopupFlags
|
||||
@native
|
||||
function ImGui.OpenPopupOnItemClick(str_id, popup_flags)
|
||||
if popup_flags == nil then popup_flags = 0 end
|
||||
|
||||
|
||||
+43
-2
@@ -2990,6 +2990,7 @@ end
|
||||
--- @param max number
|
||||
--- @param format string
|
||||
--- @param flags ImGuiSliderFlags
|
||||
@native
|
||||
function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags)
|
||||
IM_ASSERT((flags == 1 or bit32.band(flags, ImGuiSliderFlags.InvalidMask_) == 0), "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.")
|
||||
|
||||
@@ -3058,6 +3059,22 @@ end
|
||||
--- @param max number
|
||||
--- @param format string
|
||||
--- @param flags ImGuiSliderFlags
|
||||
-- [Luau] memo of string.format(format, value) for drag/slider value text (same values are redrawn every frame).
|
||||
-- ponytail: whole-memo reset at 4096 entries, LRU if values churn
|
||||
local fmt_memo, fmt_memo_n = {}, 0
|
||||
local DRAG_TEXT_ALIGN = ImVec2(0.5, 0.5)
|
||||
function FormatCached(format, v)
|
||||
local m = fmt_memo[format]
|
||||
if m == nil then m = {}; fmt_memo[format] = m end
|
||||
local r = m[v]
|
||||
if r == nil then
|
||||
if fmt_memo_n >= 4096 then table.clear(fmt_memo); m = {}; fmt_memo[format] = m; fmt_memo_n = 0 end
|
||||
r = ImFormatString(format, v); m[v] = r; fmt_memo_n += 1
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
@native
|
||||
function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, flags)
|
||||
if v_speed == nil then v_speed = 1.0 end
|
||||
if flags == nil then flags = 0 end
|
||||
@@ -3151,7 +3168,7 @@ function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, fla
|
||||
-- TODO: ImGui.DataTypeFormatString() should be used here instead of ImFormatString()
|
||||
|
||||
-- Display value using user-provided display format so user can add prefix/suffix/decorations to the value
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, ImFormatString(format, data), nil, nil, ImVec2(0.5, 0.5))
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN)
|
||||
|
||||
if label_size.x > 0.0 then
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
@@ -3184,6 +3201,7 @@ end
|
||||
--- @param v_max? int
|
||||
--- @param format? string
|
||||
--- @param flags? ImGuiSliderFlags
|
||||
@native
|
||||
function ImGui.DragInt(label, v, v_speed, v_min, v_max, format, flags)
|
||||
if v_speed == nil then v_speed = 1.0 end
|
||||
if v_min == nil then v_min = 0 end
|
||||
@@ -3773,7 +3791,7 @@ function ImGui.SliderScalar(label, data_type, data, min, max, format, flags)
|
||||
-- if g.LogEnabled then
|
||||
-- ImGui.LogSetNextTextDecoration("{", "}")
|
||||
-- end
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, ImFormatString(format, data), nil, nil, ImVec2(0.5, 0.5))
|
||||
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN)
|
||||
|
||||
if label_size.x > 0.0 then
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
@@ -5845,6 +5863,7 @@ local fmt_table_float = {
|
||||
--- @param label string
|
||||
--- @param col float[]
|
||||
--- @param flags ImGuiColorEditFlags
|
||||
@native
|
||||
function ImGui.ColorEdit4(label, col, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
@@ -5859,6 +5878,27 @@ function ImGui.ColorEdit4(label, col, flags)
|
||||
local w_full = ImGui.CalcItemWidth()
|
||||
g.NextItemData:ClearFlags()
|
||||
|
||||
-- [Luau] Fast path for a row that is entirely clipped (e.g. long lists such as Style Editor > Colors): nothing
|
||||
-- inside would draw, be hovered or receive input, so only reproduce the layout (same group size, baseline and
|
||||
-- last item rect as the full path). Not taken while anything could depend on the inner items: an active item
|
||||
-- or popup, keyboard navigation, logging, or the ID debug hook.
|
||||
if label_display_end == 1 and bit32.band(flags, bit32.bor(ImGuiColorEditFlags.NoInputs, ImGuiColorEditFlags.NoSmallPreview)) == 0
|
||||
and g.ActiveId == 0 and g.OpenPopupStack.Size == 0 and not g.NavCursorVisible and not g.NavAnyRequest
|
||||
and not g.LogEnabled and g.DebugHookIdInfoId == 0 then
|
||||
local w_button = square_sz + style.ItemInnerSpacing.x
|
||||
local w = ImMax(w_full - w_button, 1.0) + w_button
|
||||
local p = window.DC.CursorPos
|
||||
local cr = window.ClipRect
|
||||
if p.y + square_sz < cr.Min.y or p.y > cr.Max.y or p.x + w < cr.Min.x or p.x > cr.Max.x then
|
||||
ImGui.BeginGroup()
|
||||
local bb = ImRect(p.x, p.y, p.x + w, p.y + square_sz)
|
||||
ImGui.ItemSize(ImVec2(w, square_sz), style.FramePadding.y)
|
||||
ImGui.ItemAdd(bb, 0)
|
||||
ImGui.EndGroup()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
ImGui.BeginGroup()
|
||||
ImGui.PushID(label)
|
||||
local set_current_color_edit_id = (g.ColorEditCurrentID == 0)
|
||||
@@ -6570,6 +6610,7 @@ end
|
||||
--- @param col ImVec4
|
||||
--- @param flags? ImGuiColorEditFlags
|
||||
--- @param size_arg? ImVec2
|
||||
@native
|
||||
function ImGui.ColorButton(desc_id, col, flags, size_arg)
|
||||
if flags == nil then flags = 0 end
|
||||
if size_arg == nil then size_arg = ImVec2(0, 0) end
|
||||
|
||||
@@ -160,7 +160,7 @@ ROBLOX = setmetatable({
|
||||
Color3 = { new = function(r, g, b) return { R = r or 0, G = g or 0, B = b or 0 } end },
|
||||
Content = { fromObject = function(o) return { Object = o } end },
|
||||
warn = function(...) print("WARN", ...) end,
|
||||
os = { clock = function() return FAKE_TIME end, time = os.time },
|
||||
os = { clock = function() return FAKE_TIME end, time = os.time, realclock = os.clock },
|
||||
}, { __index = realG })
|
||||
|
||||
local mod = newInst("ModuleScript", "ImGui", ReplicatedStorage); rawset(mod, "_src", "ImGui.luau")
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
-- Checksum of draw data + layout of Style Editor > Colors while scrolling its list (fast-path equivalence check)
|
||||
local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui"))
|
||||
local ImGui, ImVec2 = G.ImGui, G.ImVec2
|
||||
ImGui.CreateContext()
|
||||
G.ImGui_ImplRoblox.Init()
|
||||
local io = ImGui.GetIO()
|
||||
local realBTI = ImGui.BeginTabItem
|
||||
ImGui.BeginTabItem = function(label, p_open, flags)
|
||||
if label == "Colors" then flags = bit32.bor(flags or 0, G.ImGuiTabItemFlags.SetSelected) end
|
||||
return realBTI(label, p_open, flags)
|
||||
end
|
||||
local frame, h = 0, 0
|
||||
local function mix(v) h = (h * 31 + math.floor(v * 64 + 0.5)) % 2147483647 end
|
||||
game:GetService("RunService").Stepped:Connect(function()
|
||||
frame += 1
|
||||
G.ImGui_ImplRoblox.NewFrame()
|
||||
io.DeltaTime = 1 / 60
|
||||
io:AddMousePosEvent(200, 400 + (frame % 5) * 13)
|
||||
if frame > 5 then io:AddMouseWheelEvent(0, (frame % 60 < 35) and -1 or 1) end
|
||||
ImGui.NewFrame()
|
||||
ImGui.SetNextWindowPos(ImVec2(20, 20)); ImGui.SetNextWindowSize(ImVec2(550, 700))
|
||||
ImGui.Begin("Style Editor"); ImGui.ShowStyleEditor(); ImGui.End()
|
||||
ImGui.Render()
|
||||
for _, dl in ImGui.GetDrawData().CmdLists:iter() do
|
||||
local vb, id = dl.VtxBuffer.Buf, dl.IdxBuffer.Data
|
||||
for i = 1, dl.VtxBuffer.Size do local o = (i - 1) * 36; mix(buffer.readf64(vb, o)); mix(buffer.readf64(vb, o + 8)); mix(buffer.readu32(vb, o + 32) / 64) end
|
||||
for i = 1, dl.IdxBuffer.Size do mix(id[i]) end
|
||||
end
|
||||
for _, w in ipairs(ImGui.GetCurrentContext().Windows.Data) do mix(w.ContentSize.x); mix(w.ContentSize.y); mix(w.Scroll.y); mix(w.ScrollMax.y) end
|
||||
G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
|
||||
if frame == ARG_FRAMES - 1 then print("COLORSHASH", h) end
|
||||
end)
|
||||
@@ -0,0 +1,71 @@
|
||||
-- Per-widget cost: wraps every ImGui.* function with self-time timing, shows the Style Editor on its Colors tab
|
||||
-- (or the demo with --open-only ...), prints a table sorted by total self time and by cost per call.
|
||||
local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui"))
|
||||
local ImGui, ImVec2 = G.ImGui, G.ImVec2
|
||||
ImGui.CreateContext()
|
||||
G.ImGui_ImplRoblox.Init()
|
||||
local io = ImGui.GetIO()
|
||||
local STYLE = type(ARG_OPEN) ~= "table"
|
||||
|
||||
local realBTI = ImGui.BeginTabItem
|
||||
ImGui.BeginTabItem = function(label, p_open, flags)
|
||||
if label == "Colors" and STYLE then flags = bit32.bor(flags or 0, G.ImGuiTabItemFlags.SetSelected) end
|
||||
return realBTI(label, p_open, flags)
|
||||
end
|
||||
|
||||
local self_t, calls = {}, {}
|
||||
local stack_child = {} -- time spent in nested wrapped calls, per depth
|
||||
local depth, enabled = 0, false
|
||||
local clock = os.realclock or os.clock -- harness fakes os.clock; realclock is the real one
|
||||
for name, fn in pairs(ImGui) do
|
||||
if type(fn) == "function" and name ~= "NewFrame" and name ~= "Render" and name ~= "EndFrame" then
|
||||
ImGui[name] = function(...)
|
||||
if not enabled then return fn(...) end
|
||||
depth += 1; stack_child[depth] = 0
|
||||
local t0 = clock()
|
||||
local r = table.pack(fn(...))
|
||||
local dt = clock() - t0
|
||||
local own = dt - stack_child[depth]
|
||||
depth -= 1
|
||||
if depth > 0 then stack_child[depth] += dt end
|
||||
self_t[name] = (self_t[name] or 0) + own; calls[name] = (calls[name] or 0) + 1
|
||||
return table.unpack(r, 1, r.n)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local frame = 0
|
||||
game:GetService("RunService").Stepped:Connect(function()
|
||||
frame += 1
|
||||
G.ImGui_ImplRoblox.NewFrame()
|
||||
io:AddMousePosEvent(5, 5)
|
||||
ImGui.NewFrame()
|
||||
enabled = frame > 10
|
||||
if STYLE then
|
||||
ImGui.SetNextWindowPos(ImVec2(20, 20)); ImGui.SetNextWindowSize(ImVec2(550, 900))
|
||||
ImGui.Begin("Style Editor"); ImGui.ShowStyleEditor(); ImGui.End()
|
||||
else
|
||||
ImGui.ShowDemoWindow(true)
|
||||
end
|
||||
enabled = false
|
||||
ImGui.Render()
|
||||
G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
|
||||
if frame == ARG_FRAMES - 1 then
|
||||
local nf = frame - 10
|
||||
local names = {}
|
||||
local total = 0
|
||||
for k, v in pairs(self_t) do table.insert(names, k); total += v end
|
||||
table.sort(names, function(a, b) return self_t[a] > self_t[b] end)
|
||||
print(string.format("TOTAL %.3f ms/frame (wrapped calls, incl. wrapper overhead)", total / nf * 1000))
|
||||
print("== by self time per frame")
|
||||
for i = 1, math.min(20, #names) do local k = names[i]
|
||||
print(string.format("%7.3f ms %6.1f%% %5d calls %6.1f us/call %s", self_t[k] / nf * 1000, 100 * self_t[k] / total, calls[k] / nf, self_t[k] / calls[k] * 1e6, k)) end
|
||||
table.sort(names, function(a, b) return self_t[a] / calls[a] > self_t[b] / calls[b] end)
|
||||
print("== by cost per call (>= 1 call/frame)")
|
||||
local shown = 0
|
||||
for _, k in ipairs(names) do
|
||||
if calls[k] >= nf and shown < 15 then shown += 1
|
||||
print(string.format("%6.1f us/call %5d calls %s", self_t[k] / calls[k] * 1e6, calls[k] / nf, k)) end
|
||||
end
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user