diff --git a/build/ImGui.linemap.json b/build/ImGui.linemap.json index 4fb7453..a6adc4f 100644 --- a/build/ImGui.linemap.json +++ b/build/ImGui.linemap.json @@ -1 +1 @@ -[[46, "imgui.lua"], [21466, "imgui_demo.lua"], [33318, "imgui_draw.lua"], [41521, "imgui_h.lua"], [44455, "imgui_impl_roblox.lua"], [46103, "imgui_impl_roblox_fonts.lua"], [52506, "imgui_internal.lua"], [56228, "imgui_tables.lua"], [61287, "imgui_widgets.lua"], [73263, "imstb_rectpack.lua"], [73927, "imstb_textedit.lua"], [75469, "imstb_truetype.lua"], [78257, "imstd_minstdio.lua"]] \ No newline at end of file +[[46, "imgui.lua"], [22580, "imgui_demo.lua"], [34431, "imgui_draw.lua"], [42736, "imgui_h.lua"], [45681, "imgui_impl_roblox.lua"], [47329, "imgui_impl_roblox_fonts.lua"], [53732, "imgui_internal.lua"], [57611, "imgui_tables.lua"], [62711, "imgui_widgets.lua"], [74825, "imstb_rectpack.lua"], [75489, "imstb_textedit.lua"], [77031, "imstb_truetype.lua"], [79819, "imstd_minstdio.lua"]] \ No newline at end of file diff --git a/build/ImGui.luau b/build/ImGui.luau index f3b2abd..81b6bcc 100644 --- a/build/ImGui.luau +++ b/build/ImGui.luau @@ -1,7 +1,7 @@ --!optimize 2 -- GENERATED by tools/bundle.py from *.lua, backends/, fonts/ - do not edit -local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImGuiDataType, ImStb, IM_TRUNC, ImGuiKey, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, IM_ASSERT_USER_ERROR_RET, ImHashStr, ImS32, ImGuiColorEditFlags, ImIsPowerOfTwo, ImAbs, ImVec4_Copy, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, IM_ASSERT_PARANOID, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, ImGui_ImplRoblox_GetBackendData, stbte, ImColor, ImCos, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiLocKey, ImU32, ExampleTreeFuncs, ImGuiListClipper, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImSin, ImGuiTabBarFlags, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImFabs, ImGuiCol, ImGuiSelectionBasicStorage, ImLengthSqr, ImS8, ImU8, ExampleAppPropertyEditorMT, ImGuiChildFlags, ImGuiLastItemData_Copy, ImGuiScrollFlags, ImLog, ImMemchr, ImStrByte, ExampleSelectionWithDeletionMT, IMGUI_DEBUG_LOG_VIEWPORT, ImFontCalcWordWrapPositionEx, ImGuiInputEvent, ImGuiTextBuffer, ImPow, ImTrunc64, CustomConstraints, ExampleAppLogMT, IMGUI_DEBUG_LOG_FONT, IMGUI_DEBUG_LOG_SELECTION, ImAddClampOverflow, ImFontAtlasBuildInit, ImFontAtlasFontDestroyOutput, ImGuiComboFlags, ImGuiLastItemData, ImGuiPayload_IsDataType, ImGuiPopupFlags, ImGuiSliderFlags, ImGuiTextFilter, ImRotate, ImSqrt, ImSubClampOverflow, ImTextClassifierSetCharClass, MyDocument, ShowExampleMenuFile, CalcCornerArcStepAndCount, CalcNextScrollFromScrollTargetAndClamp, IMGUI_PAYLOAD_TYPE_WINDOW, IMGUI_VERSION, ImCharIsBlankW, ImCharIsSeparatorW, ImFmod, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImFontConfig, ImGuiInputTextFlags, ImGuiNavMoveFlags, ImGuiStyle_Copy, ImHashData, ImVec1_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, ExampleTree_CreateNode, IMGUI_PAYLOAD_TYPE_COLOR_4F, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC, IM_F32_TO_INT8_UNBOUND, IM_PI, ImCharIsBlankA, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroySourceData, ImFontAtlasFontDiscardBakes, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImFontAtlasRectId_GetIndex, ImFontAtlasTextureAdd, ImFontAtlasTextureBlockQueueUpload, ImFontAtlasTextureGrow, ImFontBaked_BuildGrowIndex, ImFontGlyph, ImGuiTableColumn, ImGuiWindowClass, ImGui_ImplRoblox_RenderDrawData, ImParseFormatFindStart, ImRect_CopyFromV4, ImTextureRect, ImTextureRef, MyItem_s_current_sort_specs, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, DockSettingsHandler_ClearAll, EditTableSizingFlags, ExampleSelectionWithDeletion, IMGUI_DEBUG_LOG_TABLE, IMGUI_PAYLOAD_TYPE_COLOR_3F, IM_FREE, ImDrawListSplitter, ImFontAtlasBakedDiscard, ImFontAtlasBuildDestroy, ImFontAtlasBuildSetTexture, ImFontAtlasBuildSetupFontBakedFallback, ImFontAtlasPackDiscardRect, ImFontAtlasPackGetRectSafe +local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImStb, ImGuiDataType, IM_TRUNC, ImGuiKey, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, ImHashStr, IM_ASSERT_USER_ERROR_RET, ImIsPowerOfTwo, ImS32, ImGuiColorEditFlags, ImVec4_Copy, ImAbs, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, IM_ASSERT_PARANOID, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, ImGui_ImplRoblox_GetBackendData, stbte, ImColor, ImCos, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiListClipper, ImGuiLocKey, ImU32, ExampleTreeFuncs, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImSin, ImGuiTabBarFlags, ImLengthSqr, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImFabs, ImGuiCol, ImGuiSelectionBasicStorage, ImS8, ImU8, ExampleAppPropertyEditorMT, ImGuiChildFlags, ImGuiLastItemData_Copy, ImGuiTextBuffer, IMGUI_DEBUG_LOG_IO, ImGuiScrollFlags, ImLog, ImMemchr, ImStrByte, ExampleSelectionWithDeletionMT, IMGUI_DEBUG_LOG_VIEWPORT, ImFontCalcWordWrapPositionEx, ImGuiInputEvent, ImHashData, ImPow, ImTrunc64, CustomConstraints, ExampleAppLogMT, IMGUI_DEBUG_LOG_FONT, IMGUI_DEBUG_LOG_SELECTION, IMGUI_DISABLE_DEBUG_TOOLS, ImAddClampOverflow, ImFontAtlasBuildInit, ImFontAtlasFontDestroyOutput, ImGuiComboFlags, ImGuiLastItemData, ImGuiPayload_IsDataType, ImGuiPopupFlags, ImGuiSliderFlags, ImGuiTextFilter, ImRotate, ImSqrt, ImSubClampOverflow, ImTextClassifierSetCharClass, ImTextureRef, MyDocument, ShowExampleMenuFile, CalcCornerArcStepAndCount, CalcNextScrollFromScrollTargetAndClamp, IMGUI_PAYLOAD_TYPE_WINDOW, IMGUI_VERSION, ImCharIsBlankW, ImCharIsSeparatorW, ImFmod, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImFontConfig, ImGuiInputTextFlags, ImGuiNavMoveFlags, ImGuiStyle_Copy, ImVec1_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, ExampleTree_CreateNode, IMGUI_PAYLOAD_TYPE_COLOR_4F, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC, IM_F32_TO_INT8_UNBOUND, IM_PI, ImCharIsBlankA, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroySourceData, ImFontAtlasFontDiscardBakes, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImFontAtlasRectId_GetIndex, ImFontAtlasTextureAdd, ImFontAtlasTextureBlockQueueUpload, ImFontAtlasTextureGrow, ImFontBaked_BuildGrowIndex, ImFontGlyph, ImGuiTableColumn, ImGuiWindowClass, ImGui_ImplRoblox_RenderDrawData, ImParseFormatFindStart, ImRect_CopyFromV4, ImTextureRect, MyItem_s_current_sort_specs, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, DockSettingsHandler_ClearAll, EditTableSizingFlags, ExampleSelectionWithDeletion, IMGUI_DEBUG_LOG_TABLE, IMGUI_PAYLOAD_TYPE_COLOR_3F, IM_FREE, ImDrawCmd, ImDrawList, ImDrawListSplitter, ImDrawVtx_Pos, ImFontAtlasBakedDiscard local type, mathMin, mathMax, mathFloor, mathCeil, bitOr, bitLShift = type, math.min, math.max, math.floor, math.ceil, bit32.bor, bit32.lshift local function IM_COL32(R, G, B, A) return (bitOr(bitLShift(A, 24 --[[IM_COL32_A_SHIFT]]), bitLShift(B, 16 --[[IM_COL32_B_SHIFT]]), bitLShift(G, 8 --[[IM_COL32_G_SHIFT]]), bitLShift(R, 0 --[[IM_COL32_R_SHIFT]]))) end @native @@ -476,6 +476,15 @@ IMGUI_DISABLE_DEBUG_TOOLS = false -- Disable metrics/debugger and other debug to --- @type ImGuiContext? local GImGui = nil +-- [Luau] IM_DEBUG_BREAK() (imgui_internal.h macro): Lua can't break into a debugger. It calls the optional user hook +-- g.DebugBreakCallback(g) instead (a context field added by this port; the library can't be patched from outside the bundle). +local function IM_DEBUG_BREAK() + local g = GImGui + if g ~= nil and g.DebugBreakCallback ~= nil then + g.DebugBreakCallback(g) + end +end + ImGui = {} ImStd = {} -- Contains functions that originally don't belong to cpp namespaces @@ -522,6 +531,17 @@ function ImGui.MemFree(owner, field) return GImAllocatorFreeFunc(owner, field, GImAllocatorUserData) end +-- [Luau] g.DemoMarkerCallback (fun(file, line, section)) is not in ImGuiContext() yet: nil unless set by the user. +--- @param file string +--- @param line int +--- @param section string +function ImGui.DemoMarker(file, line, section) + local g = GImGui + if g.DemoMarkerCallback ~= nil then + g.DemoMarkerCallback(file, line, section) + end +end + -- We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames" --- @param info ImGuiDebugAllocInfo --- @param frame_count int @@ -1401,6 +1421,11 @@ function ImGui.DockContextDeleteNode(ctx, node) dc.Nodes[node.ID] = nil end +-- Pre C++0x doesn't allow us to use a function-local type (without linkage) as template parameter, so we moved this here. +local function ImGuiDockContextPruneNodeData() + return { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 } +end + -- Garbage collect unused nodes (run once at init time) function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local g = ctx @@ -1410,7 +1435,7 @@ function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local pool = {} local function GetOrAdd(id) local d = pool[id] - if not d then d = { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 }; pool[id] = d end + if not d then d = ImGuiDockContextPruneNodeData(); pool[id] = d end return d end @@ -1980,6 +2005,10 @@ function ImGui.DockNodeHideHostWindow(node) if node.TabBar then ImGui.DockNodeRemoveTabBar(node) end end +local function ImGuiDockNodeTreeInfo() + return { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } +end + -- Search function called once by root node in DockNodeUpdate() local function DockNodeFindInfo(node, info) if node.Windows.Size > 0 then @@ -2120,7 +2149,7 @@ function ImGui.DockNodeUpdateForRootNode(node) -- - Setup central node pointers -- - Find if there's only a single visible window in the hierarchy (in which case we need to display a regular title bar -> FIXME-DOCK: that last part is not done yet!) -- Cannot merge this with DockNodeUpdateFlagsAndCollapse() because FirstNodeWithWindows is found after window removal and child collapsing - local info = { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } + local info = ImGuiDockNodeTreeInfo() DockNodeFindInfo(node, info) node.CentralNode = info.CentralNode node.OnlyNodeWithWindows = (info.CountNodesWithWindows == 1) and info.FirstNodeWithWindows or nil @@ -3765,6 +3794,12 @@ function ImGui.DockBuilderRemoveNode(node_id) ImGui.DockContextRemoveNode(g, node, true) end +--- @param a ImGuiDockNode +--- @param b ImGuiDockNode +local function DockNodeComparerDepthMostFirst(a, b) -- [Luau] table.sort() "less than" predicate + return ImGui.DockNodeGetDepth(a) > ImGui.DockNodeGetDepth(b) +end + -- root_id = 0 to remove all, root_id != 0 to remove child of given node. function ImGui.DockBuilderRemoveNodeChildNodes(root_id) local g = ImGui.GetCurrentContext() @@ -3817,9 +3852,7 @@ function ImGui.DockBuilderRemoveNodeChildNodes(root_id) -- Not really efficient, but easier to destroy a whole hierarchy considering DockContextRemoveNode is attempting to merge nodes if #nodes_to_remove > 1 then - local depth = {} - for _, n in ipairs(nodes_to_remove) do depth[n] = ImGui.DockNodeGetDepth(n) end - table.sort(nodes_to_remove, function(a, b) return depth[a] > depth[b] end) + table.sort(nodes_to_remove, DockNodeComparerDepthMostFirst) end for _, n in ipairs(nodes_to_remove) do ImGui.DockContextRemoveNode(g, n, false) @@ -5167,6 +5200,79 @@ function ImStd.ImTextFindValidUtf8CodepointEnd(text, in_text_start, in_text_end, return prev end +------------------------------------------------------------------------------- +-- [SECTION] MISC HELPERS/UTILITIES (Geometry functions) +------------------------------------------------------------------------------- + +--- @param p1 ImVec2 +--- @param p2 ImVec2 +--- @param p3 ImVec2 +--- @param p4 ImVec2 +--- @param p ImVec2 +--- @param num_segments int +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPoint(p1, p2, p3, p4, p, num_segments) + assert(num_segments > 0) -- Use ImBezierCubicClosestPointCasteljau() + local p_last = p1 + local p_closest = ImVec2(0, 0) + local p_closest_dist2 = 3.4028234663853e+38 --[[FLT_MAX]] + local t_step = 1.0 / num_segments + for i_step = 1, num_segments do + local p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step) + local p_line = ImStd.ImLineClosestPoint(p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < p_closest_dist2 then + p_closest = p_line + p_closest_dist2 = dist2 + end + p_last = p_current + end + return ImVec2(p_closest.x, p_closest.y) +end + +-- Closely mimics PathBezierToCasteljau() in imgui_draw.cpp +-- [Luau] p_closest / p_last / p_closest_dist2 are C++ references: kept in the `st` table. +local function ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x2, y2, x3, y3, x4, y4, max_error_sqr, level) + local dx = x4 - x1 + local dy = y4 - y1 + local d2 = ((x2 - x4) * dy - (y2 - y4) * dx) + local d3 = ((x3 - x4) * dy - (y3 - y4) * dx) + d2 = (d2 >= 0) and d2 or -d2 + d3 = (d3 >= 0) and d3 or -d3 + if (d2 + d3) * (d2 + d3) < max_error_sqr * (dx * dx + dy * dy) then + local p_current = ImVec2(x4, y4) + local p_line = ImStd.ImLineClosestPoint(st.p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < st.p_closest_dist2 then + st.p_closest = p_line + st.p_closest_dist2 = dist2 + end + st.p_last = p_current + elseif level < 10 then + local x12, y12 = (x1 + x2) * 0.5, (y1 + y2) * 0.5 + local x23, y23 = (x2 + x3) * 0.5, (y2 + y3) * 0.5 + local x34, y34 = (x3 + x4) * 0.5, (y3 + y4) * 0.5 + local x123, y123 = (x12 + x23) * 0.5, (y12 + y23) * 0.5 + local x234, y234 = (x23 + x34) * 0.5, (y23 + y34) * 0.5 + local x1234, y1234 = (x123 + x234) * 0.5, (y123 + y234) * 0.5 + ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x12, y12, x123, y123, x1234, y1234, max_error_sqr, level + 1) + ImBezierCubicClosestPointCasteljauStep(p, st, x1234, y1234, x234, y234, x34, y34, x4, y4, max_error_sqr, level + 1) + end +end + +-- tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationMaxError +-- Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPointCasteljau(p1, p2, p3, p4, p, max_error) + assert(max_error > 0.0) + local st = { p_last = p1, p_closest = ImVec2(0, 0), p_closest_dist2 = 3.4028234663853e+38 --[[FLT_MAX]] } + local max_error_sqr = max_error * max_error + ImBezierCubicClosestPointCasteljauStep(p, st, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, max_error_sqr, 0) + return ImVec2(st.p_closest.x, st.p_closest.y) +end + --- @param a ImVec2 --- @param b ImVec2 --- @param p ImVec2 @@ -5354,6 +5460,20 @@ function ImGui.UpdateCurrentFontSize(restore_font_size_after_scaling) g.DrawListSharedData.FontScale = g.FontBakedScale end +-- Exposed in case user may want to override setting density. +-- IMPORTANT: Begin()/End() is overriding density. Be considerate of this you change it. +-- [Luau] upstream g.CurrentPixelDensity is g.FontRasterizerDensity in this port. +--- @param pixel_density float +function ImGui.SetPixelDensity(pixel_density) + local g = GImGui + assert(bit32.band(g.IO.BackendFlags, 16 --[[ImGuiBackendFlags.RendererHasTextures]]) ~= 0) + if g.FontRasterizerDensity == pixel_density then + return + end + g.FontRasterizerDensity = pixel_density + ImGui.UpdateCurrentFontSize(0.0) +end + -- Use ImDrawList:_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList. -- - Whereas ImDrawList:PushTexture()/PopTexture() is not to be used across Begin() calls. -- - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did... @@ -5498,6 +5618,22 @@ function ImGui.GetDefaultFont() return g.IO.FontDefault and g.IO.FontDefault or atlas.Fonts[1] end +-- EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates. Textures logic will be automatically be updated in NewFrame(). +--- @param tex ImTextureData +function ImGui.RegisterUserTexture(tex) + local g = GImGui + tex.RefCount = tex.RefCount + 1 + g.UserTextures:push_back(tex) +end + +--- @param tex ImTextureData +function ImGui.UnregisterUserTexture(tex) + local g = GImGui + assert(tex.RefCount > 0) + tex.RefCount = tex.RefCount - 1 + g.UserTextures:find_erase(tex) +end + --- @param atlas ImFontAtlas function ImGui.RegisterFontAtlas(atlas) local g = GImGui @@ -5580,6 +5716,16 @@ local GLocalizationEntriesEnUS = { ImGuiLocEntry(ImGuiLocKey.DockingDragToUndockOrMoveNode, "Click and drag to move or undock whole node."), } +-- [Luau] Default platform handlers (upstream: next to the metrics section; defined here so Initialize() can see the local). +-- Roblox has no shell: IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS path. Default clipboard/IME handlers are OS-specific: left nil +-- (the backends install their own clipboard handlers). +local function Platform_OpenInShellFn_DefaultImpl(ctx, path) return false end + +-- Setup default ImGuiPlatformIO clipboard/IME handlers +local function InitializeDefaultPlatformHandlers(platform_io) + platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl +end + function ImGui.Initialize() local g = GImGui assert(not g.Initialized and not g.SettingsLoaded) @@ -5592,6 +5738,23 @@ function ImGui.Initialize() -- Setup default localization table ImGui.LocalizeRegisterEntries(GLocalizationEntriesEnUS, #GLocalizationEntriesEnUS) + -- Setup default ImGuiPlatformIO clipboard/IME handlers. + InitializeDefaultPlatformHandlers(g.PlatformIO) + + -- [Luau] Debug tools context fields not (yet) in ImGuiContext() (imgui_internal.lua): initialized here. + if g.DebugItemPickerActive == nil then g.DebugItemPickerActive = false end -- Item picker is active (started with DebugStartItemPicker()) + if g.DebugItemPickerMouseButton == nil then g.DebugItemPickerMouseButton = 0 --[[ImGuiMouseButton.Left]] end + if g.DebugItemPickerBreakId == nil then g.DebugItemPickerBreakId = 0 end -- Will call IM_DEBUG_BREAK() when encountering this ID + if g.DebugFlashStyleColorTime == nil then g.DebugFlashStyleColorTime = 0.0 end + if g.DebugFlashStyleColorBackup == nil then g.DebugFlashStyleColorBackup = ImVec4(0, 0, 0, 0) end + if g.DebugLocateId == nil then g.DebugLocateId = 0 end -- Storage for DebugLocateItem(): ID to locate + if g.DebugLocateFrames == nil then g.DebugLocateFrames = 0 end -- Storage for DebugLocateItem(): number of frames to display + if g.DebugBreakInLocateId == nil then g.DebugBreakInLocateId = false end -- Debug break in ItemAdd() call for g.DebugLocateId. + if g.DebugBreakKeyChord == nil then g.DebugBreakKeyChord = 611 --[[ImGuiKey.Pause]] end -- = ImGuiKey_Pause + if g.DebugBreakInShortcutRouting == nil then g.DebugBreakInShortcutRouting = 0 --[[ImGuiKey.None]] end + if g.DebugLogAutoDisableFrames == nil then g.DebugLogAutoDisableFrames = 0 end + if g.DebugLogAutoDisableFlags == nil then g.DebugLogAutoDisableFlags = 0 --[[ImGuiDebugLogFlags.None]] end + -- Create default viewport local viewport = ImGuiViewportP() viewport.ID = IMGUI_VIEWPORT_DEFAULT_ID @@ -5992,6 +6155,21 @@ local function WindowSettingsHandler_ClearAll(ctx, handler) g.SettingsWindows:clear() end +-- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD number, 0 = invalid), so ImGuiPackedDate::IsValid()/Unpack() are inlined. +-- g.SessionDate doesn't exist in this port's context yet (no Platform_SessionDate support): treated as 0. +local function WindowSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for _, settings in g.SettingsWindows:iter() do + local is_valid = (settings.LastUsedDate or 0) ~= 0 + if ((args._DiscardOlderThanDate or 0) ~= 0 and (settings.LastUsedDate or 0) < args._DiscardOlderThanDate) or (args.DiscardWhenMissingDate and not is_valid) then + settings.WantDelete = true + end + if args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate or 0 + end + end +end + local function WindowSettingsHandler_ReadOpen(ctx, handler, name) local id = ImHashStr(name) local settings = ImGui.FindWindowSettingsByID(id) @@ -6107,6 +6285,7 @@ function ImGui.WindowSettingsAddSettingsHandler() ini_handler.TypeName = "Window" ini_handler.TypeHash = ImHashStr("Window") ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll + ini_handler.CleanupFn = WindowSettingsHandler_Cleanup ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll @@ -6482,6 +6661,20 @@ function ImGui.ItemAdd(bb, id, nav_bb_arg, extra_flags) end end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + if id == g.DebugLocateId then + ImGui.DebugLocateItemResolveWithLastItem() + end + + -- [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". + -- Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". + -- READ THE FAQ: https://dearimgui.com/faq + assert(id ~= window.ID, "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!") + end +end + if id ~= 0 and g.DeactivatedItemData.ID == id then g.DeactivatedItemData.ElapseFrame = g.FrameCount end @@ -7967,6 +8160,21 @@ end return false end +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + -- [DEBUG] Item Picker tool! + -- We perform the check here because reaching is path is rare (1~ time a frame), + -- making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered + -- items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost. + if g.DebugItemPickerActive and g.HoveredIdPreviousFrame == id then + ImGui.GetForegroundDrawList():AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)) + end + if g.DebugItemPickerBreakId == id then + IM_DEBUG_BREAK() + end + end +end + if g.NavHighlightItemUnderNav and (bit32.band(item_flags, 32768 --[[ImGuiItemFlags.NoNavDisableMouseHover]]) == 0) then return false end @@ -8074,6 +8282,19 @@ function MT.ImGuiIO:AddInputCharacterUTF16(c) self:AddInputCharacter(cp) end +--- @param str string +function MT.ImGuiIO:AddInputCharactersUTF8(str) + if not self.AppAcceptingEvents then + return + end + local p, str_end = 1, #str + 1 + while p < str_end and string.byte(str, p) ~= 0 do + local len, c = ImStd.ImTextCharFromUtf8(str, p, str_end) + p = p + len + self:AddInputCharacter(c) + end +end + -- Clear all incoming events. function MT.ImGuiIO:ClearEventsQueue() assert(self.Ctx ~= nil) @@ -8126,7 +8347,7 @@ end --- @param type ImGuiInputEventType --- @param arg? int --- @return ImGuiInputEvent? -function MT.ImGuiIO:FindLatestInputEvent(ctx, type, arg) +local function FindLatestInputEvent(ctx, type, arg) if arg == nil then arg = -1 end local g = ctx @@ -8176,7 +8397,7 @@ function MT.ImGuiIO:AddKeyAnalogEvent(key, down, analog_value) end -- Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed) - local latest_event = self:FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], key) + local latest_event = FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], key) local key_data = ImGui.GetKeyData(g, key) local latest_key_down = latest_event and latest_event.Key.Down or key_data.Down local latest_key_analog = latest_event and latest_event.Key.AnalogValue or key_data.AnalogValue @@ -8206,6 +8427,23 @@ function MT.ImGuiIO:AddKeyEvent(key, down) self:AddKeyAnalogEvent(key, down, (down and 1.0 or 0.0)) end +-- [Optional] Call after AddKeyEvent(). +-- Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices. +-- If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. +--- @param key ImGuiKey +--- @param native_keycode int +--- @param native_scancode int +--- @param native_legacy_index? int +function MT.ImGuiIO:SetKeyEventNativeData(key, native_keycode, native_scancode, native_legacy_index) + if native_legacy_index == nil then native_legacy_index = -1 end + if key == 0 --[[ImGuiKey.None]] then + return + end + assert(ImGui.IsNamedKey(key)) -- >= 512 + assert(native_legacy_index == -1 or (native_legacy_index >= 0 and native_legacy_index < 512)) -- [Luau] inline IsLegacyKey(): >= 0 && <= 511 + -- Yet unused: key, native_keycode, native_scancode, native_legacy_index +end + -- 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. --- @param accepting_events bool function MT.ImGuiIO:SetAppAcceptingEvents(accepting_events) @@ -8231,7 +8469,7 @@ function MT.ImGuiIO:AddMouseViewportEvent(viewport_id) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 4 --[[ImGuiInputEventType.MouseViewport]]) + local latest_event = FindLatestInputEvent(g, 4 --[[ImGuiInputEventType.MouseViewport]]) local latest_viewport_id if latest_event then latest_viewport_id = latest_event.MouseViewport.HoveredViewportID @@ -8256,7 +8494,7 @@ function MT.ImGuiIO:AddFocusEvent(focused) local g = self.Ctx -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 7 --[[ImGuiInputEventType.Focus]]) + local latest_event = FindLatestInputEvent(g, 7 --[[ImGuiInputEventType.Focus]]) local latest_focused = latest_event and latest_event.AppFocused.Focused or (not g.IO.AppFocusLost) if latest_focused == focused or (self.ConfigDebugIgnoreFocusLoss and not focused) then return @@ -8293,7 +8531,7 @@ function MT.ImGuiIO:AddMousePosEvent(x, y) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 1 --[[ImGuiInputEventType.MousePos]]) + local latest_event = FindLatestInputEvent(g, 1 --[[ImGuiInputEventType.MousePos]]) local latest_pos = latest_event and ImVec2(latest_event.MousePos.PosX, latest_event.MousePos.PosY) or self.MousePos if latest_pos.x == x_val and latest_pos.y == y_val then return @@ -8331,7 +8569,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 3 --[[ImGuiInputEventType.MouseButton]], mouse_button) + local latest_event = FindLatestInputEvent(g, 3 --[[ImGuiInputEventType.MouseButton]], mouse_button) local latest_button_down = latest_event and latest_event.MouseButton.Down or self.MouseDown[mouse_button] if latest_button_down == down then return @@ -8341,7 +8579,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) -- - Note that this is actual physical Ctrl which is ImGuiMod_Super for us. -- - At this point we want from !down to down, so this is handling the initial press. if self.ConfigMacOSXBehaviors and mouse_button == 0 and down then - local latest_super_event = self:FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], 32768 --[[ImGuiMod_Super]]) + local latest_super_event = FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], 32768 --[[ImGuiMod_Super]]) if latest_super_event and latest_super_event.Key.Down or self.KeySuper then -- IMGUI_DEBUG_LOG_IO("[io] Super+Left Click aliased into Right Click\n") self.MouseCtrlLeftAsRightClick = true @@ -8991,7 +9229,7 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) -- [DEBUG] Debug break requested by user if g.DebugBreakInShortcutRouting == key_chord then - -- IM_DEBUG_BREAK() + IM_DEBUG_BREAK() end if bit32.band(flags, 65536 --[[ImGuiInputFlags.RouteUnlessBgFocused]]) ~= 0 then @@ -9062,6 +9300,18 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) return routing_data.RoutingCurr == owner_id end +-- Currently unused by core (but used by tests) +-- Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. +--- @param key_chord ImGuiKeyChord +--- @param owner_id ImGuiID +--- @return bool +function ImGui.TestShortcutRouting(key_chord, owner_id) + local routing_id = GetRoutingIdFromOwnerId(owner_id) + key_chord = ImGui.FixupKeyChord(key_chord) + local routing_data = ImGui.GetShortcutRoutingData(key_chord) -- FIXME: Could avoid creating entry. + return routing_data.RoutingCurr == routing_id +end + -- We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position. --- @param mouse_pos? ImVec2 function ImGui.IsMousePosValid(mouse_pos) @@ -9290,6 +9540,39 @@ function ImGui.ResetMouseDragDelta(button) ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos) end +--- @param source ImGuiInputSource +--- @return string +local function GetInputSourceName(source) + local input_source_names = { "None", "Mouse", "Keyboard", "Gamepad" } + assert(#input_source_names == 4 --[[ImGuiInputSource.COUNT]]) + if source < 0 or source >= 4 --[[ImGuiInputSource.COUNT]] then + return "Unknown" + end + return input_source_names[source + 1] +end +--- @param source ImGuiMouseSource +--- @return string +local function GetMouseSourceName(source) + local mouse_source_names = { "Mouse", "TouchScreen", "Pen" } + assert(#mouse_source_names == 3 --[[ImGuiMouseSource.COUNT]]) + if source < 0 or source >= 3 --[[ImGuiMouseSource.COUNT]] then + return "Unknown" + end + return mouse_source_names[source + 1] +end +--- @param prefix string +--- @param e ImGuiInputEvent +local function DebugPrintInputEvent(prefix, e) + local T = ImGuiInputEventType + if e.Type == T.MousePos then if e.MousePos.PosX == -3.4028234663853e+38 --[[FLT_MAX]] and e.MousePos.PosY == -3.4028234663853e+38 --[[FLT_MAX]] then IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix) else IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix, e.MousePos.PosX, e.MousePos.PosY, GetMouseSourceName(e.MousePos.MouseSource)) end return end + if e.Type == T.MouseButton then IMGUI_DEBUG_LOG_IO("[io] %s: MouseButton %d %s (%s)\n", prefix, e.MouseButton.Button, e.MouseButton.Down and "Down" or "Up", GetMouseSourceName(e.MouseButton.MouseSource)) return end + if e.Type == T.MouseWheel then IMGUI_DEBUG_LOG_IO("[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix, e.MouseWheel.WheelX, e.MouseWheel.WheelY, GetMouseSourceName(e.MouseWheel.MouseSource)) return end + if e.Type == T.MouseViewport then IMGUI_DEBUG_LOG_IO("[io] %s: MouseViewport (0x%08X)\n", prefix, e.MouseViewport.HoveredViewportID) return end + if e.Type == T.Key then IMGUI_DEBUG_LOG_IO("[io] %s: Key \"%s\" %s\n", prefix, ImGui.GetKeyName(e.Key.Key), e.Key.Down and "Down" or "Up") return end + if e.Type == T.Text then IMGUI_DEBUG_LOG_IO("[io] %s: Text: '%s' (U+%08X)\n", prefix, utf8.char(e.Text.Char), e.Text.Char) return end -- [Luau] utf8.char() instead of ImTextCharToUtf8() + if e.Type == T.Focus then IMGUI_DEBUG_LOG_IO("[io] %s: AppFocused %d\n", prefix, e.AppFocused.Focused and 1 or 0) return end +end + do local key_changed_mask = ImBitArray(ImGuiKey.NamedKey_COUNT) @@ -9422,6 +9705,15 @@ function ImGui.UpdateInputEvents(trickle_fast_inputs) event_n = event_n + 1 end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if event_n ~= 1 and bit32.band(g.DebugLogFlags, 128 --[[ImGuiDebugLogFlags.EventIO]]) ~= 0 then -- [Luau] event_n is the 1-based next index: processed count = event_n - 1 + for n = 1, g.InputEventsQueue.Size do + DebugPrintInputEvent((n < event_n) and "Processed" or "Remaining", g.InputEventsQueue.Data[n]) + end + end +end + -- Remaining events will be processed on the next frame -- FIXME-MULTITHREADING: io.AddKeyEvent() etc. calls are mostly thread-safe apart from the fact they push to this -- queue which may be resized here. Could potentially rework this to narrow down the section needing a mutex? (#5772) @@ -9618,6 +9910,12 @@ end --- @param window ImGuiWindow --- @nodiscard +--- @param window ImGuiWindow +--- @return ImGuiWindow +local function GetWindowForTitleAndMenuHeight(window) + return (window.DockNodeAsHost and window.DockNodeAsHost.VisibleWindow) and window.DockNodeAsHost.VisibleWindow or window +end + local function CalcWindowMinSize(window) -- We give windows non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) -- FIXME: Essentially we want to restrict manual resizing to WindowMinSize+Decoration, and allow api resizing to be smaller. @@ -9653,7 +9951,7 @@ local function CalcWindowMinSize(window) end -- Reduce artifacts with very small windows - local window_for_height = window + local window_for_height = GetWindowForTitleAndMenuHeight(window) size_min.y = ImMax(size_min.y, window_for_height.TitleBarHeight + window_for_height.MenuBarHeight + ImMax(0, g.Style.WindowRounding - 1)) return size_min @@ -9841,6 +10139,29 @@ end --- @param resize_grip_col table --- @param visibility_rect ImRect --- @return int, int, int +--- @param window ImGuiWindow +--- @param n int +--- @return ImGuiID +function ImGui.GetWindowResizeCornerID(window, n) + assert(n >= 0 and n < 4) + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] ImHashData(&n, sizeof(int), id): same hashing as window:GetID(n) used by UpdateWindowManualResize() + return id +end + +--- @param window ImGuiWindow +--- @param dir ImGuiDir +--- @return ImGuiID +function ImGui.GetWindowResizeBorderID(window, dir) + assert(dir >= 0 and dir < 4) + local n = dir + 4 + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] see GetWindowResizeCornerID() + return id +end + local function UpdateWindowManualResize(window, resize_grip_count, resize_grip_col, visibility_rect) local g = GImGui local flags = window.Flags @@ -10472,6 +10793,21 @@ end --- @param border_n int --- @param border_col ImU32 --- @param border_size float +--- @param window ImGuiWindow +--- @param visibility_rect ImRect +local function ClampWindowPos(window, visibility_rect) + local size_for_clamping = ImVec2(window.Size.x, window.Size.y) + local move_from_title_bar_only = bit32.band(window.BgClickFlags, 1 --[[ImGuiWindowBgClickFlags.Move]]) == 0 + if move_from_title_bar_only and window.DockNodeAsHost then + size_for_clamping.y = ImGui.GetFrameHeight() -- Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here. + elseif move_from_title_bar_only and bit32.band(window.Flags, 1 --[[ImGuiWindowFlags.NoTitleBar]]) == 0 then + size_for_clamping.y = window.TitleBarHeight + end + -- [Luau] in place (window.Pos may be referenced elsewhere): window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max) + window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - size_for_clamping.x, visibility_rect.Max.x) + window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping.y, visibility_rect.Max.y) +end + local function RenderWindowOuterSingleBorder(window, border_n, border_col, border_size) local def = ImGuiResizeBorderDef[border_n + 1] local rounding = window.WindowRounding @@ -11139,6 +11475,11 @@ function ImGui.GetWindowDrawList() return window.DrawList end +--- @return ImFontBaked +function ImGui.GetFontBaked() + return GImGui.FontBaked +end + function ImGui.GetFont() return GImGui.Font end @@ -11761,6 +12102,11 @@ function ImGui.Begin(name, open, flags) window = CreateNewWindow(name, flags) --- @cast window ImGuiWindow end + -- [DEBUG] Debug break requested by user + if g.DebugBreakInWindow == window.ID then + IM_DEBUG_BREAK() + end + if bit32.band(g.NextWindowData.HasFlags, 256 --[[ImGuiNextWindowDataFlags.HasWindowFlags]]) ~= 0 then flags = bit32.band(bit32.bor(flags, g.NextWindowData.WindowFlagsSet), bit32.bnot(g.NextWindowData.WindowFlagsClear)) end @@ -12259,12 +12605,7 @@ function ImGui.Begin(name, open, flags) -- FIXME: Similar to code in GetWindowAllowedExtentRect() if not window_pos_set_by_api and bit32.band(flags, 16777216 --[[ImGuiWindowFlags.ChildWindow]]) == 0 then if not window.ViewportOwned and viewport_rect:GetWidth() > 0 and viewport_rect:GetHeight() > 0.0 then - local size_for_clamping_y = window.Size.y - if bit32.band(window.BgClickFlags, 1 --[[ImGuiWindowBgClickFlags.Move]]) == 0 and bit32.band(window.Flags, 1 --[[ImGuiWindowFlags.NoTitleBar]]) == 0 then - size_for_clamping_y = window.TitleBarHeight - end - window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - window.Size.x, visibility_rect.Max.x) - window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping_y, visibility_rect.Max.y) + ClampWindowPos(window, visibility_rect) end end window.Pos.x = ImTrunc(window.Pos.x) window.Pos.y = ImTrunc(window.Pos.y) @@ -12699,6 +13040,13 @@ function ImGui.Begin(name, open, flags) window.DC.WindowItemStatusFlags = bit32.bor(window.DC.WindowItemStatusFlags, 1 --[[ImGuiItemStatusFlags.HoveredRect]]) end ImGui.SetLastItemDataForWindow(window, title_bar_rect) + + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if g.DebugLocateId ~= 0 and (window.ID == g.DebugLocateId or window.MoveId == g.DebugLocateId) then + ImGui.DebugLocateItemResolveWithLastItem() + end +end else -- Skip refresh always mark active if (window.SkipRefresh) then @@ -13815,14 +14163,19 @@ function ImGui.NewFrame() assert(GImGui ~= nil, "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?") local g = GImGui - g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame - -- [Luau] ErrorCheckNewFrameSanityChecks() is not ported; only the parts below are inlined. - assert(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") - -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) - if g.Style.CurveTessellationTol ~= 0.0 then - g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + -- Remove pending delete hooks before frame start. + -- This deferred removal avoid issues of removal while iterating the hook vector + for n = g.Hooks.Size, 1, -1 do + if g.Hooks.Data[n].Type == 7 --[[ImGuiContextHookType.PendingRemoval_]] then + g.Hooks:erase(n) + end end - g.Style.CurveTessellationTol = 0.0 + + ImGui.CallContextHooks(g, 0 --[[ImGuiContextHookType.NewFramePre]]) + + -- Check and assert for various common IO and Configuration mistakes + g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame + ImGui.ErrorCheckNewFrameSanityChecks() g.ConfigFlagsCurrFrame = g.IO.ConfigFlags -- Load settings on first frame, save settings when modified (after a delay) @@ -14093,12 +14446,31 @@ function ImGui.NewFrame() g.CurrentItemFlags = g.ItemFlagsStack:back() g.GroupStack:resize(0) - -- [DEBUG] ID Stack Tool query - ImGui.UpdateDebugToolItemPathQuery() - -- Docking ImGui.DockContextNewFrameUpdateDocking(g) + -- [DEBUG] Update debug features +if not IMGUI_DISABLE_DEBUG_TOOLS then + ImGui.UpdateDebugToolItemPicker() + ImGui.UpdateDebugToolItemPathQuery() + ImGui.UpdateDebugToolFlashStyleColor() + if g.DebugLocateFrames > 0 then + g.DebugLocateFrames = g.DebugLocateFrames - 1 + if g.DebugLocateFrames == 0 then + g.DebugLocateId = 0 + g.DebugBreakInLocateId = false + end + end + if (g.DebugLogAutoDisableFrames or 0) > 0 then + g.DebugLogAutoDisableFrames = g.DebugLogAutoDisableFrames - 1 + if g.DebugLogAutoDisableFrames == 0 then + ImGui.DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n") + g.DebugLogFlags = bit32.band(g.DebugLogFlags, bit32.bnot(g.DebugLogAutoDisableFlags)) + g.DebugLogAutoDisableFlags = 0 --[[ImGuiDebugLogFlags.None]] + end + end +end + -- Create implicit/fallback window - which we will only render it if the user has added something to it. -- We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. -- This fallback is particularly important as it prevents ImGui:: calls from crashing. @@ -14119,6 +14491,8 @@ function ImGui.NewFrame() else g.DebugBeginReturnValueCullDepth = -1 end + + ImGui.CallContextHooks(g, 1 --[[ImGuiContextHookType.NewFramePost]]) end -- This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. @@ -14132,10 +14506,13 @@ function ImGui.EndFrame() end IM_ASSERT_USER_ERROR(g.WithinFrameScope, "Forgot to call ImGui::NewFrame()?") + ImGui.CallContextHooks(g, 2 --[[ImGuiContextHookType.EndFramePre]]) + -- [EXPERIMENTAL] Recover from errors if g.IO.ConfigErrorRecovery and g.StackSizesInNewFrame then ImGui.ErrorRecoveryTryToRecoverState(g.StackSizesInNewFrame) end + ImGui.ErrorCheckEndFrameSanityChecks() ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) @@ -14227,6 +14604,8 @@ function ImGui.EndFrame() g.IO.MouseWheel = 0.0 g.IO.MouseWheelH = 0.0 g.IO.InputQueueCharacters:resize(0) + + ImGui.CallContextHooks(g, 3 --[[ImGuiContextHookType.EndFramePost]]) end -- TODO: @@ -14244,6 +14623,7 @@ function ImGui.Render() g.FrameCountRendered = g.FrameCount g.IO.MetricsRenderWindows = 0 + ImGui.CallContextHooks(g, 4 --[[ImGuiContextHookType.RenderPre]]) -- Add background ImDrawList (for each active viewport) for _, viewport in g.Viewports:iter() do @@ -14296,6 +14676,8 @@ function ImGui.Render() g.IO.MetricsRenderVertices = g.IO.MetricsRenderVertices + draw_data.TotalVtxCount g.IO.MetricsRenderIndices = g.IO.MetricsRenderIndices + draw_data.TotalIdxCount end + + ImGui.CallContextHooks(g, 5 --[[ImGuiContextHookType.RenderPost]]) end -- Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. @@ -14378,13 +14760,16 @@ function ImGui.Shutdown() end g.DrawListSharedData.TempBuffer:clear() - -- Shutdown extensions - ImGui.DockContextShutdown(g) - -- Cleanup of other data are conditional on actually having initialized Dear ImGui. if not g.Initialized then return end + + -- Shutdown extensions + ImGui.DockContextShutdown(g) + + ImGui.CallContextHooks(g, 6 --[[ImGuiContextHookType.Shutdown]]) + -- TODO: -- Clear everything else @@ -14393,6 +14778,74 @@ function ImGui.Shutdown() g.MenusIdSubmittedThisFrame:clear() end +-- When using multiple context it can be helpful to give name a name. +-- (A) Will be visible in debugger, (B) Will be included in all IMGUI_DEBUG_LOG() calls, (C) Should be <= 15 characters long. +--- @param ctx ImGuiContext +--- @param name string +function ImGui.SetContextName(ctx, name) + ctx.ContextName = string.sub(name, 1, 15) -- [Luau] ImStrncpy() into char[16] +end + +-- [Luau] ImGuiContextHookType / ImGuiContextHook are not defined in imgui_internal.lua yet: defined here. +--- @enum ImGuiContextHookType +ImGuiContextHookType = ImGuiContextHookType or { NewFramePre = 0, NewFramePost = 1, EndFramePre = 2, EndFramePost = 3, RenderPre = 4, RenderPost = 5, Shutdown = 6, PendingRemoval_ = 7 } + +--- @class ImGuiContextHook +--- @field HookId ImGuiID -- A unique ID assigned by AddContextHook() +--- @field Type ImGuiContextHookType +--- @field Owner ImGuiID +--- @field Callback fun(ctx: ImGuiContext, hook: ImGuiContextHook)? +--- @field UserData any +if ImGuiContextHook == nil then + function ImGuiContextHook() + return { HookId = 0, Type = 0 --[[ImGuiContextHookType.NewFramePre]], Owner = 0, Callback = nil, UserData = nil } + end +end + +-- No specific ordering/dependency support, will see as needed +--- @param ctx ImGuiContext +--- @param hook ImGuiContextHook +--- @return ImGuiID +function ImGui.AddContextHook(ctx, hook) + local g = ctx + assert(hook.Callback ~= nil and (hook.HookId or 0) == 0 and hook.Type ~= 7 --[[ImGuiContextHookType.PendingRemoval_]]) + local copy = ImGuiContextHook() -- [Luau] g.Hooks.push_back(*hook): store a copy + copy.Type = hook.Type; copy.Owner = hook.Owner or 0; copy.Callback = hook.Callback; copy.UserData = hook.UserData + g.Hooks:push_back(copy) + g.HookIdNext = g.HookIdNext + 1 + g.Hooks:back().HookId = g.HookIdNext + return g.HookIdNext +end + +-- Deferred removal, avoiding issue with changing vector while iterating it +--- @param ctx ImGuiContext +--- @param hook_id ImGuiID +function ImGui.RemoveContextHook(ctx, hook_id) + local g = ctx + assert(hook_id ~= 0) + for _, hook in g.Hooks:iter() do + if hook.HookId == hook_id then + hook.Type = 7 --[[ImGuiContextHookType.PendingRemoval_]] + end + end +end + +-- Call context hooks (used by e.g. test engine) +-- We assume a small number of hooks so all stored in same array +--- @param ctx ImGuiContext +--- @param hook_type ImGuiContextHookType +function ImGui.CallContextHooks(ctx, hook_type) + local g = ctx + local hooks = g.Hooks + if hooks.Size == 0 then return end -- [Luau] fast path + for n = 1, hooks.Size do + local hook = hooks.Data[n] + if hook.Type == hook_type then + hook.Callback(g, hook) + end + end +end + -- A conformant backend should return nil on failure (e.g. clipboard data is not text). --- @return string? function ImGui.GetClipboardText() @@ -15310,6 +15763,11 @@ end --- @param fmt string --- @param ... any function ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()) +function ImGui.SetTooltipV(fmt, ...) if not ImGui.BeginTooltipEx(2 --[[ImGuiTooltipFlags.OverridePrevious]], 0 --[[ImGuiWindowFlags.None]]) then return end @@ -15322,8 +15780,12 @@ end --- @param fmt string --- @param ... any function ImGui.SetItemTooltip(fmt, ...) + ImGui.SetItemTooltipV(fmt, ...) +end + +function ImGui.SetItemTooltipV(fmt, ...) if ImGui.IsItemHovered(4096 --[[ImGuiHoveredFlags.ForTooltip]]) then - ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) end end @@ -17708,6 +18170,7 @@ function MT.ImGuiPlatformIO:ClearPlatformHandlers() self.Platform_SetWindowTitle = nil; self.Platform_SetWindowAlpha = nil; self.Platform_UpdateWindow = nil self.Platform_RenderWindow = nil; self.Platform_SwapBuffers = nil; self.Platform_GetWindowDpiScale = nil self.Platform_OnChangedViewport = nil; self.Platform_GetWindowWorkAreaInsets = nil; self.Platform_CreateVkSurface = nil + InitializeDefaultPlatformHandlers(self) -- Prevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation. end function MT.ImGuiPlatformIO:ClearRendererHandlers() @@ -17738,6 +18201,18 @@ function ImGui.FindViewportByID(viewport_id) return nil end +--- @param platform_handle any +--- @return ImGuiViewportP? +function ImGui.FindViewportByPlatformHandle(platform_handle) + local g = GImGui + for _, viewport in g.Viewports:iter() do + if viewport.PlatformHandle == platform_handle then + return viewport + end + end + return nil +end + --- @param current_window? ImGuiWindow --- @param viewport? ImGuiViewportP function ImGui.SetCurrentViewport(current_window, viewport) @@ -19856,6 +20331,99 @@ function ImGuiErrorRecoveryState() SizeOfBeginPopupStack = 0, SizeOfDisabledStack = 0 } end +function ImGui.ErrorCheckNewFrameSanityChecks() + local g = GImGui + + -- [Luau] C++-only check of the user's IM_ASSERT macro definition dropped. + + -- Check user data + -- (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) + assert(g.Initialized) + assert(g.IO.DeltaTime > 0.0 or g.FrameCount == 0, "Need a positive DeltaTime!") + assert(g.FrameCount == 0 or g.FrameCountEnded == g.FrameCount, "Forgot to call Render() or EndFrame() at the end of the previous frame?") + assert(g.IO.DisplaySize.x >= 0.0 and g.IO.DisplaySize.y >= 0.0, "Invalid DisplaySize value!") + assert(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") + assert(g.Style.CircleTessellationMaxError > 0.0, "Invalid style setting!") + assert(g.Style.Alpha >= 0.0 and g.Style.Alpha <= 1.0, "Invalid style setting!") -- Allows us to avoid a few clamps in color computations + assert(g.Style.WindowMinSize.x >= 1.0 and g.Style.WindowMinSize.y >= 1.0, "Invalid style setting!") + assert(g.Style.WindowBorderHoverPadding > 0.0, "Invalid style setting!") -- Required otherwise cannot resize from borders. + assert(g.Style.WindowMenuButtonPosition == (-1) --[[ImGuiDir.None]] or g.Style.WindowMenuButtonPosition == 0 --[[ImGuiDir.Left]] or g.Style.WindowMenuButtonPosition == 1 --[[ImGuiDir.Right]]) + assert(g.Style.ColorButtonPosition == 0 --[[ImGuiDir.Left]] or g.Style.ColorButtonPosition == 1 --[[ImGuiDir.Right]]) + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 7340032 --[[ImGuiColorEditFlags.DisplayMask_]]))) -- Check only 1 option is selected + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 25165824 --[[ImGuiColorEditFlags.DataTypeMask_]]))) -- " + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 100663296 --[[ImGuiColorEditFlags.PickerMask_]]))) -- " + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 805306368 --[[ImGuiColorEditFlags.InputMask_]]))) -- " + + assert(g.Style.TreeLinesFlags == 262144 --[[ImGuiTreeNodeFlags.DrawLinesNone]] or g.Style.TreeLinesFlags == 524288 --[[ImGuiTreeNodeFlags.DrawLinesFull]] or g.Style.TreeLinesFlags == 1048576 --[[ImGuiTreeNodeFlags.DrawLinesToNodes]]) + assert(g.IO.MouseSingleClickDelay > g.IO.MouseDoubleClickTime) + + -- Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way. + if g.IO.ConfigErrorRecovery then + assert(g.IO.ConfigErrorRecoveryEnableAssert or g.IO.ConfigErrorRecoveryEnableDebugLog or g.IO.ConfigErrorRecoveryEnableTooltip or g.ErrorCallback ~= nil) + end + + -- [Luau] Obsolete io.FontGlobalScale, ImGuiConfigFlags_NavEnableSetMousePos/NavNoCaptureKeyboard/DpiEnableScaleXXX and + -- io.Get/SetClipboardTextFn don't exist in this port: their remaps are dropped. + + -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) + if g.Style.CurveTessellationTol ~= 0.0 then + g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + end + g.Style.CurveTessellationTol = 0.0 + + -- Perform simple check: error if Docking or Viewport are enabled _exactly_ on frame 1 (instead of frame 0 or later), which is a common error leading to loss of .ini data. + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, 128 --[[ImGuiConfigFlags.DockingEnable]]) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, 128 --[[ImGuiConfigFlags.DockingEnable]]) == 0 then + assert(false, "Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) == 0 then + assert(false, "Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + + -- Perform simple checks: multi-viewport and platform windows support + if bit32.band(g.IO.ConfigFlags, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) ~= 0 then + if bit32.band(g.IO.BackendFlags, 2048 --[[ImGuiBackendFlags.PlatformHasViewports]]) ~= 0 and bit32.band(g.IO.BackendFlags, 1024 --[[ImGuiBackendFlags.RendererHasViewports]]) ~= 0 then + local pio = g.PlatformIO + assert(g.FrameCount == 0 or g.FrameCount == g.FrameCountPlatformEnded, "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.") + assert(pio.Platform_CreateWindow ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_DestroyWindow ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_GetWindowPos ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_SetWindowPos ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_GetWindowSize ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_SetWindowSize ~= nil, "Platform init didn't install handlers?") + assert(pio.Monitors.Size > 0, "Platform init didn't setup Monitors list?") + assert(g.Viewports.Data[1].PlatformUserData ~= nil or g.Viewports.Data[1].PlatformHandle ~= nil, "Platform init didn't setup main viewport.") + if g.IO.ConfigDockingTransparentPayload and bit32.band(g.IO.ConfigFlags, 128 --[[ImGuiConfigFlags.DockingEnable]]) ~= 0 then + assert(pio.Platform_SetWindowAlpha ~= nil, "Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!") + end + else + -- Disable feature, our backends do not support it + g.IO.ConfigFlags = bit32.band(g.IO.ConfigFlags, bit32.bnot(1024 --[[ImGuiConfigFlags.ViewportsEnable]])) + end + + -- Perform simple checks on platform monitor data + compute a total bounding box for quick early outs + for _, mon in g.PlatformIO.Monitors:iter() do + assert(mon.MainSize.x > 0.0 and mon.MainSize.y > 0.0, "Monitor main bounds not setup properly.") + assert(ImRect(mon.MainPos, mon.MainPos + mon.MainSize):Contains(ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)), "Monitor work bounds not setup properly. If you don't have work area information, just copy MainPos/MainSize into them.") + assert(mon.DpiScale > 0.0 and mon.DpiScale < 99.0, "Monitor DpiScale is invalid.") -- Typical correct values would be between 1.0f and 4.0f + end + end +end + +function ImGui.ErrorCheckEndFrameSanityChecks() + -- Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() + -- One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). + -- It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will + -- send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. + -- We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), + -- while still correctly asserting on mid-frame key press events. + local g = GImGui + local key_mods = ImGui.GetMergedModsFromKeys() + assert(key_mods == 0 or g.IO.KeyMods == key_mods, "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods") + + assert(g.CurrentWindowStack.Size == 1) + assert(g.CurrentWindowStack.Data[1].Window.IsFallbackWindow) +end + -- Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery. function ImGui.ErrorRecoveryStoreState(state_out) local g = GImGui @@ -19975,9 +20543,20 @@ end -- Lines are stored in g.DebugLogBuf (one chunk per call) function ImGui.DebugLog(fmt, ...) + ImGui.DebugLogV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()). Without arguments `fmt` is used verbatim. +function ImGui.DebugLogV(fmt, ...) local g = GImGui g.DebugLogBuf = g.DebugLogBuf or ImGuiTextBuffer() - local str = string.format("[%05d] ", g.FrameCount) .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) + local prefix + if g.ContextName ~= nil and g.ContextName ~= "" then + prefix = string.format("[%s] [%05d] ", g.ContextName, g.FrameCount) + else + prefix = string.format("[%05d] ", g.FrameCount) + end + local str = prefix .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) g.DebugLogBuf:append(str) -- Line index (upstream: g.DebugLogIndex). Lines are complete strings without '\n'. local lines = g.DebugLogLines @@ -20049,7 +20628,17 @@ function ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- ImGui.BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags.AllowDuplicateId, true); ... PopItemFlag()") -- Not making this too visible for fear of it being abused. ImGui.BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds.") ImGui.Separator() - ImGui.Text("(Hold Ctrl to: ") + if g.IO.ConfigDebugHighlightIdConflictsShowItemPicker then + ImGui.Text("(Hold Ctrl to: use ") + ImGui.SameLine(0.0, 0.0) + if ImGui.SmallButton("Item Picker") then + ImGui.DebugStartItemPicker() + end + ImGui.SameLine(0.0, 0.0) + ImGui.Text(" to break in item call-stack, or ") + else + ImGui.Text("(Hold Ctrl to: ") + end ImGui.SameLine(0.0, 0.0) ImGui.TextLinkOpenURL("read FAQ \"About ID Stack System\"", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage") ImGui.SameLine(0.0, 0.0) @@ -20137,6 +20726,117 @@ ImGui.MetricsHelpMarker = MetricsHelpMarker local function U8(c) return (c and c > 0) and utf8.char(c) or "" end +-- [Luau] table.sort() "less than" predicate (upstream: ImQsort() comparer returning b - a) +--- @param a ImGuiViewportP +--- @param b ImGuiViewportP +local function ViewportComparerByLastFocusedStampCount(a, b) + return b.LastFocusedStampCount < a.LastFocusedStampCount +end + +-- Draw an arbitrary US keyboard layout to visualize translated keys +--- @param draw_list ImDrawList +function ImGui.DebugRenderKeyboardPreview(draw_list) + local scale = ImGui.GetFontSize() / 13.0 + local key_size = ImVec2(35.0, 35.0) * scale + local key_rounding = 3.0 * scale + local key_face_size = ImVec2(25.0, 25.0) * scale + local key_face_pos = ImVec2(5.0, 3.0) * scale + local key_face_rounding = 2.0 * scale + local key_label_pos = ImVec2(7.0, 4.0) * scale + local key_step = ImVec2(key_size.x - 1.0, key_size.y - 1.0) + local key_row_offset = 9.0 * scale + + local board_min = ImGui.GetCursorScreenPos() + local board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0, board_min.y + 3 * key_step.y + 10.0) + local start_pos = ImVec2(board_min.x + 5.0 - key_step.x, board_min.y) + + local K = ImGuiKey + local keys_to_display = { -- { Row, Col, Label, Key } + { 0, 0, "", K.Tab }, { 0, 1, "Q", K.Q }, { 0, 2, "W", K.W }, { 0, 3, "E", K.E }, { 0, 4, "R", K.R }, + { 1, 0, "", K.CapsLock }, { 1, 1, "A", K.A }, { 1, 2, "S", K.S }, { 1, 3, "D", K.D }, { 1, 4, "F", K.F }, + { 2, 0, "", K.LeftShift }, { 2, 1, "Z", K.Z }, { 2, 2, "X", K.X }, { 2, 3, "C", K.C }, { 2, 4, "V", K.V }, + } + + -- Elements rendered manually via ImDrawList API are not clipped automatically. + -- While not strictly necessary, here IsItemVisible() is used to avoid rendering these shapes when they are out of view. + ImGui.Dummy(board_max - board_min) + if not ImGui.IsItemVisible() then + return + end + draw_list:PushClipRect(board_min, board_max, true) + for n = 1, #keys_to_display do + local key_data = keys_to_display[n] + local key_min = ImVec2(start_pos.x + key_data[2] * key_step.x + key_data[1] * key_row_offset, start_pos.y + key_data[1] * key_step.y) + local key_max = key_min + key_size + draw_list:AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding) + draw_list:AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding) + local face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y) + local face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y) + draw_list:AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0) + draw_list:AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding) + local label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y) + draw_list:AddText(label_min, IM_COL32(64, 64, 64, 255), key_data[3]) + if ImGui.IsKeyDown(key_data[4]) then + draw_list:AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding) + end + end + draw_list:PopClipRect() +end + +-- [Luau] g.DebugFlashStyleColorIdx == nil stands for ImGuiCol_COUNT (see ImGuiContext() in imgui_internal.lua). +local function DebugFlashStyleColorStop() + local g = GImGui + if g.DebugFlashStyleColorIdx ~= nil then + ImVec4_Copy(g.Style.Colors[g.DebugFlashStyleColorIdx], g.DebugFlashStyleColorBackup) + end + g.DebugFlashStyleColorIdx = nil +end + +-- Flash a given style color for some + inhibit modifications of this color via PushStyleColor() calls. +--- @param idx ImGuiCol +function ImGui.DebugFlashStyleColor(idx) + local g = GImGui + DebugFlashStyleColorStop() + g.DebugFlashStyleColorTime = 0.5 + g.DebugFlashStyleColorIdx = idx + ImVec4_Copy(g.DebugFlashStyleColorBackup, g.Style.Colors[idx]) +end + +function ImGui.UpdateDebugToolFlashStyleColor() + local g = GImGui + if g.DebugFlashStyleColorTime <= 0.0 then + return + end + local col = g.Style.Colors[g.DebugFlashStyleColorIdx] + col.x, col.y, col.z = ImGui.ColorConvertHSVtoRGB(math.cos(g.DebugFlashStyleColorTime * 6.0) * 0.5 + 0.5, 0.5, 0.5) + col.w = 1.0 + g.DebugFlashStyleColorTime = g.DebugFlashStyleColorTime - g.IO.DeltaTime + if g.DebugFlashStyleColorTime <= 0.0 then + DebugFlashStyleColorStop() + end +end + +-- [Luau] ImTextureID can be any Lua value here: numbers are returned as is, anything else is returned unchanged too +-- (there is no memcpy into an ImU64); FormatTextureRefForDebugDisplay() formats non-numbers with tostring(). +--- @param tex_id ImTextureID +function ImGui.DebugTextureIDToU64(tex_id) + return tex_id +end + +--- @param tex_ref ImTextureRef +--- @return string +local function FormatTextureRefForDebugDisplay(tex_ref) + local buf = "" + if tex_ref._TexData ~= nil then + buf = string.format("#%03d: ", tex_ref._TexData.UniqueID) + end + local v = ImGui.DebugTextureIDToU64(tex_ref:GetTexID()) + if type(v) == "number" and v >= 0 and v == math.floor(v) then + return buf .. string.format("0x%X", v) + end + return buf .. tostring(v) +end + -- Demo helper function to select among loaded fonts. -- Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one. function ImGui.ShowFontSelector(label) @@ -20224,6 +20924,22 @@ function ImGui.DebugNodeFontGlyphsForSrcMask(font, baked, src_mask) end -- [DEBUG] Display details for a single font, called by ShowStyleEditor(). +-- [DEBUG] Compute mask of inputs with the same codepoint. +-- [Luau] the port's font loaders expose FontSrcContainsGlyph() (pre-1.93 loader API) instead of FontSrcGetGlyphIndexFromCodepoint() != 0. +local function CalcFontGlyphSrcOverlapMask(atlas, font, codepoint) + local mask, count = 0, 0 + for src_n = 0, font.Sources.Size - 1 do repeat + local src = font.Sources.Data[src_n + 1] + local loader = src.FontLoader or atlas.FontLoader + if not (loader.FontSrcContainsGlyph ~= nil and loader.FontSrcContainsGlyph(atlas, src, codepoint)) then + break -- continue + end + mask = bit32.bor(mask, bit32.lshift(1, src_n)) + count = count + 1 + until true end + return (count > 1) and mask or 0 +end + function ImGui.DebugNodeFont(font) local g = ImGui.GetCurrentContext() local cfg = g.DebugMetricsConfig @@ -20268,6 +20984,39 @@ function ImGui.DebugNodeFont(font) ImGui.TreePop() end end + if font.Sources.Size > 1 and ImGui.TreeNode("Input Glyphs Overlap Detection Tool") then + ImGui.TextWrapped("- First Input that contains the glyph is used.\n" .. + "- Use ImFontConfig::GlyphExcludeRanges[] to specify ranges to ignore glyph in given Input.\n- Prefer using a small number of ranges as the list is scanned every time a new glyph is loaded,\n - e.g. GlyphExcludeRanges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };\n- This tool doesn't cache results and is slow, don't keep it open!") + if ImGui.BeginTable("table", 2) then + local c = 0 + while c < 0x10000 do + local overlap_mask = CalcFontGlyphSrcOverlapMask(atlas, font, c) + if overlap_mask ~= 0 then + local c_end = c + 1 + while c_end < 0x10000 and CalcFontGlyphSrcOverlapMask(atlas, font, c_end) == overlap_mask do + c_end = c_end + 1 + end + if ImGui.TableNextColumn() and ImGui.TreeNode(c, "U+%04X-U+%04X: %d codepoints in %d inputs", c, c_end - 1, c_end - c, ImCountSetBits(overlap_mask)) then + for n = c, c_end - 1 do + ImGui.BulletText("Codepoint U+%04X (%s)", n, U8(n)) + end + ImGui.TreePop() + end + ImGui.TableNextColumn() + for src_n = 0, font.Sources.Size - 1 do + if bit32.band(overlap_mask, bit32.lshift(1, src_n)) ~= 0 then + ImGui.Text("%d ", src_n) + ImGui.SameLine() + end + end + c = c_end - 1 + end + c = c + 1 + end + ImGui.EndTable() + end + ImGui.TreePop() + end -- Display all glyphs of the fonts in separate pages of 256 characters local builder = atlas.Builder @@ -20327,7 +21076,7 @@ function ImGui.DebugNodeTexture(tex, int_id, highlight_rect) end ImGui.PopStyleVar() ImGui.Text("Status = %s (%d), Format = %s (%d), UseColors = %d", StatusNames[tex.Status] or "?", tex.Status, FormatNames[tex.Format] or "?", tex.Format, tex.UseColors and 1 or 0) - ImGui.Text("TexID = %s", tostring(tex.TexID)) + ImGui.Text("TexRef = %s, BackendUserData = %s", FormatTextureRefForDebugDisplay(tex:GetTexRef()), tostring(tex.BackendUserData)) ImGui.TreePop() end ImGui.PopID() @@ -20472,7 +21221,7 @@ function ImGui.ShowDebugLogWindow(p_open) local clipper = ImGuiListClipper() clipper:Begin(count) while clipper:Step() do - for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.TextUnformatted(lines[line_no + 1]) end + for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.DebugTextUnformattedWithLocateItem(lines[line_no + 1]) end end g.DebugLogFlags = backup_log_flags if ImGui.GetScrollY() >= ImGui.GetScrollMaxY() then ImGui.SetScrollHereY(1.0) end @@ -20481,10 +21230,165 @@ function ImGui.ShowDebugLogWindow(p_open) return p_open end +-- Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered. +-- [Luau] line_begin is the line string, line_end its optional exclusive end byte position (default: whole string). +function ImGui.DebugTextUnformattedWithLocateItem(line_begin, line_end) + if line_end == nil then line_end = #line_begin + 1 end + ImGui.TextUnformatted(line_begin, line_end) + if not ImGui.IsItemHovered(bit32.bor(32 --[[ImGuiHoveredFlags.AllowWhenBlockedByPopup]], 128 --[[ImGuiHoveredFlags.AllowWhenBlockedByActiveItem]])) then + return + end + local g = GImGui + local text_rect = ImRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max) -- [Luau] copy (LastItemData.Rect is overwritten below) + local p = 1 + while p <= line_end - 10 do repeat -- [Luau] 1-based (C: p <= line_end - 10 with 0-based offsets) + local b0, b1 = string.byte(line_begin, p, p + 1) + local hex = string.match(line_begin, "^%x+", p + 2) + if b0 ~= 48 or (b1 ~= 120 and b1 ~= 88) or hex == nil or string.find(string.sub(line_begin, p + 10, p + 10), "^%x") then -- '0', 'x', 'X' + p = p + 1 + break -- continue + end + local id = tonumber(hex, 16) -- [Luau] sscanf("%X") + local p0 = ImGui.CalcTextSizeEx(line_begin, 1, p) + local p1 = ImGui.CalcTextSizeEx(line_begin, p, p + 10) + g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)) + if ImGui.IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true) then + ImGui.DebugLocateItemOnHover(id) + end + p = p + 11 -- p += 10, then the loop's p++ + until true end +end + ------------------------------------------------------------------------------- -- [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) ------------------------------------------------------------------------------- +-- Draw a small cross at current CursorPos in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawCursorPos(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local pos = window.DC.CursorPos + window.DrawList:AddLineV(pos.x, pos.y - 3.0, pos.y + 4.0, col, 1.0) + window.DrawList:AddLineH(pos.x - 3.0, pos.x + 4.0, pos.y, col, 1.0) +end + +-- Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawLineExtents(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local curr_x = window.DC.CursorPos.x + local line_y1 = window.DC.IsSameLine and window.DC.CursorPosPrevLine.y or window.DC.CursorPos.y + local line_y2 = line_y1 + (window.DC.IsSameLine and window.DC.PrevLineSize.y or window.DC.CurrLineSize.y) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y1, col, 1.0) + window.DrawList:AddLineV(curr_x, line_y1, line_y2, col, 1.0) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y2, col, 1.0) +end + +-- Draw last item rect in ForegroundDrawList (so it is always visible) +--- @param col? ImU32 +function ImGui.DebugDrawItemRect(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + ImGui.GetForegroundDrawList(window.Viewport):AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col) +end + +-- [DEBUG] Locate item position/rectangle given an ID. +local DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255) -- Green + +--- @param target_id ImGuiID +function ImGui.DebugLocateItem(target_id) + local g = GImGui + g.DebugLocateId = target_id + g.DebugLocateFrames = 2 + g.DebugBreakInLocateId = false +end + +-- FIXME: Doesn't work over through a modal window, because they clear HoveredWindow. +--- @param target_id ImGuiID +function ImGui.DebugLocateItemOnHover(target_id) + if target_id == 0 or not ImGui.IsItemHovered(bit32.bor(128 --[[ImGuiHoveredFlags.AllowWhenBlockedByActiveItem]], 32 --[[ImGuiHoveredFlags.AllowWhenBlockedByPopup]])) then + return + end + local g = GImGui + ImGui.DebugLocateItem(target_id) + ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport):AddRect(g.LastItemData.Rect.Min - ImVec2(3.0, 3.0), g.LastItemData.Rect.Max + ImVec2(3.0, 3.0), DEBUG_LOCATE_ITEM_COLOR) + + -- Can't easily use a context menu here because it will mess with focus, active id etc. + if g.IO.ConfigDebugIsDebuggerPresent and g.MouseStationaryTimer > 1.0 then + ImGui.DebugBreakButtonTooltip(false, "in ItemAdd()") + if ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) then + g.DebugBreakInLocateId = true + end + end +end + +function ImGui.DebugLocateItemResolveWithLastItem() + local g = GImGui + + -- [DEBUG] Debug break requested by user + if g.DebugBreakInLocateId then + IM_DEBUG_BREAK() + end + + local item_data = g.LastItemData + g.DebugLocateId = 0 + local draw_list = ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport) + local r = ImRect(item_data.Rect.Min, item_data.Rect.Max) -- [Luau] copy + r:Expand(3.0) + local p1 = g.IO.MousePos + local p2 = ImVec2((p1.x < r.Min.x) and r.Min.x or ((p1.x > r.Max.x) and r.Max.x or p1.x), (p1.y < r.Min.y) and r.Min.y or ((p1.y > r.Max.y) and r.Max.y or p1.y)) + draw_list:AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR) + draw_list:AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR) +end + +function ImGui.DebugStartItemPicker() + local g = GImGui + g.DebugItemPickerActive = true +end + +-- [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. +function ImGui.UpdateDebugToolItemPicker() + local g = GImGui + g.DebugItemPickerBreakId = 0 + if not g.DebugItemPickerActive then + return + end + + local hovered_id = g.HoveredIdPreviousFrame + ImGui.SetMouseCursor(7 --[[ImGuiMouseCursor.Hand]]) + if ImGui.IsKeyPressed(526 --[[ImGuiKey.Escape]]) then + g.DebugItemPickerActive = false + end + local change_mapping = g.IO.KeyMods == bit32.bor(4096 --[[ImGuiMod_Ctrl]], 8192 --[[ImGuiMod_Shift]]) + if not change_mapping and ImGui.IsMouseClicked(g.DebugItemPickerMouseButton) and hovered_id ~= 0 then + g.DebugItemPickerBreakId = hovered_id + g.DebugItemPickerActive = false + end + for mouse_button = 0, 2 do + if change_mapping and ImGui.IsMouseClicked(mouse_button) then + g.DebugItemPickerMouseButton = mouse_button + end + end + ImGui.SetNextWindowBgAlpha(0.70) + if not ImGui.BeginTooltip() then + return + end + ImGui.Text("HoveredId: 0x%08X", hovered_id) + ImGui.Text("Press ESC to abort picking.") + local mouse_button_names = { "Left", "Right", "Middle" } + if change_mapping then + ImGui.Text("Remap w/ Ctrl+Shift: click anywhere to select new mouse button.") + else + ImGui.TextColored(ImGui.GetStyleColorVec4((hovered_id ~= 0) and 0 --[[ImGuiCol.Text]] or 1 --[[ImGuiCol.TextDisabled]]), "Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[g.DebugItemPickerMouseButton + 1]) + end + ImGui.EndTooltip() +end + local function PathQuery(g) local q = g.DebugItemPathQuery if q == nil then @@ -20573,7 +21477,7 @@ local function SkipUncontributingPrefix(label) return label end -local function FormatLevelInfo(g, query, n, format_for_ui) +local function DebugItemPathQuery_FormatLevelInfo(query, n, format_for_ui) local info = query.Results[n + 1] local window = (info.Desc == nil and n == 0) and ImGui.FindWindowByID(info.ID) or nil if window then return string.format(format_for_ui and "\"%s\" [window]" or "%s", SkipUncontributingPrefix(window.Name)) end -- Source: window name (because the root ID don't call GetID() and so doesn't get hooked) @@ -20582,10 +21486,10 @@ local function FormatLevelInfo(g, query, n, format_for_ui) return "???" end -local function GetResultAsPath(g, query, hex_encode_non_ascii_chars) +local function DebugItemPathQuery_GetResultAsPath(query, hex_encode_non_ascii_chars) local out = {} for n = 0, #query.Results - 1 do - local desc = FormatLevelInfo(g, query, n, false) + local desc = DebugItemPathQuery_FormatLevelInfo(query, n, false) out[#out + 1] = (n == 0) and "//" or "/" desc = string.gsub(desc, "/", "\\/") if hex_encode_non_ascii_chars then @@ -20611,7 +21515,7 @@ function ImGui.ShowIDStackToolWindow(p_open) local query = PathQuery(g) local tool = g.DebugIDStackTool tool.LastActiveFrame = g.FrameCount - local result_path = GetResultAsPath(g, query, tool.OptHexEncodeNonAsciiChars) + local result_path = DebugItemPathQuery_GetResultAsPath(query, tool.OptHexEncodeNonAsciiChars) ImGui.Text("0x%08X", query.MainID) ImGui.SameLine() MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.") @@ -20644,7 +21548,7 @@ function ImGui.ShowIDStackToolWindow(p_open) ImGui.TableNextColumn() ImGui.Text("0x%08X", (n > 0) and query.Results[n].ID or 0) ImGui.TableNextColumn() - ImGui.TextUnformatted(FormatLevelInfo(g, query, n, true)) + ImGui.TextUnformatted(DebugItemPathQuery_FormatLevelInfo(query, n, true)) ImGui.TableNextColumn() ImGui.Text("0x%08X", info.ID) if n == #query.Results - 1 then ImGui.TableSetBgColor(3 --[[ImGuiTableBgTarget.CellBg]], ImGui.GetColorU32(25 --[[ImGuiCol.Header]])) end @@ -20695,6 +21599,7 @@ function ImGui.DebugNodeStorage(storage, label) if not ImGui.TreeNode(label, "%s: %d entries", label, n) then return end for k, v in pairs(storage) do ImGui.BulletText("Key 0x%08X Value { %s }", tonumber(k) or 0, tostring(v)) + ImGui.DebugLocateItemOnHover(tonumber(k) or 0) end ImGui.TreePop() end @@ -20722,50 +21627,116 @@ function ImGui.DebugNodeDrawList(window, viewport, draw_list, label) if not node_open then return end if window and not window.WasActive then ImGui.TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!") end - local vtx, idx = draw_list.VtxBuffer.Buf, draw_list.IdxBuffer.Data - for cmd_n = 1, cmd_count do + for cmd_n = 1, cmd_count do repeat local pcmd = draw_list.CmdBuffer.Data[cmd_n] if pcmd.UserCallback then - ImGui.BulletText("Callback %s", tostring(pcmd.UserCallback)) - else - local cr = pcmd.ClipRect - local open = ImGui.TreeNode(cmd_n, "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", math.floor(pcmd.ElemCount / 3), tostring(pcmd.TexRef and (pcmd.TexRef._TexID or pcmd.TexRef._TexData)), cr.x, cr.y, cr.z, cr.w) - local function ShowMeshImpl(show_mesh, show_aabb) - local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) - local vtxs_rect = ImRect(3.4028234663853e+38 --[[FLT_MAX]], 3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]]) - local base = pcmd.IdxOffset - for i = base, base + pcmd.ElemCount - 1, 3 do - local tri = {} - for n = 0, 2 do - local vi = idx[i + n + 1] + pcmd.VtxOffset - if vi > draw_list.VtxBuffer.Size then return end - tri[n + 1] = ImVec2(ImDrawVtx_Pos(vtx, vi)) - vtxs_rect:Add(tri[n + 1]) - end - if show_mesh then fg_draw_list:AddPolyline(tri, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) end -- In yellow: mesh triangles - end - if show_aabb then - fg_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU - fg_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles - end + ImGui.BulletText("Callback %s, user_data %s", tostring(pcmd.UserCallback), tostring(pcmd.UserCallbackData)) + break -- continue + end + + local texid_desc = FormatTextureRefForDebugDisplay(pcmd.TexRef) + local cr = pcmd.ClipRect + local buf = string.format("DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + math.floor(pcmd.ElemCount / 3), texid_desc, cr.x, cr.y, cr.z, cr.w) + local pcmd_node_open = ImGui.TreeNode(cmd_n - 1, "%s", buf) + if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) + end + if not pcmd_node_open then + break -- continue + end + + -- Calculate approximate coverage area (touched pixel count) + -- This will be in pixels squared as long there's no post-scaling happening to the renderer output. + -- [Luau] index values are 1-based vertex indices relative to VtxOffset (see ImDrawVtx_Pos()) + local idx_buffer = draw_list.IdxBuffer.Data + local vtx_buffer = draw_list.VtxBuffer.Buf + local total_area = 0.0 + local idx_n = pcmd.IdxOffset + while idx_n < pcmd.IdxOffset + pcmd.ElemCount do + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + pcmd.VtxOffset)) + idx_n = idx_n + 1 end - local function ShowMesh(show_mesh, show_aabb) -- DebugNodeDrawCmdShowMeshAndBoundingBox() - if not fg_draw_list then return end - fg_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. - ShowMeshImpl(show_mesh, show_aabb) - fg_draw_list:PopDrawFlag() - end - if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) then ShowMesh(cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) end - if open then - ImGui.Selectable(string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset)) - if ImGui.IsItemHovered() then ShowMesh(true, false) end - ImGui.TreePop() + total_area = total_area + ImTriangleArea(triangle[1], triangle[2], triangle[3]) + end + + -- Display vertex information summary. Hover to get all triangles drawn in wire-frame + buf = string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset, total_area) + ImGui.Selectable(buf) + if ImGui.IsItemHovered() and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false) + end + + -- Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. + local clipper = ImGuiListClipper() + clipper:Begin(math.floor(pcmd.ElemCount / 3)) -- Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while clipper:Step() do + local idx_i = pcmd.IdxOffset + clipper.DisplayStart * 3 + for prim = clipper.DisplayStart, clipper.DisplayEnd - 1 do + local lines = {} + local triangle = {} + for n = 1, 3 do + local vi = idx_buffer[idx_i + 1] + pcmd.VtxOffset + local o = (vi - 1) * 36 --[[VTX_STRIDE]] -- [Luau] packed vertex: f64 pos.x, pos.y, uv.x, uv.y, u32 col + local px, py = ImDrawVtx_Pos(vtx_buffer, vi) + triangle[n] = ImVec2(px, py) + lines[n] = string.format("%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", + (n == 1) and "Vert:" or " ", idx_i, px, py, buffer.readf64(vtx_buffer, o + 16), buffer.readf64(vtx_buffer, o + 24), ImDrawVtx_Col(vtx_buffer, vi)) + idx_i = idx_i + 1 + end + + ImGui.Selectable(table.concat(lines), false) + if fg_draw_list and ImGui.IsItemHovered() then + fg_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + fg_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) + fg_draw_list:PopDrawFlag() + end end end - end + ImGui.TreePop() + until true end ImGui.TreePop() end +-- [DEBUG] Display mesh/aabb of a ImDrawCmd +--- @param out_draw_list ImDrawList +--- @param draw_list ImDrawList +--- @param draw_cmd ImDrawCmd +--- @param show_mesh bool +--- @param show_aabb bool +function ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(out_draw_list, draw_list, draw_cmd, show_mesh, show_aabb) + assert(show_mesh or show_aabb) + + -- Draw wire-frame version of all triangles + local cr = draw_cmd.ClipRect + local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) + local vtxs_rect = ImRect(3.4028234663853e+38 --[[FLT_MAX]], 3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]]) + out_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + local idx_n, idx_end = draw_cmd.IdxOffset, draw_cmd.IdxOffset + draw_cmd.ElemCount + while idx_n < idx_end do + local idx_buffer = draw_list.IdxBuffer.Data -- We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list + local vtx_buffer = draw_list.VtxBuffer.Buf + + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + draw_cmd.VtxOffset)) + vtxs_rect:Add(triangle[n]) + idx_n = idx_n + 1 + end + if show_mesh then + out_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) -- In yellow: mesh triangles + end + end + -- Draw bounding boxes + if show_aabb then + out_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU + out_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles + end + out_draw_list:PopDrawFlag() +end + -- [DEBUG] Display contents of ImGuiTabBar function ImGui.DebugNodeTabBar(tab_bar, label) -- Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. @@ -20947,6 +21918,11 @@ function ImGui.DebugNodeWindow(window, label) if ImGui.IsItemHovered() and is_active then YellowRect(window, window.Pos, window.Pos + window.Size) end if not open then return end if window.MemoryCompacted then ImGui.TextDisabled("Note: some memory buffers have been compacted/freed.") end + + if g.IO.ConfigDebugIsDebuggerPresent and ImGui.DebugBreakButton("**DebugBreak**", "in Begin()") then + g.DebugBreakInWindow = window.ID + end + local W = ImGuiWindowFlags local flags = window.Flags local function F(f, s) return (bit32.band(flags, f) ~= 0) and s or "" end @@ -20971,6 +21947,7 @@ function ImGui.DebugNodeWindow(window, label) else ImGui.BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window.NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y) end + ImGui.DebugLocateItemOnHover(window.NavLastIds[layer]) end ImGui.BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window.DC.NavLayersActiveMask, window.NavLastChildNavWindow and window.NavLastChildNavWindow.Name or "NULL") ImGui.BulletText("Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window.Viewport and (window.Viewport.Idx or 0) or -1, window.ViewportOwned and " (Owned)" or "", window.ViewportId or 0, window.ViewportPos.x, window.ViewportPos.y) @@ -21039,6 +22016,16 @@ function ImGui.DebugNodeViewport(viewport) end end +--- @param monitor ImGuiPlatformMonitor +--- @param label string +--- @param idx int +function ImGui.DebugNodePlatformMonitor(monitor, label, idx) + ImGui.BulletText("%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)", + label, idx, monitor.DpiScale * 100.0, + monitor.MainPos.x, monitor.MainPos.y, monitor.MainPos.x + monitor.MainSize.x, monitor.MainPos.y + monitor.MainSize.y, monitor.MainSize.x, monitor.MainSize.y, + monitor.WorkPos.x, monitor.WorkPos.y, monitor.WorkPos.x + monitor.WorkSize.x, monitor.WorkPos.y + monitor.WorkSize.y, monitor.WorkSize.x, monitor.WorkSize.y) +end + -- Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. function ImGui.DebugTextEncoding(str) ImGui.Text("Text: \"%s\"", str) @@ -21119,8 +22106,15 @@ function ImGui.ShowMetricsWindow(p_open) return p_open end + -- [DEBUG] Clear debug breaks hooks after exactly one cycle. + ImGui.DebugBreakClearData() + -- Basic info ImGui.Text("Dear ImGui %s (%d)", IMGUI_VERSION, 19298 --[[IMGUI_VERSION_NUM]]) + if g.ContextName ~= nil and g.ContextName ~= "" then + ImGui.SameLine() + ImGui.Text("(Context Name: \"%s\")", g.ContextName) + end ImGui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / math.max(io.Framerate, 0.0001), io.Framerate) ImGui.Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, math.floor(io.MetricsRenderIndices / 3)) ImGui.Text("%d visible windows, %d current allocations", io.MetricsRenderWindows, g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount) @@ -21131,6 +22125,18 @@ function ImGui.ShowMetricsWindow(p_open) -- Tools if ImGui.TreeNode("Tools") then + -- Debug Break features + -- The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. + ImGui.SeparatorTextEx(0, "Debug breaks", nil, ImGui.CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x) + ImGui.SameLine() + MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.") + local picker_toggled + picker_toggled, g.DebugItemPickerActive = ImGui.Checkbox("Show Item Picker", g.DebugItemPickerActive) + if picker_toggled and g.DebugItemPickerActive then + ImGui.DebugStartItemPicker() + end + _, io.ConfigDebugIsDebuggerPresent = ImGui.Checkbox("Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", io.ConfigDebugIsDebuggerPresent) + ImGui.SeparatorText("Visualize") _, cfg.ShowDebugLog = ImGui.Checkbox("Show Debug Log", cfg.ShowDebugLog == true) ImGui.SameLine(); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code.") @@ -21211,12 +22217,47 @@ function ImGui.ShowMetricsWindow(p_open) -- Viewports if ImGui.TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size) then + cfg.HighlightMonitorIdx = -1 + local open = ImGui.TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size) + ImGui.SameLine() + MetricsHelpMarker("Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors.") + if open then + for i = 1, g.PlatformIO.Monitors.Size do + ImGui.DebugNodePlatformMonitor(g.PlatformIO.Monitors.Data[i], "Monitor", i - 1) + if ImGui.IsItemHovered() then + cfg.HighlightMonitorIdx = i - 1 -- 0-based, like Monitors:index_from_ptr() + end + end + if g.FallbackMonitor then ImGui.DebugNodePlatformMonitor(g.FallbackMonitor, "Fallback", 0) end + ImGui.TreePop() + end + ImGui.SetNextItemOpen(true, 2 --[[ImGuiCond.Once]]) if ImGui.TreeNode("Windows Minimap") then ImGui.RenderViewportsThumbnails() ImGui.TreePop() end cfg.HighlightViewportID = 0 + + ImGui.BulletText("MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)", g.MouseViewport and g.MouseViewport.ID or 0, g.IO.MouseHoveredViewport or 0, g.MouseLastHoveredViewport and g.MouseLastHoveredViewport.ID or 0) + if ImGui.TreeNode("Inferred Z order (front-to-back)") then + local viewports = {} + for n = 1, g.Viewports.Size do viewports[n] = g.Viewports.Data[n] end + if #viewports > 1 then + table.sort(viewports, ViewportComparerByLastFocusedStampCount) + end + for _, viewport in ipairs(viewports) do + ImGui.BulletText("Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"", + viewport.Idx, viewport.ID, viewport.LastFocusedStampCount, + (g.PlatformIO.Platform_GetWindowFocus and viewport.PlatformWindowCreated) and (g.PlatformIO.Platform_GetWindowFocus(viewport) and "1" or "0") or "N/A", + viewport.Window and viewport.Window.Name or "N/A") + if ImGui.IsItemHovered() then + cfg.HighlightViewportID = viewport.ID + end + end + ImGui.TreePop() + end + for _, viewport in g.Viewports:iter() do ImGui.DebugNodeViewport(viewport) end ImGui.TreePop() end @@ -21361,6 +22402,12 @@ function ImGui.ShowMetricsWindow(p_open) if ImGui.IsKeyReleased(key) then ImGui.SameLine(); ImGui.Text("\"%s\"", ImGui.GetKeyName(key)) end end ImGui.Text("Keys mods: %s%s%s%s", io.KeyCtrl and "Ctrl " or "", io.KeyShift and "Shift " or "", io.KeyAlt and "Alt " or "", io.KeySuper and "Super " or "") + ImGui.Text("Chars queue:") + for i = 1, io.InputQueueCharacters.Size do + local c = io.InputQueueCharacters.Data[i] + ImGui.SameLine(); ImGui.Text("'%s' (0x%04X)", (c > 32 and c <= 255) and string.char(c) or "?", c) -- FIXME: We should convert 'c' to UTF-8 here but the functions are not public. + end + ImGui.DebugRenderKeyboardPreview(ImGui.GetWindowDrawList()) ImGui.Unindent() ImGui.Text("MOUSE STATE") ImGui.Indent() @@ -21374,6 +22421,7 @@ function ImGui.ShowMetricsWindow(p_open) for i = 0, 2 do if ImGui.IsMouseReleased(i) then ImGui.SameLine(); ImGui.Text("b%d", i) end end ImGui.Text("Mouse wheel: %.1f", io.MouseWheel) ImGui.Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer) + ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource or 0 --[[ImGuiMouseSource.Mouse]])) -- [Luau] field may be unset (C++: zero-initialized) ImGui.Unindent() ImGui.Text("MOUSE WHEELING") ImGui.Indent() @@ -21397,16 +22445,20 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.Unindent() ImGui.Text("ITEMS") ImGui.Indent() - ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap)) + ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap), GetInputSourceName(g.ActiveIdSource or 0 --[[ImGuiInputSource.None]])) -- [Luau] field may be unset (C++: zero-initialized) + ImGui.DebugLocateItemOnHover(g.ActiveId) ImGui.Text("ActiveIdWindow: '%s'", N(g.ActiveIdWindow)) ImGui.Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, B(g.HoveredIdAllowOverlap)) -- Not displaying g.HoveredId as it is update mid-frame ImGui.Text("HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId or 0, g.HoverItemDelayTimer or 0, g.HoverItemDelayClearTimer or 0) ImGui.Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\"", B(g.DragDropActive), g.DragDropPayload.SourceId or 0, tostring(g.DragDropPayload.DataType or "")) + ImGui.DebugLocateItemOnHover(g.DragDropPayload.SourceId or 0) ImGui.Unindent() ImGui.Text("NAV,FOCUS") ImGui.Indent() ImGui.Text("NavWindow: '%s'", N(g.NavWindow)) ImGui.Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer) + ImGui.DebugLocateItemOnHover(g.NavId) + ImGui.Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource or 0 --[[ImGuiInputSource.None]])) ImGui.Text("NavLastValidSelectionUserData = %s", tostring(g.NavLastValidSelectionUserData)) -- [Port] any Lua value: tostring() instead of %lld (0x%llX) ImGui.Text("NavActive: %d, NavVisible: %d", B(io.NavActive), B(io.NavVisible)) ImGui.Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId or 0, g.NavActivatePressedId or 0) @@ -21457,6 +22509,68 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.End() return p_open end + +function ImGui.DebugBreakClearData() + -- Those fields are scattered in their respective subsystem to stay in hot-data locations + local g = GImGui + g.DebugBreakInWindow = 0 + g.DebugBreakInTable = 0 + g.DebugBreakInShortcutRouting = 0 --[[ImGuiKey.None]] +end + +--- @param keyboard_only bool +--- @param description_of_location string +function ImGui.DebugBreakButtonTooltip(keyboard_only, description_of_location) + if not ImGui.BeginItemTooltip() then + return + end + ImGui.Text("To call IM_DEBUG_BREAK() %s:", description_of_location) + ImGui.Separator() + ImGui.TextUnformatted(keyboard_only and "- Press 'Pause/Break' on keyboard." or "- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space.") + ImGui.Separator() + ImGui.TextUnformatted("Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!") -- [Luau] IM_DEBUG_BREAK() calls g.DebugBreakCallback (if set) instead + ImGui.EndTooltip() +end + +-- Special button that doesn't take focus, doesn't take input owner, and can be activated without a click etc. +-- In order to reduce interferences with the contents we are trying to debug into. +--- @param label string +--- @param description_of_location string +--- @return bool +function ImGui.DebugBreakButton(label, description_of_location) + local window = ImGui.GetCurrentWindow() + if window.SkipItems then + return false + end + + local g = GImGui + local id = window:GetID(label) + local label_size = ImGui.CalcTextSize(label, nil, true) + local pos = window.DC.CursorPos + ImVec2(0.0, window.DC.CurrLineTextBaseOffset) + local size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0, label_size.y) + + local bb = ImRect(pos, pos + size) + ImGui.ItemSize(size, 0.0) + if not ImGui.ItemAdd(bb, id) then + return false + end + + -- WE DO NOT USE ButtonEx() or ButtonBehavior() in order to reduce our side-effects. + local hovered = ImGui.ItemHoverable(bb, id, g.CurrentItemFlags) + local pressed = hovered and (ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) or ImGui.IsMouseClicked(0) or g.NavActivateId == id) + ImGui.DebugBreakButtonTooltip(false, description_of_location) + + local src = ImGui.GetStyleColorVec4(hovered and 23 --[[ImGuiCol.ButtonHovered]] or 22 --[[ImGuiCol.Button]]) + local col4f = ImVec4(src.x, src.y, src.z, src.w) -- [Luau] copy + local h, s, v = ImGui.ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z) + col4f.x, col4f.y, col4f.z = ImGui.ColorConvertHSVtoRGB(h + 0.20, s, v) + + ImGui.RenderNavCursor(bb, id) + ImGui.RenderFrame(bb.Min, bb.Max, ImGui.GetColorU32(col4f), true, g.Style.FrameRounding) + ImGui.RenderTextClipped(bb.Min, bb.Max, label, nil, label_size, g.Style.ButtonTextAlign, bb) + + return pressed +end end --[[ [SECTION] METRICS/DEBUGGER WINDOW, DEBUG LOG, ID STACK TOOL, FONT DEBUG ]] return true -- [Roblox] ModuleScripts must return exactly one value @@ -21679,7 +22793,7 @@ function ShowDockingDisabledMessage() end -- Helper to wire demo markers located in code to an interactive browser (e.g. https://pthom.github.io/imgui_explorer) -function IMGUI_DEMO_MARKER(section) end -- [Port] no ImGui.DemoMarker() hook in this port: no-op +function IMGUI_DEMO_MARKER(section) ImGui.DemoMarker("imgui_demo.lua", 0, section) end -- [Port] no __LINE__ in Lua: line is 0 -- Sneakily forward declare functions which aren't worth putting in public API yet -- [Port] ImGui.ShowFontAtlas(atlas) and ImGui.TreeNodeSetOpen(storage_id, is_open) are already public here. @@ -22163,8 +23277,7 @@ function DemoWindowMenuBar(demo_data) _, demo_data.ShowDebugLog = ImGui.MenuItem("Debug Log", nil, demo_data.ShowDebugLog, has_debug_tools) _, demo_data.ShowIDStackTool = ImGui.MenuItem("ID Stack Tool", nil, demo_data.ShowIDStackTool, has_debug_tools) local is_debugger_present = io.ConfigDebugIsDebuggerPresent - local has_item_picker = ImGui.DebugStartItemPicker ~= nil -- [Port] ImGui.DebugStartItemPicker() is not ported yet: menu item disabled until it is - if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools and has_item_picker) then -- and is_debugger_present + if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools) then -- and is_debugger_present ImGui.DebugStartItemPicker() end if not is_debugger_present then @@ -30369,7 +31482,7 @@ function ImGui.ShowStyleEditor(ref) end ImGui.PushID(i) if ImGui.Button("?") then - if ImGui.DebugFlashStyleColor then ImGui.DebugFlashStyleColor(i) end -- [Port] DebugFlashStyleColor() is not in the library yet + ImGui.DebugFlashStyleColor(i) end ImGui.SetItemTooltip("Flash given color to identify places where it is used.") ImGui.SameLine() @@ -37472,6 +38585,42 @@ function MT.ImDrawData:AddDrawList(draw_list) ImGui.AddDrawListToDrawDataEx(self, self.CmdLists, draw_list) end +-- For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! +-- [Luau] IdxBuffer values are 1-based vertex indices +function MT.ImDrawData:DeIndexAllBuffers() + local new_vtx_buffer = ImDrawVtxBuffer() + self.TotalVtxCount = 0; self.TotalIdxCount = 0 + for i = 1, self.CmdLists.Size do + repeat + local draw_list = self.CmdLists.Data[i] + if draw_list.IdxBuffer.Size == 0 then + break -- continue + end + new_vtx_buffer:resize(draw_list.IdxBuffer.Size) + local src, dst, idx = draw_list.VtxBuffer.Buf, new_vtx_buffer.Buf, draw_list.IdxBuffer.Data + for j = 1, draw_list.IdxBuffer.Size do + buffer.copy(dst, (j - 1) * 36 --[[VTX_STRIDE]], src, (idx[j] - 1) * 36 --[[VTX_STRIDE]], 36 --[[VTX_STRIDE]]) + end + draw_list.VtxBuffer, new_vtx_buffer = new_vtx_buffer, draw_list.VtxBuffer -- swap() + draw_list.IdxBuffer:resize(0) + self.TotalVtxCount = self.TotalVtxCount + draw_list.VtxBuffer.Size + until true + end +end + +-- Helper to scale the ClipRect field of each ImDrawCmd. +-- Use if your final output buffer is at a different scale than draw_data->DisplaySize, +-- or if there is a difference between your window resolution and framebuffer resolution. +function MT.ImDrawData:ScaleClipRects(fb_scale) + for i = 1, self.CmdLists.Size do + local draw_list = self.CmdLists.Data[i] + for j = 1, draw_list.CmdBuffer.Size do + local cmd = draw_list.CmdBuffer.Data[j] + cmd.ClipRect = ImVec4(cmd.ClipRect.x * fb_scale.x, cmd.ClipRect.y * fb_scale.y, cmd.ClipRect.z * fb_scale.x, cmd.ClipRect.w * fb_scale.y) + end + end +end + local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN = 4 local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX = 512 @@ -37579,6 +38728,29 @@ function MT.ImDrawList:_ClearFreeMemory() self._Splitter:ClearFreeMemory() end +-- Note: For multi-threaded rendering, consider using `imgui_threaded_rendering` from https://github.com/ocornut/imgui_club +-- [Luau] C++ copies the vectors by value: copy the ImDrawCmd structs and the vertex buffer bytes +--- @return ImDrawList +function MT.ImDrawList:CloneOutput() + local dst = ImDrawList(nil) + for i = 1, self.CmdBuffer.Size do + local src_cmd = self.CmdBuffer.Data[i] + local cmd = ImDrawCmd() + for k, v in pairs(src_cmd) do cmd[k] = v end + cmd.ClipRect = ImVec4(src_cmd.ClipRect.x, src_cmd.ClipRect.y, src_cmd.ClipRect.z, src_cmd.ClipRect.w) + if src_cmd.TexRef then cmd.TexRef = ImTextureRef(src_cmd.TexRef._TexID); cmd.TexRef._TexData = src_cmd.TexRef._TexData end + dst.CmdBuffer:push_back(cmd) + end + if self.IdxBuffer.Size > 0 then + dst.IdxBuffer:resize(self.IdxBuffer.Size) + table.move(self.IdxBuffer.Data, 1, self.IdxBuffer.Size, 1, dst.IdxBuffer.Data) + end + dst.VtxBuffer:resize(self.VtxBuffer.Size) + buffer.copy(dst.VtxBuffer.Buf, 0, self.VtxBuffer.Buf, 0, self.VtxBuffer.Size * 36 --[[VTX_STRIDE]]) + dst.Flags = self.Flags + return dst +end + function MT.ImDrawList:AddDrawCmd() local draw_cmd = ImDrawCmd() @@ -38136,6 +39308,22 @@ function MT.ImDrawList:PrimRectUV(a, c, uv_a, uv_c, col) self._IdxWritePtr = idx_write_ptr + 6 end +function MT.ImDrawList:PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col) + local idx = self._VtxCurrentIdx + local idx_data = self.IdxBuffer.Data; local vtx_data = self.VtxBuffer.Buf + local idx_write_ptr = self._IdxWritePtr + idx_data[idx_write_ptr + 0] = idx; idx_data[idx_write_ptr + 1] = idx + 1; idx_data[idx_write_ptr + 2] = idx + 2 + idx_data[idx_write_ptr + 3] = idx; idx_data[idx_write_ptr + 4] = idx + 2; idx_data[idx_write_ptr + 5] = idx + 3 + local vtx_write_ptr = self._VtxWritePtr + WV(vtx_data, vtx_write_ptr + 0, a.x, a.y, uv_a.x, uv_a.y, col) + WV(vtx_data, vtx_write_ptr + 1, b.x, b.y, uv_b.x, uv_b.y, col) + WV(vtx_data, vtx_write_ptr + 2, c.x, c.y, uv_c.x, uv_c.y, col) + WV(vtx_data, vtx_write_ptr + 3, d.x, d.y, uv_d.x, uv_d.y, col) + self._VtxWritePtr = vtx_write_ptr + 4 + self._VtxCurrentIdx = idx + 4 + self._IdxWritePtr = idx_write_ptr + 6 +end + --- @param thickness float --- @return float -- [Luau] local function (also MT.ImDrawList._CalculateCenterBiasedOffset) @@ -40125,6 +41313,30 @@ function MT.ImDrawList:AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col) end end +function MT.ImDrawList:AddImageQuad(tex_ref, p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + if uv1 == nil then uv1 = ImVec2(0, 0) end + if uv2 == nil then uv2 = ImVec2(1, 0) end + if uv3 == nil then uv3 = ImVec2(1, 1) end + if uv4 == nil then uv4 = ImVec2(0, 1) end + if col == nil then col = 4294967295 --[[IM_COL32_WHITE]] end + + if bit32.band(col, 4278190080 --[[IM_COL32_A_MASK]]) == 0 then + return + end + + local push_texture_id = tex_ref ~= self._CmdHeader.TexRef + if push_texture_id then + self:PushTexture(tex_ref) + end + + self:PrimReserve(6, 4) + self:PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + + if push_texture_id then + self:PopTexture() + end +end + --- @param tex_ref ImTextureRef --- @param p_min ImVec2 --- @param p_max ImVec2 @@ -40218,6 +41430,9 @@ function MT.ImDrawList:PopClipRect() self:_OnChangedClipRect() end +function MT.ImDrawList:GetClipRectMin() local cr = self._ClipRectStack:back(); return ImVec2(cr.x, cr.y) end +function MT.ImDrawList:GetClipRectMax() local cr = self._ClipRectStack:back(); return ImVec2(cr.z, cr.w) end + --- @param center ImVec2 --- @param radius float --- @param a_min_sample int @@ -42019,8 +43234,8 @@ end --- @field UserCallbackData any --- @field UserCallbackDataSize int --- @field UserCallbackDataOffset int -local IM_DRAWCMD = {} -IM_DRAWCMD.__index = IM_DRAWCMD +MT.ImDrawCmd = {} +MT.ImDrawCmd.__index = MT.ImDrawCmd --- @return ImDrawCmd --- @nodiscard @@ -42035,11 +43250,11 @@ function ImDrawCmd() UserCallbackData = nil, -- 4-8 -- Callback user data (when UserCallback != nil). If called AddCallback() with size == 0, this is a copy of the AddCallback() argument. If called AddCallback() with size > 0, this is pointing to a buffer where data is stored. UserCallbackDataSize = 0, -- 4 -- Size of callback user data when using storage, otherwise 0. UserCallbackDataOffset = 0 -- 4 -- [Internal] Offset of callback user data when using storage, otherwise -1. - }, IM_DRAWCMD) + }, MT.ImDrawCmd) end --- @return ImTextureID -function IM_DRAWCMD:GetTexID() +function MT.ImDrawCmd:GetTexID() local tex_id = (self.TexRef._TexData) and self.TexRef._TexData.TexID or self.TexRef._TexID if self.TexRef._TexData ~= nil then assert(tex_id ~= (-1) --[[ImTextureID_Invalid]], "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!") @@ -42295,11 +43510,14 @@ end --- @param x int --- @param y int +function MT.ImTextureData:GetPixels() assert(self.Pixels ~= nil); return self.Pixels end function MT.ImTextureData:GetPixelsAt(x, y) return self.Pixels, (x + y * self.Width) * self.BytesPerPixel + 1 end +function MT.ImTextureData:GetSizeInBytes() return self.Width * self.Height * self.BytesPerPixel end function MT.ImTextureData:GetPitch() return self.Width * self.BytesPerPixel end +function MT.ImTextureData:GetTexRef() local tex_ref = ImTextureRef(); tex_ref._TexData = self; tex_ref._TexID = (-1) --[[ImTextureID_Invalid]]; return tex_ref end function MT.ImTextureData:GetTexID() return self.TexID end --- @param tex_id ImTextureID @@ -42319,8 +43537,8 @@ function MT.ImTextureData:SetStatus(status) self.Status = status if (status == 1 --- @class ImTextureRef --- @field _TexData? ImTextureData --- @field _TexID ImTextureID -local IM_TEXTURE_REF = {} -IM_TEXTURE_REF.__index = IM_TEXTURE_REF +MT.ImTextureRef = {} +MT.ImTextureRef.__index = MT.ImTextureRef --- @return ImTextureRef --- @nodiscard @@ -42329,7 +43547,14 @@ function ImTextureRef(tex_id) -- Members (either are set, never both!) _TexData = nil, -- A texture, generally owned by a ImFontAtlas. Will convert to ImTextureID during render loop, after texture has been uploaded. _TexID = tex_id or (-1) --[[ImTextureID_Invalid]] -- _OR_ Low-level backend texture identifier, if already uploaded or created by user/app. Generally provided to e.g. ImGui.Image() calls. - }, IM_TEXTURE_REF) + }, MT.ImTextureRef) +end + +-- This is provided for consistency (but we don't actually use this) +--- @return ImTextureID +function MT.ImTextureRef:GetTexID() + assert(not (self._TexData ~= nil and self._TexID ~= (-1) --[[ImTextureID_Invalid]])) + if self._TexData then return self._TexData.TexID else return self._TexID end end ------------------------------------------------------------------------------- @@ -44063,7 +45288,8 @@ function MT.ImGuiInputTextCallbackData:InsertChars(pos, new_text) self.SelectionStart = self.CursorPos; self.SelectionEnd = self.CursorPos end -function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.CursorPos = self.BufTextLen; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SetSelection(s, e) assert(s >= 0 and s <= self.BufTextLen); assert(e >= 0 and e <= self.BufTextLen); self.SelectionStart = s; self.CursorPos = e; self.SelectionEnd = e end function MT.ImGuiInputTextCallbackData:ClearSelection() self.SelectionStart = self.BufTextLen; self.SelectionEnd = self.BufTextLen end function MT.ImGuiInputTextCallbackData:HasSelection() return self.SelectionStart ~= self.SelectionEnd end @@ -53211,6 +54437,27 @@ function ImCharIsBlankA(c) return c == 32 or c == 9 end --- @param c char function ImCharIsBlankW(c) return c == 32 or c == 9 or c == 0x3000 end +--- @param c char +function ImCharIsXdigitA(c) return (c >= 48 and c <= 57) or (c >= 65 and c <= 70) or (c >= 97 and c <= 102) end + +--- @param lhs ImVec2 +--- @param fail_value float +function ImInvLength(lhs, fail_value) local d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if d > 0.0 then return ImRsqrt(d) end; return fail_value end +function ImRoundPositive64(f) return _Trunc(f + 0.5) end -- Positive values only. +function ImRoundSigned64(f) if f >= 0.0 then return _Trunc(f + 0.5) else return _Trunc(f - 0.5) end end +-- [Luau] C '%' truncates toward zero; math.fmod matches it +function ImModPositive(a, b) return math.fmod(a + b, b) end +function ImIsFloatAboveGuaranteedIntegerPrecision(f) return f <= -16777216 or f >= 16777216 end + +-- Helper: ImVec2i (2D vector, integer) / ImVec2ih (2D vector, half-size integer, for long-term packed storage) +-- [Luau] both are plain ImVec2 holding whole numbers +function ImVec2i(x, y) return ImVec2(x or 0, y or 0) end +--- @overload fun(rhs: ImVec2): ImVec2 +function ImVec2ih(x, y) + if type(x) == "table" then return ImVec2(_Trunc(x.x), _Trunc(x.y)) end + return ImVec2(x or 0, y or 0) +end + --- @enum ImGuiNavMoveFlags ImGuiNavMoveFlags = { @@ -53509,6 +54756,28 @@ function ImBitArraySetBit(arr, n) arr[idx] = bitOr(arr[idx], mask) end +-- [Luau] bit arrays are ImU32[] tables with 1-based word indices; bit indices 'n' are 1-based like the functions above +--- @param bitcount int +function ImBitArrayGetStorageSizeInBytes(bitcount) return bitLShift(bitRShift(bitcount + 31, 5), 2) end +--- @param arr ImU32[] +--- @param bitcount int +function ImBitArrayClearAllBits(arr, bitcount) for i = 1, bitRShift(bitcount + 31, 5) do arr[i] = 0 end end +function ImBitArrayTestBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); return bitAnd(arr[bitRShift(n - 1, 5) + 1], mask) ~= 0 end +function ImBitArrayClearBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); local idx = bitRShift(n - 1, 5) + 1; arr[idx] = bitAnd(arr[idx], bitNot(mask)) end +-- Works on range [n..n2) +function ImBitArraySetBitRange(arr, n, n2) + n = n - 1; n2 = n2 - 1 -- [Luau] to 0-based + n2 = n2 - 1 + while n <= n2 do + local a_mod = bitAnd(n, 31) + local b_mod = ((n2 > bitOr(n, 31)) and 31 or bitAnd(n2, 31)) + 1 + local mask = bitAnd(2 ^ b_mod - 1, bitNot(2 ^ a_mod - 1)) + local idx = bitRShift(n, 5) + 1 + arr[idx] = bitOr(arr[idx], mask) + n = bitAnd(n + 32, bitNot(31)) + end +end + -- Bit array for named keys --- @alias ImBitArrayForNamedKeys ImBitArray @@ -53535,11 +54804,30 @@ function ImBitArray(BITCOUNT, OFFSET) --- @param n int # 1-based this.SetBit = function(self, n) n = n + OFFSET; assert(n >= 1 and n <= BITCOUNT); ImBitArraySetBit(self.Data, n); end + --- @param n int # 1-based + this.ClearBit = function(self, n) n = n + OFFSET; assert(n >= 1 and n <= BITCOUNT); ImBitArrayClearBit(self.Data, n); end + --- @param n int # 1-based, range [n..n2) + this.SetBitRange = function(self, n, n2) n = n + OFFSET; n2 = n2 + OFFSET; assert(n >= 1 and n <= BITCOUNT and n2 > n and n2 <= BITCOUNT + 1); ImBitArraySetBitRange(self.Data, n, n2); end + this:ClearAllBits() return this end +-- Helper: ImBitVector +-- Store 1-bit per value. +--- @class ImBitVector +--- @field Storage ImVector +MT.ImBitVector = {} +MT.ImBitVector.__index = MT.ImBitVector +function ImBitVector() return setmetatable({ Storage = ImVector() }, MT.ImBitVector) end +function MT.ImBitVector:Create(sz) self.Storage:resize(bitRShift(sz + 31, 5)); for i = 1, self.Storage.Size do self.Storage.Data[i] = 0 end end +function MT.ImBitVector:Clear() self.Storage:clear() end +--- @param n int # 1-based +function MT.ImBitVector:TestBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); return IM_BITARRAY_TESTBIT(self.Storage.Data, n) end +function MT.ImBitVector:SetBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); ImBitArraySetBit(self.Storage.Data, n) end +function MT.ImBitVector:ClearBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); ImBitArrayClearBit(self.Storage.Data, n) end + -- Stateful path API, add points then finish with PathFillConvex() or PathStroke() -- - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. -- so e.g. 'PathArcTo(center, radius, PI * -0.5, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5)' won't have correct anti-aliasing when followed by PathFillConvex(). @@ -53771,9 +55059,13 @@ end --- @param key string --- @return ImGuiStyleVarInfo --- @nodiscard +MT.ImGuiStyleVarInfo = {} +MT.ImGuiStyleVarInfo.__index = MT.ImGuiStyleVarInfo function ImGuiStyleVarInfo(count, data_type, key) - return { Count = count, DataType = data_type, Key = key } + return setmetatable({ Count = count, DataType = data_type, Key = key }, MT.ImGuiStyleVarInfo) end +-- [Luau] no pointers: returns the field value (number, or the live ImVec2 table) of 'parent' (e.g. ImGuiStyle) +function MT.ImGuiStyleVarInfo:GetVarPtr(parent) return parent[self.Key] end -- Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. --- @class ImGuiStyleMod @@ -53888,11 +55180,11 @@ end --- @field RefVal any --- @field StorageId ImGuiID --- @field ColorMarker ImU32 -local IMGUI_NEXT_ITEM_DATA = {} -IMGUI_NEXT_ITEM_DATA.__index = IMGUI_NEXT_ITEM_DATA +MT.ImGuiNextItemData = {} +MT.ImGuiNextItemData.__index = MT.ImGuiNextItemData -- Also cleared manually by ItemAdd()! -function IMGUI_NEXT_ITEM_DATA:ClearFlags() +function MT.ImGuiNextItemData:ClearFlags() self.HasFlags = 0 --[[ImGuiNextItemDataFlags.None]] self.ItemFlagsSet = 0 --[[ImGuiItemFlags.None]] end @@ -53915,7 +55207,7 @@ function ImGuiNextItemData() RefVal = 0, -- Not exposed yet, for ImGuiInputTextFlags.ParseEmptyAsRefVal StorageId = 0, -- Set by SetNextItemStorageID() ColorMarker = 0 -- Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags.ColorMarkers. - }, IMGUI_NEXT_ITEM_DATA) + }, MT.ImGuiNextItemData) end -- Storage for SetNexWindow** functions @@ -53938,10 +55230,10 @@ end --- @field BgAlphaVal number? --- @field MenuBarOffsetMinVal ImVec2? --- @field RefreshFlagsVal int? -local IMGUI_NEXT_WINDOW_DATA = {} -IMGUI_NEXT_WINDOW_DATA.__index = IMGUI_NEXT_WINDOW_DATA +MT.ImGuiNextWindowData = {} +MT.ImGuiNextWindowData.__index = MT.ImGuiNextWindowData -function IMGUI_NEXT_WINDOW_DATA:ClearFlags() +function MT.ImGuiNextWindowData:ClearFlags() self.HasFlags = 0 --[[ImGuiNextWindowDataFlags.None]] end @@ -53980,7 +55272,7 @@ function ImGuiNextWindowData() RefreshFlagsVal = nil, CacheKeySet = false, -- [Port] SetNextWindowCached() CacheKeyVal = nil - }, IMGUI_NEXT_WINDOW_DATA) + }, MT.ImGuiNextWindowData) end --- @enum ImGuiWindowBgClickFlags @@ -54243,21 +55535,29 @@ local function ImGuiInputTextState() SelectedAllMouseLock = false, -- after a double-click to select all, we ignore further mouse drags to update selection EditedBefore = false, -- edited since activated EditedThisFrame = false, -- edited this frame + WantReloadUserBuf = false, -- force a reload of user buf so it may be modified externally. may be automatic in future version. + LastMoveDirectionLR = 0 --[[ImGuiDir.Left]], -- ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s + ReloadSelectionStart = 0, + ReloadSelectionEnd = 0, } return setmetatable(this, MT.ImGuiInputTextState) end +function MT.ImGuiInputTextState:ClearText() self.TextLen = 0; self.TextA.Data[1] = 0; self:CursorClamp() end +function MT.ImGuiInputTextState:ClearFreeMemory() self.TextA:clear(); self.TextToRevertTo:clear() end +function MT.ImGuiInputTextState:GetText() if self.TextA.Data then return self.TextA.Data else return { 0 } end end -- [Luau] byte table (char[]) + -- Internal temporary state for deactivating InputText() instances. -- Store as part of ImGuiDeactivatedItemData? --- @class ImGuiInputTextDeactivatedState --- @field ID ImGuiID # widget id owning the text state (which just got deactivated) --- @field ElapseFrame int --- @field TextA ImVector # text buffer -local IMGUI_INPUT_TEXT_DEACTIVATED_STATE = {} -IMGUI_INPUT_TEXT_DEACTIVATED_STATE.__index = IMGUI_INPUT_TEXT_DEACTIVATED_STATE +MT.ImGuiInputTextDeactivatedState = {} +MT.ImGuiInputTextDeactivatedState.__index = MT.ImGuiInputTextDeactivatedState -function IMGUI_INPUT_TEXT_DEACTIVATED_STATE:ClearFreeMemory() +function MT.ImGuiInputTextDeactivatedState:ClearFreeMemory() self.ID = 0 self.ElapseFrame = 0 self.TextA:clear() @@ -54270,7 +55570,7 @@ local function ImGuiInputTextDeactivatedState() ID = 0, -- widget id owning the text state (which just got deactivated) ElapseFrame = 0, TextA = ImVector() -- text buffer - }, IMGUI_INPUT_TEXT_DEACTIVATED_STATE) + }, MT.ImGuiInputTextDeactivatedState) end --- @alias ImGuiKeyRoutingIndex ImS16 @@ -54303,10 +55603,10 @@ end --- @field Index ImGuiKeyRoutingIndex[] # Index of first entry in Entries[] --- @field Entries ImVector --- @field EntriesNext ImVector # Double-buffer to avoid reallocation (could use a shared buffer) -local _ImGuiKeyRoutingTable = {} -_ImGuiKeyRoutingTable.__index = _ImGuiKeyRoutingTable +MT.ImGuiKeyRoutingTable = {} +MT.ImGuiKeyRoutingTable.__index = MT.ImGuiKeyRoutingTable -function _ImGuiKeyRoutingTable:Clear() +function MT.ImGuiKeyRoutingTable:Clear() for n = 1, 155 --[[ImGuiKey.NamedKey_COUNT]] do self.Index[n] = -1 end self.Entries:clear() self.EntriesNext:clear() @@ -54318,7 +55618,7 @@ local function ImGuiKeyRoutingTable() Index = {}, -- Index of first entry in Entries[] Entries = ImVector(), EntriesNext = ImVector() -- Double-buffer to avoid reallocation (could use a shared buffer) - }, _ImGuiKeyRoutingTable) + }, MT.ImGuiKeyRoutingTable) this:Clear() @@ -54404,10 +55704,10 @@ end --- @field DistBox float # Move -- Best candidate box distance to current NavId --- @field DistCenter float # Move -- Best candidate center distance to current NavId --- @field DistAxial float # Move -- Best candidate axial distance to current NavId -local IMGUI_NAV_ITEM_DATA = {} -IMGUI_NAV_ITEM_DATA.__index = IMGUI_NAV_ITEM_DATA +MT.ImGuiNavItemData = {} +MT.ImGuiNavItemData.__index = MT.ImGuiNavItemData -function IMGUI_NAV_ITEM_DATA:Clear() +function MT.ImGuiNavItemData:Clear() self.Window = nil self.ID = 0 self.FocusScopeId = 0 @@ -54420,7 +55720,7 @@ end --- @return ImGuiNavItemData local function ImGuiNavItemData() - local this = setmetatable({ }, IMGUI_NAV_ITEM_DATA) + local this = setmetatable({ }, MT.ImGuiNavItemData) this.RectRel = ImRect() this:Clear() return this @@ -54993,7 +56293,7 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct DockContext = ImGuiDockContext(), DockNodeWindowMenuHandler = nil, DebugHoveredDockNode = nil, -- Hovered dock node. - CurrentTabBarStack = ImVector(), -- holds ImGuiTabBar references directly (no ImGuiPtrOrIndex needed in Lua) + CurrentTabBarStack = ImVector(), -- ImVector ShrinkWidthBuffer = ImVector(), -- ImGuiShrinkWidthItem -- Multi-Select state @@ -55157,10 +56457,10 @@ end --- @field WantApply bool # Set when loaded from .ini data --- @field WantDelete bool # Set to invalidate/delete the settings entry --- @field Name string # Window name -local IMGUI_WINDOW_SETTINGS = {} -IMGUI_WINDOW_SETTINGS.__index = IMGUI_WINDOW_SETTINGS +MT.ImGuiWindowSettings = {} +MT.ImGuiWindowSettings.__index = MT.ImGuiWindowSettings -function IMGUI_WINDOW_SETTINGS:GetName() +function MT.ImGuiWindowSettings:GetName() return self.Name end @@ -55180,7 +56480,7 @@ function ImGuiWindowSettings() DockOrder = -1, -- Order of the last time the window was visible within its DockNode. This is used to reorder windows that are reappearing on the same frame. Same value between windows that were active and windows that were none are possible. ClassId = 0, -- ID of window class if specified LastUsedDate = 0, - }, IMGUI_WINDOW_SETTINGS) + }, MT.ImGuiWindowSettings) end -- Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. @@ -55896,6 +57196,8 @@ function ImGuiInputEvent() end -- [Internal] Key ranges +ImGuiKey_LegacyNativeKey_BEGIN = 0 +ImGuiKey_LegacyNativeKey_END = 512 ImGuiKey_Keyboard_BEGIN = ImGuiKey.NamedKey_BEGIN ImGuiKey_Keyboard_END = ImGuiKey.GamepadStart ImGuiKey_Gamepad_BEGIN = ImGuiKey.GamepadStart @@ -56220,6 +57522,87 @@ end --- @nodiscard function ImGuiFocusScopeData() return { ID = nil, WindowID = nil } end +------------------------------------------------------------------------------- +-- [Luau] Inline struct helpers / constructors from imgui.h + imgui_internal.h +------------------------------------------------------------------------------- + +-- Helper for running a block of code not more than once a frame +-- [Luau] no operator bool(): call the object, e.g. 'if once() then ... end' +MT.ImGuiOnceUponAFrame = {} +MT.ImGuiOnceUponAFrame.__index = MT.ImGuiOnceUponAFrame +MT.ImGuiOnceUponAFrame.__call = function(self) local current_frame = ImGui.GetFrameCount(); if self.RefFrame == current_frame then return false end; self.RefFrame = current_frame; return true end +function ImGuiOnceUponAFrame() return setmetatable({ RefFrame = -1 }, MT.ImGuiOnceUponAFrame) end + +-- [Internal] ImGuiTextFilter item +-- [Luau] stores the item text as a Lua string (upstream: Begin pointer + Len) +--- @param buf string +--- @param b int # 1-based +--- @param e int # exclusive +function ImGuiTextFilterItem(buf, b, e) assert(e > b); return { Text = string.sub(buf, b, e - 1), CountInclude = 0, MatchIncludesMask = 0 } end + +-- A date in YYYYMMDD format packed into 16-bits +--- @class ImGuiPackedDate +MT.ImGuiPackedDate = {} +MT.ImGuiPackedDate.__index = MT.ImGuiPackedDate +--- @param yyyymmdd? int +function ImGuiPackedDate(yyyymmdd) + local this = setmetatable({ Year = 0, Month = 0, Day = 0 }, MT.ImGuiPackedDate) + if yyyymmdd ~= nil then -- Pack + this.Year = bitAnd(math.floor(yyyymmdd / 10000) - 2000, 0x7F) -- Year since 2000 (7 bits) + this.Month = bitAnd(math.floor(yyyymmdd / 100) % 100, 0x0F) -- Month (1-12) (4 bits) + this.Day = bitAnd(yyyymmdd % 100, 0x1F) -- Day (1-31) (5 bits) + end + return this +end +function MT.ImGuiPackedDate:IsValid() return self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 end +function MT.ImGuiPackedDate:Unpack() if self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 then return ((self.Year + 2000) * 10000) + (self.Month * 100) + self.Day end; return 0 end -- Unpack +function MT.ImGuiPackedDate:SubtractMonths(m) while m > 0 do if self.Month == 1 then self.Year = bitAnd(self.Year - 1, 0x7F) end; self.Month = (self.Month == 1) and 12 or self.Month - 1; m = m - 1 end end -- FIXME-OPT: Stupid but enough for what we do with it. + +-- Pointer or index, e.g. g.CurrentTabBarStack[] +-- [Luau] overload by argument type: number = index, otherwise pointer +function ImGuiPtrOrIndex(ptr_or_index) + if type(ptr_or_index) == "number" then return { Ptr = nil, Index = ptr_or_index } end + return { Ptr = ptr_or_index, Index = -1 } +end + +-- Note that Max is exclusive, so perhaps should be using a Begin/End convention. +--- @class ImGuiListClipperRange +MT.ImGuiListClipperRange = {} +function MT.ImGuiListClipperRange.FromIndices(min, max) return { Min = min, Max = max, PosToIndexConvert = false, PosToIndexOffsetMin = 0, PosToIndexOffsetMax = 0 } end +function MT.ImGuiListClipperRange.FromPositions(y1, y2, off_min, off_max) return { Min = _Trunc(y1), Max = _Trunc(y2), PosToIndexConvert = true, PosToIndexOffsetMin = off_min, PosToIndexOffsetMax = off_max } end + +-- Temporary clipper data, buffers shared/reused between instances +--- @class ImGuiListClipperData +MT.ImGuiListClipperData = {} +MT.ImGuiListClipperData.__index = MT.ImGuiListClipperData +function ImGuiListClipperData() return setmetatable({ ListClipper = nil, LossynessOffset = 0.0, StepNo = 0, ItemsFrozen = 0, Ranges = ImVector() }, MT.ImGuiListClipperData) end +function MT.ImGuiListClipperData:Reset(clipper) self.ListClipper = clipper; self.StepNo = 0; self.ItemsFrozen = 0; self.Ranges:resize(0) end + +function ImGuiStackLevelInfo() return { ID = 0, QueryFrameCount = 0, QuerySuccess = false, DataType = -1, DescOffset = -1 } end +function ImGuiDebugItemPathQuery() return { MainID = 0, Active = false, Complete = false, Step = 0, Results = ImVector(), ResultsDescBuf = ImGuiTextBuffer(), ResultPathBuf = ImGuiTextBuffer() } end +function ImGuiIDStackTool() return { OptHexEncodeNonAsciiChars = true, OptCopyToClipboardOnCtrlC = false, LastActiveFrame = -1, CopyToClipboardLastTime = -3.4028234663853e+38 --[[FLT_MAX]] } end +function ImGuiContextHook() return { HookId = 0, Type = 0, Owner = 0, Callback = nil, UserData = nil } end + +------------------------------------------------------------------------------- +-- [Luau] ImGui:: inline helpers from imgui_internal.h +------------------------------------------------------------------------------- + +function ImGui.GetCurrentTable() local g = GImGui; return g.CurrentTable end +--- @param window ImGuiWindow +--- @param parent_window ImGuiWindow? +function ImGui.SetWindowParentWindowForFocusRoute(window, parent_window) window.ParentWindowForFocusRoute = parent_window end -- You may also use SetNextWindowClass()'s FocusRouteParentWindowId field. +function ImGui.GetPixelDensity() return GImGui.FontRasterizerDensity end -- [Luau] g.FontRasterizerDensity == upstream g.CurrentPixelDensity +function ImGui.ScrollToBringRectIntoView(window, rect) ImGui.ScrollToRect(window, rect, 2 --[[ImGuiScrollFlags.KeepVisibleEdgeY]]) end +function ImGui.GetItemStatusFlags() local g = GImGui; return g.LastItemData.StatusFlags end +function ImGui.GetActiveID() local g = GImGui; return g.ActiveId end +function ImGui.GetFocusID() local g = GImGui; return g.NavId end +function ImGui.IsLegacyKey(key) return key >= 0 --[[ImGuiKey_LegacyNativeKey_BEGIN]] and key < 512 --[[ImGuiKey_LegacyNativeKey_END]] end +function ImGui.GetWindowDockNode() local g = GImGui; return g.CurrentWindow.DockNode end +function ImGui.GetCurrentFocusScope() local g = GImGui; return g.CurrentFocusScopeId end -- Focus scope we are outputting into, set by PushFocusScope() +function ImGui.GetCurrentTabBar() local g = GImGui; return g.CurrentTabBar end +-- This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. +function ImGui.IsItemActiveAsInputText() local g = GImGui; return g.ActiveId ~= 0 and g.ActiveId == g.LastItemData.ID and g.InputTextState.ID == g.LastItemData.ID end + return true -- [Roblox] ModuleScripts must return exactly one value end @@ -56558,9 +57941,13 @@ end -- Storage for a table .ini settings --- @class ImGuiTableSettings +MT.ImGuiTableSettings = {} +MT.ImGuiTableSettings.__index = MT.ImGuiTableSettings function ImGuiTableSettings() - return { ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} } + return setmetatable({ ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} }, MT.ImGuiTableSettings) end +-- [Luau] column settings are stored in a 0-based .Columns table (upstream: allocated right after the struct) +function MT.ImGuiTableSettings:GetColumnSettings() return self.Columns end -- Storage data for a single column for legacy Columns() api --- @class ImGuiOldColumnData @@ -60621,6 +62008,17 @@ function ImGui.TableLoadSettingsForColumn(column, column_settings, load_flags) column.SortDirection = column_settings.SortDirection end +-- [Luau] boolean "less than" for table.sort; takes (table, lhs column idx, rhs column idx) instead of ImGuiTableFixDisplayOrderColumnData +local function TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) + -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. + local lhs_order, rhs_order = table_.Columns[lhs_idx].DisplayOrder, table_.Columns[rhs_idx].DisplayOrder + if lhs_order < 0 then lhs_order = lhs_order + 0x10000 end + if rhs_order < 0 then rhs_order = rhs_order + 0x10000 end + local order_delta = lhs_order - rhs_order + if order_delta ~= 0 then return order_delta < 0 end + return lhs_idx < rhs_idx +end + -- Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2) function ImGui.TableFixDisplayOrder(table_) if band(table_.Flags, 2 --[[ImGuiTableFlags.Reorderable]]) == 0 then @@ -60635,17 +62033,7 @@ function ImGui.TableFixDisplayOrder(table_) fdo_columns[n + 1] = n end -- Sort by DisplayOrder and then Index - -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. - local function key(idx) - local o = table_.Columns[idx].DisplayOrder - if o < 0 then o = o + 0x10000 end - return o - end - table.sort(fdo_columns, function(lhs_idx, rhs_idx) - local a, b = key(lhs_idx), key(rhs_idx) - if a ~= b then return a < b end - return lhs_idx < rhs_idx - end) + table.sort(fdo_columns, function(lhs_idx, rhs_idx) return TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) end) for n = 0, table_.ColumnsCount - 1 do table_.Columns[fdo_columns[n + 1]].DisplayOrder = n end @@ -60654,6 +62042,27 @@ function ImGui.TableFixDisplayOrder(table_) end end +local function TableSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for i = 0, g.Tables:GetMapSize() - 1 do + local table_ = g.Tables:GetByIndex(i) + if table_ then + table_.SettingsOffset = -1 + end + end + -- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD int, 0 = none); g.SessionDate is an ImGuiPackedDate when set + for _, settings in g.SettingsTables:iter() do + local is_valid = ImGuiPackedDate(settings.LastUsedDate):IsValid() + if args._DiscardOlderThanDate ~= 0 and settings.LastUsedDate < args._DiscardOlderThanDate then + settings.ID = 0 + elseif args.DiscardWhenMissingDate and not is_valid then + settings.ID = 0 + elseif args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate and g.SessionDate:Unpack() or 0 + end + end +end + local function ForEachTable(g, fn) for i = 0, g.Tables:GetMapSize() - 1 do local t = g.Tables:GetByIndex(i) @@ -60779,6 +62188,7 @@ function ImGui.TableSettingsAddSettingsHandler() ini_handler.ReadLineFn = TableSettingsHandler_ReadLine ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll ini_handler.WriteAllFn = TableSettingsHandler_WriteAll + ini_handler.CleanupFn = TableSettingsHandler_Cleanup ImGui.AddSettingsHandler(ini_handler) end @@ -60842,6 +62252,20 @@ function ImGui.TableGcCompactSettings() ForEachTable(g, function(t) t.SettingsOffset = -1 end) end +------------------------------------------------------------------------------- +-- [SECTION] Tables: Debugging +------------------------------------------------------------------------------- +-- [Luau] global (upstream: static) so ImGui.DebugNodeTable() in imgui.lua can use it + +function DebugNodeTableGetSizingPolicyDesc(sizing_policy) + sizing_policy = band(sizing_policy, 57344 --[[ImGuiTableFlags.SizingMask_]]) + if sizing_policy == 8192 --[[ImGuiTableFlags.SizingFixedFit]] then return "FixedFit" end + if sizing_policy == 16384 --[[ImGuiTableFlags.SizingFixedSame]] then return "FixedSame" end + if sizing_policy == 24576 --[[ImGuiTableFlags.SizingStretchProp]] then return "StretchProp" end + if sizing_policy == 32768 --[[ImGuiTableFlags.SizingStretchSame]] then return "StretchSame" end + return "N/A" +end + ------------------------------------------------------------------------------- -- [SECTION] Columns, BeginColumns, EndColumns, etc. -- (This is a legacy API, prefer using BeginTable/EndTable!) @@ -63884,12 +65308,14 @@ function ImGui.RoundScalarWithFormatT(format, data_type, v) return v -- Don't apply if the value is not visible in the format string end - -- TODO: Sanitize format + -- Sanitize format + local fmt_sanitized = ImParseFormatSanitizeForPrinting(string.sub(format, fmt_start), nil, 32) -- Format value with our rounding, and read back - local str = ImFormatString(format, v) + local v_str = ImFormatString(fmt_sanitized, v) + -- [Luau] leading spaces: ImAtof() skips them - v = ImAtof(str) or v + v = ImAtof(v_str) or v return v end @@ -63975,6 +65401,30 @@ local function ImParseFormatTrimDecorations(fmt) return string.sub(fmt, fmt_start, fmt_end - 1) end +-- Sanitize format +-- - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi +-- - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. +-- [Luau] fmt_out is a byte table (may be nil); returns the sanitized format as a string +--- @param fmt_in string +--- @param fmt_out char[]? +--- @param fmt_out_size size_t +function ImParseFormatSanitizeForPrinting(fmt_in, fmt_out, fmt_out_size) + local fmt_end = ImParseFormatFindEnd(fmt_in, 1) + -- IM_UNUSED(fmt_out_size) + assert(fmt_end < fmt_out_size) -- Format is too long, let us know if this happens to you! + fmt_out = fmt_out or {} + local n = 0 + for i = 1, fmt_end - 1 do + local c = string.byte(fmt_in, i) + if c ~= 39 and c ~= 36 and c ~= 95 then -- Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. + n = n + 1 + fmt_out[n] = c + end + end + fmt_out[n + 1] = 0 -- Zero-terminate + return string.char(unpack(fmt_out, 1, n)) +end + -- - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" --- @param fmt_in string --- @param fmt_out char[] @@ -64576,6 +66026,18 @@ function ImGui.DragBehaviorT(TYPE, SIGNEDTYPE, data_type, v, v_speed, v_min, v_m return v, true end +local function ShortcutsForCancel(id) + local g = GImGui + local is_cancel_with_keyboard = ImGui.Shortcut(526 --[[ImGuiKey.Escape]], 0 --[[ImGuiInputFlags.None]], id) + -- [Luau] ImGuiKey_NavGamepadCancel macro inlined (io.ConfigNavSwapGamepadButtons is not ported: always FaceRight) + local is_cancel_with_gamepad = bit32.band(g.IO.ConfigFlags, 2 --[[ImGuiConfigFlags.NavEnableGamepad]]) ~= 0 and bit32.band(g.IO.BackendFlags, 1 --[[ImGuiBackendFlags.HasGamepad]]) ~= 0 and ImGui.Shortcut(635 --[[ImGuiKey.GamepadFaceRight]], 0 --[[ImGuiInputFlags.None]], id) + local is_cancel_with_mouse = ImGui.IsMouseReleased(1 --[[ImGuiMouseButton.Right]], id) + if is_cancel_with_mouse then + ImGui.SetKeyOwner(657 --[[ImGuiKey.MouseRight]], id) + end + return is_cancel_with_keyboard or is_cancel_with_gamepad or is_cancel_with_mouse +end + --- @param id ImGuiID --- @param data_type ImGuiDataType --- @param v number @@ -64597,6 +66059,13 @@ function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags) elseif (g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]]) and g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then ImGui.ClearActiveID() end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end end if g.ActiveId ~= id then return v, false @@ -65155,9 +66624,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ local set_new_value = false local clicked_t = 0.0 if g.ActiveIdSource == 1 --[[ImGuiInputSource.Mouse]] then - if not g.IO.MouseDown[0] then - ImGui.ClearActiveID() - else + do local mouse_abs_pos = g.IO.MousePos[axis_k] if g.ActiveIdIsJustActivated then local grab_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) @@ -65177,11 +66644,6 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ set_new_value = true end elseif g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]] then - if g.ActiveIdIsJustActivated then - g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation - g.SliderCurrentAccumDirty = false - end - local input_delta = (axis == 1 --[[ImGuiAxis.X]]) and ImGui.GetNavTweakPressedAmount(axis) or -ImGui.GetNavTweakPressedAmount(axis) if input_delta ~= 0.0 then local tweak_slow = ImGui.IsKeyDown((g.NavInputSource == 3 --[[ImGuiInputSource.Gamepad]]) and 642 --[[ImGuiKey.NavGamepadTweakSlow]] or 4096 --[[ImGuiKey.NavKeyboardTweakSlow]]) @@ -65208,9 +66670,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ end local delta = g.SliderCurrentAccum - if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then - ImGui.ClearActiveID() - elseif g.SliderCurrentAccumDirty then + if g.SliderCurrentAccumDirty then clicked_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) if (clicked_t >= 1.0 and delta > 0.0) or (clicked_t <= 0.0 and delta < 0.0) then -- This is to avoid applying the saturation when already past the limits @@ -65302,6 +66762,30 @@ function ImGui.SliderBehavior(bb, id, data_type, v, min, max, format, flags, out assert((flags == 1 or bit32.band(flags, 1879048207 --[[ImGuiSliderFlags.InvalidMask_]]) == 0), "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.") assert(bit32.band(flags, 256 --[[ImGuiSliderFlags.WrapAround]]) == 0) -- Not supported by SliderXXX(), only by DragXXX() + -- Things we can do easily outside the SliderBehaviorT<> template, saves code generation. + local g = GImGui + if g.ActiveId == id then + if g.ActiveIdSource == 1 --[[ImGuiInputSource.Mouse]] and not g.IO.MouseDown[0] then + ImGui.ClearActiveID() + end + if g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]] then + if g.ActiveIdIsJustActivated then + g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation + g.SliderCurrentAccumDirty = false + end + if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then + ImGui.ClearActiveID() + end + end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end + end + if data_type == 0 --[[ImGuiDataType.S8]] then local v32 = (ImS32)((ImS8)(v)); local r v32, r = ImGui.SliderBehaviorT(ImS32, ImS32, bb, id, 4 --[[ImGuiDataType.S32]], v32, min, max, format, flags, out_grab_bb) @@ -65888,7 +67372,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) local len = obj.TextLen idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) while idx <= len and not ImStb.is_word_boundary_from_left(obj, idx) do @@ -65899,7 +67383,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) local len = obj.TextLen while idx <= len and not ImStb.is_word_boundary_from_right(obj, idx) do @@ -65913,9 +67397,9 @@ end function ImStb.TEXTEDIT_MOVEWORDRIGHT(obj, idx) local g = obj.Ctx if g.IO.ConfigMacOSXBehaviors then - return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) else - return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) end end @@ -66116,6 +67600,13 @@ function MT.ImGuiInputTextState:CursorClamp() end function MT.ImGuiInputTextState:HasSelection() return self.Stb.select_start ~= self.Stb.select_end end +function MT.ImGuiInputTextState:ClearSelection() self.Stb.select_start = self.Stb.cursor; self.Stb.select_end = self.Stb.cursor end +-- [Luau] positions are 1-based byte indices (upstream: 0-based) +function MT.ImGuiInputTextState:GetCursorPos() return self.Stb.cursor end +function MT.ImGuiInputTextState:GetSelectionStart() return self.Stb.select_start end +function MT.ImGuiInputTextState:GetSelectionEnd() return self.Stb.select_end end +function MT.ImGuiInputTextState:SetSelection(start, _end) self.Stb.select_start = start; self.Stb.cursor = _end; self.Stb.select_end = _end end +function MT.ImGuiInputTextState:GetPreferredOffsetX() if self.Stb.has_preferred_x then return self.Stb.preferred_x else return -1 end end function MT.ImGuiInputTextState:SelectAll() self.Stb.select_start = 1 @@ -66124,6 +67615,10 @@ function MT.ImGuiInputTextState:SelectAll() self.Stb.has_preferred_x = false end +function MT.ImGuiInputTextState:ReloadUserBufAndSelectAll() self.WantReloadUserBuf = true; self.ReloadSelectionStart = 1; self.ReloadSelectionEnd = 2147483647 --[[INT_MAX]] end +function MT.ImGuiInputTextState:ReloadUserBufAndKeepSelection() self.WantReloadUserBuf = true; self.ReloadSelectionStart = self.Stb.select_start; self.ReloadSelectionEnd = self.Stb.select_end end +function MT.ImGuiInputTextState:ReloadUserBufAndMoveToEnd() self.WantReloadUserBuf = true; self.ReloadSelectionStart = 2147483647 --[[INT_MAX]]; self.ReloadSelectionEnd = 2147483647 --[[INT_MAX]] end + end function ImGui.PushPasswordFont() @@ -66275,9 +67770,9 @@ local function InputTextFilterCharacter(ctx, state, char, callback, user_data, i callback_data.EventFlag = 2097152 --[[ImGuiInputTextFlags.CallbackCharFilter]] callback_data.EventChar = c callback_data.EventActivated = (state ~= nil and g.ActiveId == state.ID and g.ActiveIdIsJustActivated) - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 callback_data.UserData = user_data if callback(callback_data) ~= 0 then return char, false @@ -66859,7 +68354,7 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback if not stbte.HAS_SELECTION(state.Stb) then stbte.prep_selection_at_cursor(state.Stb) end - state.Stb.cursor = STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) + state.Stb.cursor = ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) state.Stb.select_end = state.Stb.cursor stbte.clamp(state, state.Stb) else @@ -67188,9 +68683,9 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback callback_data.BufTextLen = state.TextLen callback_data.BufSize = state.BufCapacity callback_data.BufDirty = false - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based, stb ones 1-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 -- Call user code callback(callback_data) @@ -67200,12 +68695,12 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback assert(callback_data.Buf == callback_buf) -- Invalid to modify those fields assert(callback_data.BufSize == state.BufCapacity) assert(callback_data.Flags == flags) - if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor then + if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor - 1 then state.CursorFollow = true end - state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) - state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) - state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) + 1 + state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) + 1 + state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + 1 if callback_data.BufDirty then -- Callback may update buffer and thus set buf_dirty even in read-only mode. assert(callback_data.BufTextLen == ImStd.ImStrlen(callback_data.Buf)) -- You need to maintain BufTextLen if you change the text! @@ -67569,6 +69064,47 @@ function ImGui.InputTextWithHint(label, hint, buf, buf_size, flags, callback, us return ImGui.InputTextEx(label, hint, buf, buf_size, ImVec2(0, 0), flags, callback, user_data) end +-- [Luau] stb positions/undo indices are 1-based in this port (displayed as-is) +--- @param state ImGuiInputTextState +function ImGui.DebugNodeInputTextState(state) + local g = GImGui + local stb_state = state.Stb + local undo_state = stb_state.undostate + ImGui.Text("ID: 0x%08X, ActiveID: 0x%08X", state.ID, g.ActiveId) + if ImGui.DebugLocateItemOnHover then ImGui.DebugLocateItemOnHover(state.ID) end -- [Luau] not ported yet + local wrap_dir = "" + if bit32.band(state.Flags, 16777216 --[[ImGuiInputTextFlags.WordWrap]]) ~= 0 then + if state.LastMoveDirectionLR == 0 --[[ImGuiDir.Left]] then wrap_dir = " (L)" else wrap_dir = " (R)" end + end + ImGui.Text("TextLen: %d, Cursor: %d%s, Selection: %d..%d", state.TextLen, stb_state.cursor, wrap_dir, stb_state.select_start, stb_state.select_end) + ImGui.Text("BufCapacity: %d, LineCount: %d", state.BufCapacity, state.LineCount) + ImGui.Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state.TextA.Size, state.TextA.Capacity) + ImGui.Text("has_preferred_x: %d (%.2f)", stb_state.has_preferred_x and 1 or 0, stb_state.preferred_x) + ImGui.Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state.undo_point, undo_state.redo_point, undo_state.undo_char_point, undo_state.redo_char_point) + if ImGui.BeginChild("undopoints", ImVec2(0.0, ImGui.GetTextLineHeight() * 10), bit32.bor(1 --[[ImGuiChildFlags.Borders]], 8 --[[ImGuiChildFlags.ResizeY]])) then -- Visualize undo state + ImGui.PushStyleVar(14 --[[ImGuiStyleVar.ItemSpacing]], ImVec2(0, 0)) + for n = 1, 99 --[[IMSTB_TEXTEDIT_UNDOSTATECOUNT]] do + local undo_rec = undo_state.undo_rec[n] + local undo_rec_type = (n < undo_state.undo_point) and "u" or ((n >= undo_state.redo_point) and "r" or " ") + if undo_rec_type == " " then + ImGui.BeginDisabled() + end + local buf_preview_len = (undo_rec_type ~= " " and undo_rec.char_storage ~= -1) and undo_rec.insert_length or 0 + local buf_preview_str = "" + if buf_preview_len > 0 then + buf_preview_str = string.char(unpack(undo_state.undo_char, undo_rec.char_storage, undo_rec.char_storage + buf_preview_len - 1)) + end + ImGui.Text("%s [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%s\"", + undo_rec_type, n, undo_rec.where, undo_rec.insert_length, undo_rec.delete_length, undo_rec.char_storage, buf_preview_str) + if undo_rec_type == " " then + ImGui.EndDisabled() + end + end + ImGui.PopStyleVar() + end + ImGui.EndChild() +end + ------------------------------------------------------------------------------- -- [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. ------------------------------------------------------------------------------- @@ -71934,14 +73470,37 @@ local function TabItemGetSectionIdx(tab) return 1 end +-- [Luau] comparers return a boolean "less than" for table.sort (upstream: ImQsort int comparers) +local function TabItemComparerBySection(a, b) + if a == nil or b == nil then return false end + local a_section = TabItemGetSectionIdx(a) + local b_section = TabItemGetSectionIdx(b) + if a_section ~= b_section then + return a_section < b_section + end + return a.IndexDuringLayout < b.IndexDuringLayout +end + +local function TabItemComparerByBeginOrder(a, b) + return a.BeginOrder < b.BeginOrder +end + +local function GetTabBarFromTabBarRef(ref) + local g = GImGui + if ref.Ptr then return ref.Ptr else return g.TabBars:GetByIndex(ref.Index) end +end + +local function GetTabBarRefFromTabBar(tab_bar) + local g = GImGui + if g.TabBars:Contains(tab_bar) then + return ImGuiPtrOrIndex(g.TabBars:GetIndex(tab_bar)) + end + return ImGuiPtrOrIndex(tab_bar) +end + -- Stable sorts (C++ ImQsort is not stable, but the comparers are total orders in practice) local function SortTabsBySection(tab_bar) - table.sort(tab_bar.Tabs.Data, function(a, b) - if a == nil or b == nil then return false end - local sa, sb = TabItemGetSectionIdx(a), TabItemGetSectionIdx(b) - if sa ~= sb then return sa < sb end - return a.IndexDuringLayout < b.IndexDuringLayout - end) + table.sort(tab_bar.Tabs.Data, TabItemComparerBySection) end local function SortTabsByBeginOrder(tab_bar) @@ -71949,7 +73508,7 @@ local function SortTabsByBeginOrder(tab_bar) if not data then return end local arr = {} for i = 1, tab_bar.Tabs.Size do arr[i] = data[i] end - table.sort(arr, function(a, b) return a.BeginOrder < b.BeginOrder end) + table.sort(arr, TabItemComparerByBeginOrder) for i = 1, tab_bar.Tabs.Size do data[i] = arr[i] end end @@ -71963,6 +73522,12 @@ end -- Spacing: Horizontal spacing at the end of the section. local function ImGuiTabBarSection() return { TabCount = 0, Width = 0.0, WidthAfterShrinkMinWidth = 0.0, Spacing = 0.0 } end +-- [Luau] boolean "less than" for table.sort. Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects +local function ShrinkWidthItemComparer(a, b) + if a.Width ~= b.Width then return a.Width > b.Width end + return a.Index > b.Index -- b->Index - a->Index +end + -- Shrink excess width from a set of item, by removing width from the larger items first. -- Set items Width to -1.0f to disable shrinking this item. -- items: 1-based array of ImGuiShrinkWidthItem, `first` = 1-based index of first item, `count` items @@ -71976,10 +73541,7 @@ function ImGui.ShrinkWidths(items, first, count, width_excess, width_min) -- Sort largest first, smallest last. local slice = {} for n = 1, count do slice[n] = items[first + n - 1] end - table.sort(slice, function(a, b) - if a.Width ~= b.Width then return a.Width > b.Width end - return a.Index > b.Index -- ShrinkWidthItemComparer: b->Index - a->Index (Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects) - end) + table.sort(slice, ShrinkWidthItemComparer) for n = 1, count do items[first + n - 1] = slice[n] end local it = slice local count_same_width = 1 @@ -72090,7 +73652,7 @@ function ImGui.BeginTabBarEx(tab_bar, tab_bar_bb, flags) end -- Add to stack - g.CurrentTabBarStack:push_back(tab_bar) + g.CurrentTabBarStack:push_back(GetTabBarRefFromTabBar(tab_bar)) g.CurrentTabBar = tab_bar tab_bar.Window = window @@ -72172,7 +73734,7 @@ function ImGui.EndTabBar() end g.CurrentTabBarStack:pop_back() - if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = g.CurrentTabBarStack.Data[g.CurrentTabBarStack.Size] end + if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = GetTabBarFromTabBarRef(g.CurrentTabBarStack:back()) end end -- This is called only once a frame before by the first call to ItemTab() @@ -78487,6 +80049,7 @@ return { CalcNextScrollFromScrollTargetAndClamp = CalcNextScrollFromScrollTargetAndClamp, CustomConstraints = CustomConstraints, DBL_MAX = DBL_MAX, + DebugNodeTableGetSizingPolicyDesc = DebugNodeTableGetSizingPolicyDesc, DemoWindowColumns = DemoWindowColumns, DemoWindowInputs = DemoWindowInputs, DemoWindowLayout = DemoWindowLayout, @@ -78644,14 +80207,23 @@ return { ImAtan2 = ImAtan2, ImAtof = ImAtof, ImBezierCubicCalc = ImBezierCubicCalc, + ImBezierCubicClosestPoint = ImBezierCubicClosestPoint, + ImBezierCubicClosestPointCasteljau = ImBezierCubicClosestPointCasteljau, ImBezierQuadraticCalc = ImBezierQuadraticCalc, ImBitArray = ImBitArray, + ImBitArrayClearAllBits = ImBitArrayClearAllBits, + ImBitArrayClearBit = ImBitArrayClearBit, + ImBitArrayGetStorageSizeInBytes = ImBitArrayGetStorageSizeInBytes, ImBitArraySetBit = ImBitArraySetBit, + ImBitArraySetBitRange = ImBitArraySetBitRange, + ImBitArrayTestBit = ImBitArrayTestBit, + ImBitVector = ImBitVector, ImCeil = ImCeil, ImCeilFast = ImCeilFast, ImCharIsBlankA = ImCharIsBlankA, ImCharIsBlankW = ImCharIsBlankW, ImCharIsSeparatorW = ImCharIsSeparatorW, + ImCharIsXdigitA = ImCharIsXdigitA, ImClamp = ImClamp, ImColor = ImColor, ImCos = ImCos, @@ -78766,8 +80338,11 @@ return { ImGuiCond = ImGuiCond, ImGuiConfigFlags = ImGuiConfigFlags, ImGuiContext = ImGuiContext, + ImGuiContextHook = ImGuiContextHook, + ImGuiContextHookType = ImGuiContextHookType, ImGuiDataAuthority = ImGuiDataAuthority, ImGuiDataType = ImGuiDataType, + ImGuiDebugItemPathQuery = ImGuiDebugItemPathQuery, ImGuiDebugLogFlags = ImGuiDebugLogFlags, ImGuiDemoDockspaceArgs = ImGuiDemoDockspaceArgs, ImGuiDemoWindowData = ImGuiDemoWindowData, @@ -78783,6 +80358,7 @@ return { ImGuiFocusedFlags = ImGuiFocusedFlags, ImGuiGroupData = ImGuiGroupData, ImGuiHoveredFlags = ImGuiHoveredFlags, + ImGuiIDStackTool = ImGuiIDStackTool, ImGuiIO = ImGuiIO, ImGuiInputEvent = ImGuiInputEvent, ImGuiInputEventAppFocused = ImGuiInputEventAppFocused, @@ -78811,12 +80387,15 @@ return { ImGuiKey_Gamepad_END = ImGuiKey_Gamepad_END, ImGuiKey_Keyboard_BEGIN = ImGuiKey_Keyboard_BEGIN, ImGuiKey_Keyboard_END = ImGuiKey_Keyboard_END, + ImGuiKey_LegacyNativeKey_BEGIN = ImGuiKey_LegacyNativeKey_BEGIN, + ImGuiKey_LegacyNativeKey_END = ImGuiKey_LegacyNativeKey_END, ImGuiKey_Mouse_BEGIN = ImGuiKey_Mouse_BEGIN, ImGuiKey_Mouse_END = ImGuiKey_Mouse_END, ImGuiLastItemData = ImGuiLastItemData, ImGuiLastItemData_Copy = ImGuiLastItemData_Copy, ImGuiLayoutType = ImGuiLayoutType, ImGuiListClipper = ImGuiListClipper, + ImGuiListClipperData = ImGuiListClipperData, ImGuiListClipperFlags = ImGuiListClipperFlags, ImGuiLocKey = ImGuiLocKey, ImGuiLogFlags = ImGuiLogFlags, @@ -78843,6 +80422,8 @@ return { ImGuiOldColumnData = ImGuiOldColumnData, ImGuiOldColumnFlags = ImGuiOldColumnFlags, ImGuiOldColumns = ImGuiOldColumns, + ImGuiOnceUponAFrame = ImGuiOnceUponAFrame, + ImGuiPackedDate = ImGuiPackedDate, ImGuiPayload = ImGuiPayload, ImGuiPayload_Clear = ImGuiPayload_Clear, ImGuiPayload_IsDataType = ImGuiPayload_IsDataType, @@ -78858,6 +80439,7 @@ return { ImGuiPopupData = ImGuiPopupData, ImGuiPopupFlags = ImGuiPopupFlags, ImGuiPopupPositionPolicy = ImGuiPopupPositionPolicy, + ImGuiPtrOrIndex = ImGuiPtrOrIndex, ImGuiScrollFlags = ImGuiScrollFlags, ImGuiSelectableFlags = ImGuiSelectableFlags, ImGuiSelectionBasicStorage = ImGuiSelectionBasicStorage, @@ -78871,6 +80453,7 @@ return { ImGuiShrinkWidthItem = ImGuiShrinkWidthItem, ImGuiSliderFlags = ImGuiSliderFlags, ImGuiSortDirection = ImGuiSortDirection, + ImGuiStackLevelInfo = ImGuiStackLevelInfo, ImGuiStyle = ImGuiStyle, ImGuiStyleMod = ImGuiStyleMod, ImGuiStyleVar = ImGuiStyleVar, @@ -78894,6 +80477,7 @@ return { ImGuiTableTempData = ImGuiTableTempData, ImGuiTextBuffer = ImGuiTextBuffer, ImGuiTextFilter = ImGuiTextFilter, + ImGuiTextFilterItem = ImGuiTextFilterItem, ImGuiTextFlags = ImGuiTextFlags, ImGuiTooltipFlags = ImGuiTooltipFlags, ImGuiTreeNodeFlags = ImGuiTreeNodeFlags, @@ -78929,6 +80513,8 @@ return { ImHashData = ImHashData, ImHashStr = ImHashStr, ImHashStrRaw = ImHashStrRaw, + ImInvLength = ImInvLength, + ImIsFloatAboveGuaranteedIntegerPrecision = ImIsFloatAboveGuaranteedIntegerPrecision, ImIsPowerOfTwo = ImIsPowerOfTwo, ImIsTruncated = ImIsTruncated, ImIsTruncated4 = ImIsTruncated4, @@ -78939,8 +80525,10 @@ return { ImMax = ImMax, ImMemchr = ImMemchr, ImMin = ImMin, + ImModPositive = ImModPositive, ImMul = ImMul, ImParseFormatFindStart = ImParseFormatFindStart, + ImParseFormatSanitizeForPrinting = ImParseFormatSanitizeForPrinting, ImParseFormatSanitizeForScanning = ImParseFormatSanitizeForScanning, ImPool = ImPool, ImPow = ImPow, @@ -78949,6 +80537,8 @@ return { ImRect_CopyFromV4 = ImRect_CopyFromV4, ImRotate = ImRotate, ImRound64 = ImRound64, + ImRoundPositive64 = ImRoundPositive64, + ImRoundSigned64 = ImRoundSigned64, ImRsqrt = ImRsqrt, ImRsqrtPrecise = ImRsqrtPrecise, ImS16 = ImS16, @@ -78993,6 +80583,8 @@ return { ImVec2_CopyV = ImVec2_CopyV, ImVec2_MulVX = ImVec2_MulVX, ImVec2_SubVA = ImVec2_SubVA, + ImVec2i = ImVec2i, + ImVec2ih = ImVec2ih, ImVec4 = ImVec4, ImVec4_Copy = ImVec4_Copy, ImVector = ImVector, diff --git a/build/ImGuiTyped.luau b/build/ImGuiTyped.luau index 1c3a091..7f50e51 100644 --- a/build/ImGuiTyped.luau +++ b/build/ImGuiTyped.luau @@ -6,6 +6,7 @@ export type ImVec4 = { x: number, y: number, z: number, w: number, [any]: any } export type ImGuiAPI = { AcceptDragDropPayload: (type: string, flags: number?) -> any, ActivateItemByID: (...any) -> ...any, + AddContextHook: (...any) -> ...any, AddDrawListToDrawDataEx: (...any) -> ...any, AddSettingsHandler: (...any) -> ...any, AddUpdateViewport: (...any) -> ...any, @@ -72,6 +73,7 @@ export type ImGuiAPI = { CalcTypematicRepeatAmount: (...any) -> ...any, CalcWindowNextAutoFitSize: (...any) -> ...any, CalcWrapWidthForPos: (...any) -> ...any, + CallContextHooks: (...any) -> ...any, Checkbox: (label: string, v: boolean?) -> (boolean, boolean?), CheckboxFlags: (...any) -> ...any, CleanupIniSettings: (...any) -> ...any, @@ -111,15 +113,29 @@ export type ImGuiAPI = { DataTypeGetInfo: (...any) -> ...any, DataTypeIsZero: (...any) -> ...any, DebugAllocHook: (...any) -> ...any, + DebugBreakButton: (...any) -> ...any, + DebugBreakButtonTooltip: (...any) -> ...any, + DebugBreakClearData: (...any) -> ...any, + DebugDrawCursorPos: (...any) -> ...any, + DebugDrawItemRect: (...any) -> ...any, + DebugDrawLineExtents: (...any) -> ...any, + DebugFlashStyleColor: (idx: number) -> (), DebugHookIdInfo: (...any) -> ...any, + DebugLocateItem: (...any) -> ...any, + DebugLocateItemOnHover: (...any) -> ...any, + DebugLocateItemResolveWithLastItem: (...any) -> ...any, DebugLog: (fmt: string, ...any) -> (), + DebugLogV: (fmt: string, ...any) -> (), DebugNodeColumns: (...any) -> ...any, DebugNodeDockNode: (...any) -> ...any, + DebugNodeDrawCmdShowMeshAndBoundingBox: (...any) -> ...any, DebugNodeDrawList: (...any) -> ...any, DebugNodeFont: (...any) -> ...any, DebugNodeFontGlyph: (...any) -> ...any, DebugNodeFontGlyphsForSrcMask: (...any) -> ...any, + DebugNodeInputTextState: (...any) -> ...any, DebugNodeMultiSelectState: (...any) -> ...any, + DebugNodePlatformMonitor: (...any) -> ...any, DebugNodeStorage: (...any) -> ...any, DebugNodeTabBar: (...any) -> ...any, DebugNodeTable: (...any) -> ...any, @@ -131,8 +147,13 @@ export type ImGuiAPI = { DebugNodeWindowSettings: (...any) -> ...any, DebugNodeWindowsList: (...any) -> ...any, DebugNodeWindowsListByBeginStackParent: (...any) -> ...any, + DebugRenderKeyboardPreview: (...any) -> ...any, DebugRenderViewportThumbnail: (...any) -> ...any, + DebugStartItemPicker: () -> (), DebugTextEncoding: (str: string) -> (), + DebugTextUnformattedWithLocateItem: (...any) -> ...any, + DebugTextureIDToU64: (...any) -> ...any, + DemoMarker: (...any) -> ...any, DestroyContext: (ctx: any) -> ...any, DestroyPlatformWindow: (...any) -> ...any, DestroyPlatformWindows: () -> (), @@ -247,6 +268,8 @@ export type ImGuiAPI = { EndTable: () -> (), EndTooltip: () -> (), ErrorCheckEndFrameFinalizeErrorTooltip: (...any) -> ...any, + ErrorCheckEndFrameSanityChecks: (...any) -> ...any, + ErrorCheckNewFrameSanityChecks: (...any) -> ...any, ErrorCheckUsingSetCursorPosToExtendParentBoundaries: (...any) -> ...any, ErrorLog: (...any) -> ...any, ErrorRecoveryStoreState: (...any) -> ...any, @@ -265,6 +288,7 @@ export type ImGuiAPI = { FindRenderedTextEnd: (...any) -> ...any, FindSettingsHandler: (...any) -> ...any, FindViewportByID: (viewport_id: number) -> any, + FindViewportByPlatformHandle: (platform_handle: any) -> ...any, FindWindowByID: (...any) -> ...any, FindWindowByName: (...any) -> ...any, FindWindowDisplayIndex: (...any) -> ...any, @@ -279,6 +303,7 @@ export type ImGuiAPI = { GcAwakeTransientWindowBuffers: (...any) -> ...any, GcCompactTransientMiscBuffers: (...any) -> ...any, GcCompactTransientWindowBuffers: (...any) -> ...any, + GetActiveID: (...any) -> ...any, GetBackgroundDrawList: (viewport: any) -> ...any, GetBoxSelectState: (...any) -> ...any, GetClipboardText: () -> any, @@ -293,6 +318,9 @@ export type ImGuiAPI = { GetContentRegionAvail: () -> ImVec2, GetContentRegionMax: (...any) -> ...any, GetCurrentContext: () -> any, + GetCurrentFocusScope: (...any) -> ...any, + GetCurrentTabBar: (...any) -> ...any, + GetCurrentTable: (...any) -> ...any, GetCurrentWindow: (...any) -> ...any, GetCurrentWindowRead: (...any) -> ...any, GetCursorPos: () -> ImVec2, @@ -304,7 +332,9 @@ export type ImGuiAPI = { GetDragDropPayload: () -> any, GetDrawData: () -> any, GetDrawListSharedData: () -> any, + GetFocusID: (...any) -> ...any, GetFont: () -> any, + GetFontBaked: () -> any, GetFontSize: () -> number, GetFontTexUvWhitePixel: () -> ImVec2, GetForegroundDrawList: (viewport: any) -> ...any, @@ -322,6 +352,7 @@ export type ImGuiAPI = { GetItemRectMax: () -> ImVec2, GetItemRectMin: () -> ImVec2, GetItemRectSize: () -> ImVec2, + GetItemStatusFlags: (...any) -> ...any, GetKeyChordName: (...any) -> ...any, GetKeyData: (...any) -> ...any, GetKeyMagnitude2d: (...any) -> ...any, @@ -340,6 +371,7 @@ export type ImGuiAPI = { GetMousePosOnOpeningCurrentPopup: () -> ImVec2, GetMultiSelectState: (...any) -> ...any, GetNavTweakPressedAmount: (...any) -> ...any, + GetPixelDensity: (...any) -> ...any, GetPlatformIO: () -> any, GetPopupAllowedExtentRect: (...any) -> ...any, GetRoundedFontSize: (...any) -> ...any, @@ -369,10 +401,13 @@ export type ImGuiAPI = { GetWindowContentRegionMax: (...any) -> ...any, GetWindowContentRegionMin: (...any) -> ...any, GetWindowDockID: () -> number, + GetWindowDockNode: (...any) -> ...any, GetWindowDpiScale: () -> number, GetWindowDrawList: () -> any, GetWindowHeight: () -> number, GetWindowPos: () -> ImVec2, + GetWindowResizeBorderID: (...any) -> ...any, + GetWindowResizeCornerID: (...any) -> ...any, GetWindowScrollbarID: (...any) -> ...any, GetWindowScrollbarRect: (...any) -> ...any, GetWindowSize: () -> ImVec2, @@ -414,6 +449,7 @@ export type ImGuiAPI = { IsInNavFocusRoute: (...any) -> ...any, IsItemActivated: () -> boolean, IsItemActive: () -> boolean, + IsItemActiveAsInputText: (...any) -> ...any, IsItemClicked: (mouse_button: number?) -> boolean, IsItemDeactivated: () -> boolean, IsItemDeactivatedAfterEdit: () -> boolean, @@ -430,6 +466,7 @@ export type ImGuiAPI = { IsKeyReleased: (...any) -> ...any, IsKeyboardKey: (...any) -> ...any, IsLRModKey: (...any) -> ...any, + IsLegacyKey: (...any) -> ...any, IsMouseClicked: (button: number, is_repeat: boolean?) -> boolean, IsMouseClickedEx: (...any) -> ...any, IsMouseDoubleClicked: (...any) -> ...any, @@ -569,6 +606,8 @@ export type ImGuiAPI = { RadioButton: (...any) -> ...any, RadioButtonEx: (...any) -> ...any, RegisterFontAtlas: (...any) -> ...any, + RegisterUserTexture: (...any) -> ...any, + RemoveContextHook: (...any) -> ...any, RemoveSettingsHandler: (...any) -> ...any, Render: () -> (), RenderArrow: (...any) -> ...any, @@ -604,6 +643,7 @@ export type ImGuiAPI = { ScaleRatioFromValueT: (...any) -> ...any, ScaleValueFromRatioT: (...any) -> ...any, ScaleWindowsInViewport: (...any) -> ...any, + ScrollToBringRectIntoView: (...any) -> ...any, ScrollToItem: (...any) -> ...any, ScrollToRect: (...any) -> ...any, ScrollToRectEx: (...any) -> ...any, @@ -621,6 +661,7 @@ export type ImGuiAPI = { SetColorEditOptions: (...any) -> ...any, SetColumnOffset: (column_index: number, offset: number) -> (), SetColumnWidth: (column_index: number, width: number) -> (), + SetContextName: (...any) -> ...any, SetCurrentContext: (ctx: any) -> ...any, SetCurrentFont: (...any) -> ...any, SetCurrentViewport: (...any) -> ...any, @@ -634,6 +675,7 @@ export type ImGuiAPI = { SetItemDefaultFocus: () -> (), SetItemKeyOwner: (...any) -> ...any, SetItemTooltip: (fmt: string, ...any) -> (), + SetItemTooltipV: (fmt: string, ...any) -> (), SetKeyOwner: (...any) -> ...any, SetKeyOwnersForKeyChord: (...any) -> ...any, SetKeyboardFocusHere: (offset: number?) -> (), @@ -671,6 +713,7 @@ export type ImGuiAPI = { SetNextWindowSize: (size: ImVec2, cond: number?) -> (), SetNextWindowSizeConstraints: (size_min: ImVec2, size_max: ImVec2, custom_callback: any, custom_callback_user_data: any) -> ...any, SetNextWindowViewport: (id: number) -> (), + SetPixelDensity: (...any) -> ...any, SetScrollFromPosX: (...any) -> ...any, SetScrollFromPosY: (...any) -> ...any, SetScrollHereX: (center_x_ratio: number?) -> (), @@ -681,6 +724,7 @@ export type ImGuiAPI = { SetStateStorage: (tree: any) -> ...any, SetTabItemClosed: (label: string) -> (), SetTooltip: (fmt: string, ...any) -> (), + SetTooltipV: (fmt: string, ...any) -> (), SetWindowClipRectBeforeSetChannel: (...any) -> ...any, SetWindowCollapsed: (...any) -> ...any, SetWindowDock: (...any) -> ...any, @@ -688,6 +732,7 @@ export type ImGuiAPI = { SetWindowFontScale: (...any) -> ...any, SetWindowHiddenAndSkipItemsForCurrentFrame: (...any) -> ...any, SetWindowHitTestHole: (...any) -> ...any, + SetWindowParentWindowForFocusRoute: (...any) -> ...any, SetWindowPos: (...any) -> ...any, SetWindowSize: (...any) -> ...any, SetWindowViewport: (...any) -> ...any, @@ -836,6 +881,7 @@ export type ImGuiAPI = { TempInputScalar: (...any) -> ...any, TempInputText: (...any) -> ...any, TestKeyOwner: (...any) -> ...any, + TestShortcutRouting: (...any) -> ...any, Text: (fmt: string, ...any) -> (), TextAligned: (...any) -> ...any, TextBufferToString: (buf: {number}) -> string, @@ -867,9 +913,12 @@ export type ImGuiAPI = { TypingSelectFindNextSingleCharMatch: (...any) -> ...any, Unindent: (indent_w: number?) -> (), UnregisterFontAtlas: (...any) -> ...any, + UnregisterUserTexture: (...any) -> ...any, UpdateAliasKey: (...any) -> ...any, UpdateCurrentFontSize: (...any) -> ...any, + UpdateDebugToolFlashStyleColor: (...any) -> ...any, UpdateDebugToolItemPathQuery: (...any) -> ...any, + UpdateDebugToolItemPicker: (...any) -> ...any, UpdateFontsEndFrame: (...any) -> ...any, UpdateFontsNewFrame: (...any) -> ...any, UpdateHoveredWindowAndCaptureFlags: (...any) -> ...any, diff --git a/build/imgui_love.linemap.json b/build/imgui_love.linemap.json index 9a8dea0..892315e 100644 --- a/build/imgui_love.linemap.json +++ b/build/imgui_love.linemap.json @@ -1 +1 @@ -[[183, "imgui.lua"], [21603, "imgui_demo.lua"], [33455, "imgui_draw.lua"], [41658, "imgui_h.lua"], [44592, "imgui_impl_love.lua"], [45132, "imgui_internal.lua"], [48854, "imgui_tables.lua"], [53913, "imgui_widgets.lua"], [65889, "imstb_rectpack.lua"], [66553, "imstb_textedit.lua"], [68095, "imstb_truetype.lua"], [70883, "imstd_minstdio.lua"]] \ No newline at end of file +[[183, "imgui.lua"], [22717, "imgui_demo.lua"], [34568, "imgui_draw.lua"], [42873, "imgui_h.lua"], [45818, "imgui_impl_love.lua"], [46358, "imgui_internal.lua"], [50237, "imgui_tables.lua"], [55337, "imgui_widgets.lua"], [67451, "imstb_rectpack.lua"], [68115, "imstb_textedit.lua"], [69657, "imstb_truetype.lua"], [72445, "imstd_minstdio.lua"]] \ No newline at end of file diff --git a/build/imgui_love.lua b/build/imgui_love.lua index ae48a2d..9ddb82f 100644 --- a/build/imgui_love.lua +++ b/build/imgui_love.lua @@ -138,7 +138,7 @@ if not utf8 then end -local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImGuiKey, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImGuiDataType, ImStb, IM_TRUNC, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, IM_ASSERT_USER_ERROR_RET, ImHashStr, ImS32, ImGuiColorEditFlags, ImIsPowerOfTwo, ImAbs, ImVec4_Copy, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, IM_ASSERT_PARANOID, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, stbte, ImColor, ImCos, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiLocKey, ImU32, ExampleTreeFuncs, ImGuiListClipper, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImSin, ImGuiTabBarFlags, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, ImGuiMouseCursor, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImFabs, ImGuiCol, ImGuiSelectionBasicStorage, ImLengthSqr, ImS8, ImU8, ExampleAppPropertyEditorMT, ImGuiScrollFlags, ImGui_ImplLOVE_GetBackendData, ImLog, ExampleSelectionWithDeletionMT, CustomConstraints, ExampleAppLogMT, ImFontAtlasBuildInit, ImFontAtlasFontDestroyOutput, ImGuiComboFlags, ImGuiPopupFlags, ImGuiSliderFlags, ImTextClassifierSetCharClass, MyDocument, ShowExampleMenuFile, CalcCornerArcStepAndCount, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImFontConfig, ImGuiInputTextFlags, ImGuiStyle_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroySourceData, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImGuiTableColumn, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, IM_FREE, ImDrawListSplitter, ImGuiDragDropFlags, ImGuiFocusedFlags, stb_text_locate_coord, stb_text_makeundo_insert, stb_text_makeundo_replace, stb_textedit_find_charpos, stbtt_GetGlyphShape, ImGuiTableColumnSortSpecs, ImGuiTableInstanceData, ImGuiTableSettings, stb_text_makeundo_delete, stb_text_redo, stb_text_undo, stb_textedit_click, stb_textedit_drag, stbtt_FindGlyphIndex, stbtt_GetFontOffsetForIndex, stbtt_GetFontVMetrics, stbtt_GetGlyphBitmapBox, stbtt_GetGlyphHMetrics, stbtt_InitFont, stbtt_MakeGlyphBitmapSubpixelPrefilter, stbtt_ScaleForPixelHeight, stbtt__GetGlyphInfoT2, stbtt__GetGlyphShapeT2, stbtt_fontinfo, ImGuiOldColumnData, ImGuiOldColumnFlags, ImGuiOldColumns, ImGuiTable, ImGuiTableColumnSettings, ImGuiTableSortSpecs, ImGuiTableTempData, ImGui_ImplLOVE_CreateTexture, ImGui_ImplLOVE_DestroyTexture, ImGui_ImplLOVE_Init, ImGui_ImplLOVE_NewFrame, ImGui_ImplLOVE_RenderDrawData, ImGui_ImplLOVE_Shutdown, ImGui_ImplLOVE_UpdateTexture, stbrp_init_target, IMGUI_TABLE_MAX_COLUMNS, IMSTB_TEXTEDIT_UNDOSTATECOUNT, IM_COL32_DISABLE, ImGui_ImplLove, STB_TEXTEDIT_K_BACKSPACE, STB_TEXTEDIT_K_DELETE, STB_TEXTEDIT_K_DOWN, STB_TEXTEDIT_K_LEFT, STB_TEXTEDIT_K_LINEEND, STB_TEXTEDIT_K_LINESTART, STB_TEXTEDIT_K_PGDOWN, STB_TEXTEDIT_K_PGUP, STB_TEXTEDIT_K_REDO, STB_TEXTEDIT_K_RIGHT, STB_TEXTEDIT_K_SHIFT, STB_TEXTEDIT_K_TEXTEND +local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImGuiKey, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImStb, ImGuiDataType, IM_TRUNC, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, ImHashStr, IM_ASSERT_USER_ERROR_RET, ImIsPowerOfTwo, ImS32, ImGuiColorEditFlags, ImVec4_Copy, ImAbs, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, IM_ASSERT_PARANOID, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, stbte, ImColor, ImCos, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiListClipper, ImGuiLocKey, ImU32, ExampleTreeFuncs, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImSin, ImGuiTabBarFlags, ImLengthSqr, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, ImGuiMouseCursor, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImFabs, ImGuiCol, ImGuiSelectionBasicStorage, ImS8, ImU8, ExampleAppPropertyEditorMT, ImGuiScrollFlags, ImGui_ImplLOVE_GetBackendData, ImLog, ExampleSelectionWithDeletionMT, CustomConstraints, ExampleAppLogMT, ImFontAtlasBuildInit, ImFontAtlasFontDestroyOutput, ImGuiComboFlags, ImGuiPopupFlags, ImGuiSliderFlags, ImTextClassifierSetCharClass, MyDocument, ShowExampleMenuFile, CalcCornerArcStepAndCount, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImFontConfig, ImGuiInputTextFlags, ImGuiStyle_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroySourceData, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImGuiTableColumn, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, IM_FREE, ImDrawListSplitter, ImGuiDragDropFlags, ImGuiFocusedFlags, stb_text_locate_coord, stb_text_makeundo_insert, stb_text_makeundo_replace, stb_textedit_find_charpos, stbtt_GetGlyphShape, ImGuiTableColumnSortSpecs, ImGuiTableInstanceData, ImGuiTableSettings, stb_text_makeundo_delete, stb_text_redo, stb_text_undo, stb_textedit_click, stb_textedit_drag, stbtt_FindGlyphIndex, stbtt_GetFontOffsetForIndex, stbtt_GetFontVMetrics, stbtt_GetGlyphBitmapBox, stbtt_GetGlyphHMetrics, stbtt_InitFont, stbtt_MakeGlyphBitmapSubpixelPrefilter, stbtt_ScaleForPixelHeight, stbtt__GetGlyphInfoT2, stbtt__GetGlyphShapeT2, stbtt_fontinfo, ImGuiOldColumnData, ImGuiOldColumnFlags, ImGuiOldColumns, ImGuiTable, ImGuiTableColumnSettings, ImGuiTableSortSpecs, ImGuiTableTempData, ImGui_ImplLOVE_CreateTexture, ImGui_ImplLOVE_DestroyTexture, ImGui_ImplLOVE_Init, ImGui_ImplLOVE_NewFrame, ImGui_ImplLOVE_RenderDrawData, ImGui_ImplLOVE_Shutdown, ImGui_ImplLOVE_UpdateTexture, stbrp_init_target, DebugNodeTableGetSizingPolicyDesc, IMGUI_TABLE_MAX_COLUMNS, IMSTB_TEXTEDIT_UNDOSTATECOUNT, IM_COL32_DISABLE, ImGui_ImplLove, STB_TEXTEDIT_K_BACKSPACE, STB_TEXTEDIT_K_DELETE, STB_TEXTEDIT_K_DOWN, STB_TEXTEDIT_K_LEFT, STB_TEXTEDIT_K_LINEEND, STB_TEXTEDIT_K_LINESTART, STB_TEXTEDIT_K_PGDOWN, STB_TEXTEDIT_K_PGUP, STB_TEXTEDIT_K_REDO, STB_TEXTEDIT_K_RIGHT, STB_TEXTEDIT_K_SHIFT local type, mathMin, mathMax, mathFloor, mathCeil, bitOr, bitLShift = type, math.min, math.max, math.floor, math.ceil, bit32.bor, bit32.lshift local function IM_COL32(R, G, B, A) return (bitOr(bitLShift(A, 24 --[[IM_COL32_A_SHIFT]]), bitLShift(B, 16 --[[IM_COL32_B_SHIFT]]), bitLShift(G, 8 --[[IM_COL32_G_SHIFT]]), bitLShift(R, 0 --[[IM_COL32_R_SHIFT]]))) end @@ -613,6 +613,15 @@ IMGUI_DISABLE_DEBUG_TOOLS = false -- Disable metrics/debugger and other debug to --- @type ImGuiContext? local GImGui = nil +-- [Luau] IM_DEBUG_BREAK() (imgui_internal.h macro): Lua can't break into a debugger. It calls the optional user hook +-- g.DebugBreakCallback(g) instead (a context field added by this port; the library can't be patched from outside the bundle). +local function IM_DEBUG_BREAK() + local g = GImGui + if g ~= nil and g.DebugBreakCallback ~= nil then + g.DebugBreakCallback(g) + end +end + ImGui = {} ImStd = {} -- Contains functions that originally don't belong to cpp namespaces @@ -659,6 +668,17 @@ function ImGui.MemFree(owner, field) return GImAllocatorFreeFunc(owner, field, GImAllocatorUserData) end +-- [Luau] g.DemoMarkerCallback (fun(file, line, section)) is not in ImGuiContext() yet: nil unless set by the user. +--- @param file string +--- @param line int +--- @param section string +function ImGui.DemoMarker(file, line, section) + local g = GImGui + if g.DemoMarkerCallback ~= nil then + g.DemoMarkerCallback(file, line, section) + end +end + -- We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames" --- @param info ImGuiDebugAllocInfo --- @param frame_count int @@ -1538,6 +1558,11 @@ function ImGui.DockContextDeleteNode(ctx, node) dc.Nodes[node.ID] = nil end +-- Pre C++0x doesn't allow us to use a function-local type (without linkage) as template parameter, so we moved this here. +local function ImGuiDockContextPruneNodeData() + return { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 } +end + -- Garbage collect unused nodes (run once at init time) function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local g = ctx @@ -1547,7 +1572,7 @@ function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local pool = {} local function GetOrAdd(id) local d = pool[id] - if not d then d = { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 }; pool[id] = d end + if not d then d = ImGuiDockContextPruneNodeData(); pool[id] = d end return d end @@ -2117,6 +2142,10 @@ function ImGui.DockNodeHideHostWindow(node) if node.TabBar then ImGui.DockNodeRemoveTabBar(node) end end +local function ImGuiDockNodeTreeInfo() + return { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } +end + -- Search function called once by root node in DockNodeUpdate() local function DockNodeFindInfo(node, info) if node.Windows.Size > 0 then @@ -2257,7 +2286,7 @@ function ImGui.DockNodeUpdateForRootNode(node) -- - Setup central node pointers -- - Find if there's only a single visible window in the hierarchy (in which case we need to display a regular title bar -> FIXME-DOCK: that last part is not done yet!) -- Cannot merge this with DockNodeUpdateFlagsAndCollapse() because FirstNodeWithWindows is found after window removal and child collapsing - local info = { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } + local info = ImGuiDockNodeTreeInfo() DockNodeFindInfo(node, info) node.CentralNode = info.CentralNode node.OnlyNodeWithWindows = (info.CountNodesWithWindows == 1) and info.FirstNodeWithWindows or nil @@ -3902,6 +3931,12 @@ function ImGui.DockBuilderRemoveNode(node_id) ImGui.DockContextRemoveNode(g, node, true) end +--- @param a ImGuiDockNode +--- @param b ImGuiDockNode +local function DockNodeComparerDepthMostFirst(a, b) -- [Luau] table.sort() "less than" predicate + return ImGui.DockNodeGetDepth(a) > ImGui.DockNodeGetDepth(b) +end + -- root_id = 0 to remove all, root_id != 0 to remove child of given node. function ImGui.DockBuilderRemoveNodeChildNodes(root_id) local g = ImGui.GetCurrentContext() @@ -3954,9 +3989,7 @@ function ImGui.DockBuilderRemoveNodeChildNodes(root_id) -- Not really efficient, but easier to destroy a whole hierarchy considering DockContextRemoveNode is attempting to merge nodes if #nodes_to_remove > 1 then - local depth = {} - for _, n in ipairs(nodes_to_remove) do depth[n] = ImGui.DockNodeGetDepth(n) end - table.sort(nodes_to_remove, function(a, b) return depth[a] > depth[b] end) + table.sort(nodes_to_remove, DockNodeComparerDepthMostFirst) end for _, n in ipairs(nodes_to_remove) do ImGui.DockContextRemoveNode(g, n, false) @@ -5304,6 +5337,79 @@ function ImStd.ImTextFindValidUtf8CodepointEnd(text, in_text_start, in_text_end, return prev end +------------------------------------------------------------------------------- +-- [SECTION] MISC HELPERS/UTILITIES (Geometry functions) +------------------------------------------------------------------------------- + +--- @param p1 ImVec2 +--- @param p2 ImVec2 +--- @param p3 ImVec2 +--- @param p4 ImVec2 +--- @param p ImVec2 +--- @param num_segments int +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPoint(p1, p2, p3, p4, p, num_segments) + assert(num_segments > 0) -- Use ImBezierCubicClosestPointCasteljau() + local p_last = p1 + local p_closest = ImVec2(0, 0) + local p_closest_dist2 = 3.4028234663853e+38 --[[FLT_MAX]] + local t_step = 1.0 / num_segments + for i_step = 1, num_segments do + local p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step) + local p_line = ImStd.ImLineClosestPoint(p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < p_closest_dist2 then + p_closest = p_line + p_closest_dist2 = dist2 + end + p_last = p_current + end + return ImVec2(p_closest.x, p_closest.y) +end + +-- Closely mimics PathBezierToCasteljau() in imgui_draw.cpp +-- [Luau] p_closest / p_last / p_closest_dist2 are C++ references: kept in the `st` table. +local function ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x2, y2, x3, y3, x4, y4, max_error_sqr, level) + local dx = x4 - x1 + local dy = y4 - y1 + local d2 = ((x2 - x4) * dy - (y2 - y4) * dx) + local d3 = ((x3 - x4) * dy - (y3 - y4) * dx) + d2 = (d2 >= 0) and d2 or -d2 + d3 = (d3 >= 0) and d3 or -d3 + if (d2 + d3) * (d2 + d3) < max_error_sqr * (dx * dx + dy * dy) then + local p_current = ImVec2(x4, y4) + local p_line = ImStd.ImLineClosestPoint(st.p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < st.p_closest_dist2 then + st.p_closest = p_line + st.p_closest_dist2 = dist2 + end + st.p_last = p_current + elseif level < 10 then + local x12, y12 = (x1 + x2) * 0.5, (y1 + y2) * 0.5 + local x23, y23 = (x2 + x3) * 0.5, (y2 + y3) * 0.5 + local x34, y34 = (x3 + x4) * 0.5, (y3 + y4) * 0.5 + local x123, y123 = (x12 + x23) * 0.5, (y12 + y23) * 0.5 + local x234, y234 = (x23 + x34) * 0.5, (y23 + y34) * 0.5 + local x1234, y1234 = (x123 + x234) * 0.5, (y123 + y234) * 0.5 + ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x12, y12, x123, y123, x1234, y1234, max_error_sqr, level + 1) + ImBezierCubicClosestPointCasteljauStep(p, st, x1234, y1234, x234, y234, x34, y34, x4, y4, max_error_sqr, level + 1) + end +end + +-- tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationMaxError +-- Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPointCasteljau(p1, p2, p3, p4, p, max_error) + assert(max_error > 0.0) + local st = { p_last = p1, p_closest = ImVec2(0, 0), p_closest_dist2 = 3.4028234663853e+38 --[[FLT_MAX]] } + local max_error_sqr = max_error * max_error + ImBezierCubicClosestPointCasteljauStep(p, st, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, max_error_sqr, 0) + return ImVec2(st.p_closest.x, st.p_closest.y) +end + --- @param a ImVec2 --- @param b ImVec2 --- @param p ImVec2 @@ -5491,6 +5597,20 @@ function ImGui.UpdateCurrentFontSize(restore_font_size_after_scaling) g.DrawListSharedData.FontScale = g.FontBakedScale end +-- Exposed in case user may want to override setting density. +-- IMPORTANT: Begin()/End() is overriding density. Be considerate of this you change it. +-- [Luau] upstream g.CurrentPixelDensity is g.FontRasterizerDensity in this port. +--- @param pixel_density float +function ImGui.SetPixelDensity(pixel_density) + local g = GImGui + assert(bit32.band(g.IO.BackendFlags, 16 --[[ImGuiBackendFlags.RendererHasTextures]]) ~= 0) + if g.FontRasterizerDensity == pixel_density then + return + end + g.FontRasterizerDensity = pixel_density + ImGui.UpdateCurrentFontSize(0.0) +end + -- Use ImDrawList:_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList. -- - Whereas ImDrawList:PushTexture()/PopTexture() is not to be used across Begin() calls. -- - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did... @@ -5635,6 +5755,22 @@ function ImGui.GetDefaultFont() return g.IO.FontDefault and g.IO.FontDefault or atlas.Fonts[1] end +-- EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates. Textures logic will be automatically be updated in NewFrame(). +--- @param tex ImTextureData +function ImGui.RegisterUserTexture(tex) + local g = GImGui + tex.RefCount = tex.RefCount + 1 + g.UserTextures:push_back(tex) +end + +--- @param tex ImTextureData +function ImGui.UnregisterUserTexture(tex) + local g = GImGui + assert(tex.RefCount > 0) + tex.RefCount = tex.RefCount - 1 + g.UserTextures:find_erase(tex) +end + --- @param atlas ImFontAtlas function ImGui.RegisterFontAtlas(atlas) local g = GImGui @@ -5717,6 +5853,16 @@ local GLocalizationEntriesEnUS = { ImGuiLocEntry(ImGuiLocKey.DockingDragToUndockOrMoveNode, "Click and drag to move or undock whole node."), } +-- [Luau] Default platform handlers (upstream: next to the metrics section; defined here so Initialize() can see the local). +-- Roblox has no shell: IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS path. Default clipboard/IME handlers are OS-specific: left nil +-- (the backends install their own clipboard handlers). +local function Platform_OpenInShellFn_DefaultImpl(ctx, path) return false end + +-- Setup default ImGuiPlatformIO clipboard/IME handlers +local function InitializeDefaultPlatformHandlers(platform_io) + platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl +end + function ImGui.Initialize() local g = GImGui assert(not g.Initialized and not g.SettingsLoaded) @@ -5729,6 +5875,23 @@ function ImGui.Initialize() -- Setup default localization table ImGui.LocalizeRegisterEntries(GLocalizationEntriesEnUS, #GLocalizationEntriesEnUS) + -- Setup default ImGuiPlatformIO clipboard/IME handlers. + InitializeDefaultPlatformHandlers(g.PlatformIO) + + -- [Luau] Debug tools context fields not (yet) in ImGuiContext() (imgui_internal.lua): initialized here. + if g.DebugItemPickerActive == nil then g.DebugItemPickerActive = false end -- Item picker is active (started with DebugStartItemPicker()) + if g.DebugItemPickerMouseButton == nil then g.DebugItemPickerMouseButton = 0 --[[ImGuiMouseButton.Left]] end + if g.DebugItemPickerBreakId == nil then g.DebugItemPickerBreakId = 0 end -- Will call IM_DEBUG_BREAK() when encountering this ID + if g.DebugFlashStyleColorTime == nil then g.DebugFlashStyleColorTime = 0.0 end + if g.DebugFlashStyleColorBackup == nil then g.DebugFlashStyleColorBackup = ImVec4(0, 0, 0, 0) end + if g.DebugLocateId == nil then g.DebugLocateId = 0 end -- Storage for DebugLocateItem(): ID to locate + if g.DebugLocateFrames == nil then g.DebugLocateFrames = 0 end -- Storage for DebugLocateItem(): number of frames to display + if g.DebugBreakInLocateId == nil then g.DebugBreakInLocateId = false end -- Debug break in ItemAdd() call for g.DebugLocateId. + if g.DebugBreakKeyChord == nil then g.DebugBreakKeyChord = 611 --[[ImGuiKey.Pause]] end -- = ImGuiKey_Pause + if g.DebugBreakInShortcutRouting == nil then g.DebugBreakInShortcutRouting = 0 --[[ImGuiKey.None]] end + if g.DebugLogAutoDisableFrames == nil then g.DebugLogAutoDisableFrames = 0 end + if g.DebugLogAutoDisableFlags == nil then g.DebugLogAutoDisableFlags = 0 --[[ImGuiDebugLogFlags.None]] end + -- Create default viewport local viewport = ImGuiViewportP() viewport.ID = IMGUI_VIEWPORT_DEFAULT_ID @@ -6129,6 +6292,21 @@ local function WindowSettingsHandler_ClearAll(ctx, handler) g.SettingsWindows:clear() end +-- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD number, 0 = invalid), so ImGuiPackedDate::IsValid()/Unpack() are inlined. +-- g.SessionDate doesn't exist in this port's context yet (no Platform_SessionDate support): treated as 0. +local function WindowSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for _, settings in g.SettingsWindows:iter() do + local is_valid = (settings.LastUsedDate or 0) ~= 0 + if ((args._DiscardOlderThanDate or 0) ~= 0 and (settings.LastUsedDate or 0) < args._DiscardOlderThanDate) or (args.DiscardWhenMissingDate and not is_valid) then + settings.WantDelete = true + end + if args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate or 0 + end + end +end + local function WindowSettingsHandler_ReadOpen(ctx, handler, name) local id = ImHashStr(name) local settings = ImGui.FindWindowSettingsByID(id) @@ -6244,6 +6422,7 @@ function ImGui.WindowSettingsAddSettingsHandler() ini_handler.TypeName = "Window" ini_handler.TypeHash = ImHashStr("Window") ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll + ini_handler.CleanupFn = WindowSettingsHandler_Cleanup ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll @@ -6619,6 +6798,20 @@ function ImGui.ItemAdd(bb, id, nav_bb_arg, extra_flags) end end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + if id == g.DebugLocateId then + ImGui.DebugLocateItemResolveWithLastItem() + end + + -- [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". + -- Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". + -- READ THE FAQ: https://dearimgui.com/faq + assert(id ~= window.ID, "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!") + end +end + if id ~= 0 and g.DeactivatedItemData.ID == id then g.DeactivatedItemData.ElapseFrame = g.FrameCount end @@ -8104,6 +8297,21 @@ end return false end +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + -- [DEBUG] Item Picker tool! + -- We perform the check here because reaching is path is rare (1~ time a frame), + -- making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered + -- items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost. + if g.DebugItemPickerActive and g.HoveredIdPreviousFrame == id then + ImGui.GetForegroundDrawList():AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)) + end + if g.DebugItemPickerBreakId == id then + IM_DEBUG_BREAK() + end + end +end + if g.NavHighlightItemUnderNav and (bit32.band(item_flags, 32768 --[[ImGuiItemFlags.NoNavDisableMouseHover]]) == 0) then return false end @@ -8211,6 +8419,19 @@ function MT.ImGuiIO:AddInputCharacterUTF16(c) self:AddInputCharacter(cp) end +--- @param str string +function MT.ImGuiIO:AddInputCharactersUTF8(str) + if not self.AppAcceptingEvents then + return + end + local p, str_end = 1, #str + 1 + while p < str_end and string.byte(str, p) ~= 0 do + local len, c = ImStd.ImTextCharFromUtf8(str, p, str_end) + p = p + len + self:AddInputCharacter(c) + end +end + -- Clear all incoming events. function MT.ImGuiIO:ClearEventsQueue() assert(self.Ctx ~= nil) @@ -8263,7 +8484,7 @@ end --- @param type ImGuiInputEventType --- @param arg? int --- @return ImGuiInputEvent? -function MT.ImGuiIO:FindLatestInputEvent(ctx, type, arg) +local function FindLatestInputEvent(ctx, type, arg) if arg == nil then arg = -1 end local g = ctx @@ -8313,7 +8534,7 @@ function MT.ImGuiIO:AddKeyAnalogEvent(key, down, analog_value) end -- Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed) - local latest_event = self:FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], key) + local latest_event = FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], key) local key_data = ImGui.GetKeyData(g, key) local latest_key_down = latest_event and latest_event.Key.Down or key_data.Down local latest_key_analog = latest_event and latest_event.Key.AnalogValue or key_data.AnalogValue @@ -8343,6 +8564,23 @@ function MT.ImGuiIO:AddKeyEvent(key, down) self:AddKeyAnalogEvent(key, down, (down and 1.0 or 0.0)) end +-- [Optional] Call after AddKeyEvent(). +-- Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices. +-- If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. +--- @param key ImGuiKey +--- @param native_keycode int +--- @param native_scancode int +--- @param native_legacy_index? int +function MT.ImGuiIO:SetKeyEventNativeData(key, native_keycode, native_scancode, native_legacy_index) + if native_legacy_index == nil then native_legacy_index = -1 end + if key == 0 --[[ImGuiKey.None]] then + return + end + assert(ImGui.IsNamedKey(key)) -- >= 512 + assert(native_legacy_index == -1 or (native_legacy_index >= 0 and native_legacy_index < 512)) -- [Luau] inline IsLegacyKey(): >= 0 && <= 511 + -- Yet unused: key, native_keycode, native_scancode, native_legacy_index +end + -- 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. --- @param accepting_events bool function MT.ImGuiIO:SetAppAcceptingEvents(accepting_events) @@ -8368,7 +8606,7 @@ function MT.ImGuiIO:AddMouseViewportEvent(viewport_id) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 4 --[[ImGuiInputEventType.MouseViewport]]) + local latest_event = FindLatestInputEvent(g, 4 --[[ImGuiInputEventType.MouseViewport]]) local latest_viewport_id if latest_event then latest_viewport_id = latest_event.MouseViewport.HoveredViewportID @@ -8393,7 +8631,7 @@ function MT.ImGuiIO:AddFocusEvent(focused) local g = self.Ctx -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 7 --[[ImGuiInputEventType.Focus]]) + local latest_event = FindLatestInputEvent(g, 7 --[[ImGuiInputEventType.Focus]]) local latest_focused = latest_event and latest_event.AppFocused.Focused or (not g.IO.AppFocusLost) if latest_focused == focused or (self.ConfigDebugIgnoreFocusLoss and not focused) then return @@ -8430,7 +8668,7 @@ function MT.ImGuiIO:AddMousePosEvent(x, y) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 1 --[[ImGuiInputEventType.MousePos]]) + local latest_event = FindLatestInputEvent(g, 1 --[[ImGuiInputEventType.MousePos]]) local latest_pos = latest_event and ImVec2(latest_event.MousePos.PosX, latest_event.MousePos.PosY) or self.MousePos if latest_pos.x == x_val and latest_pos.y == y_val then return @@ -8468,7 +8706,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, 3 --[[ImGuiInputEventType.MouseButton]], mouse_button) + local latest_event = FindLatestInputEvent(g, 3 --[[ImGuiInputEventType.MouseButton]], mouse_button) local latest_button_down = latest_event and latest_event.MouseButton.Down or self.MouseDown[mouse_button] if latest_button_down == down then return @@ -8478,7 +8716,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) -- - Note that this is actual physical Ctrl which is ImGuiMod_Super for us. -- - At this point we want from !down to down, so this is handling the initial press. if self.ConfigMacOSXBehaviors and mouse_button == 0 and down then - local latest_super_event = self:FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], 32768 --[[ImGuiMod_Super]]) + local latest_super_event = FindLatestInputEvent(g, 5 --[[ImGuiInputEventType.Key]], 32768 --[[ImGuiMod_Super]]) if latest_super_event and latest_super_event.Key.Down or self.KeySuper then -- IMGUI_DEBUG_LOG_IO("[io] Super+Left Click aliased into Right Click\n") self.MouseCtrlLeftAsRightClick = true @@ -9128,7 +9366,7 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) -- [DEBUG] Debug break requested by user if g.DebugBreakInShortcutRouting == key_chord then - -- IM_DEBUG_BREAK() + IM_DEBUG_BREAK() end if bit32.band(flags, 65536 --[[ImGuiInputFlags.RouteUnlessBgFocused]]) ~= 0 then @@ -9199,6 +9437,18 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) return routing_data.RoutingCurr == owner_id end +-- Currently unused by core (but used by tests) +-- Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. +--- @param key_chord ImGuiKeyChord +--- @param owner_id ImGuiID +--- @return bool +function ImGui.TestShortcutRouting(key_chord, owner_id) + local routing_id = GetRoutingIdFromOwnerId(owner_id) + key_chord = ImGui.FixupKeyChord(key_chord) + local routing_data = ImGui.GetShortcutRoutingData(key_chord) -- FIXME: Could avoid creating entry. + return routing_data.RoutingCurr == routing_id +end + -- We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position. --- @param mouse_pos? ImVec2 function ImGui.IsMousePosValid(mouse_pos) @@ -9427,6 +9677,39 @@ function ImGui.ResetMouseDragDelta(button) ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos) end +--- @param source ImGuiInputSource +--- @return string +local function GetInputSourceName(source) + local input_source_names = { "None", "Mouse", "Keyboard", "Gamepad" } + assert(#input_source_names == 4 --[[ImGuiInputSource.COUNT]]) + if source < 0 or source >= 4 --[[ImGuiInputSource.COUNT]] then + return "Unknown" + end + return input_source_names[source + 1] +end +--- @param source ImGuiMouseSource +--- @return string +local function GetMouseSourceName(source) + local mouse_source_names = { "Mouse", "TouchScreen", "Pen" } + assert(#mouse_source_names == 3 --[[ImGuiMouseSource.COUNT]]) + if source < 0 or source >= 3 --[[ImGuiMouseSource.COUNT]] then + return "Unknown" + end + return mouse_source_names[source + 1] +end +--- @param prefix string +--- @param e ImGuiInputEvent +local function DebugPrintInputEvent(prefix, e) + local T = ImGuiInputEventType + if e.Type == T.MousePos then if e.MousePos.PosX == -3.4028234663853e+38 --[[FLT_MAX]] and e.MousePos.PosY == -3.4028234663853e+38 --[[FLT_MAX]] then IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix) else IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix, e.MousePos.PosX, e.MousePos.PosY, GetMouseSourceName(e.MousePos.MouseSource)) end return end + if e.Type == T.MouseButton then IMGUI_DEBUG_LOG_IO("[io] %s: MouseButton %d %s (%s)\n", prefix, e.MouseButton.Button, e.MouseButton.Down and "Down" or "Up", GetMouseSourceName(e.MouseButton.MouseSource)) return end + if e.Type == T.MouseWheel then IMGUI_DEBUG_LOG_IO("[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix, e.MouseWheel.WheelX, e.MouseWheel.WheelY, GetMouseSourceName(e.MouseWheel.MouseSource)) return end + if e.Type == T.MouseViewport then IMGUI_DEBUG_LOG_IO("[io] %s: MouseViewport (0x%08X)\n", prefix, e.MouseViewport.HoveredViewportID) return end + if e.Type == T.Key then IMGUI_DEBUG_LOG_IO("[io] %s: Key \"%s\" %s\n", prefix, ImGui.GetKeyName(e.Key.Key), e.Key.Down and "Down" or "Up") return end + if e.Type == T.Text then IMGUI_DEBUG_LOG_IO("[io] %s: Text: '%s' (U+%08X)\n", prefix, utf8.char(e.Text.Char), e.Text.Char) return end -- [Luau] utf8.char() instead of ImTextCharToUtf8() + if e.Type == T.Focus then IMGUI_DEBUG_LOG_IO("[io] %s: AppFocused %d\n", prefix, e.AppFocused.Focused and 1 or 0) return end +end + do local key_changed_mask = ImBitArray(ImGuiKey.NamedKey_COUNT) @@ -9559,6 +9842,15 @@ function ImGui.UpdateInputEvents(trickle_fast_inputs) event_n = event_n + 1 end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if event_n ~= 1 and bit32.band(g.DebugLogFlags, 128 --[[ImGuiDebugLogFlags.EventIO]]) ~= 0 then -- [Luau] event_n is the 1-based next index: processed count = event_n - 1 + for n = 1, g.InputEventsQueue.Size do + DebugPrintInputEvent((n < event_n) and "Processed" or "Remaining", g.InputEventsQueue.Data[n]) + end + end +end + -- Remaining events will be processed on the next frame -- FIXME-MULTITHREADING: io.AddKeyEvent() etc. calls are mostly thread-safe apart from the fact they push to this -- queue which may be resized here. Could potentially rework this to narrow down the section needing a mutex? (#5772) @@ -9755,6 +10047,12 @@ end --- @param window ImGuiWindow --- @nodiscard +--- @param window ImGuiWindow +--- @return ImGuiWindow +local function GetWindowForTitleAndMenuHeight(window) + return (window.DockNodeAsHost and window.DockNodeAsHost.VisibleWindow) and window.DockNodeAsHost.VisibleWindow or window +end + local function CalcWindowMinSize(window) -- We give windows non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) -- FIXME: Essentially we want to restrict manual resizing to WindowMinSize+Decoration, and allow api resizing to be smaller. @@ -9790,7 +10088,7 @@ local function CalcWindowMinSize(window) end -- Reduce artifacts with very small windows - local window_for_height = window + local window_for_height = GetWindowForTitleAndMenuHeight(window) size_min.y = ImMax(size_min.y, window_for_height.TitleBarHeight + window_for_height.MenuBarHeight + ImMax(0, g.Style.WindowRounding - 1)) return size_min @@ -9978,6 +10276,29 @@ end --- @param resize_grip_col table --- @param visibility_rect ImRect --- @return int, int, int +--- @param window ImGuiWindow +--- @param n int +--- @return ImGuiID +function ImGui.GetWindowResizeCornerID(window, n) + assert(n >= 0 and n < 4) + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] ImHashData(&n, sizeof(int), id): same hashing as window:GetID(n) used by UpdateWindowManualResize() + return id +end + +--- @param window ImGuiWindow +--- @param dir ImGuiDir +--- @return ImGuiID +function ImGui.GetWindowResizeBorderID(window, dir) + assert(dir >= 0 and dir < 4) + local n = dir + 4 + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] see GetWindowResizeCornerID() + return id +end + local function UpdateWindowManualResize(window, resize_grip_count, resize_grip_col, visibility_rect) local g = GImGui local flags = window.Flags @@ -10609,6 +10930,21 @@ end --- @param border_n int --- @param border_col ImU32 --- @param border_size float +--- @param window ImGuiWindow +--- @param visibility_rect ImRect +local function ClampWindowPos(window, visibility_rect) + local size_for_clamping = ImVec2(window.Size.x, window.Size.y) + local move_from_title_bar_only = bit32.band(window.BgClickFlags, 1 --[[ImGuiWindowBgClickFlags.Move]]) == 0 + if move_from_title_bar_only and window.DockNodeAsHost then + size_for_clamping.y = ImGui.GetFrameHeight() -- Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here. + elseif move_from_title_bar_only and bit32.band(window.Flags, 1 --[[ImGuiWindowFlags.NoTitleBar]]) == 0 then + size_for_clamping.y = window.TitleBarHeight + end + -- [Luau] in place (window.Pos may be referenced elsewhere): window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max) + window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - size_for_clamping.x, visibility_rect.Max.x) + window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping.y, visibility_rect.Max.y) +end + local function RenderWindowOuterSingleBorder(window, border_n, border_col, border_size) local def = ImGuiResizeBorderDef[border_n + 1] local rounding = window.WindowRounding @@ -11276,6 +11612,11 @@ function ImGui.GetWindowDrawList() return window.DrawList end +--- @return ImFontBaked +function ImGui.GetFontBaked() + return GImGui.FontBaked +end + function ImGui.GetFont() return GImGui.Font end @@ -11898,6 +12239,11 @@ function ImGui.Begin(name, open, flags) window = CreateNewWindow(name, flags) --- @cast window ImGuiWindow end + -- [DEBUG] Debug break requested by user + if g.DebugBreakInWindow == window.ID then + IM_DEBUG_BREAK() + end + if bit32.band(g.NextWindowData.HasFlags, 256 --[[ImGuiNextWindowDataFlags.HasWindowFlags]]) ~= 0 then flags = bit32.band(bit32.bor(flags, g.NextWindowData.WindowFlagsSet), bit32.bnot(g.NextWindowData.WindowFlagsClear)) end @@ -12396,12 +12742,7 @@ function ImGui.Begin(name, open, flags) -- FIXME: Similar to code in GetWindowAllowedExtentRect() if not window_pos_set_by_api and bit32.band(flags, 16777216 --[[ImGuiWindowFlags.ChildWindow]]) == 0 then if not window.ViewportOwned and viewport_rect:GetWidth() > 0 and viewport_rect:GetHeight() > 0.0 then - local size_for_clamping_y = window.Size.y - if bit32.band(window.BgClickFlags, 1 --[[ImGuiWindowBgClickFlags.Move]]) == 0 and bit32.band(window.Flags, 1 --[[ImGuiWindowFlags.NoTitleBar]]) == 0 then - size_for_clamping_y = window.TitleBarHeight - end - window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - window.Size.x, visibility_rect.Max.x) - window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping_y, visibility_rect.Max.y) + ClampWindowPos(window, visibility_rect) end end window.Pos.x = ImTrunc(window.Pos.x) window.Pos.y = ImTrunc(window.Pos.y) @@ -12836,6 +13177,13 @@ function ImGui.Begin(name, open, flags) window.DC.WindowItemStatusFlags = bit32.bor(window.DC.WindowItemStatusFlags, 1 --[[ImGuiItemStatusFlags.HoveredRect]]) end ImGui.SetLastItemDataForWindow(window, title_bar_rect) + + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if g.DebugLocateId ~= 0 and (window.ID == g.DebugLocateId or window.MoveId == g.DebugLocateId) then + ImGui.DebugLocateItemResolveWithLastItem() + end +end else -- Skip refresh always mark active if (window.SkipRefresh) then @@ -13952,14 +14300,19 @@ function ImGui.NewFrame() assert(GImGui ~= nil, "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?") local g = GImGui - g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame - -- [Luau] ErrorCheckNewFrameSanityChecks() is not ported; only the parts below are inlined. - assert(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") - -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) - if g.Style.CurveTessellationTol ~= 0.0 then - g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + -- Remove pending delete hooks before frame start. + -- This deferred removal avoid issues of removal while iterating the hook vector + for n = g.Hooks.Size, 1, -1 do + if g.Hooks.Data[n].Type == 7 --[[ImGuiContextHookType.PendingRemoval_]] then + g.Hooks:erase(n) + end end - g.Style.CurveTessellationTol = 0.0 + + ImGui.CallContextHooks(g, 0 --[[ImGuiContextHookType.NewFramePre]]) + + -- Check and assert for various common IO and Configuration mistakes + g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame + ImGui.ErrorCheckNewFrameSanityChecks() g.ConfigFlagsCurrFrame = g.IO.ConfigFlags -- Load settings on first frame, save settings when modified (after a delay) @@ -14230,12 +14583,31 @@ function ImGui.NewFrame() g.CurrentItemFlags = g.ItemFlagsStack:back() g.GroupStack:resize(0) - -- [DEBUG] ID Stack Tool query - ImGui.UpdateDebugToolItemPathQuery() - -- Docking ImGui.DockContextNewFrameUpdateDocking(g) + -- [DEBUG] Update debug features +if not IMGUI_DISABLE_DEBUG_TOOLS then + ImGui.UpdateDebugToolItemPicker() + ImGui.UpdateDebugToolItemPathQuery() + ImGui.UpdateDebugToolFlashStyleColor() + if g.DebugLocateFrames > 0 then + g.DebugLocateFrames = g.DebugLocateFrames - 1 + if g.DebugLocateFrames == 0 then + g.DebugLocateId = 0 + g.DebugBreakInLocateId = false + end + end + if (g.DebugLogAutoDisableFrames or 0) > 0 then + g.DebugLogAutoDisableFrames = g.DebugLogAutoDisableFrames - 1 + if g.DebugLogAutoDisableFrames == 0 then + ImGui.DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n") + g.DebugLogFlags = bit32.band(g.DebugLogFlags, bit32.bnot(g.DebugLogAutoDisableFlags)) + g.DebugLogAutoDisableFlags = 0 --[[ImGuiDebugLogFlags.None]] + end + end +end + -- Create implicit/fallback window - which we will only render it if the user has added something to it. -- We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. -- This fallback is particularly important as it prevents ImGui:: calls from crashing. @@ -14256,6 +14628,8 @@ function ImGui.NewFrame() else g.DebugBeginReturnValueCullDepth = -1 end + + ImGui.CallContextHooks(g, 1 --[[ImGuiContextHookType.NewFramePost]]) end -- This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. @@ -14269,10 +14643,13 @@ function ImGui.EndFrame() end IM_ASSERT_USER_ERROR(g.WithinFrameScope, "Forgot to call ImGui::NewFrame()?") + ImGui.CallContextHooks(g, 2 --[[ImGuiContextHookType.EndFramePre]]) + -- [EXPERIMENTAL] Recover from errors if g.IO.ConfigErrorRecovery and g.StackSizesInNewFrame then ImGui.ErrorRecoveryTryToRecoverState(g.StackSizesInNewFrame) end + ImGui.ErrorCheckEndFrameSanityChecks() ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) @@ -14364,6 +14741,8 @@ function ImGui.EndFrame() g.IO.MouseWheel = 0.0 g.IO.MouseWheelH = 0.0 g.IO.InputQueueCharacters:resize(0) + + ImGui.CallContextHooks(g, 3 --[[ImGuiContextHookType.EndFramePost]]) end -- TODO: @@ -14381,6 +14760,7 @@ function ImGui.Render() g.FrameCountRendered = g.FrameCount g.IO.MetricsRenderWindows = 0 + ImGui.CallContextHooks(g, 4 --[[ImGuiContextHookType.RenderPre]]) -- Add background ImDrawList (for each active viewport) for _, viewport in g.Viewports:iter() do @@ -14433,6 +14813,8 @@ function ImGui.Render() g.IO.MetricsRenderVertices = g.IO.MetricsRenderVertices + draw_data.TotalVtxCount g.IO.MetricsRenderIndices = g.IO.MetricsRenderIndices + draw_data.TotalIdxCount end + + ImGui.CallContextHooks(g, 5 --[[ImGuiContextHookType.RenderPost]]) end -- Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. @@ -14515,13 +14897,16 @@ function ImGui.Shutdown() end g.DrawListSharedData.TempBuffer:clear() - -- Shutdown extensions - ImGui.DockContextShutdown(g) - -- Cleanup of other data are conditional on actually having initialized Dear ImGui. if not g.Initialized then return end + + -- Shutdown extensions + ImGui.DockContextShutdown(g) + + ImGui.CallContextHooks(g, 6 --[[ImGuiContextHookType.Shutdown]]) + -- TODO: -- Clear everything else @@ -14530,6 +14915,74 @@ function ImGui.Shutdown() g.MenusIdSubmittedThisFrame:clear() end +-- When using multiple context it can be helpful to give name a name. +-- (A) Will be visible in debugger, (B) Will be included in all IMGUI_DEBUG_LOG() calls, (C) Should be <= 15 characters long. +--- @param ctx ImGuiContext +--- @param name string +function ImGui.SetContextName(ctx, name) + ctx.ContextName = string.sub(name, 1, 15) -- [Luau] ImStrncpy() into char[16] +end + +-- [Luau] ImGuiContextHookType / ImGuiContextHook are not defined in imgui_internal.lua yet: defined here. +--- @enum ImGuiContextHookType +ImGuiContextHookType = ImGuiContextHookType or { NewFramePre = 0, NewFramePost = 1, EndFramePre = 2, EndFramePost = 3, RenderPre = 4, RenderPost = 5, Shutdown = 6, PendingRemoval_ = 7 } + +--- @class ImGuiContextHook +--- @field HookId ImGuiID -- A unique ID assigned by AddContextHook() +--- @field Type ImGuiContextHookType +--- @field Owner ImGuiID +--- @field Callback fun(ctx: ImGuiContext, hook: ImGuiContextHook)? +--- @field UserData any +if ImGuiContextHook == nil then + function ImGuiContextHook() + return { HookId = 0, Type = 0 --[[ImGuiContextHookType.NewFramePre]], Owner = 0, Callback = nil, UserData = nil } + end +end + +-- No specific ordering/dependency support, will see as needed +--- @param ctx ImGuiContext +--- @param hook ImGuiContextHook +--- @return ImGuiID +function ImGui.AddContextHook(ctx, hook) + local g = ctx + assert(hook.Callback ~= nil and (hook.HookId or 0) == 0 and hook.Type ~= 7 --[[ImGuiContextHookType.PendingRemoval_]]) + local copy = ImGuiContextHook() -- [Luau] g.Hooks.push_back(*hook): store a copy + copy.Type = hook.Type; copy.Owner = hook.Owner or 0; copy.Callback = hook.Callback; copy.UserData = hook.UserData + g.Hooks:push_back(copy) + g.HookIdNext = g.HookIdNext + 1 + g.Hooks:back().HookId = g.HookIdNext + return g.HookIdNext +end + +-- Deferred removal, avoiding issue with changing vector while iterating it +--- @param ctx ImGuiContext +--- @param hook_id ImGuiID +function ImGui.RemoveContextHook(ctx, hook_id) + local g = ctx + assert(hook_id ~= 0) + for _, hook in g.Hooks:iter() do + if hook.HookId == hook_id then + hook.Type = 7 --[[ImGuiContextHookType.PendingRemoval_]] + end + end +end + +-- Call context hooks (used by e.g. test engine) +-- We assume a small number of hooks so all stored in same array +--- @param ctx ImGuiContext +--- @param hook_type ImGuiContextHookType +function ImGui.CallContextHooks(ctx, hook_type) + local g = ctx + local hooks = g.Hooks + if hooks.Size == 0 then return end -- [Luau] fast path + for n = 1, hooks.Size do + local hook = hooks.Data[n] + if hook.Type == hook_type then + hook.Callback(g, hook) + end + end +end + -- A conformant backend should return nil on failure (e.g. clipboard data is not text). --- @return string? function ImGui.GetClipboardText() @@ -15447,6 +15900,11 @@ end --- @param fmt string --- @param ... any function ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()) +function ImGui.SetTooltipV(fmt, ...) if not ImGui.BeginTooltipEx(2 --[[ImGuiTooltipFlags.OverridePrevious]], 0 --[[ImGuiWindowFlags.None]]) then return end @@ -15459,8 +15917,12 @@ end --- @param fmt string --- @param ... any function ImGui.SetItemTooltip(fmt, ...) + ImGui.SetItemTooltipV(fmt, ...) +end + +function ImGui.SetItemTooltipV(fmt, ...) if ImGui.IsItemHovered(4096 --[[ImGuiHoveredFlags.ForTooltip]]) then - ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) end end @@ -17845,6 +18307,7 @@ function MT.ImGuiPlatformIO:ClearPlatformHandlers() self.Platform_SetWindowTitle = nil; self.Platform_SetWindowAlpha = nil; self.Platform_UpdateWindow = nil self.Platform_RenderWindow = nil; self.Platform_SwapBuffers = nil; self.Platform_GetWindowDpiScale = nil self.Platform_OnChangedViewport = nil; self.Platform_GetWindowWorkAreaInsets = nil; self.Platform_CreateVkSurface = nil + InitializeDefaultPlatformHandlers(self) -- Prevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation. end function MT.ImGuiPlatformIO:ClearRendererHandlers() @@ -17875,6 +18338,18 @@ function ImGui.FindViewportByID(viewport_id) return nil end +--- @param platform_handle any +--- @return ImGuiViewportP? +function ImGui.FindViewportByPlatformHandle(platform_handle) + local g = GImGui + for _, viewport in g.Viewports:iter() do + if viewport.PlatformHandle == platform_handle then + return viewport + end + end + return nil +end + --- @param current_window? ImGuiWindow --- @param viewport? ImGuiViewportP function ImGui.SetCurrentViewport(current_window, viewport) @@ -19993,6 +20468,99 @@ function ImGuiErrorRecoveryState() SizeOfBeginPopupStack = 0, SizeOfDisabledStack = 0 } end +function ImGui.ErrorCheckNewFrameSanityChecks() + local g = GImGui + + -- [Luau] C++-only check of the user's IM_ASSERT macro definition dropped. + + -- Check user data + -- (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) + assert(g.Initialized) + assert(g.IO.DeltaTime > 0.0 or g.FrameCount == 0, "Need a positive DeltaTime!") + assert(g.FrameCount == 0 or g.FrameCountEnded == g.FrameCount, "Forgot to call Render() or EndFrame() at the end of the previous frame?") + assert(g.IO.DisplaySize.x >= 0.0 and g.IO.DisplaySize.y >= 0.0, "Invalid DisplaySize value!") + assert(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") + assert(g.Style.CircleTessellationMaxError > 0.0, "Invalid style setting!") + assert(g.Style.Alpha >= 0.0 and g.Style.Alpha <= 1.0, "Invalid style setting!") -- Allows us to avoid a few clamps in color computations + assert(g.Style.WindowMinSize.x >= 1.0 and g.Style.WindowMinSize.y >= 1.0, "Invalid style setting!") + assert(g.Style.WindowBorderHoverPadding > 0.0, "Invalid style setting!") -- Required otherwise cannot resize from borders. + assert(g.Style.WindowMenuButtonPosition == (-1) --[[ImGuiDir.None]] or g.Style.WindowMenuButtonPosition == 0 --[[ImGuiDir.Left]] or g.Style.WindowMenuButtonPosition == 1 --[[ImGuiDir.Right]]) + assert(g.Style.ColorButtonPosition == 0 --[[ImGuiDir.Left]] or g.Style.ColorButtonPosition == 1 --[[ImGuiDir.Right]]) + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 7340032 --[[ImGuiColorEditFlags.DisplayMask_]]))) -- Check only 1 option is selected + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 25165824 --[[ImGuiColorEditFlags.DataTypeMask_]]))) -- " + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 100663296 --[[ImGuiColorEditFlags.PickerMask_]]))) -- " + assert(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, 805306368 --[[ImGuiColorEditFlags.InputMask_]]))) -- " + + assert(g.Style.TreeLinesFlags == 262144 --[[ImGuiTreeNodeFlags.DrawLinesNone]] or g.Style.TreeLinesFlags == 524288 --[[ImGuiTreeNodeFlags.DrawLinesFull]] or g.Style.TreeLinesFlags == 1048576 --[[ImGuiTreeNodeFlags.DrawLinesToNodes]]) + assert(g.IO.MouseSingleClickDelay > g.IO.MouseDoubleClickTime) + + -- Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way. + if g.IO.ConfigErrorRecovery then + assert(g.IO.ConfigErrorRecoveryEnableAssert or g.IO.ConfigErrorRecoveryEnableDebugLog or g.IO.ConfigErrorRecoveryEnableTooltip or g.ErrorCallback ~= nil) + end + + -- [Luau] Obsolete io.FontGlobalScale, ImGuiConfigFlags_NavEnableSetMousePos/NavNoCaptureKeyboard/DpiEnableScaleXXX and + -- io.Get/SetClipboardTextFn don't exist in this port: their remaps are dropped. + + -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) + if g.Style.CurveTessellationTol ~= 0.0 then + g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + end + g.Style.CurveTessellationTol = 0.0 + + -- Perform simple check: error if Docking or Viewport are enabled _exactly_ on frame 1 (instead of frame 0 or later), which is a common error leading to loss of .ini data. + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, 128 --[[ImGuiConfigFlags.DockingEnable]]) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, 128 --[[ImGuiConfigFlags.DockingEnable]]) == 0 then + assert(false, "Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) == 0 then + assert(false, "Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + + -- Perform simple checks: multi-viewport and platform windows support + if bit32.band(g.IO.ConfigFlags, 1024 --[[ImGuiConfigFlags.ViewportsEnable]]) ~= 0 then + if bit32.band(g.IO.BackendFlags, 2048 --[[ImGuiBackendFlags.PlatformHasViewports]]) ~= 0 and bit32.band(g.IO.BackendFlags, 1024 --[[ImGuiBackendFlags.RendererHasViewports]]) ~= 0 then + local pio = g.PlatformIO + assert(g.FrameCount == 0 or g.FrameCount == g.FrameCountPlatformEnded, "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.") + assert(pio.Platform_CreateWindow ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_DestroyWindow ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_GetWindowPos ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_SetWindowPos ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_GetWindowSize ~= nil, "Platform init didn't install handlers?") + assert(pio.Platform_SetWindowSize ~= nil, "Platform init didn't install handlers?") + assert(pio.Monitors.Size > 0, "Platform init didn't setup Monitors list?") + assert(g.Viewports.Data[1].PlatformUserData ~= nil or g.Viewports.Data[1].PlatformHandle ~= nil, "Platform init didn't setup main viewport.") + if g.IO.ConfigDockingTransparentPayload and bit32.band(g.IO.ConfigFlags, 128 --[[ImGuiConfigFlags.DockingEnable]]) ~= 0 then + assert(pio.Platform_SetWindowAlpha ~= nil, "Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!") + end + else + -- Disable feature, our backends do not support it + g.IO.ConfigFlags = bit32.band(g.IO.ConfigFlags, bit32.bnot(1024 --[[ImGuiConfigFlags.ViewportsEnable]])) + end + + -- Perform simple checks on platform monitor data + compute a total bounding box for quick early outs + for _, mon in g.PlatformIO.Monitors:iter() do + assert(mon.MainSize.x > 0.0 and mon.MainSize.y > 0.0, "Monitor main bounds not setup properly.") + assert(ImRect(mon.MainPos, mon.MainPos + mon.MainSize):Contains(ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)), "Monitor work bounds not setup properly. If you don't have work area information, just copy MainPos/MainSize into them.") + assert(mon.DpiScale > 0.0 and mon.DpiScale < 99.0, "Monitor DpiScale is invalid.") -- Typical correct values would be between 1.0f and 4.0f + end + end +end + +function ImGui.ErrorCheckEndFrameSanityChecks() + -- Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() + -- One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). + -- It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will + -- send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. + -- We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), + -- while still correctly asserting on mid-frame key press events. + local g = GImGui + local key_mods = ImGui.GetMergedModsFromKeys() + assert(key_mods == 0 or g.IO.KeyMods == key_mods, "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods") + + assert(g.CurrentWindowStack.Size == 1) + assert(g.CurrentWindowStack.Data[1].Window.IsFallbackWindow) +end + -- Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery. function ImGui.ErrorRecoveryStoreState(state_out) local g = GImGui @@ -20112,9 +20680,20 @@ end -- Lines are stored in g.DebugLogBuf (one chunk per call) function ImGui.DebugLog(fmt, ...) + ImGui.DebugLogV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()). Without arguments `fmt` is used verbatim. +function ImGui.DebugLogV(fmt, ...) local g = GImGui g.DebugLogBuf = g.DebugLogBuf or ImGuiTextBuffer() - local str = string.format("[%05d] ", g.FrameCount) .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) + local prefix + if g.ContextName ~= nil and g.ContextName ~= "" then + prefix = string.format("[%s] [%05d] ", g.ContextName, g.FrameCount) + else + prefix = string.format("[%05d] ", g.FrameCount) + end + local str = prefix .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) g.DebugLogBuf:append(str) -- Line index (upstream: g.DebugLogIndex). Lines are complete strings without '\n'. local lines = g.DebugLogLines @@ -20186,7 +20765,17 @@ function ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- ImGui.BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags.AllowDuplicateId, true); ... PopItemFlag()") -- Not making this too visible for fear of it being abused. ImGui.BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds.") ImGui.Separator() - ImGui.Text("(Hold Ctrl to: ") + if g.IO.ConfigDebugHighlightIdConflictsShowItemPicker then + ImGui.Text("(Hold Ctrl to: use ") + ImGui.SameLine(0.0, 0.0) + if ImGui.SmallButton("Item Picker") then + ImGui.DebugStartItemPicker() + end + ImGui.SameLine(0.0, 0.0) + ImGui.Text(" to break in item call-stack, or ") + else + ImGui.Text("(Hold Ctrl to: ") + end ImGui.SameLine(0.0, 0.0) ImGui.TextLinkOpenURL("read FAQ \"About ID Stack System\"", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage") ImGui.SameLine(0.0, 0.0) @@ -20274,6 +20863,117 @@ ImGui.MetricsHelpMarker = MetricsHelpMarker local function U8(c) return (c and c > 0) and utf8.char(c) or "" end +-- [Luau] table.sort() "less than" predicate (upstream: ImQsort() comparer returning b - a) +--- @param a ImGuiViewportP +--- @param b ImGuiViewportP +local function ViewportComparerByLastFocusedStampCount(a, b) + return b.LastFocusedStampCount < a.LastFocusedStampCount +end + +-- Draw an arbitrary US keyboard layout to visualize translated keys +--- @param draw_list ImDrawList +function ImGui.DebugRenderKeyboardPreview(draw_list) + local scale = ImGui.GetFontSize() / 13.0 + local key_size = ImVec2(35.0, 35.0) * scale + local key_rounding = 3.0 * scale + local key_face_size = ImVec2(25.0, 25.0) * scale + local key_face_pos = ImVec2(5.0, 3.0) * scale + local key_face_rounding = 2.0 * scale + local key_label_pos = ImVec2(7.0, 4.0) * scale + local key_step = ImVec2(key_size.x - 1.0, key_size.y - 1.0) + local key_row_offset = 9.0 * scale + + local board_min = ImGui.GetCursorScreenPos() + local board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0, board_min.y + 3 * key_step.y + 10.0) + local start_pos = ImVec2(board_min.x + 5.0 - key_step.x, board_min.y) + + local K = ImGuiKey + local keys_to_display = { -- { Row, Col, Label, Key } + { 0, 0, "", K.Tab }, { 0, 1, "Q", K.Q }, { 0, 2, "W", K.W }, { 0, 3, "E", K.E }, { 0, 4, "R", K.R }, + { 1, 0, "", K.CapsLock }, { 1, 1, "A", K.A }, { 1, 2, "S", K.S }, { 1, 3, "D", K.D }, { 1, 4, "F", K.F }, + { 2, 0, "", K.LeftShift }, { 2, 1, "Z", K.Z }, { 2, 2, "X", K.X }, { 2, 3, "C", K.C }, { 2, 4, "V", K.V }, + } + + -- Elements rendered manually via ImDrawList API are not clipped automatically. + -- While not strictly necessary, here IsItemVisible() is used to avoid rendering these shapes when they are out of view. + ImGui.Dummy(board_max - board_min) + if not ImGui.IsItemVisible() then + return + end + draw_list:PushClipRect(board_min, board_max, true) + for n = 1, #keys_to_display do + local key_data = keys_to_display[n] + local key_min = ImVec2(start_pos.x + key_data[2] * key_step.x + key_data[1] * key_row_offset, start_pos.y + key_data[1] * key_step.y) + local key_max = key_min + key_size + draw_list:AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding) + draw_list:AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding) + local face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y) + local face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y) + draw_list:AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0) + draw_list:AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding) + local label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y) + draw_list:AddText(label_min, IM_COL32(64, 64, 64, 255), key_data[3]) + if ImGui.IsKeyDown(key_data[4]) then + draw_list:AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding) + end + end + draw_list:PopClipRect() +end + +-- [Luau] g.DebugFlashStyleColorIdx == nil stands for ImGuiCol_COUNT (see ImGuiContext() in imgui_internal.lua). +local function DebugFlashStyleColorStop() + local g = GImGui + if g.DebugFlashStyleColorIdx ~= nil then + ImVec4_Copy(g.Style.Colors[g.DebugFlashStyleColorIdx], g.DebugFlashStyleColorBackup) + end + g.DebugFlashStyleColorIdx = nil +end + +-- Flash a given style color for some + inhibit modifications of this color via PushStyleColor() calls. +--- @param idx ImGuiCol +function ImGui.DebugFlashStyleColor(idx) + local g = GImGui + DebugFlashStyleColorStop() + g.DebugFlashStyleColorTime = 0.5 + g.DebugFlashStyleColorIdx = idx + ImVec4_Copy(g.DebugFlashStyleColorBackup, g.Style.Colors[idx]) +end + +function ImGui.UpdateDebugToolFlashStyleColor() + local g = GImGui + if g.DebugFlashStyleColorTime <= 0.0 then + return + end + local col = g.Style.Colors[g.DebugFlashStyleColorIdx] + col.x, col.y, col.z = ImGui.ColorConvertHSVtoRGB(math.cos(g.DebugFlashStyleColorTime * 6.0) * 0.5 + 0.5, 0.5, 0.5) + col.w = 1.0 + g.DebugFlashStyleColorTime = g.DebugFlashStyleColorTime - g.IO.DeltaTime + if g.DebugFlashStyleColorTime <= 0.0 then + DebugFlashStyleColorStop() + end +end + +-- [Luau] ImTextureID can be any Lua value here: numbers are returned as is, anything else is returned unchanged too +-- (there is no memcpy into an ImU64); FormatTextureRefForDebugDisplay() formats non-numbers with tostring(). +--- @param tex_id ImTextureID +function ImGui.DebugTextureIDToU64(tex_id) + return tex_id +end + +--- @param tex_ref ImTextureRef +--- @return string +local function FormatTextureRefForDebugDisplay(tex_ref) + local buf = "" + if tex_ref._TexData ~= nil then + buf = string.format("#%03d: ", tex_ref._TexData.UniqueID) + end + local v = ImGui.DebugTextureIDToU64(tex_ref:GetTexID()) + if type(v) == "number" and v >= 0 and v == math.floor(v) then + return buf .. string.format("0x%X", v) + end + return buf .. tostring(v) +end + -- Demo helper function to select among loaded fonts. -- Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one. function ImGui.ShowFontSelector(label) @@ -20361,6 +21061,22 @@ function ImGui.DebugNodeFontGlyphsForSrcMask(font, baked, src_mask) end -- [DEBUG] Display details for a single font, called by ShowStyleEditor(). +-- [DEBUG] Compute mask of inputs with the same codepoint. +-- [Luau] the port's font loaders expose FontSrcContainsGlyph() (pre-1.93 loader API) instead of FontSrcGetGlyphIndexFromCodepoint() != 0. +local function CalcFontGlyphSrcOverlapMask(atlas, font, codepoint) + local mask, count = 0, 0 + for src_n = 0, font.Sources.Size - 1 do repeat + local src = font.Sources.Data[src_n + 1] + local loader = src.FontLoader or atlas.FontLoader + if not (loader.FontSrcContainsGlyph ~= nil and loader.FontSrcContainsGlyph(atlas, src, codepoint)) then + break -- continue + end + mask = bit32.bor(mask, bit32.lshift(1, src_n)) + count = count + 1 + until true end + return (count > 1) and mask or 0 +end + function ImGui.DebugNodeFont(font) local g = ImGui.GetCurrentContext() local cfg = g.DebugMetricsConfig @@ -20405,6 +21121,39 @@ function ImGui.DebugNodeFont(font) ImGui.TreePop() end end + if font.Sources.Size > 1 and ImGui.TreeNode("Input Glyphs Overlap Detection Tool") then + ImGui.TextWrapped("- First Input that contains the glyph is used.\n" .. + "- Use ImFontConfig::GlyphExcludeRanges[] to specify ranges to ignore glyph in given Input.\n- Prefer using a small number of ranges as the list is scanned every time a new glyph is loaded,\n - e.g. GlyphExcludeRanges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };\n- This tool doesn't cache results and is slow, don't keep it open!") + if ImGui.BeginTable("table", 2) then + local c = 0 + while c < 0x10000 do + local overlap_mask = CalcFontGlyphSrcOverlapMask(atlas, font, c) + if overlap_mask ~= 0 then + local c_end = c + 1 + while c_end < 0x10000 and CalcFontGlyphSrcOverlapMask(atlas, font, c_end) == overlap_mask do + c_end = c_end + 1 + end + if ImGui.TableNextColumn() and ImGui.TreeNode(c, "U+%04X-U+%04X: %d codepoints in %d inputs", c, c_end - 1, c_end - c, ImCountSetBits(overlap_mask)) then + for n = c, c_end - 1 do + ImGui.BulletText("Codepoint U+%04X (%s)", n, U8(n)) + end + ImGui.TreePop() + end + ImGui.TableNextColumn() + for src_n = 0, font.Sources.Size - 1 do + if bit32.band(overlap_mask, bit32.lshift(1, src_n)) ~= 0 then + ImGui.Text("%d ", src_n) + ImGui.SameLine() + end + end + c = c_end - 1 + end + c = c + 1 + end + ImGui.EndTable() + end + ImGui.TreePop() + end -- Display all glyphs of the fonts in separate pages of 256 characters local builder = atlas.Builder @@ -20464,7 +21213,7 @@ function ImGui.DebugNodeTexture(tex, int_id, highlight_rect) end ImGui.PopStyleVar() ImGui.Text("Status = %s (%d), Format = %s (%d), UseColors = %d", StatusNames[tex.Status] or "?", tex.Status, FormatNames[tex.Format] or "?", tex.Format, tex.UseColors and 1 or 0) - ImGui.Text("TexID = %s", tostring(tex.TexID)) + ImGui.Text("TexRef = %s, BackendUserData = %s", FormatTextureRefForDebugDisplay(tex:GetTexRef()), tostring(tex.BackendUserData)) ImGui.TreePop() end ImGui.PopID() @@ -20609,7 +21358,7 @@ function ImGui.ShowDebugLogWindow(p_open) local clipper = ImGuiListClipper() clipper:Begin(count) while clipper:Step() do - for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.TextUnformatted(lines[line_no + 1]) end + for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.DebugTextUnformattedWithLocateItem(lines[line_no + 1]) end end g.DebugLogFlags = backup_log_flags if ImGui.GetScrollY() >= ImGui.GetScrollMaxY() then ImGui.SetScrollHereY(1.0) end @@ -20618,10 +21367,165 @@ function ImGui.ShowDebugLogWindow(p_open) return p_open end +-- Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered. +-- [Luau] line_begin is the line string, line_end its optional exclusive end byte position (default: whole string). +function ImGui.DebugTextUnformattedWithLocateItem(line_begin, line_end) + if line_end == nil then line_end = #line_begin + 1 end + ImGui.TextUnformatted(line_begin, line_end) + if not ImGui.IsItemHovered(bit32.bor(32 --[[ImGuiHoveredFlags.AllowWhenBlockedByPopup]], 128 --[[ImGuiHoveredFlags.AllowWhenBlockedByActiveItem]])) then + return + end + local g = GImGui + local text_rect = ImRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max) -- [Luau] copy (LastItemData.Rect is overwritten below) + local p = 1 + while p <= line_end - 10 do repeat -- [Luau] 1-based (C: p <= line_end - 10 with 0-based offsets) + local b0, b1 = string.byte(line_begin, p, p + 1) + local hex = string.match(line_begin, "^%x+", p + 2) + if b0 ~= 48 or (b1 ~= 120 and b1 ~= 88) or hex == nil or string.find(string.sub(line_begin, p + 10, p + 10), "^%x") then -- '0', 'x', 'X' + p = p + 1 + break -- continue + end + local id = tonumber(hex, 16) -- [Luau] sscanf("%X") + local p0 = ImGui.CalcTextSizeEx(line_begin, 1, p) + local p1 = ImGui.CalcTextSizeEx(line_begin, p, p + 10) + g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)) + if ImGui.IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true) then + ImGui.DebugLocateItemOnHover(id) + end + p = p + 11 -- p += 10, then the loop's p++ + until true end +end + ------------------------------------------------------------------------------- -- [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) ------------------------------------------------------------------------------- +-- Draw a small cross at current CursorPos in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawCursorPos(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local pos = window.DC.CursorPos + window.DrawList:AddLineV(pos.x, pos.y - 3.0, pos.y + 4.0, col, 1.0) + window.DrawList:AddLineH(pos.x - 3.0, pos.x + 4.0, pos.y, col, 1.0) +end + +-- Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawLineExtents(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local curr_x = window.DC.CursorPos.x + local line_y1 = window.DC.IsSameLine and window.DC.CursorPosPrevLine.y or window.DC.CursorPos.y + local line_y2 = line_y1 + (window.DC.IsSameLine and window.DC.PrevLineSize.y or window.DC.CurrLineSize.y) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y1, col, 1.0) + window.DrawList:AddLineV(curr_x, line_y1, line_y2, col, 1.0) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y2, col, 1.0) +end + +-- Draw last item rect in ForegroundDrawList (so it is always visible) +--- @param col? ImU32 +function ImGui.DebugDrawItemRect(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + ImGui.GetForegroundDrawList(window.Viewport):AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col) +end + +-- [DEBUG] Locate item position/rectangle given an ID. +local DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255) -- Green + +--- @param target_id ImGuiID +function ImGui.DebugLocateItem(target_id) + local g = GImGui + g.DebugLocateId = target_id + g.DebugLocateFrames = 2 + g.DebugBreakInLocateId = false +end + +-- FIXME: Doesn't work over through a modal window, because they clear HoveredWindow. +--- @param target_id ImGuiID +function ImGui.DebugLocateItemOnHover(target_id) + if target_id == 0 or not ImGui.IsItemHovered(bit32.bor(128 --[[ImGuiHoveredFlags.AllowWhenBlockedByActiveItem]], 32 --[[ImGuiHoveredFlags.AllowWhenBlockedByPopup]])) then + return + end + local g = GImGui + ImGui.DebugLocateItem(target_id) + ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport):AddRect(g.LastItemData.Rect.Min - ImVec2(3.0, 3.0), g.LastItemData.Rect.Max + ImVec2(3.0, 3.0), DEBUG_LOCATE_ITEM_COLOR) + + -- Can't easily use a context menu here because it will mess with focus, active id etc. + if g.IO.ConfigDebugIsDebuggerPresent and g.MouseStationaryTimer > 1.0 then + ImGui.DebugBreakButtonTooltip(false, "in ItemAdd()") + if ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) then + g.DebugBreakInLocateId = true + end + end +end + +function ImGui.DebugLocateItemResolveWithLastItem() + local g = GImGui + + -- [DEBUG] Debug break requested by user + if g.DebugBreakInLocateId then + IM_DEBUG_BREAK() + end + + local item_data = g.LastItemData + g.DebugLocateId = 0 + local draw_list = ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport) + local r = ImRect(item_data.Rect.Min, item_data.Rect.Max) -- [Luau] copy + r:Expand(3.0) + local p1 = g.IO.MousePos + local p2 = ImVec2((p1.x < r.Min.x) and r.Min.x or ((p1.x > r.Max.x) and r.Max.x or p1.x), (p1.y < r.Min.y) and r.Min.y or ((p1.y > r.Max.y) and r.Max.y or p1.y)) + draw_list:AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR) + draw_list:AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR) +end + +function ImGui.DebugStartItemPicker() + local g = GImGui + g.DebugItemPickerActive = true +end + +-- [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. +function ImGui.UpdateDebugToolItemPicker() + local g = GImGui + g.DebugItemPickerBreakId = 0 + if not g.DebugItemPickerActive then + return + end + + local hovered_id = g.HoveredIdPreviousFrame + ImGui.SetMouseCursor(7 --[[ImGuiMouseCursor.Hand]]) + if ImGui.IsKeyPressed(526 --[[ImGuiKey.Escape]]) then + g.DebugItemPickerActive = false + end + local change_mapping = g.IO.KeyMods == bit32.bor(4096 --[[ImGuiMod_Ctrl]], 8192 --[[ImGuiMod_Shift]]) + if not change_mapping and ImGui.IsMouseClicked(g.DebugItemPickerMouseButton) and hovered_id ~= 0 then + g.DebugItemPickerBreakId = hovered_id + g.DebugItemPickerActive = false + end + for mouse_button = 0, 2 do + if change_mapping and ImGui.IsMouseClicked(mouse_button) then + g.DebugItemPickerMouseButton = mouse_button + end + end + ImGui.SetNextWindowBgAlpha(0.70) + if not ImGui.BeginTooltip() then + return + end + ImGui.Text("HoveredId: 0x%08X", hovered_id) + ImGui.Text("Press ESC to abort picking.") + local mouse_button_names = { "Left", "Right", "Middle" } + if change_mapping then + ImGui.Text("Remap w/ Ctrl+Shift: click anywhere to select new mouse button.") + else + ImGui.TextColored(ImGui.GetStyleColorVec4((hovered_id ~= 0) and 0 --[[ImGuiCol.Text]] or 1 --[[ImGuiCol.TextDisabled]]), "Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[g.DebugItemPickerMouseButton + 1]) + end + ImGui.EndTooltip() +end + local function PathQuery(g) local q = g.DebugItemPathQuery if q == nil then @@ -20710,7 +21614,7 @@ local function SkipUncontributingPrefix(label) return label end -local function FormatLevelInfo(g, query, n, format_for_ui) +local function DebugItemPathQuery_FormatLevelInfo(query, n, format_for_ui) local info = query.Results[n + 1] local window = (info.Desc == nil and n == 0) and ImGui.FindWindowByID(info.ID) or nil if window then return string.format(format_for_ui and "\"%s\" [window]" or "%s", SkipUncontributingPrefix(window.Name)) end -- Source: window name (because the root ID don't call GetID() and so doesn't get hooked) @@ -20719,10 +21623,10 @@ local function FormatLevelInfo(g, query, n, format_for_ui) return "???" end -local function GetResultAsPath(g, query, hex_encode_non_ascii_chars) +local function DebugItemPathQuery_GetResultAsPath(query, hex_encode_non_ascii_chars) local out = {} for n = 0, #query.Results - 1 do - local desc = FormatLevelInfo(g, query, n, false) + local desc = DebugItemPathQuery_FormatLevelInfo(query, n, false) out[#out + 1] = (n == 0) and "//" or "/" desc = string.gsub(desc, "/", "\\/") if hex_encode_non_ascii_chars then @@ -20748,7 +21652,7 @@ function ImGui.ShowIDStackToolWindow(p_open) local query = PathQuery(g) local tool = g.DebugIDStackTool tool.LastActiveFrame = g.FrameCount - local result_path = GetResultAsPath(g, query, tool.OptHexEncodeNonAsciiChars) + local result_path = DebugItemPathQuery_GetResultAsPath(query, tool.OptHexEncodeNonAsciiChars) ImGui.Text("0x%08X", query.MainID) ImGui.SameLine() MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.") @@ -20781,7 +21685,7 @@ function ImGui.ShowIDStackToolWindow(p_open) ImGui.TableNextColumn() ImGui.Text("0x%08X", (n > 0) and query.Results[n].ID or 0) ImGui.TableNextColumn() - ImGui.TextUnformatted(FormatLevelInfo(g, query, n, true)) + ImGui.TextUnformatted(DebugItemPathQuery_FormatLevelInfo(query, n, true)) ImGui.TableNextColumn() ImGui.Text("0x%08X", info.ID) if n == #query.Results - 1 then ImGui.TableSetBgColor(3 --[[ImGuiTableBgTarget.CellBg]], ImGui.GetColorU32(25 --[[ImGuiCol.Header]])) end @@ -20832,6 +21736,7 @@ function ImGui.DebugNodeStorage(storage, label) if not ImGui.TreeNode(label, "%s: %d entries", label, n) then return end for k, v in pairs(storage) do ImGui.BulletText("Key 0x%08X Value { %s }", tonumber(k) or 0, tostring(v)) + ImGui.DebugLocateItemOnHover(tonumber(k) or 0) end ImGui.TreePop() end @@ -20859,50 +21764,116 @@ function ImGui.DebugNodeDrawList(window, viewport, draw_list, label) if not node_open then return end if window and not window.WasActive then ImGui.TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!") end - local vtx, idx = draw_list.VtxBuffer.Buf, draw_list.IdxBuffer.Data - for cmd_n = 1, cmd_count do + for cmd_n = 1, cmd_count do repeat local pcmd = draw_list.CmdBuffer.Data[cmd_n] if pcmd.UserCallback then - ImGui.BulletText("Callback %s", tostring(pcmd.UserCallback)) - else - local cr = pcmd.ClipRect - local open = ImGui.TreeNode(cmd_n, "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", math.floor(pcmd.ElemCount / 3), tostring(pcmd.TexRef and (pcmd.TexRef._TexID or pcmd.TexRef._TexData)), cr.x, cr.y, cr.z, cr.w) - local function ShowMeshImpl(show_mesh, show_aabb) - local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) - local vtxs_rect = ImRect(3.4028234663853e+38 --[[FLT_MAX]], 3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]]) - local base = pcmd.IdxOffset - for i = base, base + pcmd.ElemCount - 1, 3 do - local tri = {} - for n = 0, 2 do - local vi = idx[i + n + 1] + pcmd.VtxOffset - if vi > draw_list.VtxBuffer.Size then return end - tri[n + 1] = ImVec2(ImDrawVtx_Pos(vtx, vi)) - vtxs_rect:Add(tri[n + 1]) - end - if show_mesh then fg_draw_list:AddPolyline(tri, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) end -- In yellow: mesh triangles - end - if show_aabb then - fg_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU - fg_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles - end + ImGui.BulletText("Callback %s, user_data %s", tostring(pcmd.UserCallback), tostring(pcmd.UserCallbackData)) + break -- continue + end + + local texid_desc = FormatTextureRefForDebugDisplay(pcmd.TexRef) + local cr = pcmd.ClipRect + local buf = string.format("DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + math.floor(pcmd.ElemCount / 3), texid_desc, cr.x, cr.y, cr.z, cr.w) + local pcmd_node_open = ImGui.TreeNode(cmd_n - 1, "%s", buf) + if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) + end + if not pcmd_node_open then + break -- continue + end + + -- Calculate approximate coverage area (touched pixel count) + -- This will be in pixels squared as long there's no post-scaling happening to the renderer output. + -- [Luau] index values are 1-based vertex indices relative to VtxOffset (see ImDrawVtx_Pos()) + local idx_buffer = draw_list.IdxBuffer.Data + local vtx_buffer = draw_list.VtxBuffer.Buf + local total_area = 0.0 + local idx_n = pcmd.IdxOffset + while idx_n < pcmd.IdxOffset + pcmd.ElemCount do + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + pcmd.VtxOffset)) + idx_n = idx_n + 1 end - local function ShowMesh(show_mesh, show_aabb) -- DebugNodeDrawCmdShowMeshAndBoundingBox() - if not fg_draw_list then return end - fg_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. - ShowMeshImpl(show_mesh, show_aabb) - fg_draw_list:PopDrawFlag() - end - if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) then ShowMesh(cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) end - if open then - ImGui.Selectable(string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset)) - if ImGui.IsItemHovered() then ShowMesh(true, false) end - ImGui.TreePop() + total_area = total_area + ImTriangleArea(triangle[1], triangle[2], triangle[3]) + end + + -- Display vertex information summary. Hover to get all triangles drawn in wire-frame + buf = string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset, total_area) + ImGui.Selectable(buf) + if ImGui.IsItemHovered() and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false) + end + + -- Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. + local clipper = ImGuiListClipper() + clipper:Begin(math.floor(pcmd.ElemCount / 3)) -- Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while clipper:Step() do + local idx_i = pcmd.IdxOffset + clipper.DisplayStart * 3 + for prim = clipper.DisplayStart, clipper.DisplayEnd - 1 do + local lines = {} + local triangle = {} + for n = 1, 3 do + local vi = idx_buffer[idx_i + 1] + pcmd.VtxOffset + local o = (vi - 1) * 36 --[[VTX_STRIDE]] -- [Luau] packed vertex: f64 pos.x, pos.y, uv.x, uv.y, u32 col + local px, py = ImDrawVtx_Pos(vtx_buffer, vi) + triangle[n] = ImVec2(px, py) + lines[n] = string.format("%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", + (n == 1) and "Vert:" or " ", idx_i, px, py, buffer.readf64(vtx_buffer, o + 16), buffer.readf64(vtx_buffer, o + 24), ImDrawVtx_Col(vtx_buffer, vi)) + idx_i = idx_i + 1 + end + + ImGui.Selectable(table.concat(lines), false) + if fg_draw_list and ImGui.IsItemHovered() then + fg_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + fg_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) + fg_draw_list:PopDrawFlag() + end end end - end + ImGui.TreePop() + until true end ImGui.TreePop() end +-- [DEBUG] Display mesh/aabb of a ImDrawCmd +--- @param out_draw_list ImDrawList +--- @param draw_list ImDrawList +--- @param draw_cmd ImDrawCmd +--- @param show_mesh bool +--- @param show_aabb bool +function ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(out_draw_list, draw_list, draw_cmd, show_mesh, show_aabb) + assert(show_mesh or show_aabb) + + -- Draw wire-frame version of all triangles + local cr = draw_cmd.ClipRect + local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) + local vtxs_rect = ImRect(3.4028234663853e+38 --[[FLT_MAX]], 3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]], -3.4028234663853e+38 --[[FLT_MAX]]) + out_draw_list:PushDrawFlag(8192 --[[ImDrawFlags.AALines]], false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + local idx_n, idx_end = draw_cmd.IdxOffset, draw_cmd.IdxOffset + draw_cmd.ElemCount + while idx_n < idx_end do + local idx_buffer = draw_list.IdxBuffer.Data -- We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list + local vtx_buffer = draw_list.VtxBuffer.Buf + + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + draw_cmd.VtxOffset)) + vtxs_rect:Add(triangle[n]) + idx_n = idx_n + 1 + end + if show_mesh then + out_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, 512 --[[ImDrawFlags.Closed]]) -- In yellow: mesh triangles + end + end + -- Draw bounding boxes + if show_aabb then + out_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU + out_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles + end + out_draw_list:PopDrawFlag() +end + -- [DEBUG] Display contents of ImGuiTabBar function ImGui.DebugNodeTabBar(tab_bar, label) -- Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. @@ -21084,6 +22055,11 @@ function ImGui.DebugNodeWindow(window, label) if ImGui.IsItemHovered() and is_active then YellowRect(window, window.Pos, window.Pos + window.Size) end if not open then return end if window.MemoryCompacted then ImGui.TextDisabled("Note: some memory buffers have been compacted/freed.") end + + if g.IO.ConfigDebugIsDebuggerPresent and ImGui.DebugBreakButton("**DebugBreak**", "in Begin()") then + g.DebugBreakInWindow = window.ID + end + local W = ImGuiWindowFlags local flags = window.Flags local function F(f, s) return (bit32.band(flags, f) ~= 0) and s or "" end @@ -21108,6 +22084,7 @@ function ImGui.DebugNodeWindow(window, label) else ImGui.BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window.NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y) end + ImGui.DebugLocateItemOnHover(window.NavLastIds[layer]) end ImGui.BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window.DC.NavLayersActiveMask, window.NavLastChildNavWindow and window.NavLastChildNavWindow.Name or "NULL") ImGui.BulletText("Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window.Viewport and (window.Viewport.Idx or 0) or -1, window.ViewportOwned and " (Owned)" or "", window.ViewportId or 0, window.ViewportPos.x, window.ViewportPos.y) @@ -21176,6 +22153,16 @@ function ImGui.DebugNodeViewport(viewport) end end +--- @param monitor ImGuiPlatformMonitor +--- @param label string +--- @param idx int +function ImGui.DebugNodePlatformMonitor(monitor, label, idx) + ImGui.BulletText("%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)", + label, idx, monitor.DpiScale * 100.0, + monitor.MainPos.x, monitor.MainPos.y, monitor.MainPos.x + monitor.MainSize.x, monitor.MainPos.y + monitor.MainSize.y, monitor.MainSize.x, monitor.MainSize.y, + monitor.WorkPos.x, monitor.WorkPos.y, monitor.WorkPos.x + monitor.WorkSize.x, monitor.WorkPos.y + monitor.WorkSize.y, monitor.WorkSize.x, monitor.WorkSize.y) +end + -- Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. function ImGui.DebugTextEncoding(str) ImGui.Text("Text: \"%s\"", str) @@ -21256,8 +22243,15 @@ function ImGui.ShowMetricsWindow(p_open) return p_open end + -- [DEBUG] Clear debug breaks hooks after exactly one cycle. + ImGui.DebugBreakClearData() + -- Basic info ImGui.Text("Dear ImGui %s (%d)", IMGUI_VERSION, 19298 --[[IMGUI_VERSION_NUM]]) + if g.ContextName ~= nil and g.ContextName ~= "" then + ImGui.SameLine() + ImGui.Text("(Context Name: \"%s\")", g.ContextName) + end ImGui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / math.max(io.Framerate, 0.0001), io.Framerate) ImGui.Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, math.floor(io.MetricsRenderIndices / 3)) ImGui.Text("%d visible windows, %d current allocations", io.MetricsRenderWindows, g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount) @@ -21268,6 +22262,18 @@ function ImGui.ShowMetricsWindow(p_open) -- Tools if ImGui.TreeNode("Tools") then + -- Debug Break features + -- The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. + ImGui.SeparatorTextEx(0, "Debug breaks", nil, ImGui.CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x) + ImGui.SameLine() + MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.") + local picker_toggled + picker_toggled, g.DebugItemPickerActive = ImGui.Checkbox("Show Item Picker", g.DebugItemPickerActive) + if picker_toggled and g.DebugItemPickerActive then + ImGui.DebugStartItemPicker() + end + _, io.ConfigDebugIsDebuggerPresent = ImGui.Checkbox("Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", io.ConfigDebugIsDebuggerPresent) + ImGui.SeparatorText("Visualize") _, cfg.ShowDebugLog = ImGui.Checkbox("Show Debug Log", cfg.ShowDebugLog == true) ImGui.SameLine(); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code.") @@ -21348,12 +22354,47 @@ function ImGui.ShowMetricsWindow(p_open) -- Viewports if ImGui.TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size) then + cfg.HighlightMonitorIdx = -1 + local open = ImGui.TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size) + ImGui.SameLine() + MetricsHelpMarker("Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors.") + if open then + for i = 1, g.PlatformIO.Monitors.Size do + ImGui.DebugNodePlatformMonitor(g.PlatformIO.Monitors.Data[i], "Monitor", i - 1) + if ImGui.IsItemHovered() then + cfg.HighlightMonitorIdx = i - 1 -- 0-based, like Monitors:index_from_ptr() + end + end + if g.FallbackMonitor then ImGui.DebugNodePlatformMonitor(g.FallbackMonitor, "Fallback", 0) end + ImGui.TreePop() + end + ImGui.SetNextItemOpen(true, 2 --[[ImGuiCond.Once]]) if ImGui.TreeNode("Windows Minimap") then ImGui.RenderViewportsThumbnails() ImGui.TreePop() end cfg.HighlightViewportID = 0 + + ImGui.BulletText("MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)", g.MouseViewport and g.MouseViewport.ID or 0, g.IO.MouseHoveredViewport or 0, g.MouseLastHoveredViewport and g.MouseLastHoveredViewport.ID or 0) + if ImGui.TreeNode("Inferred Z order (front-to-back)") then + local viewports = {} + for n = 1, g.Viewports.Size do viewports[n] = g.Viewports.Data[n] end + if #viewports > 1 then + table.sort(viewports, ViewportComparerByLastFocusedStampCount) + end + for _, viewport in ipairs(viewports) do + ImGui.BulletText("Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"", + viewport.Idx, viewport.ID, viewport.LastFocusedStampCount, + (g.PlatformIO.Platform_GetWindowFocus and viewport.PlatformWindowCreated) and (g.PlatformIO.Platform_GetWindowFocus(viewport) and "1" or "0") or "N/A", + viewport.Window and viewport.Window.Name or "N/A") + if ImGui.IsItemHovered() then + cfg.HighlightViewportID = viewport.ID + end + end + ImGui.TreePop() + end + for _, viewport in g.Viewports:iter() do ImGui.DebugNodeViewport(viewport) end ImGui.TreePop() end @@ -21498,6 +22539,12 @@ function ImGui.ShowMetricsWindow(p_open) if ImGui.IsKeyReleased(key) then ImGui.SameLine(); ImGui.Text("\"%s\"", ImGui.GetKeyName(key)) end end ImGui.Text("Keys mods: %s%s%s%s", io.KeyCtrl and "Ctrl " or "", io.KeyShift and "Shift " or "", io.KeyAlt and "Alt " or "", io.KeySuper and "Super " or "") + ImGui.Text("Chars queue:") + for i = 1, io.InputQueueCharacters.Size do + local c = io.InputQueueCharacters.Data[i] + ImGui.SameLine(); ImGui.Text("'%s' (0x%04X)", (c > 32 and c <= 255) and string.char(c) or "?", c) -- FIXME: We should convert 'c' to UTF-8 here but the functions are not public. + end + ImGui.DebugRenderKeyboardPreview(ImGui.GetWindowDrawList()) ImGui.Unindent() ImGui.Text("MOUSE STATE") ImGui.Indent() @@ -21511,6 +22558,7 @@ function ImGui.ShowMetricsWindow(p_open) for i = 0, 2 do if ImGui.IsMouseReleased(i) then ImGui.SameLine(); ImGui.Text("b%d", i) end end ImGui.Text("Mouse wheel: %.1f", io.MouseWheel) ImGui.Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer) + ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource or 0 --[[ImGuiMouseSource.Mouse]])) -- [Luau] field may be unset (C++: zero-initialized) ImGui.Unindent() ImGui.Text("MOUSE WHEELING") ImGui.Indent() @@ -21534,16 +22582,20 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.Unindent() ImGui.Text("ITEMS") ImGui.Indent() - ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap)) + ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap), GetInputSourceName(g.ActiveIdSource or 0 --[[ImGuiInputSource.None]])) -- [Luau] field may be unset (C++: zero-initialized) + ImGui.DebugLocateItemOnHover(g.ActiveId) ImGui.Text("ActiveIdWindow: '%s'", N(g.ActiveIdWindow)) ImGui.Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, B(g.HoveredIdAllowOverlap)) -- Not displaying g.HoveredId as it is update mid-frame ImGui.Text("HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId or 0, g.HoverItemDelayTimer or 0, g.HoverItemDelayClearTimer or 0) ImGui.Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\"", B(g.DragDropActive), g.DragDropPayload.SourceId or 0, tostring(g.DragDropPayload.DataType or "")) + ImGui.DebugLocateItemOnHover(g.DragDropPayload.SourceId or 0) ImGui.Unindent() ImGui.Text("NAV,FOCUS") ImGui.Indent() ImGui.Text("NavWindow: '%s'", N(g.NavWindow)) ImGui.Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer) + ImGui.DebugLocateItemOnHover(g.NavId) + ImGui.Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource or 0 --[[ImGuiInputSource.None]])) ImGui.Text("NavLastValidSelectionUserData = %s", tostring(g.NavLastValidSelectionUserData)) -- [Port] any Lua value: tostring() instead of %lld (0x%llX) ImGui.Text("NavActive: %d, NavVisible: %d", B(io.NavActive), B(io.NavVisible)) ImGui.Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId or 0, g.NavActivatePressedId or 0) @@ -21594,6 +22646,68 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.End() return p_open end + +function ImGui.DebugBreakClearData() + -- Those fields are scattered in their respective subsystem to stay in hot-data locations + local g = GImGui + g.DebugBreakInWindow = 0 + g.DebugBreakInTable = 0 + g.DebugBreakInShortcutRouting = 0 --[[ImGuiKey.None]] +end + +--- @param keyboard_only bool +--- @param description_of_location string +function ImGui.DebugBreakButtonTooltip(keyboard_only, description_of_location) + if not ImGui.BeginItemTooltip() then + return + end + ImGui.Text("To call IM_DEBUG_BREAK() %s:", description_of_location) + ImGui.Separator() + ImGui.TextUnformatted(keyboard_only and "- Press 'Pause/Break' on keyboard." or "- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space.") + ImGui.Separator() + ImGui.TextUnformatted("Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!") -- [Luau] IM_DEBUG_BREAK() calls g.DebugBreakCallback (if set) instead + ImGui.EndTooltip() +end + +-- Special button that doesn't take focus, doesn't take input owner, and can be activated without a click etc. +-- In order to reduce interferences with the contents we are trying to debug into. +--- @param label string +--- @param description_of_location string +--- @return bool +function ImGui.DebugBreakButton(label, description_of_location) + local window = ImGui.GetCurrentWindow() + if window.SkipItems then + return false + end + + local g = GImGui + local id = window:GetID(label) + local label_size = ImGui.CalcTextSize(label, nil, true) + local pos = window.DC.CursorPos + ImVec2(0.0, window.DC.CurrLineTextBaseOffset) + local size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0, label_size.y) + + local bb = ImRect(pos, pos + size) + ImGui.ItemSize(size, 0.0) + if not ImGui.ItemAdd(bb, id) then + return false + end + + -- WE DO NOT USE ButtonEx() or ButtonBehavior() in order to reduce our side-effects. + local hovered = ImGui.ItemHoverable(bb, id, g.CurrentItemFlags) + local pressed = hovered and (ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) or ImGui.IsMouseClicked(0) or g.NavActivateId == id) + ImGui.DebugBreakButtonTooltip(false, description_of_location) + + local src = ImGui.GetStyleColorVec4(hovered and 23 --[[ImGuiCol.ButtonHovered]] or 22 --[[ImGuiCol.Button]]) + local col4f = ImVec4(src.x, src.y, src.z, src.w) -- [Luau] copy + local h, s, v = ImGui.ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z) + col4f.x, col4f.y, col4f.z = ImGui.ColorConvertHSVtoRGB(h + 0.20, s, v) + + ImGui.RenderNavCursor(bb, id) + ImGui.RenderFrame(bb.Min, bb.Max, ImGui.GetColorU32(col4f), true, g.Style.FrameRounding) + ImGui.RenderTextClipped(bb.Min, bb.Max, label, nil, label_size, g.Style.ButtonTextAlign, bb) + + return pressed +end end --[[ [SECTION] METRICS/DEBUGGER WINDOW, DEBUG LOG, ID STACK TOOL, FONT DEBUG ]] return true -- [Roblox] ModuleScripts must return exactly one value @@ -21816,7 +22930,7 @@ function ShowDockingDisabledMessage() end -- Helper to wire demo markers located in code to an interactive browser (e.g. https://pthom.github.io/imgui_explorer) -function IMGUI_DEMO_MARKER(section) end -- [Port] no ImGui.DemoMarker() hook in this port: no-op +function IMGUI_DEMO_MARKER(section) ImGui.DemoMarker("imgui_demo.lua", 0, section) end -- [Port] no __LINE__ in Lua: line is 0 -- Sneakily forward declare functions which aren't worth putting in public API yet -- [Port] ImGui.ShowFontAtlas(atlas) and ImGui.TreeNodeSetOpen(storage_id, is_open) are already public here. @@ -22300,8 +23414,7 @@ function DemoWindowMenuBar(demo_data) _, demo_data.ShowDebugLog = ImGui.MenuItem("Debug Log", nil, demo_data.ShowDebugLog, has_debug_tools) _, demo_data.ShowIDStackTool = ImGui.MenuItem("ID Stack Tool", nil, demo_data.ShowIDStackTool, has_debug_tools) local is_debugger_present = io.ConfigDebugIsDebuggerPresent - local has_item_picker = ImGui.DebugStartItemPicker ~= nil -- [Port] ImGui.DebugStartItemPicker() is not ported yet: menu item disabled until it is - if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools and has_item_picker) then -- and is_debugger_present + if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools) then -- and is_debugger_present ImGui.DebugStartItemPicker() end if not is_debugger_present then @@ -30506,7 +31619,7 @@ function ImGui.ShowStyleEditor(ref) end ImGui.PushID(i) if ImGui.Button("?") then - if ImGui.DebugFlashStyleColor then ImGui.DebugFlashStyleColor(i) end -- [Port] DebugFlashStyleColor() is not in the library yet + ImGui.DebugFlashStyleColor(i) end ImGui.SetItemTooltip("Flash given color to identify places where it is used.") ImGui.SameLine() @@ -37609,6 +38722,42 @@ function MT.ImDrawData:AddDrawList(draw_list) ImGui.AddDrawListToDrawDataEx(self, self.CmdLists, draw_list) end +-- For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! +-- [Luau] IdxBuffer values are 1-based vertex indices +function MT.ImDrawData:DeIndexAllBuffers() + local new_vtx_buffer = ImDrawVtxBuffer() + self.TotalVtxCount = 0; self.TotalIdxCount = 0 + for i = 1, self.CmdLists.Size do + repeat + local draw_list = self.CmdLists.Data[i] + if draw_list.IdxBuffer.Size == 0 then + break -- continue + end + new_vtx_buffer:resize(draw_list.IdxBuffer.Size) + local src, dst, idx = draw_list.VtxBuffer.Buf, new_vtx_buffer.Buf, draw_list.IdxBuffer.Data + for j = 1, draw_list.IdxBuffer.Size do + buffer.copy(dst, (j - 1) * 36 --[[VTX_STRIDE]], src, (idx[j] - 1) * 36 --[[VTX_STRIDE]], 36 --[[VTX_STRIDE]]) + end + draw_list.VtxBuffer, new_vtx_buffer = new_vtx_buffer, draw_list.VtxBuffer -- swap() + draw_list.IdxBuffer:resize(0) + self.TotalVtxCount = self.TotalVtxCount + draw_list.VtxBuffer.Size + until true + end +end + +-- Helper to scale the ClipRect field of each ImDrawCmd. +-- Use if your final output buffer is at a different scale than draw_data->DisplaySize, +-- or if there is a difference between your window resolution and framebuffer resolution. +function MT.ImDrawData:ScaleClipRects(fb_scale) + for i = 1, self.CmdLists.Size do + local draw_list = self.CmdLists.Data[i] + for j = 1, draw_list.CmdBuffer.Size do + local cmd = draw_list.CmdBuffer.Data[j] + cmd.ClipRect = ImVec4(cmd.ClipRect.x * fb_scale.x, cmd.ClipRect.y * fb_scale.y, cmd.ClipRect.z * fb_scale.x, cmd.ClipRect.w * fb_scale.y) + end + end +end + local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN = 4 local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX = 512 @@ -37716,6 +38865,29 @@ function MT.ImDrawList:_ClearFreeMemory() self._Splitter:ClearFreeMemory() end +-- Note: For multi-threaded rendering, consider using `imgui_threaded_rendering` from https://github.com/ocornut/imgui_club +-- [Luau] C++ copies the vectors by value: copy the ImDrawCmd structs and the vertex buffer bytes +--- @return ImDrawList +function MT.ImDrawList:CloneOutput() + local dst = ImDrawList(nil) + for i = 1, self.CmdBuffer.Size do + local src_cmd = self.CmdBuffer.Data[i] + local cmd = ImDrawCmd() + for k, v in pairs(src_cmd) do cmd[k] = v end + cmd.ClipRect = ImVec4(src_cmd.ClipRect.x, src_cmd.ClipRect.y, src_cmd.ClipRect.z, src_cmd.ClipRect.w) + if src_cmd.TexRef then cmd.TexRef = ImTextureRef(src_cmd.TexRef._TexID); cmd.TexRef._TexData = src_cmd.TexRef._TexData end + dst.CmdBuffer:push_back(cmd) + end + if self.IdxBuffer.Size > 0 then + dst.IdxBuffer:resize(self.IdxBuffer.Size) + table.move(self.IdxBuffer.Data, 1, self.IdxBuffer.Size, 1, dst.IdxBuffer.Data) + end + dst.VtxBuffer:resize(self.VtxBuffer.Size) + buffer.copy(dst.VtxBuffer.Buf, 0, self.VtxBuffer.Buf, 0, self.VtxBuffer.Size * 36 --[[VTX_STRIDE]]) + dst.Flags = self.Flags + return dst +end + function MT.ImDrawList:AddDrawCmd() local draw_cmd = ImDrawCmd() @@ -38273,6 +39445,22 @@ function MT.ImDrawList:PrimRectUV(a, c, uv_a, uv_c, col) self._IdxWritePtr = idx_write_ptr + 6 end +function MT.ImDrawList:PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col) + local idx = self._VtxCurrentIdx + local idx_data = self.IdxBuffer.Data; local vtx_data = self.VtxBuffer.Buf + local idx_write_ptr = self._IdxWritePtr + idx_data[idx_write_ptr + 0] = idx; idx_data[idx_write_ptr + 1] = idx + 1; idx_data[idx_write_ptr + 2] = idx + 2 + idx_data[idx_write_ptr + 3] = idx; idx_data[idx_write_ptr + 4] = idx + 2; idx_data[idx_write_ptr + 5] = idx + 3 + local vtx_write_ptr = self._VtxWritePtr + WV(vtx_data, vtx_write_ptr + 0, a.x, a.y, uv_a.x, uv_a.y, col) + WV(vtx_data, vtx_write_ptr + 1, b.x, b.y, uv_b.x, uv_b.y, col) + WV(vtx_data, vtx_write_ptr + 2, c.x, c.y, uv_c.x, uv_c.y, col) + WV(vtx_data, vtx_write_ptr + 3, d.x, d.y, uv_d.x, uv_d.y, col) + self._VtxWritePtr = vtx_write_ptr + 4 + self._VtxCurrentIdx = idx + 4 + self._IdxWritePtr = idx_write_ptr + 6 +end + --- @param thickness float --- @return float -- [Luau] local function (also MT.ImDrawList._CalculateCenterBiasedOffset) @@ -40262,6 +41450,30 @@ function MT.ImDrawList:AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col) end end +function MT.ImDrawList:AddImageQuad(tex_ref, p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + if uv1 == nil then uv1 = ImVec2(0, 0) end + if uv2 == nil then uv2 = ImVec2(1, 0) end + if uv3 == nil then uv3 = ImVec2(1, 1) end + if uv4 == nil then uv4 = ImVec2(0, 1) end + if col == nil then col = 4294967295 --[[IM_COL32_WHITE]] end + + if bit32.band(col, 4278190080 --[[IM_COL32_A_MASK]]) == 0 then + return + end + + local push_texture_id = tex_ref ~= self._CmdHeader.TexRef + if push_texture_id then + self:PushTexture(tex_ref) + end + + self:PrimReserve(6, 4) + self:PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + + if push_texture_id then + self:PopTexture() + end +end + --- @param tex_ref ImTextureRef --- @param p_min ImVec2 --- @param p_max ImVec2 @@ -40355,6 +41567,9 @@ function MT.ImDrawList:PopClipRect() self:_OnChangedClipRect() end +function MT.ImDrawList:GetClipRectMin() local cr = self._ClipRectStack:back(); return ImVec2(cr.x, cr.y) end +function MT.ImDrawList:GetClipRectMax() local cr = self._ClipRectStack:back(); return ImVec2(cr.z, cr.w) end + --- @param center ImVec2 --- @param radius float --- @param a_min_sample int @@ -42156,8 +43371,8 @@ end --- @field UserCallbackData any --- @field UserCallbackDataSize int --- @field UserCallbackDataOffset int -local IM_DRAWCMD = {} -IM_DRAWCMD.__index = IM_DRAWCMD +MT.ImDrawCmd = {} +MT.ImDrawCmd.__index = MT.ImDrawCmd --- @return ImDrawCmd --- @nodiscard @@ -42172,11 +43387,11 @@ function ImDrawCmd() UserCallbackData = nil, -- 4-8 -- Callback user data (when UserCallback != nil). If called AddCallback() with size == 0, this is a copy of the AddCallback() argument. If called AddCallback() with size > 0, this is pointing to a buffer where data is stored. UserCallbackDataSize = 0, -- 4 -- Size of callback user data when using storage, otherwise 0. UserCallbackDataOffset = 0 -- 4 -- [Internal] Offset of callback user data when using storage, otherwise -1. - }, IM_DRAWCMD) + }, MT.ImDrawCmd) end --- @return ImTextureID -function IM_DRAWCMD:GetTexID() +function MT.ImDrawCmd:GetTexID() local tex_id = (self.TexRef._TexData) and self.TexRef._TexData.TexID or self.TexRef._TexID if self.TexRef._TexData ~= nil then assert(tex_id ~= (-1) --[[ImTextureID_Invalid]], "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!") @@ -42432,11 +43647,14 @@ end --- @param x int --- @param y int +function MT.ImTextureData:GetPixels() assert(self.Pixels ~= nil); return self.Pixels end function MT.ImTextureData:GetPixelsAt(x, y) return self.Pixels, (x + y * self.Width) * self.BytesPerPixel + 1 end +function MT.ImTextureData:GetSizeInBytes() return self.Width * self.Height * self.BytesPerPixel end function MT.ImTextureData:GetPitch() return self.Width * self.BytesPerPixel end +function MT.ImTextureData:GetTexRef() local tex_ref = ImTextureRef(); tex_ref._TexData = self; tex_ref._TexID = (-1) --[[ImTextureID_Invalid]]; return tex_ref end function MT.ImTextureData:GetTexID() return self.TexID end --- @param tex_id ImTextureID @@ -42456,8 +43674,8 @@ function MT.ImTextureData:SetStatus(status) self.Status = status if (status == 1 --- @class ImTextureRef --- @field _TexData? ImTextureData --- @field _TexID ImTextureID -local IM_TEXTURE_REF = {} -IM_TEXTURE_REF.__index = IM_TEXTURE_REF +MT.ImTextureRef = {} +MT.ImTextureRef.__index = MT.ImTextureRef --- @return ImTextureRef --- @nodiscard @@ -42466,7 +43684,14 @@ function ImTextureRef(tex_id) -- Members (either are set, never both!) _TexData = nil, -- A texture, generally owned by a ImFontAtlas. Will convert to ImTextureID during render loop, after texture has been uploaded. _TexID = tex_id or (-1) --[[ImTextureID_Invalid]] -- _OR_ Low-level backend texture identifier, if already uploaded or created by user/app. Generally provided to e.g. ImGui.Image() calls. - }, IM_TEXTURE_REF) + }, MT.ImTextureRef) +end + +-- This is provided for consistency (but we don't actually use this) +--- @return ImTextureID +function MT.ImTextureRef:GetTexID() + assert(not (self._TexData ~= nil and self._TexID ~= (-1) --[[ImTextureID_Invalid]])) + if self._TexData then return self._TexData.TexID else return self._TexID end end ------------------------------------------------------------------------------- @@ -44200,7 +45425,8 @@ function MT.ImGuiInputTextCallbackData:InsertChars(pos, new_text) self.SelectionStart = self.CursorPos; self.SelectionEnd = self.CursorPos end -function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.CursorPos = self.BufTextLen; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SetSelection(s, e) assert(s >= 0 and s <= self.BufTextLen); assert(e >= 0 and e <= self.BufTextLen); self.SelectionStart = s; self.CursorPos = e; self.SelectionEnd = e end function MT.ImGuiInputTextCallbackData:ClearSelection() self.SelectionStart = self.BufTextLen; self.SelectionEnd = self.BufTextLen end function MT.ImGuiInputTextCallbackData:HasSelection() return self.SelectionStart ~= self.SelectionEnd end @@ -45837,6 +47063,27 @@ function ImCharIsBlankA(c) return c == 32 or c == 9 end --- @param c char function ImCharIsBlankW(c) return c == 32 or c == 9 or c == 0x3000 end +--- @param c char +function ImCharIsXdigitA(c) return (c >= 48 and c <= 57) or (c >= 65 and c <= 70) or (c >= 97 and c <= 102) end + +--- @param lhs ImVec2 +--- @param fail_value float +function ImInvLength(lhs, fail_value) local d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if d > 0.0 then return ImRsqrt(d) end; return fail_value end +function ImRoundPositive64(f) return _Trunc(f + 0.5) end -- Positive values only. +function ImRoundSigned64(f) if f >= 0.0 then return _Trunc(f + 0.5) else return _Trunc(f - 0.5) end end +-- [Luau] C '%' truncates toward zero; math.fmod matches it +function ImModPositive(a, b) return math.fmod(a + b, b) end +function ImIsFloatAboveGuaranteedIntegerPrecision(f) return f <= -16777216 or f >= 16777216 end + +-- Helper: ImVec2i (2D vector, integer) / ImVec2ih (2D vector, half-size integer, for long-term packed storage) +-- [Luau] both are plain ImVec2 holding whole numbers +function ImVec2i(x, y) return ImVec2(x or 0, y or 0) end +--- @overload fun(rhs: ImVec2): ImVec2 +function ImVec2ih(x, y) + if type(x) == "table" then return ImVec2(_Trunc(x.x), _Trunc(x.y)) end + return ImVec2(x or 0, y or 0) +end + --- @enum ImGuiNavMoveFlags ImGuiNavMoveFlags = { @@ -46135,6 +47382,28 @@ function ImBitArraySetBit(arr, n) arr[idx] = bitOr(arr[idx], mask) end +-- [Luau] bit arrays are ImU32[] tables with 1-based word indices; bit indices 'n' are 1-based like the functions above +--- @param bitcount int +function ImBitArrayGetStorageSizeInBytes(bitcount) return bitLShift(bitRShift(bitcount + 31, 5), 2) end +--- @param arr ImU32[] +--- @param bitcount int +function ImBitArrayClearAllBits(arr, bitcount) for i = 1, bitRShift(bitcount + 31, 5) do arr[i] = 0 end end +function ImBitArrayTestBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); return bitAnd(arr[bitRShift(n - 1, 5) + 1], mask) ~= 0 end +function ImBitArrayClearBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); local idx = bitRShift(n - 1, 5) + 1; arr[idx] = bitAnd(arr[idx], bitNot(mask)) end +-- Works on range [n..n2) +function ImBitArraySetBitRange(arr, n, n2) + n = n - 1; n2 = n2 - 1 -- [Luau] to 0-based + n2 = n2 - 1 + while n <= n2 do + local a_mod = bitAnd(n, 31) + local b_mod = ((n2 > bitOr(n, 31)) and 31 or bitAnd(n2, 31)) + 1 + local mask = bitAnd(2 ^ b_mod - 1, bitNot(2 ^ a_mod - 1)) + local idx = bitRShift(n, 5) + 1 + arr[idx] = bitOr(arr[idx], mask) + n = bitAnd(n + 32, bitNot(31)) + end +end + -- Bit array for named keys --- @alias ImBitArrayForNamedKeys ImBitArray @@ -46161,11 +47430,30 @@ function ImBitArray(BITCOUNT, OFFSET) --- @param n int # 1-based this.SetBit = function(self, n) n = n + OFFSET; assert(n >= 1 and n <= BITCOUNT); ImBitArraySetBit(self.Data, n); end + --- @param n int # 1-based + this.ClearBit = function(self, n) n = n + OFFSET; assert(n >= 1 and n <= BITCOUNT); ImBitArrayClearBit(self.Data, n); end + --- @param n int # 1-based, range [n..n2) + this.SetBitRange = function(self, n, n2) n = n + OFFSET; n2 = n2 + OFFSET; assert(n >= 1 and n <= BITCOUNT and n2 > n and n2 <= BITCOUNT + 1); ImBitArraySetBitRange(self.Data, n, n2); end + this:ClearAllBits() return this end +-- Helper: ImBitVector +-- Store 1-bit per value. +--- @class ImBitVector +--- @field Storage ImVector +MT.ImBitVector = {} +MT.ImBitVector.__index = MT.ImBitVector +function ImBitVector() return setmetatable({ Storage = ImVector() }, MT.ImBitVector) end +function MT.ImBitVector:Create(sz) self.Storage:resize(bitRShift(sz + 31, 5)); for i = 1, self.Storage.Size do self.Storage.Data[i] = 0 end end +function MT.ImBitVector:Clear() self.Storage:clear() end +--- @param n int # 1-based +function MT.ImBitVector:TestBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); return IM_BITARRAY_TESTBIT(self.Storage.Data, n) end +function MT.ImBitVector:SetBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); ImBitArraySetBit(self.Storage.Data, n) end +function MT.ImBitVector:ClearBit(n) assert(n <= bitLShift(self.Storage.Size, 5)); ImBitArrayClearBit(self.Storage.Data, n) end + -- Stateful path API, add points then finish with PathFillConvex() or PathStroke() -- - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. -- so e.g. 'PathArcTo(center, radius, PI * -0.5, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5)' won't have correct anti-aliasing when followed by PathFillConvex(). @@ -46397,9 +47685,13 @@ end --- @param key string --- @return ImGuiStyleVarInfo --- @nodiscard +MT.ImGuiStyleVarInfo = {} +MT.ImGuiStyleVarInfo.__index = MT.ImGuiStyleVarInfo function ImGuiStyleVarInfo(count, data_type, key) - return { Count = count, DataType = data_type, Key = key } + return setmetatable({ Count = count, DataType = data_type, Key = key }, MT.ImGuiStyleVarInfo) end +-- [Luau] no pointers: returns the field value (number, or the live ImVec2 table) of 'parent' (e.g. ImGuiStyle) +function MT.ImGuiStyleVarInfo:GetVarPtr(parent) return parent[self.Key] end -- Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. --- @class ImGuiStyleMod @@ -46514,11 +47806,11 @@ end --- @field RefVal any --- @field StorageId ImGuiID --- @field ColorMarker ImU32 -local IMGUI_NEXT_ITEM_DATA = {} -IMGUI_NEXT_ITEM_DATA.__index = IMGUI_NEXT_ITEM_DATA +MT.ImGuiNextItemData = {} +MT.ImGuiNextItemData.__index = MT.ImGuiNextItemData -- Also cleared manually by ItemAdd()! -function IMGUI_NEXT_ITEM_DATA:ClearFlags() +function MT.ImGuiNextItemData:ClearFlags() self.HasFlags = 0 --[[ImGuiNextItemDataFlags.None]] self.ItemFlagsSet = 0 --[[ImGuiItemFlags.None]] end @@ -46541,7 +47833,7 @@ function ImGuiNextItemData() RefVal = 0, -- Not exposed yet, for ImGuiInputTextFlags.ParseEmptyAsRefVal StorageId = 0, -- Set by SetNextItemStorageID() ColorMarker = 0 -- Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags.ColorMarkers. - }, IMGUI_NEXT_ITEM_DATA) + }, MT.ImGuiNextItemData) end -- Storage for SetNexWindow** functions @@ -46564,10 +47856,10 @@ end --- @field BgAlphaVal number? --- @field MenuBarOffsetMinVal ImVec2? --- @field RefreshFlagsVal int? -local IMGUI_NEXT_WINDOW_DATA = {} -IMGUI_NEXT_WINDOW_DATA.__index = IMGUI_NEXT_WINDOW_DATA +MT.ImGuiNextWindowData = {} +MT.ImGuiNextWindowData.__index = MT.ImGuiNextWindowData -function IMGUI_NEXT_WINDOW_DATA:ClearFlags() +function MT.ImGuiNextWindowData:ClearFlags() self.HasFlags = 0 --[[ImGuiNextWindowDataFlags.None]] end @@ -46606,7 +47898,7 @@ function ImGuiNextWindowData() RefreshFlagsVal = nil, CacheKeySet = false, -- [Port] SetNextWindowCached() CacheKeyVal = nil - }, IMGUI_NEXT_WINDOW_DATA) + }, MT.ImGuiNextWindowData) end --- @enum ImGuiWindowBgClickFlags @@ -46869,21 +48161,29 @@ local function ImGuiInputTextState() SelectedAllMouseLock = false, -- after a double-click to select all, we ignore further mouse drags to update selection EditedBefore = false, -- edited since activated EditedThisFrame = false, -- edited this frame + WantReloadUserBuf = false, -- force a reload of user buf so it may be modified externally. may be automatic in future version. + LastMoveDirectionLR = 0 --[[ImGuiDir.Left]], -- ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s + ReloadSelectionStart = 0, + ReloadSelectionEnd = 0, } return setmetatable(this, MT.ImGuiInputTextState) end +function MT.ImGuiInputTextState:ClearText() self.TextLen = 0; self.TextA.Data[1] = 0; self:CursorClamp() end +function MT.ImGuiInputTextState:ClearFreeMemory() self.TextA:clear(); self.TextToRevertTo:clear() end +function MT.ImGuiInputTextState:GetText() if self.TextA.Data then return self.TextA.Data else return { 0 } end end -- [Luau] byte table (char[]) + -- Internal temporary state for deactivating InputText() instances. -- Store as part of ImGuiDeactivatedItemData? --- @class ImGuiInputTextDeactivatedState --- @field ID ImGuiID # widget id owning the text state (which just got deactivated) --- @field ElapseFrame int --- @field TextA ImVector # text buffer -local IMGUI_INPUT_TEXT_DEACTIVATED_STATE = {} -IMGUI_INPUT_TEXT_DEACTIVATED_STATE.__index = IMGUI_INPUT_TEXT_DEACTIVATED_STATE +MT.ImGuiInputTextDeactivatedState = {} +MT.ImGuiInputTextDeactivatedState.__index = MT.ImGuiInputTextDeactivatedState -function IMGUI_INPUT_TEXT_DEACTIVATED_STATE:ClearFreeMemory() +function MT.ImGuiInputTextDeactivatedState:ClearFreeMemory() self.ID = 0 self.ElapseFrame = 0 self.TextA:clear() @@ -46896,7 +48196,7 @@ local function ImGuiInputTextDeactivatedState() ID = 0, -- widget id owning the text state (which just got deactivated) ElapseFrame = 0, TextA = ImVector() -- text buffer - }, IMGUI_INPUT_TEXT_DEACTIVATED_STATE) + }, MT.ImGuiInputTextDeactivatedState) end --- @alias ImGuiKeyRoutingIndex ImS16 @@ -46929,10 +48229,10 @@ end --- @field Index ImGuiKeyRoutingIndex[] # Index of first entry in Entries[] --- @field Entries ImVector --- @field EntriesNext ImVector # Double-buffer to avoid reallocation (could use a shared buffer) -local _ImGuiKeyRoutingTable = {} -_ImGuiKeyRoutingTable.__index = _ImGuiKeyRoutingTable +MT.ImGuiKeyRoutingTable = {} +MT.ImGuiKeyRoutingTable.__index = MT.ImGuiKeyRoutingTable -function _ImGuiKeyRoutingTable:Clear() +function MT.ImGuiKeyRoutingTable:Clear() for n = 1, 155 --[[ImGuiKey.NamedKey_COUNT]] do self.Index[n] = -1 end self.Entries:clear() self.EntriesNext:clear() @@ -46944,7 +48244,7 @@ local function ImGuiKeyRoutingTable() Index = {}, -- Index of first entry in Entries[] Entries = ImVector(), EntriesNext = ImVector() -- Double-buffer to avoid reallocation (could use a shared buffer) - }, _ImGuiKeyRoutingTable) + }, MT.ImGuiKeyRoutingTable) this:Clear() @@ -47030,10 +48330,10 @@ end --- @field DistBox float # Move -- Best candidate box distance to current NavId --- @field DistCenter float # Move -- Best candidate center distance to current NavId --- @field DistAxial float # Move -- Best candidate axial distance to current NavId -local IMGUI_NAV_ITEM_DATA = {} -IMGUI_NAV_ITEM_DATA.__index = IMGUI_NAV_ITEM_DATA +MT.ImGuiNavItemData = {} +MT.ImGuiNavItemData.__index = MT.ImGuiNavItemData -function IMGUI_NAV_ITEM_DATA:Clear() +function MT.ImGuiNavItemData:Clear() self.Window = nil self.ID = 0 self.FocusScopeId = 0 @@ -47046,7 +48346,7 @@ end --- @return ImGuiNavItemData local function ImGuiNavItemData() - local this = setmetatable({ }, IMGUI_NAV_ITEM_DATA) + local this = setmetatable({ }, MT.ImGuiNavItemData) this.RectRel = ImRect() this:Clear() return this @@ -47619,7 +48919,7 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct DockContext = ImGuiDockContext(), DockNodeWindowMenuHandler = nil, DebugHoveredDockNode = nil, -- Hovered dock node. - CurrentTabBarStack = ImVector(), -- holds ImGuiTabBar references directly (no ImGuiPtrOrIndex needed in Lua) + CurrentTabBarStack = ImVector(), -- ImVector ShrinkWidthBuffer = ImVector(), -- ImGuiShrinkWidthItem -- Multi-Select state @@ -47783,10 +49083,10 @@ end --- @field WantApply bool # Set when loaded from .ini data --- @field WantDelete bool # Set to invalidate/delete the settings entry --- @field Name string # Window name -local IMGUI_WINDOW_SETTINGS = {} -IMGUI_WINDOW_SETTINGS.__index = IMGUI_WINDOW_SETTINGS +MT.ImGuiWindowSettings = {} +MT.ImGuiWindowSettings.__index = MT.ImGuiWindowSettings -function IMGUI_WINDOW_SETTINGS:GetName() +function MT.ImGuiWindowSettings:GetName() return self.Name end @@ -47806,7 +49106,7 @@ function ImGuiWindowSettings() DockOrder = -1, -- Order of the last time the window was visible within its DockNode. This is used to reorder windows that are reappearing on the same frame. Same value between windows that were active and windows that were none are possible. ClassId = 0, -- ID of window class if specified LastUsedDate = 0, - }, IMGUI_WINDOW_SETTINGS) + }, MT.ImGuiWindowSettings) end -- Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. @@ -48522,6 +49822,8 @@ function ImGuiInputEvent() end -- [Internal] Key ranges +ImGuiKey_LegacyNativeKey_BEGIN = 0 +ImGuiKey_LegacyNativeKey_END = 512 ImGuiKey_Keyboard_BEGIN = ImGuiKey.NamedKey_BEGIN ImGuiKey_Keyboard_END = ImGuiKey.GamepadStart ImGuiKey_Gamepad_BEGIN = ImGuiKey.GamepadStart @@ -48846,6 +50148,87 @@ end --- @nodiscard function ImGuiFocusScopeData() return { ID = nil, WindowID = nil } end +------------------------------------------------------------------------------- +-- [Luau] Inline struct helpers / constructors from imgui.h + imgui_internal.h +------------------------------------------------------------------------------- + +-- Helper for running a block of code not more than once a frame +-- [Luau] no operator bool(): call the object, e.g. 'if once() then ... end' +MT.ImGuiOnceUponAFrame = {} +MT.ImGuiOnceUponAFrame.__index = MT.ImGuiOnceUponAFrame +MT.ImGuiOnceUponAFrame.__call = function(self) local current_frame = ImGui.GetFrameCount(); if self.RefFrame == current_frame then return false end; self.RefFrame = current_frame; return true end +function ImGuiOnceUponAFrame() return setmetatable({ RefFrame = -1 }, MT.ImGuiOnceUponAFrame) end + +-- [Internal] ImGuiTextFilter item +-- [Luau] stores the item text as a Lua string (upstream: Begin pointer + Len) +--- @param buf string +--- @param b int # 1-based +--- @param e int # exclusive +function ImGuiTextFilterItem(buf, b, e) assert(e > b); return { Text = string.sub(buf, b, e - 1), CountInclude = 0, MatchIncludesMask = 0 } end + +-- A date in YYYYMMDD format packed into 16-bits +--- @class ImGuiPackedDate +MT.ImGuiPackedDate = {} +MT.ImGuiPackedDate.__index = MT.ImGuiPackedDate +--- @param yyyymmdd? int +function ImGuiPackedDate(yyyymmdd) + local this = setmetatable({ Year = 0, Month = 0, Day = 0 }, MT.ImGuiPackedDate) + if yyyymmdd ~= nil then -- Pack + this.Year = bitAnd(math.floor(yyyymmdd / 10000) - 2000, 0x7F) -- Year since 2000 (7 bits) + this.Month = bitAnd(math.floor(yyyymmdd / 100) % 100, 0x0F) -- Month (1-12) (4 bits) + this.Day = bitAnd(yyyymmdd % 100, 0x1F) -- Day (1-31) (5 bits) + end + return this +end +function MT.ImGuiPackedDate:IsValid() return self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 end +function MT.ImGuiPackedDate:Unpack() if self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 then return ((self.Year + 2000) * 10000) + (self.Month * 100) + self.Day end; return 0 end -- Unpack +function MT.ImGuiPackedDate:SubtractMonths(m) while m > 0 do if self.Month == 1 then self.Year = bitAnd(self.Year - 1, 0x7F) end; self.Month = (self.Month == 1) and 12 or self.Month - 1; m = m - 1 end end -- FIXME-OPT: Stupid but enough for what we do with it. + +-- Pointer or index, e.g. g.CurrentTabBarStack[] +-- [Luau] overload by argument type: number = index, otherwise pointer +function ImGuiPtrOrIndex(ptr_or_index) + if type(ptr_or_index) == "number" then return { Ptr = nil, Index = ptr_or_index } end + return { Ptr = ptr_or_index, Index = -1 } +end + +-- Note that Max is exclusive, so perhaps should be using a Begin/End convention. +--- @class ImGuiListClipperRange +MT.ImGuiListClipperRange = {} +function MT.ImGuiListClipperRange.FromIndices(min, max) return { Min = min, Max = max, PosToIndexConvert = false, PosToIndexOffsetMin = 0, PosToIndexOffsetMax = 0 } end +function MT.ImGuiListClipperRange.FromPositions(y1, y2, off_min, off_max) return { Min = _Trunc(y1), Max = _Trunc(y2), PosToIndexConvert = true, PosToIndexOffsetMin = off_min, PosToIndexOffsetMax = off_max } end + +-- Temporary clipper data, buffers shared/reused between instances +--- @class ImGuiListClipperData +MT.ImGuiListClipperData = {} +MT.ImGuiListClipperData.__index = MT.ImGuiListClipperData +function ImGuiListClipperData() return setmetatable({ ListClipper = nil, LossynessOffset = 0.0, StepNo = 0, ItemsFrozen = 0, Ranges = ImVector() }, MT.ImGuiListClipperData) end +function MT.ImGuiListClipperData:Reset(clipper) self.ListClipper = clipper; self.StepNo = 0; self.ItemsFrozen = 0; self.Ranges:resize(0) end + +function ImGuiStackLevelInfo() return { ID = 0, QueryFrameCount = 0, QuerySuccess = false, DataType = -1, DescOffset = -1 } end +function ImGuiDebugItemPathQuery() return { MainID = 0, Active = false, Complete = false, Step = 0, Results = ImVector(), ResultsDescBuf = ImGuiTextBuffer(), ResultPathBuf = ImGuiTextBuffer() } end +function ImGuiIDStackTool() return { OptHexEncodeNonAsciiChars = true, OptCopyToClipboardOnCtrlC = false, LastActiveFrame = -1, CopyToClipboardLastTime = -3.4028234663853e+38 --[[FLT_MAX]] } end +function ImGuiContextHook() return { HookId = 0, Type = 0, Owner = 0, Callback = nil, UserData = nil } end + +------------------------------------------------------------------------------- +-- [Luau] ImGui:: inline helpers from imgui_internal.h +------------------------------------------------------------------------------- + +function ImGui.GetCurrentTable() local g = GImGui; return g.CurrentTable end +--- @param window ImGuiWindow +--- @param parent_window ImGuiWindow? +function ImGui.SetWindowParentWindowForFocusRoute(window, parent_window) window.ParentWindowForFocusRoute = parent_window end -- You may also use SetNextWindowClass()'s FocusRouteParentWindowId field. +function ImGui.GetPixelDensity() return GImGui.FontRasterizerDensity end -- [Luau] g.FontRasterizerDensity == upstream g.CurrentPixelDensity +function ImGui.ScrollToBringRectIntoView(window, rect) ImGui.ScrollToRect(window, rect, 2 --[[ImGuiScrollFlags.KeepVisibleEdgeY]]) end +function ImGui.GetItemStatusFlags() local g = GImGui; return g.LastItemData.StatusFlags end +function ImGui.GetActiveID() local g = GImGui; return g.ActiveId end +function ImGui.GetFocusID() local g = GImGui; return g.NavId end +function ImGui.IsLegacyKey(key) return key >= 0 --[[ImGuiKey_LegacyNativeKey_BEGIN]] and key < 512 --[[ImGuiKey_LegacyNativeKey_END]] end +function ImGui.GetWindowDockNode() local g = GImGui; return g.CurrentWindow.DockNode end +function ImGui.GetCurrentFocusScope() local g = GImGui; return g.CurrentFocusScopeId end -- Focus scope we are outputting into, set by PushFocusScope() +function ImGui.GetCurrentTabBar() local g = GImGui; return g.CurrentTabBar end +-- This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. +function ImGui.IsItemActiveAsInputText() local g = GImGui; return g.ActiveId ~= 0 and g.ActiveId == g.LastItemData.ID and g.InputTextState.ID == g.LastItemData.ID end + return true -- [Roblox] ModuleScripts must return exactly one value end @@ -49184,9 +50567,13 @@ end -- Storage for a table .ini settings --- @class ImGuiTableSettings +MT.ImGuiTableSettings = {} +MT.ImGuiTableSettings.__index = MT.ImGuiTableSettings function ImGuiTableSettings() - return { ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} } + return setmetatable({ ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} }, MT.ImGuiTableSettings) end +-- [Luau] column settings are stored in a 0-based .Columns table (upstream: allocated right after the struct) +function MT.ImGuiTableSettings:GetColumnSettings() return self.Columns end -- Storage data for a single column for legacy Columns() api --- @class ImGuiOldColumnData @@ -53247,6 +54634,17 @@ function ImGui.TableLoadSettingsForColumn(column, column_settings, load_flags) column.SortDirection = column_settings.SortDirection end +-- [Luau] boolean "less than" for table.sort; takes (table, lhs column idx, rhs column idx) instead of ImGuiTableFixDisplayOrderColumnData +local function TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) + -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. + local lhs_order, rhs_order = table_.Columns[lhs_idx].DisplayOrder, table_.Columns[rhs_idx].DisplayOrder + if lhs_order < 0 then lhs_order = lhs_order + 0x10000 end + if rhs_order < 0 then rhs_order = rhs_order + 0x10000 end + local order_delta = lhs_order - rhs_order + if order_delta ~= 0 then return order_delta < 0 end + return lhs_idx < rhs_idx +end + -- Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2) function ImGui.TableFixDisplayOrder(table_) if band(table_.Flags, 2 --[[ImGuiTableFlags.Reorderable]]) == 0 then @@ -53261,17 +54659,7 @@ function ImGui.TableFixDisplayOrder(table_) fdo_columns[n + 1] = n end -- Sort by DisplayOrder and then Index - -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. - local function key(idx) - local o = table_.Columns[idx].DisplayOrder - if o < 0 then o = o + 0x10000 end - return o - end - table.sort(fdo_columns, function(lhs_idx, rhs_idx) - local a, b = key(lhs_idx), key(rhs_idx) - if a ~= b then return a < b end - return lhs_idx < rhs_idx - end) + table.sort(fdo_columns, function(lhs_idx, rhs_idx) return TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) end) for n = 0, table_.ColumnsCount - 1 do table_.Columns[fdo_columns[n + 1]].DisplayOrder = n end @@ -53280,6 +54668,27 @@ function ImGui.TableFixDisplayOrder(table_) end end +local function TableSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for i = 0, g.Tables:GetMapSize() - 1 do + local table_ = g.Tables:GetByIndex(i) + if table_ then + table_.SettingsOffset = -1 + end + end + -- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD int, 0 = none); g.SessionDate is an ImGuiPackedDate when set + for _, settings in g.SettingsTables:iter() do + local is_valid = ImGuiPackedDate(settings.LastUsedDate):IsValid() + if args._DiscardOlderThanDate ~= 0 and settings.LastUsedDate < args._DiscardOlderThanDate then + settings.ID = 0 + elseif args.DiscardWhenMissingDate and not is_valid then + settings.ID = 0 + elseif args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate and g.SessionDate:Unpack() or 0 + end + end +end + local function ForEachTable(g, fn) for i = 0, g.Tables:GetMapSize() - 1 do local t = g.Tables:GetByIndex(i) @@ -53405,6 +54814,7 @@ function ImGui.TableSettingsAddSettingsHandler() ini_handler.ReadLineFn = TableSettingsHandler_ReadLine ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll ini_handler.WriteAllFn = TableSettingsHandler_WriteAll + ini_handler.CleanupFn = TableSettingsHandler_Cleanup ImGui.AddSettingsHandler(ini_handler) end @@ -53468,6 +54878,20 @@ function ImGui.TableGcCompactSettings() ForEachTable(g, function(t) t.SettingsOffset = -1 end) end +------------------------------------------------------------------------------- +-- [SECTION] Tables: Debugging +------------------------------------------------------------------------------- +-- [Luau] global (upstream: static) so ImGui.DebugNodeTable() in imgui.lua can use it + +function DebugNodeTableGetSizingPolicyDesc(sizing_policy) + sizing_policy = band(sizing_policy, 57344 --[[ImGuiTableFlags.SizingMask_]]) + if sizing_policy == 8192 --[[ImGuiTableFlags.SizingFixedFit]] then return "FixedFit" end + if sizing_policy == 16384 --[[ImGuiTableFlags.SizingFixedSame]] then return "FixedSame" end + if sizing_policy == 24576 --[[ImGuiTableFlags.SizingStretchProp]] then return "StretchProp" end + if sizing_policy == 32768 --[[ImGuiTableFlags.SizingStretchSame]] then return "StretchSame" end + return "N/A" +end + ------------------------------------------------------------------------------- -- [SECTION] Columns, BeginColumns, EndColumns, etc. -- (This is a legacy API, prefer using BeginTable/EndTable!) @@ -56510,12 +57934,14 @@ function ImGui.RoundScalarWithFormatT(format, data_type, v) return v -- Don't apply if the value is not visible in the format string end - -- TODO: Sanitize format + -- Sanitize format + local fmt_sanitized = ImParseFormatSanitizeForPrinting(string.sub(format, fmt_start), nil, 32) -- Format value with our rounding, and read back - local str = ImFormatString(format, v) + local v_str = ImFormatString(fmt_sanitized, v) + -- [Luau] leading spaces: ImAtof() skips them - v = ImAtof(str) or v + v = ImAtof(v_str) or v return v end @@ -56601,6 +58027,30 @@ local function ImParseFormatTrimDecorations(fmt) return string.sub(fmt, fmt_start, fmt_end - 1) end +-- Sanitize format +-- - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi +-- - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. +-- [Luau] fmt_out is a byte table (may be nil); returns the sanitized format as a string +--- @param fmt_in string +--- @param fmt_out char[]? +--- @param fmt_out_size size_t +function ImParseFormatSanitizeForPrinting(fmt_in, fmt_out, fmt_out_size) + local fmt_end = ImParseFormatFindEnd(fmt_in, 1) + -- IM_UNUSED(fmt_out_size) + assert(fmt_end < fmt_out_size) -- Format is too long, let us know if this happens to you! + fmt_out = fmt_out or {} + local n = 0 + for i = 1, fmt_end - 1 do + local c = string.byte(fmt_in, i) + if c ~= 39 and c ~= 36 and c ~= 95 then -- Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. + n = n + 1 + fmt_out[n] = c + end + end + fmt_out[n + 1] = 0 -- Zero-terminate + return string.char(unpack(fmt_out, 1, n)) +end + -- - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" --- @param fmt_in string --- @param fmt_out char[] @@ -57202,6 +58652,18 @@ function ImGui.DragBehaviorT(TYPE, SIGNEDTYPE, data_type, v, v_speed, v_min, v_m return v, true end +local function ShortcutsForCancel(id) + local g = GImGui + local is_cancel_with_keyboard = ImGui.Shortcut(526 --[[ImGuiKey.Escape]], 0 --[[ImGuiInputFlags.None]], id) + -- [Luau] ImGuiKey_NavGamepadCancel macro inlined (io.ConfigNavSwapGamepadButtons is not ported: always FaceRight) + local is_cancel_with_gamepad = bit32.band(g.IO.ConfigFlags, 2 --[[ImGuiConfigFlags.NavEnableGamepad]]) ~= 0 and bit32.band(g.IO.BackendFlags, 1 --[[ImGuiBackendFlags.HasGamepad]]) ~= 0 and ImGui.Shortcut(635 --[[ImGuiKey.GamepadFaceRight]], 0 --[[ImGuiInputFlags.None]], id) + local is_cancel_with_mouse = ImGui.IsMouseReleased(1 --[[ImGuiMouseButton.Right]], id) + if is_cancel_with_mouse then + ImGui.SetKeyOwner(657 --[[ImGuiKey.MouseRight]], id) + end + return is_cancel_with_keyboard or is_cancel_with_gamepad or is_cancel_with_mouse +end + --- @param id ImGuiID --- @param data_type ImGuiDataType --- @param v number @@ -57223,6 +58685,13 @@ function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags) elseif (g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]]) and g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then ImGui.ClearActiveID() end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end end if g.ActiveId ~= id then return v, false @@ -57781,9 +59250,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ local set_new_value = false local clicked_t = 0.0 if g.ActiveIdSource == 1 --[[ImGuiInputSource.Mouse]] then - if not g.IO.MouseDown[0] then - ImGui.ClearActiveID() - else + do local mouse_abs_pos = g.IO.MousePos[axis_k] if g.ActiveIdIsJustActivated then local grab_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) @@ -57803,11 +59270,6 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ set_new_value = true end elseif g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]] then - if g.ActiveIdIsJustActivated then - g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation - g.SliderCurrentAccumDirty = false - end - local input_delta = (axis == 1 --[[ImGuiAxis.X]]) and ImGui.GetNavTweakPressedAmount(axis) or -ImGui.GetNavTweakPressedAmount(axis) if input_delta ~= 0.0 then local tweak_slow = ImGui.IsKeyDown((g.NavInputSource == 3 --[[ImGuiInputSource.Gamepad]]) and 642 --[[ImGuiKey.NavGamepadTweakSlow]] or 4096 --[[ImGuiKey.NavKeyboardTweakSlow]]) @@ -57834,9 +59296,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ end local delta = g.SliderCurrentAccum - if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then - ImGui.ClearActiveID() - elseif g.SliderCurrentAccumDirty then + if g.SliderCurrentAccumDirty then clicked_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) if (clicked_t >= 1.0 and delta > 0.0) or (clicked_t <= 0.0 and delta < 0.0) then -- This is to avoid applying the saturation when already past the limits @@ -57928,6 +59388,30 @@ function ImGui.SliderBehavior(bb, id, data_type, v, min, max, format, flags, out assert((flags == 1 or bit32.band(flags, 1879048207 --[[ImGuiSliderFlags.InvalidMask_]]) == 0), "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.") assert(bit32.band(flags, 256 --[[ImGuiSliderFlags.WrapAround]]) == 0) -- Not supported by SliderXXX(), only by DragXXX() + -- Things we can do easily outside the SliderBehaviorT<> template, saves code generation. + local g = GImGui + if g.ActiveId == id then + if g.ActiveIdSource == 1 --[[ImGuiInputSource.Mouse]] and not g.IO.MouseDown[0] then + ImGui.ClearActiveID() + end + if g.ActiveIdSource == 2 --[[ImGuiInputSource.Keyboard]] or g.ActiveIdSource == 3 --[[ImGuiInputSource.Gamepad]] then + if g.ActiveIdIsJustActivated then + g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation + g.SliderCurrentAccumDirty = false + end + if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then + ImGui.ClearActiveID() + end + end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end + end + if data_type == 0 --[[ImGuiDataType.S8]] then local v32 = (ImS32)((ImS8)(v)); local r v32, r = ImGui.SliderBehaviorT(ImS32, ImS32, bb, id, 4 --[[ImGuiDataType.S32]], v32, min, max, format, flags, out_grab_bb) @@ -58514,7 +59998,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) local len = obj.TextLen idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) while idx <= len and not ImStb.is_word_boundary_from_left(obj, idx) do @@ -58525,7 +60009,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) local len = obj.TextLen while idx <= len and not ImStb.is_word_boundary_from_right(obj, idx) do @@ -58539,9 +60023,9 @@ end function ImStb.TEXTEDIT_MOVEWORDRIGHT(obj, idx) local g = obj.Ctx if g.IO.ConfigMacOSXBehaviors then - return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) else - return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) end end @@ -58742,6 +60226,13 @@ function MT.ImGuiInputTextState:CursorClamp() end function MT.ImGuiInputTextState:HasSelection() return self.Stb.select_start ~= self.Stb.select_end end +function MT.ImGuiInputTextState:ClearSelection() self.Stb.select_start = self.Stb.cursor; self.Stb.select_end = self.Stb.cursor end +-- [Luau] positions are 1-based byte indices (upstream: 0-based) +function MT.ImGuiInputTextState:GetCursorPos() return self.Stb.cursor end +function MT.ImGuiInputTextState:GetSelectionStart() return self.Stb.select_start end +function MT.ImGuiInputTextState:GetSelectionEnd() return self.Stb.select_end end +function MT.ImGuiInputTextState:SetSelection(start, _end) self.Stb.select_start = start; self.Stb.cursor = _end; self.Stb.select_end = _end end +function MT.ImGuiInputTextState:GetPreferredOffsetX() if self.Stb.has_preferred_x then return self.Stb.preferred_x else return -1 end end function MT.ImGuiInputTextState:SelectAll() self.Stb.select_start = 1 @@ -58750,6 +60241,10 @@ function MT.ImGuiInputTextState:SelectAll() self.Stb.has_preferred_x = false end +function MT.ImGuiInputTextState:ReloadUserBufAndSelectAll() self.WantReloadUserBuf = true; self.ReloadSelectionStart = 1; self.ReloadSelectionEnd = 2147483647 --[[INT_MAX]] end +function MT.ImGuiInputTextState:ReloadUserBufAndKeepSelection() self.WantReloadUserBuf = true; self.ReloadSelectionStart = self.Stb.select_start; self.ReloadSelectionEnd = self.Stb.select_end end +function MT.ImGuiInputTextState:ReloadUserBufAndMoveToEnd() self.WantReloadUserBuf = true; self.ReloadSelectionStart = 2147483647 --[[INT_MAX]]; self.ReloadSelectionEnd = 2147483647 --[[INT_MAX]] end + end function ImGui.PushPasswordFont() @@ -58901,9 +60396,9 @@ local function InputTextFilterCharacter(ctx, state, char, callback, user_data, i callback_data.EventFlag = 2097152 --[[ImGuiInputTextFlags.CallbackCharFilter]] callback_data.EventChar = c callback_data.EventActivated = (state ~= nil and g.ActiveId == state.ID and g.ActiveIdIsJustActivated) - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 callback_data.UserData = user_data if callback(callback_data) ~= 0 then return char, false @@ -59485,7 +60980,7 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback if not stbte.HAS_SELECTION(state.Stb) then stbte.prep_selection_at_cursor(state.Stb) end - state.Stb.cursor = STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) + state.Stb.cursor = ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) state.Stb.select_end = state.Stb.cursor stbte.clamp(state, state.Stb) else @@ -59814,9 +61309,9 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback callback_data.BufTextLen = state.TextLen callback_data.BufSize = state.BufCapacity callback_data.BufDirty = false - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based, stb ones 1-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 -- Call user code callback(callback_data) @@ -59826,12 +61321,12 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback assert(callback_data.Buf == callback_buf) -- Invalid to modify those fields assert(callback_data.BufSize == state.BufCapacity) assert(callback_data.Flags == flags) - if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor then + if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor - 1 then state.CursorFollow = true end - state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) - state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) - state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) + 1 + state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) + 1 + state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + 1 if callback_data.BufDirty then -- Callback may update buffer and thus set buf_dirty even in read-only mode. assert(callback_data.BufTextLen == ImStd.ImStrlen(callback_data.Buf)) -- You need to maintain BufTextLen if you change the text! @@ -60195,6 +61690,47 @@ function ImGui.InputTextWithHint(label, hint, buf, buf_size, flags, callback, us return ImGui.InputTextEx(label, hint, buf, buf_size, ImVec2(0, 0), flags, callback, user_data) end +-- [Luau] stb positions/undo indices are 1-based in this port (displayed as-is) +--- @param state ImGuiInputTextState +function ImGui.DebugNodeInputTextState(state) + local g = GImGui + local stb_state = state.Stb + local undo_state = stb_state.undostate + ImGui.Text("ID: 0x%08X, ActiveID: 0x%08X", state.ID, g.ActiveId) + if ImGui.DebugLocateItemOnHover then ImGui.DebugLocateItemOnHover(state.ID) end -- [Luau] not ported yet + local wrap_dir = "" + if bit32.band(state.Flags, 16777216 --[[ImGuiInputTextFlags.WordWrap]]) ~= 0 then + if state.LastMoveDirectionLR == 0 --[[ImGuiDir.Left]] then wrap_dir = " (L)" else wrap_dir = " (R)" end + end + ImGui.Text("TextLen: %d, Cursor: %d%s, Selection: %d..%d", state.TextLen, stb_state.cursor, wrap_dir, stb_state.select_start, stb_state.select_end) + ImGui.Text("BufCapacity: %d, LineCount: %d", state.BufCapacity, state.LineCount) + ImGui.Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state.TextA.Size, state.TextA.Capacity) + ImGui.Text("has_preferred_x: %d (%.2f)", stb_state.has_preferred_x and 1 or 0, stb_state.preferred_x) + ImGui.Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state.undo_point, undo_state.redo_point, undo_state.undo_char_point, undo_state.redo_char_point) + if ImGui.BeginChild("undopoints", ImVec2(0.0, ImGui.GetTextLineHeight() * 10), bit32.bor(1 --[[ImGuiChildFlags.Borders]], 8 --[[ImGuiChildFlags.ResizeY]])) then -- Visualize undo state + ImGui.PushStyleVar(14 --[[ImGuiStyleVar.ItemSpacing]], ImVec2(0, 0)) + for n = 1, 99 --[[IMSTB_TEXTEDIT_UNDOSTATECOUNT]] do + local undo_rec = undo_state.undo_rec[n] + local undo_rec_type = (n < undo_state.undo_point) and "u" or ((n >= undo_state.redo_point) and "r" or " ") + if undo_rec_type == " " then + ImGui.BeginDisabled() + end + local buf_preview_len = (undo_rec_type ~= " " and undo_rec.char_storage ~= -1) and undo_rec.insert_length or 0 + local buf_preview_str = "" + if buf_preview_len > 0 then + buf_preview_str = string.char(unpack(undo_state.undo_char, undo_rec.char_storage, undo_rec.char_storage + buf_preview_len - 1)) + end + ImGui.Text("%s [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%s\"", + undo_rec_type, n, undo_rec.where, undo_rec.insert_length, undo_rec.delete_length, undo_rec.char_storage, buf_preview_str) + if undo_rec_type == " " then + ImGui.EndDisabled() + end + end + ImGui.PopStyleVar() + end + ImGui.EndChild() +end + ------------------------------------------------------------------------------- -- [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. ------------------------------------------------------------------------------- @@ -64560,14 +66096,37 @@ local function TabItemGetSectionIdx(tab) return 1 end +-- [Luau] comparers return a boolean "less than" for table.sort (upstream: ImQsort int comparers) +local function TabItemComparerBySection(a, b) + if a == nil or b == nil then return false end + local a_section = TabItemGetSectionIdx(a) + local b_section = TabItemGetSectionIdx(b) + if a_section ~= b_section then + return a_section < b_section + end + return a.IndexDuringLayout < b.IndexDuringLayout +end + +local function TabItemComparerByBeginOrder(a, b) + return a.BeginOrder < b.BeginOrder +end + +local function GetTabBarFromTabBarRef(ref) + local g = GImGui + if ref.Ptr then return ref.Ptr else return g.TabBars:GetByIndex(ref.Index) end +end + +local function GetTabBarRefFromTabBar(tab_bar) + local g = GImGui + if g.TabBars:Contains(tab_bar) then + return ImGuiPtrOrIndex(g.TabBars:GetIndex(tab_bar)) + end + return ImGuiPtrOrIndex(tab_bar) +end + -- Stable sorts (C++ ImQsort is not stable, but the comparers are total orders in practice) local function SortTabsBySection(tab_bar) - table.sort(tab_bar.Tabs.Data, function(a, b) - if a == nil or b == nil then return false end - local sa, sb = TabItemGetSectionIdx(a), TabItemGetSectionIdx(b) - if sa ~= sb then return sa < sb end - return a.IndexDuringLayout < b.IndexDuringLayout - end) + table.sort(tab_bar.Tabs.Data, TabItemComparerBySection) end local function SortTabsByBeginOrder(tab_bar) @@ -64575,7 +66134,7 @@ local function SortTabsByBeginOrder(tab_bar) if not data then return end local arr = {} for i = 1, tab_bar.Tabs.Size do arr[i] = data[i] end - table.sort(arr, function(a, b) return a.BeginOrder < b.BeginOrder end) + table.sort(arr, TabItemComparerByBeginOrder) for i = 1, tab_bar.Tabs.Size do data[i] = arr[i] end end @@ -64589,6 +66148,12 @@ end -- Spacing: Horizontal spacing at the end of the section. local function ImGuiTabBarSection() return { TabCount = 0, Width = 0.0, WidthAfterShrinkMinWidth = 0.0, Spacing = 0.0 } end +-- [Luau] boolean "less than" for table.sort. Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects +local function ShrinkWidthItemComparer(a, b) + if a.Width ~= b.Width then return a.Width > b.Width end + return a.Index > b.Index -- b->Index - a->Index +end + -- Shrink excess width from a set of item, by removing width from the larger items first. -- Set items Width to -1.0f to disable shrinking this item. -- items: 1-based array of ImGuiShrinkWidthItem, `first` = 1-based index of first item, `count` items @@ -64602,10 +66167,7 @@ function ImGui.ShrinkWidths(items, first, count, width_excess, width_min) -- Sort largest first, smallest last. local slice = {} for n = 1, count do slice[n] = items[first + n - 1] end - table.sort(slice, function(a, b) - if a.Width ~= b.Width then return a.Width > b.Width end - return a.Index > b.Index -- ShrinkWidthItemComparer: b->Index - a->Index (Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects) - end) + table.sort(slice, ShrinkWidthItemComparer) for n = 1, count do items[first + n - 1] = slice[n] end local it = slice local count_same_width = 1 @@ -64716,7 +66278,7 @@ function ImGui.BeginTabBarEx(tab_bar, tab_bar_bb, flags) end -- Add to stack - g.CurrentTabBarStack:push_back(tab_bar) + g.CurrentTabBarStack:push_back(GetTabBarRefFromTabBar(tab_bar)) g.CurrentTabBar = tab_bar tab_bar.Window = window @@ -64798,7 +66360,7 @@ function ImGui.EndTabBar() end g.CurrentTabBarStack:pop_back() - if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = g.CurrentTabBarStack.Data[g.CurrentTabBarStack.Size] end + if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = GetTabBarFromTabBarRef(g.CurrentTabBarStack:back()) end end -- This is called only once a frame before by the first call to ItemTab() @@ -71113,6 +72675,7 @@ return { CalcNextScrollFromScrollTargetAndClamp = CalcNextScrollFromScrollTargetAndClamp, CustomConstraints = CustomConstraints, DBL_MAX = DBL_MAX, + DebugNodeTableGetSizingPolicyDesc = DebugNodeTableGetSizingPolicyDesc, DemoWindowColumns = DemoWindowColumns, DemoWindowInputs = DemoWindowInputs, DemoWindowLayout = DemoWindowLayout, @@ -71270,14 +72833,23 @@ return { ImAtan2 = ImAtan2, ImAtof = ImAtof, ImBezierCubicCalc = ImBezierCubicCalc, + ImBezierCubicClosestPoint = ImBezierCubicClosestPoint, + ImBezierCubicClosestPointCasteljau = ImBezierCubicClosestPointCasteljau, ImBezierQuadraticCalc = ImBezierQuadraticCalc, ImBitArray = ImBitArray, + ImBitArrayClearAllBits = ImBitArrayClearAllBits, + ImBitArrayClearBit = ImBitArrayClearBit, + ImBitArrayGetStorageSizeInBytes = ImBitArrayGetStorageSizeInBytes, ImBitArraySetBit = ImBitArraySetBit, + ImBitArraySetBitRange = ImBitArraySetBitRange, + ImBitArrayTestBit = ImBitArrayTestBit, + ImBitVector = ImBitVector, ImCeil = ImCeil, ImCeilFast = ImCeilFast, ImCharIsBlankA = ImCharIsBlankA, ImCharIsBlankW = ImCharIsBlankW, ImCharIsSeparatorW = ImCharIsSeparatorW, + ImCharIsXdigitA = ImCharIsXdigitA, ImClamp = ImClamp, ImColor = ImColor, ImCos = ImCos, @@ -71392,8 +72964,11 @@ return { ImGuiCond = ImGuiCond, ImGuiConfigFlags = ImGuiConfigFlags, ImGuiContext = ImGuiContext, + ImGuiContextHook = ImGuiContextHook, + ImGuiContextHookType = ImGuiContextHookType, ImGuiDataAuthority = ImGuiDataAuthority, ImGuiDataType = ImGuiDataType, + ImGuiDebugItemPathQuery = ImGuiDebugItemPathQuery, ImGuiDebugLogFlags = ImGuiDebugLogFlags, ImGuiDemoDockspaceArgs = ImGuiDemoDockspaceArgs, ImGuiDemoWindowData = ImGuiDemoWindowData, @@ -71409,6 +72984,7 @@ return { ImGuiFocusedFlags = ImGuiFocusedFlags, ImGuiGroupData = ImGuiGroupData, ImGuiHoveredFlags = ImGuiHoveredFlags, + ImGuiIDStackTool = ImGuiIDStackTool, ImGuiIO = ImGuiIO, ImGuiInputEvent = ImGuiInputEvent, ImGuiInputEventAppFocused = ImGuiInputEventAppFocused, @@ -71437,12 +73013,15 @@ return { ImGuiKey_Gamepad_END = ImGuiKey_Gamepad_END, ImGuiKey_Keyboard_BEGIN = ImGuiKey_Keyboard_BEGIN, ImGuiKey_Keyboard_END = ImGuiKey_Keyboard_END, + ImGuiKey_LegacyNativeKey_BEGIN = ImGuiKey_LegacyNativeKey_BEGIN, + ImGuiKey_LegacyNativeKey_END = ImGuiKey_LegacyNativeKey_END, ImGuiKey_Mouse_BEGIN = ImGuiKey_Mouse_BEGIN, ImGuiKey_Mouse_END = ImGuiKey_Mouse_END, ImGuiLastItemData = ImGuiLastItemData, ImGuiLastItemData_Copy = ImGuiLastItemData_Copy, ImGuiLayoutType = ImGuiLayoutType, ImGuiListClipper = ImGuiListClipper, + ImGuiListClipperData = ImGuiListClipperData, ImGuiListClipperFlags = ImGuiListClipperFlags, ImGuiLocKey = ImGuiLocKey, ImGuiLogFlags = ImGuiLogFlags, @@ -71469,6 +73048,8 @@ return { ImGuiOldColumnData = ImGuiOldColumnData, ImGuiOldColumnFlags = ImGuiOldColumnFlags, ImGuiOldColumns = ImGuiOldColumns, + ImGuiOnceUponAFrame = ImGuiOnceUponAFrame, + ImGuiPackedDate = ImGuiPackedDate, ImGuiPayload = ImGuiPayload, ImGuiPayload_Clear = ImGuiPayload_Clear, ImGuiPayload_IsDataType = ImGuiPayload_IsDataType, @@ -71484,6 +73065,7 @@ return { ImGuiPopupData = ImGuiPopupData, ImGuiPopupFlags = ImGuiPopupFlags, ImGuiPopupPositionPolicy = ImGuiPopupPositionPolicy, + ImGuiPtrOrIndex = ImGuiPtrOrIndex, ImGuiScrollFlags = ImGuiScrollFlags, ImGuiSelectableFlags = ImGuiSelectableFlags, ImGuiSelectionBasicStorage = ImGuiSelectionBasicStorage, @@ -71497,6 +73079,7 @@ return { ImGuiShrinkWidthItem = ImGuiShrinkWidthItem, ImGuiSliderFlags = ImGuiSliderFlags, ImGuiSortDirection = ImGuiSortDirection, + ImGuiStackLevelInfo = ImGuiStackLevelInfo, ImGuiStyle = ImGuiStyle, ImGuiStyleMod = ImGuiStyleMod, ImGuiStyleVar = ImGuiStyleVar, @@ -71520,6 +73103,7 @@ return { ImGuiTableTempData = ImGuiTableTempData, ImGuiTextBuffer = ImGuiTextBuffer, ImGuiTextFilter = ImGuiTextFilter, + ImGuiTextFilterItem = ImGuiTextFilterItem, ImGuiTextFlags = ImGuiTextFlags, ImGuiTooltipFlags = ImGuiTooltipFlags, ImGuiTreeNodeFlags = ImGuiTreeNodeFlags, @@ -71548,6 +73132,8 @@ return { ImHashData = ImHashData, ImHashStr = ImHashStr, ImHashStrRaw = ImHashStrRaw, + ImInvLength = ImInvLength, + ImIsFloatAboveGuaranteedIntegerPrecision = ImIsFloatAboveGuaranteedIntegerPrecision, ImIsPowerOfTwo = ImIsPowerOfTwo, ImIsTruncated = ImIsTruncated, ImIsTruncated4 = ImIsTruncated4, @@ -71558,8 +73144,10 @@ return { ImMax = ImMax, ImMemchr = ImMemchr, ImMin = ImMin, + ImModPositive = ImModPositive, ImMul = ImMul, ImParseFormatFindStart = ImParseFormatFindStart, + ImParseFormatSanitizeForPrinting = ImParseFormatSanitizeForPrinting, ImParseFormatSanitizeForScanning = ImParseFormatSanitizeForScanning, ImPool = ImPool, ImPow = ImPow, @@ -71568,6 +73156,8 @@ return { ImRect_CopyFromV4 = ImRect_CopyFromV4, ImRotate = ImRotate, ImRound64 = ImRound64, + ImRoundPositive64 = ImRoundPositive64, + ImRoundSigned64 = ImRoundSigned64, ImRsqrt = ImRsqrt, ImRsqrtPrecise = ImRsqrtPrecise, ImS16 = ImS16, @@ -71612,6 +73202,8 @@ return { ImVec2_CopyV = ImVec2_CopyV, ImVec2_MulVX = ImVec2_MulVX, ImVec2_SubVA = ImVec2_SubVA, + ImVec2i = ImVec2i, + ImVec2ih = ImVec2ih, ImVec4 = ImVec4, ImVec4_Copy = ImVec4_Copy, ImVector = ImVector, diff --git a/docs/PORT_STATUS.txt b/docs/PORT_STATUS.txt index a76f8ea..8e51d4a 100644 --- a/docs/PORT_STATUS.txt +++ b/docs/PORT_STATUS.txt @@ -12,20 +12,20 @@ Known low scores that are not missing code: data-driven port code (e.g. DemoWind polyline stroker (AddPolyline), Lua-native replacements (ImGuiStorage, ImStr*, ImFormatString -> string.format). upstream file funcs ported by size similarity stubs -imgui.cpp 786 87.4% 93.5% 75.1% 2 -imgui_widgets.cpp 308 93.8% 98.7% 78.4% 1 -imgui_draw.cpp 258 96.1% 98.2% 61.1% 1 -imgui_tables.cpp 113 96.5% 99.0% 74.0% 0 -imgui_demo.cpp 56 100.0% 100.0% 55.8% 0 -imgui.h 110 58.2% 41.7% 60.2% 0 -imgui_internal.h 269 63.2% 67.5% 68.5% 1 -TOTAL 1900 85.4% 96.1% 70.3% 5 +imgui.cpp 786 94.9% 98.5% 75.9% 4 +imgui_widgets.cpp 308 100.0% 100.0% 78.6% 1 +imgui_draw.cpp 258 98.1% 99.2% 60.9% 1 +imgui_tables.cpp 113 99.1% 100.0% 74.0% 0 +imgui_demo.cpp 56 100.0% 100.0% 54.9% 0 +imgui.h 110 66.4% 51.6% 63.4% 0 +imgui_internal.h 269 83.6% 83.9% 68.2% 1 +TOTAL 1900 93.3% 98.8% 70.6% 7 -upstream code reproduced (similarity x ported size / all upstream size): 67.5% -Public API (imgui.h, namespace ImGui) 368 / 376 97.9% -Internal API (imgui_internal.h, namespace ImGui) 417 / 443 94.1% +upstream code reproduced (similarity x ported size / all upstream size): 69.7% +Public API (imgui.h, namespace ImGui) 374 / 376 99.5% +Internal API (imgui_internal.h, namespace ImGui) 443 / 443 100.0% Enum values (imgui.h + imgui_internal.h) 1037 / 1078 96.2% -Struct fields (imgui.h + imgui_internal.h) 1840 / 1926 95.5% +Struct fields (imgui.h + imgui_internal.h) 1864 / 1926 96.8% Legend: [x] ported (sim %) [~] stub [ ] not ported [-] excluded (c++-only / obsolete / os-specific / #if 0 / test-engine) @@ -41,89 +41,89 @@ imgui.cpp [ ] FreeWrapper -- USER FACING STRUCTURES (ImGuiStyle, ImGuiIO, ImGuiPlatformIO) - [x] 33% ImGuiStyle::ImGuiStyle imgui_internal.lua:1530 - [x] 83% ImGuiStyle::ScaleAllSizes imgui.lua:4779 - [x] 12% ImGuiIO::ImGuiIO imgui_h.lua:1215 - [x] 83% ImGuiIO::AddInputCharacter imgui.lua:7983 - [x] 83% ImGuiIO::AddInputCharacterUTF16 imgui.lua:8004 - [ ] ImGuiIO::AddInputCharactersUTF8 - [x] 83% ImGuiIO::ClearEventsQueue imgui.lua:8033 - [x] 80% ImGuiIO::ClearInputKeys imgui.lua:8040 - [x] 75% ImGuiIO::ClearInputMouse imgui.lua:8058 - [ ] FindLatestInputEvent - [x] 89% ImGuiIO::AddKeyAnalogEvent imgui.lua:8111 - [x] 89% ImGuiIO::AddKeyEvent imgui.lua:8157 - [ ] ImGuiIO::SetKeyEventNativeData - [x] 100% ImGuiIO::SetAppAcceptingEvents imgui.lua:8166 - [x] 75% ImGuiIO::AddMousePosEvent imgui.lua:8232 - [x] 87% ImGuiIO::AddMouseButtonEvent imgui.lua:8271 - [x] 87% ImGuiIO::AddMouseWheelEvent imgui.lua:8323 - [x] 96% ImGuiIO::AddMouseSourceEvent imgui.lua:8173 - [x] 87% ImGuiIO::AddMouseViewportEvent imgui.lua:8180 - [x] 84% ImGuiIO::AddFocusEvent imgui.lua:8209 - [x] 15% ImGuiPlatformIO::ImGuiPlatformIO imgui_h.lua:1553 + [x] 33% ImGuiStyle::ImGuiStyle imgui_internal.lua:1596 + [x] 83% ImGuiStyle::ScaleAllSizes imgui.lua:4812 + [x] 12% ImGuiIO::ImGuiIO imgui_h.lua:1225 + [x] 83% ImGuiIO::AddInputCharacter imgui.lua:8191 + [x] 83% ImGuiIO::AddInputCharacterUTF16 imgui.lua:8212 + [x] 53% ImGuiIO::AddInputCharactersUTF8 imgui.lua:8241 + [x] 83% ImGuiIO::ClearEventsQueue imgui.lua:8254 + [x] 80% ImGuiIO::ClearInputKeys imgui.lua:8261 + [x] 75% ImGuiIO::ClearInputMouse imgui.lua:8279 + [x] 82% FindLatestInputEvent imgui.lua:8305 + [x] 89% ImGuiIO::AddKeyAnalogEvent imgui.lua:8332 + [x] 89% ImGuiIO::AddKeyEvent imgui.lua:8378 + [x] 67% ImGuiIO::SetKeyEventNativeData imgui.lua:8392 + [x] 100% ImGuiIO::SetAppAcceptingEvents imgui.lua:8404 + [x] 75% ImGuiIO::AddMousePosEvent imgui.lua:8470 + [x] 87% ImGuiIO::AddMouseButtonEvent imgui.lua:8509 + [x] 87% ImGuiIO::AddMouseWheelEvent imgui.lua:8561 + [x] 96% ImGuiIO::AddMouseSourceEvent imgui.lua:8411 + [x] 87% ImGuiIO::AddMouseViewportEvent imgui.lua:8418 + [x] 84% ImGuiIO::AddFocusEvent imgui.lua:8447 + [x] 15% ImGuiPlatformIO::ImGuiPlatformIO imgui_h.lua:1563 -- MISC HELPERS/UTILITIES (Geometry functions) - [ ] ImBezierCubicClosestPoint - [ ] ImBezierCubicClosestPointCasteljauStep - [ ] ImBezierCubicClosestPointCasteljau - [x] 100% ImLineClosestPoint imgui.lua:5130 - [x] 100% ImTriangleContainsPoint imgui.lua:5148 - [x] 96% ImTriangleBarycentricCoords imgui.lua:5160 - [x] 94% ImTriangleClosestPoint imgui.lua:5179 + [x] 87% ImBezierCubicClosestPoint imgui.lua:5170 + [x] 88% ImBezierCubicClosestPointCasteljauStep imgui.lua:5191 + [x] 81% ImBezierCubicClosestPointCasteljau imgui.lua:5223 + [x] 100% ImLineClosestPoint imgui.lua:5236 + [x] 100% ImTriangleContainsPoint imgui.lua:5254 + [x] 96% ImTriangleBarycentricCoords imgui.lua:5266 + [x] 94% ImTriangleClosestPoint imgui.lua:5285 -- MISC HELPERS/UTILITIES (String, Format, Hash functions) [ ] ImStricmp [ ] ImStrnicmp - [x] 81% ImStrncpy imgui.lua:5204 + [x] 81% ImStrncpy imgui.lua:5310 [ ] ImStrdup [ ] ImMemdup [ ] ImStrdupcpy [ ] ImStrchrRange [ ] ImStrlenW [ ] ImStreolRange - [x] 42% ImStrbol imgui.lua:5218 + [x] 42% ImStrbol imgui.lua:5324 [ ] ImStristr - [x] 69% ImStrTrimBlanks imgui.lua:5228 + [x] 69% ImStrTrimBlanks imgui.lua:5334 [ ] ImStrSkipBlank - [x] n/a ImFormatString imgui.lua:4666 = string . format + [x] n/a ImFormatString imgui.lua:4699 = string . format [ ] ImFormatStringV [ ] ImFormatStringToTempBuffer [ ] ImFormatStringToTempBufferV - [x] 19% ImHashData imgui.lua:4883 - [x] 20% ImHashStr imgui.lua:4917 + [x] 19% ImHashData imgui.lua:4916 + [x] 20% ImHashStr imgui.lua:4950 [ ] ImHashSkipUncontributingPrefix -- MISC HELPERS/UTILITIES (File functions) - [~] 0% ImFileOpen imgui.lua:4702 stub - [x] 29% ImFileClose imgui.lua:4719 - [x] 16% ImFileGetSize imgui.lua:4720 - [x] 10% ImFileRead imgui.lua:4725 + [~] 0% ImFileOpen imgui.lua:4735 stub + [x] 29% ImFileClose imgui.lua:4752 + [x] 16% ImFileGetSize imgui.lua:4753 + [x] 10% ImFileRead imgui.lua:4758 [ ] ImFileWrite - [x] 39% ImFileLoadToMemory imgui.lua:4747 + [x] 39% ImFileLoadToMemory imgui.lua:4780 -- MISC HELPERS/UTILITIES (ImText* functions) - [x] 37% ImTextCharFromUtf8 imgui.lua:4984 + [x] 37% ImTextCharFromUtf8 imgui.lua:5017 [ ] ImTextStrFromUtf8 [ ] ImTextCountCharsFromUtf8 - [x] 69% ImTextCharToUtf8_inline imgui.lua:5037 - [x] 93% ImTextCharToUtf8 imgui.lua:5076 - [x] 5% ImTextCountUtf8BytesFromChar imgui.lua:5087 + [x] 69% ImTextCharToUtf8_inline imgui.lua:5070 + [x] 93% ImTextCharToUtf8 imgui.lua:5109 + [x] 5% ImTextCountUtf8BytesFromChar imgui.lua:5120 [ ] ImTextStrToUtf8 [ ] ImTextCountUtf8BytesFromStr - [x] 74% ImTextFindPreviousUtf8Codepoint imgui.lua:5095 - [x] 86% ImTextFindValidUtf8CodepointEnd imgui.lua:5110 - [x] 41% ImTextCountLines imgui_tables.lua:3782 + [x] 74% ImTextFindPreviousUtf8Codepoint imgui.lua:5128 + [x] 86% ImTextFindValidUtf8CodepointEnd imgui.lua:5143 + [x] 41% ImTextCountLines imgui_tables.lua:3786 -- MISC HELPERS/UTILITIES (Color functions) - [x] 73% ImAlphaBlendColors imgui.lua:14400 - [x] 41% ImGui::ColorConvertU32ToFloat4 imgui.lua:14411 - [x] 16% ImGui::ColorConvertFloat4ToU32 imgui.lua:14430 - [x] 87% ImGui::ColorConvertRGBtoHSV imgui.lua:14441 - [x] 61% ImGui::ColorConvertHSVtoRGB imgui.lua:14466 + [x] 73% ImAlphaBlendColors imgui.lua:14853 + [x] 41% ImGui::ColorConvertU32ToFloat4 imgui.lua:14864 + [x] 16% ImGui::ColorConvertFloat4ToU32 imgui.lua:14883 + [x] 87% ImGui::ColorConvertRGBtoHSV imgui.lua:14894 + [x] 61% ImGui::ColorConvertHSVtoRGB imgui.lua:14919 -- ImGuiStorage - [x] 69% ImLowerBound imgui_widgets.lua:5160 + [x] 69% ImLowerBound imgui_widgets.lua:5231 [ ] PairComparerByID [ ] ImGuiStorage::BuildSortByKey [ ] ImGuiStorage::GetInt @@ -141,769 +141,769 @@ imgui.cpp [ ] ImGuiStorage::SetAllInt -- ImGuiTextFilter - [x] 32% ImGuiTextFilter::ImGuiTextFilter imgui.lua:19361 - [x] 36% ImGuiTextFilter::Draw imgui.lua:19371 - [x] 62% ImGuiTextFilter::DrawWithHint imgui.lua:19378 - [x] 49% ImGuiTextFilter::Build imgui.lua:19393 - [x] 56% ImGuiTextFilter::PassFilter imgui.lua:19454 + [x] 32% ImGuiTextFilter::ImGuiTextFilter imgui.lua:19836 + [x] 36% ImGuiTextFilter::Draw imgui.lua:19846 + [x] 62% ImGuiTextFilter::DrawWithHint imgui.lua:19853 + [x] 49% ImGuiTextFilter::Build imgui.lua:19868 + [x] 56% ImGuiTextFilter::PassFilter imgui.lua:19929 -- ImGuiTextBuffer, ImGuiTextIndex - [x] 5% ImGuiTextBuffer::append imgui_h.lua:2776 - [x] 17% ImGuiTextBuffer::appendf imgui_h.lua:2777 + [x] 5% ImGuiTextBuffer::append imgui_h.lua:2787 + [x] 17% ImGuiTextBuffer::appendf imgui_h.lua:2788 [ ] ImGuiTextBuffer::appendfv [ ] ImGuiTextIndex::append -- ImGuiListClipper - [x] 86% GetSkipItemForListClipping imgui.lua:19492 - [x] 71% ImGuiListClipper_SortAndFuseRanges imgui.lua:19502 - [x] 89% ImGuiListClipper_SeekCursorAndSetupPrevLine imgui.lua:19526 - [x] 8% ImGuiListClipper::ImGuiListClipper imgui.lua:19559 + [x] 86% GetSkipItemForListClipping imgui.lua:19967 + [x] 71% ImGuiListClipper_SortAndFuseRanges imgui.lua:19977 + [x] 89% ImGuiListClipper_SeekCursorAndSetupPrevLine imgui.lua:20001 + [x] 8% ImGuiListClipper::ImGuiListClipper imgui.lua:20034 [-] ImGuiListClipper::~ImGuiListClipper c++-only - [x] 64% ImGuiListClipper::Begin imgui.lua:19566 - [x] 79% ImGuiListClipper::End imgui.lua:19595 - [x] 61% ImGuiListClipper::IncludeItemsByIndex imgui.lua:19621 - [x] 80% ImGuiListClipper::SeekCursorForItem imgui.lua:19632 - [x] 79% ImGuiListClipper_StepInternal imgui.lua:19639 - [x] 40% ImGuiListClipper::Step imgui.lua:19788 - [x] 92% ImGui::CalcClipRectVisibleItemsY imgui.lua:14498 + [x] 64% ImGuiListClipper::Begin imgui.lua:20041 + [x] 79% ImGuiListClipper::End imgui.lua:20070 + [x] 61% ImGuiListClipper::IncludeItemsByIndex imgui.lua:20096 + [x] 80% ImGuiListClipper::SeekCursorForItem imgui.lua:20107 + [x] 79% ImGuiListClipper_StepInternal imgui.lua:20114 + [x] 40% ImGuiListClipper::Step imgui.lua:20263 + [x] 92% ImGui::CalcClipRectVisibleItemsY imgui.lua:14951 -- STYLING - [x] 90% ImGui::GetStyle imgui.lua:14509 - [x] 71% ImGui::GetStyleColorVec4 imgui.lua:18911 - [x] 26% ImGui::GetColorU32 imgui.lua:14523 - [x] 50% ImGui::PushStyleColor imgui.lua:14561 - [x] 68% ImGui::PopStyleColor imgui.lua:14578 - [x] 74% ImGui::GetStyleVarInfo imgui.lua:14645 - [x] 56% ImGui::PushStyleVar imgui.lua:14653 - [x] 91% ImGui::PushStyleVarX imgui.lua:14672 - [x] 91% ImGui::PushStyleVarY imgui.lua:14683 - [x] 70% ImGui::PopStyleVar imgui.lua:14693 - [x] 1% ImGui::GetStyleColorName imgui.lua:19221 + [x] 90% ImGui::GetStyle imgui.lua:14962 + [x] 71% ImGui::GetStyleColorVec4 imgui.lua:19386 + [x] 26% ImGui::GetColorU32 imgui.lua:14976 + [x] 50% ImGui::PushStyleColor imgui.lua:15014 + [x] 68% ImGui::PopStyleColor imgui.lua:15031 + [x] 74% ImGui::GetStyleVarInfo imgui.lua:15098 + [x] 56% ImGui::PushStyleVar imgui.lua:15106 + [x] 91% ImGui::PushStyleVarX imgui.lua:15125 + [x] 91% ImGui::PushStyleVarY imgui.lua:15136 + [x] 70% ImGui::PopStyleVar imgui.lua:15146 + [x] 1% ImGui::GetStyleColorName imgui.lua:19696 -- RENDER HELPERS - [x] 46% ImGui::FindRenderedTextEnd imgui.lua:10069 - [x] 76% ImGui::RenderText imgui.lua:10090 - [x] 79% ImGui::RenderTextWrapped imgui.lua:10120 - [x] 85% ImGui::RenderTextClippedEx imgui.lua:10153 - [x] 80% ImGui::RenderTextClipped imgui.lua:10190 - [x] 90% ImGui::RenderTextEllipsis imgui.lua:10325 - [x] 86% ImGui::RenderFrame imgui.lua:10384 - [x] 94% ImGui::RenderFrameBorder imgui.lua:10404 - [x] 99% ImGui::RenderColorComponentMarker imgui.lua:10417 - [x] 85% ImGui::RenderNavCursor imgui.lua:10213 - [x] 85% ImGui::RenderMouseCursor imgui.lua:10273 + [x] 46% ImGui::FindRenderedTextEnd imgui.lua:10390 + [x] 76% ImGui::RenderText imgui.lua:10411 + [x] 79% ImGui::RenderTextWrapped imgui.lua:10441 + [x] 85% ImGui::RenderTextClippedEx imgui.lua:10474 + [x] 80% ImGui::RenderTextClipped imgui.lua:10511 + [x] 90% ImGui::RenderTextEllipsis imgui.lua:10646 + [x] 86% ImGui::RenderFrame imgui.lua:10705 + [x] 94% ImGui::RenderFrameBorder imgui.lua:10725 + [x] 99% ImGui::RenderColorComponentMarker imgui.lua:10738 + [x] 85% ImGui::RenderNavCursor imgui.lua:10534 + [x] 85% ImGui::RenderMouseCursor imgui.lua:10594 -- INITIALIZATION, SHUTDOWN - [x] 100% ImGui::GetCurrentContext imgui.lua:5487 - [x] 35% ImGui::SetCurrentContext imgui.lua:5492 - [x] 100% ImGui::SetAllocatorFunctions imgui.lua:5503 + [x] 100% ImGui::GetCurrentContext imgui.lua:5623 + [x] 35% ImGui::SetCurrentContext imgui.lua:5628 + [x] 100% ImGui::SetAllocatorFunctions imgui.lua:5639 [ ] ImGui::GetAllocatorFunctions - [x] 87% ImGui::CreateContext imgui.lua:5580 - [x] 83% ImGui::DestroyContext imgui.lua:5592 - [x] 6% ImGuiContext::ImGuiContext imgui_internal.lua:2251 + [x] 87% ImGui::CreateContext imgui.lua:5743 + [x] 83% ImGui::DestroyContext imgui.lua:5755 + [x] 5% ImGuiContext::ImGuiContext imgui_internal.lua:2325 [-] ImGuiContext::~ImGuiContext c++-only - [x] 78% ImGui::Initialize imgui.lua:5538 - [x] 44% ImGui::Shutdown imgui.lua:14315 - [ ] ImGui::SetContextName - [ ] ImGui::AddContextHook - [ ] ImGui::RemoveContextHook - [ ] ImGui::CallContextHooks + [x] 66% ImGui::Initialize imgui.lua:5684 + [x] 47% ImGui::Shutdown imgui.lua:14697 + [x] 48% ImGui::SetContextName imgui.lua:14740 + [x] 59% ImGui::AddContextHook imgui.lua:14764 + [x] 83% ImGui::RemoveContextHook imgui.lua:14778 + [x] 58% ImGui::CallContextHooks imgui.lua:14792 -- MAIN CODE (most of the code! lots of stuff, needs tidying up!) - [x] 11% ImGuiWindow::ImGuiWindow imgui_internal.lua:2855 + [x] 11% ImGuiWindow::ImGuiWindow imgui_internal.lua:2929 [-] ImGuiWindow::~ImGuiWindow c++-only - [x] 74% SetCurrentWindow imgui.lua:10805 - [x] 85% ImGui::GcCompactTransientMiscBuffers imgui.lua:10826 - [x] 94% ImGui::GcCompactTransientWindowBuffers imgui.lua:10845 - [x] 96% ImGui::GcAwakeTransientWindowBuffers imgui.lua:10857 - [x] 86% ImGui::SetActiveID imgui.lua:7429 - [x] 100% ImGui::ClearActiveID imgui.lua:7495 - [x] 98% ImGui::SetHoveredID imgui.lua:7609 - [x] 84% ImGui::GetHoveredID imgui.lua:7100 - [x] 85% ImGui::MarkItemEdited imgui.lua:7643 - [x] 93% ImGui::IsWindowContentHoverable imgui.lua:7676 - [x] 87% CalcDelayFromHoveredFlags imgui.lua:7621 - [x] 50% ApplyHoverFlagsForTooltip imgui.lua:7634 - [x] 87% ImGui::IsItemHovered imgui.lua:7716 - [x] 85% ImGui::ItemHoverable imgui.lua:7848 - [x] 64% ImGui::IsClippedEx imgui.lua:7937 - [x] 91% ImGui::SetLastItemData imgui.lua:7958 - [x] 98% ImGui::SetLastItemDataForWindow imgui.lua:7969 - [x] 93% ImGui::SetLastItemDataForChildWindowItem imgui.lua:11285 - [x] 95% ImGui::CalcWrapWidthForPos imgui.lua:10037 - [x] 77% ImGui::MemAlloc imgui.lua:457 - [x] 79% ImGui::MemFree imgui.lua:470 - [ ] ImGui::DemoMarker - [x] 79% ImGui::DebugAllocHook imgui.lua:485 - [x] 91% ImGui::GetClipboardText imgui.lua:14353 - [x] 100% ImGui::SetClipboardText imgui.lua:14359 - [x] 100% ImGui::GetVersion imgui.lua:19218 - [x] 57% ImGui::GetIO imgui.lua:14366 - [x] 90% ImGui::GetPlatformIO imgui.lua:14369 - [x] 86% ImGui::GetDrawData imgui.lua:14304 - [x] 100% ImGui::GetTime imgui.lua:14310 - [x] 100% ImGui::GetFrameCount imgui.lua:19210 - [x] 87% GetViewportBgFgDrawList imgui.lua:13639 - [x] 80% ImGui::GetBackgroundDrawList imgui.lua:13663 - [x] 80% ImGui::GetForegroundDrawList imgui.lua:13675 - [x] 100% ImGui::GetDrawListSharedData imgui.lua:11533 - [x] 90% ImGui::StartMouseMovingWindow imgui.lua:11462 - [x] 94% ImGui::StartMouseMovingWindowOrNode imgui.lua:4527 - [x] 85% ImGui::StopMouseMovingWindow imgui.lua:7400 - [x] 95% ImGui::UpdateMouseMovingWindowNewFrame imgui.lua:11494 - [x] 88% ImGui::UpdateMouseMovingWindowEndFrame imgui.lua:11591 - [x] 65% TranslateWindow imgui.lua:11662 - [x] 88% ScaleWindow imgui.lua:14921 - [x] 100% IsWindowActiveAndVisible imgui.lua:9570 - [x] 93% ImGui::UpdateHoveredWindowAndCaptureFlags imgui.lua:13037 - [x] 80% SetupDrawListSharedData imgui.lua:13514 - [x] 87% ImGui::NewFrame imgui.lua:13769 - [x] 63% ChildWindowComparer imgui.lua:13689 - [x] 89% AddWindowToSortBuffer imgui.lua:13704 - [x] 86% AddWindowToDrawData imgui.lua:13718 - [x] 64% GetWindowDisplayLayer imgui.lua:13734 - [x] 100% AddRootWindowToDrawData imgui.lua:13740 - [x] 63% FlattenDrawDataIntoSingleLayer imgui.lua:13745 - [x] 83% InitViewportDrawData imgui.lua:13548 - [x] 52% ImGui::PushClipRect imgui.lua:13617 - [x] 42% ImGui::PopClipRect imgui.lua:13626 - [x] 60% ImGui::RenderDimmedBackgroundBehindWindow imgui.lua:18992 - [x] 83% ImGui::FindBottomMostVisibleWindowWithinBeginStack imgui.lua:18965 - [x] 81% ImGui::RenderDimmedBackgrounds imgui.lua:19013 - [x] 84% ImGui::EndFrame imgui.lua:14080 - [x] 74% ImGui::Render imgui.lua:14191 - [x] 17% ImGui::CalcTextSize imgui.lua:14264 - [x] 79% ImGui::FindHoveredWindowEx imgui.lua:12951 - [x] 95% ImGui::IsItemActive imgui.lua:6979 - [x] 97% ImGui::IsItemActivated imgui.lua:7020 - [x] 95% ImGui::IsItemDeactivated imgui.lua:7006 - [x] 100% ImGui::IsItemDeactivatedAfterEdit imgui.lua:7015 - [x] 100% ImGui::IsItemFocused imgui.lua:6990 - [x] 67% ImGui::IsItemClicked imgui.lua:7033 - [x] 57% ImGui::IsItemToggledOpen imgui.lua:7038 - [x] 84% ImGui::IsItemToggledSelection imgui.lua:7048 - [x] 100% ImGui::IsAnyItemHovered imgui.lua:7057 - [x] 67% ImGui::IsAnyItemActive imgui.lua:7062 - [x] 100% ImGui::IsAnyItemFocused imgui.lua:7066 - [x] 74% ImGui::IsItemVisible imgui.lua:7071 - [x] 74% ImGui::IsItemEdited imgui.lua:7075 - [x] 71% ImGui::SetNextItemAllowOverlap imgui.lua:7082 - [x] 93% ImGui::SetActiveIdUsingAllKeyboardKeys imgui.lua:11115 - [x] 67% ImGui::GetItemID imgui.lua:7087 - [x] 100% ImGui::GetItemRectMin imgui.lua:11124 - [x] 100% ImGui::GetItemRectMax imgui.lua:11130 - [x] 67% ImGui::GetItemRectSize imgui.lua:7096 - [x] 67% ImGui::GetItemFlags imgui.lua:7091 - [x] 43% ImGui::BeginChild imgui.lua:11274 - [x] 81% ImGui::BeginChildEx imgui.lua:11140 - [x] 90% ImGui::EndChild imgui.lua:11290 - [x] 83% ImGui::FindFrontMostVisibleChildWindow imgui.lua:5629 - [x] 42% SetWindowConditionAllowFlags imgui.lua:5641 - [x] 73% ImGui::FindWindowByID imgui.lua:11675 - [x] 100% ImGui::FindWindowByName imgui.lua:11685 - [x] 86% ApplyWindowSettings imgui.lua:5655 - [x] 61% InitOrLoadWindowSettings imgui.lua:5694 - [x] 73% CreateNewWindow imgui.lua:5715 - [x] 75% GetWindowForTitleDisplay imgui.lua:6236 - [ ] GetWindowForTitleAndMenuHeight - [x] 72% CalcWindowMinSize imgui.lua:9576 - [x] 86% CalcWindowSizeAfterConstraint imgui.lua:9621 - [x] 79% CalcWindowContentSizes imgui.lua:9656 - [x] 86% CalcWindowAutoFitSize imgui.lua:9681 - [x] 85% ImGui::CalcWindowNextAutoFitSize imgui.lua:9730 - [x] 84% GetWindowBgColorIdx imgui.lua:9741 - [x] 89% CalcResizePosSizeFromAnyCorner imgui.lua:9756 - [x] 94% GetResizeBorderRect imgui.lua:4856 - [ ] ImGui::GetWindowResizeCornerID - [ ] ImGui::GetWindowResizeBorderID - [x] 71% ImGui::UpdateWindowManualResize imgui.lua:9799 - [ ] ClampWindowPos - [x] 95% RenderWindowOuterSingleBorder imgui.lua:10430 - [x] 94% ImGui::RenderWindowOuterBorders imgui.lua:10605 = RenderWindowOuterBorders - [x] 84% ImGui::RenderWindowDecorations imgui.lua:10474 - [x] 93% ImGui::RenderWindowTitleBarContents imgui.lua:10615 - [x] 85% ImGui::UpdateWindowParentAndRootLinks imgui.lua:10711 - [x] 33% ImGui::UpdateWindowSkipRefresh imgui.lua:10741 - [x] 92% SetWindowActiveForSkipRefresh imgui.lua:10793 - [x] 82% ImGui::Begin imgui.lua:11702 - [x] 86% ImGui::End imgui.lua:12771 - [x] 84% ImGui::PushItemFlag imgui.lua:12860 - [x] 96% ImGui::PopItemFlag imgui.lua:12875 - [x] 79% ImGui::BeginDisabled imgui.lua:12890 - [x] 87% ImGui::EndDisabled imgui.lua:12906 - [x] 78% ImGui::BeginDisabledOverrideReenable imgui.lua:12922 - [x] 88% ImGui::EndDisabledOverrideReenable imgui.lua:12933 - [x] 54% ImGui::PushTextWrapPos imgui.lua:14718 - [x] 69% ImGui::PopTextWrapPos imgui.lua:14729 - [x] 100% GetCombinedRootWindow imgui.lua:14741 - [x] 100% ImGui::IsWindowChildOf imgui.lua:14760 - [x] 84% ImGui::IsWindowInBeginStack imgui.lua:14780 - [x] 100% ImGui::IsWindowWithinBeginStackOf imgui.lua:14792 - [x] 91% ImGui::IsWindowAbove imgui.lua:14810 - [x] 90% ImGui::IsWindowHovered imgui.lua:14836 - [x] 67% ImGui::GetWindowDockID imgui.lua:4511 - [x] 67% ImGui::IsWindowDocked imgui.lua:4515 - [x] 100% ImGui::GetWindowWidth imgui.lua:10867 - [x] 74% ImGui::GetWindowHeight imgui.lua:11000 - [x] 56% ImGui::GetWindowPos imgui.lua:11005 - [x] 61% ImGui::SetWindowPos imgui.lua:10875 - [x] 55% ImGui::GetWindowSize imgui.lua:11010 - [x] 76% ImGui::SetWindowSize imgui.lua:10917 - [x] 55% ImGui::SetWindowCollapsed imgui.lua:10962 - [x] 59% ImGui::SetWindowHitTestHole imgui.lua:10986 - [x] 97% ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame imgui.lua:11033 - [x] 55% ImGui::IsWindowCollapsed imgui.lua:10992 - [x] 55% ImGui::IsWindowAppearing imgui.lua:10996 - [x] 72% ImGui::SetNextWindowPos imgui.lua:11042 - [x] 74% ImGui::SetNextWindowSize imgui.lua:11058 - [x] 87% ImGui::SetNextWindowSizeConstraints imgui.lua:11077 - [x] 65% ImGui::SetNextWindowContentSize imgui.lua:11376 - [x] 74% ImGui::SetNextWindowScroll imgui.lua:11383 - [x] 77% ImGui::SetNextWindowCollapsed imgui.lua:11391 - [x] 80% ImGui::SetNextWindowBgAlpha imgui.lua:11086 - [x] 80% ImGui::SetNextWindowViewport imgui.lua:11406 - [x] 76% ImGui::SetNextWindowDockID imgui.lua:4519 - [x] 50% ImGui::SetNextWindowClass imgui.lua:11413 - [x] 69% ImGui::SetNextWindowRefreshPolicy imgui.lua:11423 - [x] 47% ImGui::SetNextWindowFlags imgui.lua:11357 - [x] 47% ImGui::SetNextWindowChildFlags imgui.lua:11339 - [x] 100% ImGui::GetWindowDrawList imgui.lua:11092 - [x] 22% ImGui::GetWindowDpiScale imgui.lua:11443 - [x] 42% ImGui::GetWindowViewport imgui.lua:11447 - [x] 100% ImGui::GetFont imgui.lua:11097 - [ ] ImGui::GetFontBaked - [x] 100% ImGui::GetFontSize imgui.lua:11104 - [x] 100% ImGui::GetFontTexUvWhitePixel imgui.lua:11109 + [x] 74% SetCurrentWindow imgui.lua:11141 + [x] 85% ImGui::GcCompactTransientMiscBuffers imgui.lua:11162 + [x] 94% ImGui::GcCompactTransientWindowBuffers imgui.lua:11181 + [x] 96% ImGui::GcAwakeTransientWindowBuffers imgui.lua:11193 + [x] 86% ImGui::SetActiveID imgui.lua:7622 + [x] 100% ImGui::ClearActiveID imgui.lua:7688 + [x] 98% ImGui::SetHoveredID imgui.lua:7802 + [x] 84% ImGui::GetHoveredID imgui.lua:7293 + [x] 85% ImGui::MarkItemEdited imgui.lua:7836 + [x] 93% ImGui::IsWindowContentHoverable imgui.lua:7869 + [x] 87% CalcDelayFromHoveredFlags imgui.lua:7814 + [x] 50% ApplyHoverFlagsForTooltip imgui.lua:7827 + [x] 87% ImGui::IsItemHovered imgui.lua:7909 + [x] 89% ImGui::ItemHoverable imgui.lua:8041 + [x] 64% ImGui::IsClippedEx imgui.lua:8145 + [x] 91% ImGui::SetLastItemData imgui.lua:8166 + [x] 98% ImGui::SetLastItemDataForWindow imgui.lua:8177 + [x] 93% ImGui::SetLastItemDataForChildWindowItem imgui.lua:11626 + [x] 95% ImGui::CalcWrapWidthForPos imgui.lua:10358 + [x] 77% ImGui::MemAlloc imgui.lua:466 + [x] 79% ImGui::MemFree imgui.lua:479 + [x] 100% ImGui::DemoMarker imgui.lua:493 + [x] 79% ImGui::DebugAllocHook imgui.lua:505 + [x] 91% ImGui::GetClipboardText imgui.lua:14806 + [x] 100% ImGui::SetClipboardText imgui.lua:14812 + [x] 100% ImGui::GetVersion imgui.lua:19693 + [x] 57% ImGui::GetIO imgui.lua:14819 + [x] 90% ImGui::GetPlatformIO imgui.lua:14822 + [x] 86% ImGui::GetDrawData imgui.lua:14686 + [x] 100% ImGui::GetTime imgui.lua:14692 + [x] 100% ImGui::GetFrameCount imgui.lua:19685 + [x] 87% GetViewportBgFgDrawList imgui.lua:13987 + [x] 80% ImGui::GetBackgroundDrawList imgui.lua:14011 + [x] 80% ImGui::GetForegroundDrawList imgui.lua:14023 + [x] 100% ImGui::GetDrawListSharedData imgui.lua:11874 + [x] 90% ImGui::StartMouseMovingWindow imgui.lua:11803 + [x] 94% ImGui::StartMouseMovingWindowOrNode imgui.lua:4560 + [x] 85% ImGui::StopMouseMovingWindow imgui.lua:7593 + [x] 95% ImGui::UpdateMouseMovingWindowNewFrame imgui.lua:11835 + [x] 88% ImGui::UpdateMouseMovingWindowEndFrame imgui.lua:11932 + [x] 65% TranslateWindow imgui.lua:12003 + [x] 88% ScaleWindow imgui.lua:15374 + [x] 100% IsWindowActiveAndVisible imgui.lua:9862 + [x] 93% ImGui::UpdateHoveredWindowAndCaptureFlags imgui.lua:13385 + [x] 80% SetupDrawListSharedData imgui.lua:13862 + [x] 90% ImGui::NewFrame imgui.lua:14117 + [x] 63% ChildWindowComparer imgui.lua:14037 + [x] 89% AddWindowToSortBuffer imgui.lua:14052 + [x] 86% AddWindowToDrawData imgui.lua:14066 + [x] 64% GetWindowDisplayLayer imgui.lua:14082 + [x] 100% AddRootWindowToDrawData imgui.lua:14088 + [x] 63% FlattenDrawDataIntoSingleLayer imgui.lua:14093 + [x] 83% InitViewportDrawData imgui.lua:13896 + [x] 52% ImGui::PushClipRect imgui.lua:13965 + [x] 42% ImGui::PopClipRect imgui.lua:13974 + [x] 60% ImGui::RenderDimmedBackgroundBehindWindow imgui.lua:19467 + [x] 83% ImGui::FindBottomMostVisibleWindowWithinBeginStack imgui.lua:19440 + [x] 81% ImGui::RenderDimmedBackgrounds imgui.lua:19488 + [x] 86% ImGui::EndFrame imgui.lua:14454 + [x] 76% ImGui::Render imgui.lua:14570 + [x] 17% ImGui::CalcTextSize imgui.lua:14646 + [x] 79% ImGui::FindHoveredWindowEx imgui.lua:13299 + [x] 95% ImGui::IsItemActive imgui.lua:7172 + [x] 97% ImGui::IsItemActivated imgui.lua:7213 + [x] 95% ImGui::IsItemDeactivated imgui.lua:7199 + [x] 100% ImGui::IsItemDeactivatedAfterEdit imgui.lua:7208 + [x] 100% ImGui::IsItemFocused imgui.lua:7183 + [x] 67% ImGui::IsItemClicked imgui.lua:7226 + [x] 57% ImGui::IsItemToggledOpen imgui.lua:7231 + [x] 84% ImGui::IsItemToggledSelection imgui.lua:7241 + [x] 100% ImGui::IsAnyItemHovered imgui.lua:7250 + [x] 67% ImGui::IsAnyItemActive imgui.lua:7255 + [x] 100% ImGui::IsAnyItemFocused imgui.lua:7259 + [x] 74% ImGui::IsItemVisible imgui.lua:7264 + [x] 74% ImGui::IsItemEdited imgui.lua:7268 + [x] 71% ImGui::SetNextItemAllowOverlap imgui.lua:7275 + [x] 93% ImGui::SetActiveIdUsingAllKeyboardKeys imgui.lua:11456 + [x] 67% ImGui::GetItemID imgui.lua:7280 + [x] 100% ImGui::GetItemRectMin imgui.lua:11465 + [x] 100% ImGui::GetItemRectMax imgui.lua:11471 + [x] 67% ImGui::GetItemRectSize imgui.lua:7289 + [x] 67% ImGui::GetItemFlags imgui.lua:7284 + [x] 43% ImGui::BeginChild imgui.lua:11615 + [x] 81% ImGui::BeginChildEx imgui.lua:11481 + [x] 90% ImGui::EndChild imgui.lua:11631 + [x] 83% ImGui::FindFrontMostVisibleChildWindow imgui.lua:5792 + [x] 42% SetWindowConditionAllowFlags imgui.lua:5804 + [x] 73% ImGui::FindWindowByID imgui.lua:12016 + [x] 100% ImGui::FindWindowByName imgui.lua:12026 + [x] 86% ApplyWindowSettings imgui.lua:5818 + [x] 61% InitOrLoadWindowSettings imgui.lua:5857 + [x] 73% CreateNewWindow imgui.lua:5878 + [x] 75% GetWindowForTitleDisplay imgui.lua:6415 + [x] 91% GetWindowForTitleAndMenuHeight imgui.lua:9870 + [x] 73% CalcWindowMinSize imgui.lua:9874 + [x] 86% CalcWindowSizeAfterConstraint imgui.lua:9919 + [x] 79% CalcWindowContentSizes imgui.lua:9954 + [x] 86% CalcWindowAutoFitSize imgui.lua:9979 + [x] 85% ImGui::CalcWindowNextAutoFitSize imgui.lua:10028 + [x] 84% GetWindowBgColorIdx imgui.lua:10039 + [x] 89% CalcResizePosSizeFromAnyCorner imgui.lua:10054 + [x] 94% GetResizeBorderRect imgui.lua:4889 + [x] 91% ImGui::GetWindowResizeCornerID imgui.lua:10100 + [x] 92% ImGui::GetWindowResizeBorderID imgui.lua:10111 + [x] 71% ImGui::UpdateWindowManualResize imgui.lua:10120 + [x] 69% ClampWindowPos imgui.lua:10753 + [x] 95% RenderWindowOuterSingleBorder imgui.lua:10766 + [x] 94% ImGui::RenderWindowOuterBorders imgui.lua:10941 = RenderWindowOuterBorders + [x] 84% ImGui::RenderWindowDecorations imgui.lua:10810 + [x] 93% ImGui::RenderWindowTitleBarContents imgui.lua:10951 + [x] 85% ImGui::UpdateWindowParentAndRootLinks imgui.lua:11047 + [x] 33% ImGui::UpdateWindowSkipRefresh imgui.lua:11077 + [x] 92% SetWindowActiveForSkipRefresh imgui.lua:11129 + [x] 82% ImGui::Begin imgui.lua:12043 + [x] 86% ImGui::End imgui.lua:13119 + [x] 84% ImGui::PushItemFlag imgui.lua:13208 + [x] 96% ImGui::PopItemFlag imgui.lua:13223 + [x] 79% ImGui::BeginDisabled imgui.lua:13238 + [x] 87% ImGui::EndDisabled imgui.lua:13254 + [x] 78% ImGui::BeginDisabledOverrideReenable imgui.lua:13270 + [x] 88% ImGui::EndDisabledOverrideReenable imgui.lua:13281 + [x] 54% ImGui::PushTextWrapPos imgui.lua:15171 + [x] 69% ImGui::PopTextWrapPos imgui.lua:15182 + [x] 100% GetCombinedRootWindow imgui.lua:15194 + [x] 100% ImGui::IsWindowChildOf imgui.lua:15213 + [x] 84% ImGui::IsWindowInBeginStack imgui.lua:15233 + [x] 100% ImGui::IsWindowWithinBeginStackOf imgui.lua:15245 + [x] 91% ImGui::IsWindowAbove imgui.lua:15263 + [x] 90% ImGui::IsWindowHovered imgui.lua:15289 + [x] 67% ImGui::GetWindowDockID imgui.lua:4544 + [x] 67% ImGui::IsWindowDocked imgui.lua:4548 + [x] 100% ImGui::GetWindowWidth imgui.lua:11203 + [x] 74% ImGui::GetWindowHeight imgui.lua:11336 + [x] 56% ImGui::GetWindowPos imgui.lua:11341 + [x] 61% ImGui::SetWindowPos imgui.lua:11211 + [x] 55% ImGui::GetWindowSize imgui.lua:11346 + [x] 76% ImGui::SetWindowSize imgui.lua:11253 + [x] 55% ImGui::SetWindowCollapsed imgui.lua:11298 + [x] 59% ImGui::SetWindowHitTestHole imgui.lua:11322 + [x] 97% ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame imgui.lua:11369 + [x] 55% ImGui::IsWindowCollapsed imgui.lua:11328 + [x] 55% ImGui::IsWindowAppearing imgui.lua:11332 + [x] 72% ImGui::SetNextWindowPos imgui.lua:11378 + [x] 74% ImGui::SetNextWindowSize imgui.lua:11394 + [x] 87% ImGui::SetNextWindowSizeConstraints imgui.lua:11413 + [x] 65% ImGui::SetNextWindowContentSize imgui.lua:11717 + [x] 74% ImGui::SetNextWindowScroll imgui.lua:11724 + [x] 77% ImGui::SetNextWindowCollapsed imgui.lua:11732 + [x] 80% ImGui::SetNextWindowBgAlpha imgui.lua:11422 + [x] 80% ImGui::SetNextWindowViewport imgui.lua:11747 + [x] 76% ImGui::SetNextWindowDockID imgui.lua:4552 + [x] 50% ImGui::SetNextWindowClass imgui.lua:11754 + [x] 69% ImGui::SetNextWindowRefreshPolicy imgui.lua:11764 + [x] 47% ImGui::SetNextWindowFlags imgui.lua:11698 + [x] 47% ImGui::SetNextWindowChildFlags imgui.lua:11680 + [x] 100% ImGui::GetWindowDrawList imgui.lua:11428 + [x] 22% ImGui::GetWindowDpiScale imgui.lua:11784 + [x] 42% ImGui::GetWindowViewport imgui.lua:11788 + [x] 100% ImGui::GetFont imgui.lua:11438 + [x] 100% ImGui::GetFontBaked imgui.lua:11434 + [x] 100% ImGui::GetFontSize imgui.lua:11445 + [x] 100% ImGui::GetFontTexUvWhitePixel imgui.lua:11450 [-] ImGui::SetWindowFontScale obsolete - [x] 93% ImGui::PushFocusScope imgui.lua:15926 - [x] 56% ImGui::PopFocusScope imgui.lua:15935 - [x] 91% ImGui::IsInNavFocusRoute imgui.lua:15947 - [x] 71% ImGui::SetNavFocusScope imgui.lua:15961 - [x] 76% ImGui::FocusItem imgui.lua:19181 - [x] 100% ImGui::ActivateItemByID imgui.lua:19194 - [x] 81% ImGui::SetKeyboardFocusHere imgui.lua:19153 - [x] 98% ImGui::SetItemDefaultFocus imgui.lua:16001 - [x] 91% ImGui::SetStateStorage imgui.lua:19212 - [x] 74% ImGui::GetStateStorage imgui.lua:19211 - [x] 72% ImGui::IsRectVisible imgui.lua:6795 + [x] 93% ImGui::PushFocusScope imgui.lua:16388 + [x] 56% ImGui::PopFocusScope imgui.lua:16397 + [x] 91% ImGui::IsInNavFocusRoute imgui.lua:16409 + [x] 71% ImGui::SetNavFocusScope imgui.lua:16423 + [x] 76% ImGui::FocusItem imgui.lua:19656 + [x] 100% ImGui::ActivateItemByID imgui.lua:19669 + [x] 81% ImGui::SetKeyboardFocusHere imgui.lua:19628 + [x] 98% ImGui::SetItemDefaultFocus imgui.lua:16463 + [x] 91% ImGui::SetStateStorage imgui.lua:19687 + [x] 74% ImGui::GetStateStorage imgui.lua:19686 + [x] 72% ImGui::IsRectVisible imgui.lua:6988 -- FONTS, TEXTURES - [x] 91% ImGui::UpdateTexturesNewFrame imgui.lua:5374 - [x] 84% ImGui::UpdateTexturesEndFrame imgui.lua:5397 - [x] 95% ImGui::UpdateFontsNewFrame imgui.lua:5413 - [x] 100% ImGui::UpdateFontsEndFrame imgui.lua:5442 - [x] 93% ImGui::GetDefaultFont imgui.lua:5447 - [ ] ImGui::RegisterUserTexture - [ ] ImGui::UnregisterUserTexture - [x] 87% ImGui::RegisterFontAtlas imgui.lua:5457 - [x] 84% ImGui::UnregisterFontAtlas imgui.lua:5471 - [x] 92% ImGui::SetCurrentFont imgui.lua:5320 - [x] 72% ImGui::UpdateCurrentFontSize imgui.lua:5265 - [ ] ImGui::SetPixelDensity - [x] 93% ImGui::PushFont imgui.lua:5340 - [x] 86% ImGui::PopFont imgui.lua:5359 + [x] 91% ImGui::UpdateTexturesNewFrame imgui.lua:5494 + [x] 84% ImGui::UpdateTexturesEndFrame imgui.lua:5517 + [x] 95% ImGui::UpdateFontsNewFrame imgui.lua:5533 + [x] 100% ImGui::UpdateFontsEndFrame imgui.lua:5562 + [x] 93% ImGui::GetDefaultFont imgui.lua:5567 + [x] 73% ImGui::RegisterUserTexture imgui.lua:5578 + [x] 81% ImGui::UnregisterUserTexture imgui.lua:5585 + [x] 87% ImGui::RegisterFontAtlas imgui.lua:5593 + [x] 84% ImGui::UnregisterFontAtlas imgui.lua:5607 + [x] 92% ImGui::SetCurrentFont imgui.lua:5440 + [x] 72% ImGui::UpdateCurrentFontSize imgui.lua:5371 + [x] 83% ImGui::SetPixelDensity imgui.lua:5422 + [x] 93% ImGui::PushFont imgui.lua:5460 + [x] 86% ImGui::PopFont imgui.lua:5479 -- ID STACK - [x] 46% ImGuiWindow::GetID imgui.lua:7542 - [x] 76% ImGuiWindow::GetIDFromPos imgui.lua:7563 - [x] 47% ImGuiWindow::GetIDFromRectangle imgui.lua:7572 - [x] 53% ImGui::PushID imgui.lua:7505 - [x] 62% ImGui::PushOverrideID imgui.lua:7517 - [x] 39% ImGui::GetIDWithSeed imgui.lua:7594 - [x] 68% ImGui::PopID imgui.lua:7530 - [x] 38% ImGui::GetID imgui.lua:7582 + [x] 46% ImGuiWindow::GetID imgui.lua:7735 + [x] 76% ImGuiWindow::GetIDFromPos imgui.lua:7756 + [x] 47% ImGuiWindow::GetIDFromRectangle imgui.lua:7765 + [x] 53% ImGui::PushID imgui.lua:7698 + [x] 62% ImGui::PushOverrideID imgui.lua:7710 + [x] 39% ImGui::GetIDWithSeed imgui.lua:7787 + [x] 68% ImGui::PopID imgui.lua:7723 + [x] 38% ImGui::GetID imgui.lua:7775 -- INPUTS - [x] 84% GetModForLRModKey imgui.lua:8411 - [x] 74% ImGui::FixupKeyChord imgui.lua:8428 - [x] 52% ImGui::GetKeyData imgui.lua:8440 - [x] 85% ImGui::GetKeyName imgui.lua:8641 - [x] 43% ImGui::GetKeyChordName imgui.lua:8598 - [x] 76% ImGui::CalcTypematicRepeatAmount imgui.lua:8683 - [x] 81% ImGui::GetTypematicRepeatRate imgui.lua:8714 - [x] 96% ImGui::GetKeyPressedAmount imgui.lua:8727 - [x] 77% ImGui::GetKeyMagnitude2d imgui.lua:8458 - [x] 83% ImGui::UpdateKeyRoutingTable imgui.lua:8742 - [x] 70% GetRoutingIdFromOwnerId imgui.lua:8788 - [x] 84% ImGui::GetShortcutRoutingData imgui.lua:8795 - [x] 86% CalcRoutingScore imgui.lua:8847 - [x] 69% IsKeyChordPotentiallyCharInput imgui.lua:8901 - [x] 73% ImGui::SetShortcutRouting imgui.lua:8928 - [ ] ImGui::TestShortcutRouting - [x] 81% ImGui::IsKeyDown imgui.lua:8507 - [x] 9% ImGui::IsKeyPressed imgui.lua:8522 - [x] 84% ImGui::IsKeyReleased imgui.lua:8531 - [x] 69% ImGui::IsMouseDown imgui.lua:9043 - [x] 13% ImGui::IsMouseClicked imgui.lua:9053 - [x] 69% ImGui::IsMouseReleased imgui.lua:9094 - [x] 86% ImGui::IsMouseReleasedWithDelay imgui.lua:9108 - [x] 71% ImGui::IsMouseDoubleClicked imgui.lua:9124 - [x] 83% ImGui::GetMouseClickedCount imgui.lua:9132 - [x] 99% LastItemOverlayButtonForNullId imgui.lua:9140 - [x] 91% ImGui::GetItemClickedCountWithSingleClickDelay imgui.lua:9176 - [x] 29% ImGui::IsMouseHoveringRect imgui.lua:6266 - [x] 81% ImGui::IsMouseDragPastThreshold imgui.lua:6299 - [x] 77% ImGui::IsMouseDragging imgui.lua:6312 - [x] 67% ImGui::GetMousePos imgui.lua:9202 - [x] 85% ImGui::TeleportMousePos imgui.lua:6326 - [x] 93% ImGui::GetMousePosOnOpeningCurrentPopup imgui.lua:9207 - [x] 80% ImGui::IsMousePosValid imgui.lua:9022 - [x] 75% ImGui::IsAnyMouseDown imgui.lua:9031 - [x] 87% ImGui::GetMouseDragDelta imgui.lua:9221 - [x] 71% ImGui::ResetMouseDragDelta imgui.lua:9240 - [x] 100% ImGui::GetMouseCursor imgui.lua:14378 - [x] 100% ImGui::SetMouseCursor imgui.lua:14387 - [x] 92% UpdateAliasKey imgui.lua:13131 - [x] 42% GetMergedModsFromKeys imgui.lua:13139 - [x] 85% ImGui::UpdateKeyboardInputs imgui.lua:13152 - [x] 88% ImGui::UpdateMouseInputs imgui.lua:13230 - [x] 91% LockWheelingWindow imgui.lua:13338 - [x] 76% FindBestWheelingWindow imgui.lua:13359 - [x] 92% ImGui::UpdateMouseWheel imgui.lua:13409 - [x] 60% ImGui::SetNextFrameWantCaptureKeyboard imgui.lua:19216 - [x] 60% ImGui::SetNextFrameWantCaptureMouse imgui.lua:19217 - [ ] GetInputSourceName - [ ] GetMouseSourceName - [ ] DebugPrintInputEvent - [x] 78% ImGui::UpdateInputEvents imgui.lua:9257 - [x] 80% ImGui::GetKeyOwner imgui.lua:8657 - [x] 84% ImGui::TestKeyOwner imgui.lua:8471 - [x] 80% ImGui::SetKeyOwner imgui.lua:9412 - [x] 59% ImGui::SetKeyOwnersForKeyChord imgui.lua:9434 - [x] 79% ImGui::SetItemKeyOwner imgui.lua:9462 - [x] 75% ImGui::IsKeyChordPressed imgui.lua:9489 - [x] 76% ImGui::SetNextItemShortcut imgui.lua:9512 - [x] 88% ImGui::ItemHandleShortcut imgui.lua:6337 - [x] 73% ImGui::Shortcut imgui.lua:9525 + [x] 84% GetModForLRModKey imgui.lua:8649 + [x] 74% ImGui::FixupKeyChord imgui.lua:8666 + [x] 52% ImGui::GetKeyData imgui.lua:8678 + [x] 85% ImGui::GetKeyName imgui.lua:8879 + [x] 43% ImGui::GetKeyChordName imgui.lua:8836 + [x] 76% ImGui::CalcTypematicRepeatAmount imgui.lua:8921 + [x] 81% ImGui::GetTypematicRepeatRate imgui.lua:8952 + [x] 96% ImGui::GetKeyPressedAmount imgui.lua:8965 + [x] 77% ImGui::GetKeyMagnitude2d imgui.lua:8696 + [x] 83% ImGui::UpdateKeyRoutingTable imgui.lua:8980 + [x] 70% GetRoutingIdFromOwnerId imgui.lua:9026 + [x] 84% ImGui::GetShortcutRoutingData imgui.lua:9033 + [x] 86% CalcRoutingScore imgui.lua:9085 + [x] 69% IsKeyChordPotentiallyCharInput imgui.lua:9139 + [x] 71% ImGui::SetShortcutRouting imgui.lua:9166 + [x] 97% ImGui::TestShortcutRouting imgui.lua:9263 + [x] 81% ImGui::IsKeyDown imgui.lua:8745 + [x] 9% ImGui::IsKeyPressed imgui.lua:8760 + [x] 84% ImGui::IsKeyReleased imgui.lua:8769 + [x] 69% ImGui::IsMouseDown imgui.lua:9293 + [x] 13% ImGui::IsMouseClicked imgui.lua:9303 + [x] 69% ImGui::IsMouseReleased imgui.lua:9344 + [x] 86% ImGui::IsMouseReleasedWithDelay imgui.lua:9358 + [x] 71% ImGui::IsMouseDoubleClicked imgui.lua:9374 + [x] 83% ImGui::GetMouseClickedCount imgui.lua:9382 + [x] 99% LastItemOverlayButtonForNullId imgui.lua:9390 + [x] 91% ImGui::GetItemClickedCountWithSingleClickDelay imgui.lua:9426 + [x] 29% ImGui::IsMouseHoveringRect imgui.lua:6445 + [x] 81% ImGui::IsMouseDragPastThreshold imgui.lua:6478 + [x] 77% ImGui::IsMouseDragging imgui.lua:6491 + [x] 67% ImGui::GetMousePos imgui.lua:9452 + [x] 85% ImGui::TeleportMousePos imgui.lua:6505 + [x] 93% ImGui::GetMousePosOnOpeningCurrentPopup imgui.lua:9457 + [x] 80% ImGui::IsMousePosValid imgui.lua:9272 + [x] 75% ImGui::IsAnyMouseDown imgui.lua:9281 + [x] 87% ImGui::GetMouseDragDelta imgui.lua:9471 + [x] 71% ImGui::ResetMouseDragDelta imgui.lua:9490 + [x] 100% ImGui::GetMouseCursor imgui.lua:14831 + [x] 100% ImGui::SetMouseCursor imgui.lua:14840 + [x] 92% UpdateAliasKey imgui.lua:13479 + [x] 42% GetMergedModsFromKeys imgui.lua:13487 + [x] 85% ImGui::UpdateKeyboardInputs imgui.lua:13500 + [x] 88% ImGui::UpdateMouseInputs imgui.lua:13578 + [x] 91% LockWheelingWindow imgui.lua:13686 + [x] 76% FindBestWheelingWindow imgui.lua:13707 + [x] 92% ImGui::UpdateMouseWheel imgui.lua:13757 + [x] 60% ImGui::SetNextFrameWantCaptureKeyboard imgui.lua:19691 + [x] 60% ImGui::SetNextFrameWantCaptureMouse imgui.lua:19692 + [x] 97% GetInputSourceName imgui.lua:9500 + [x] 97% GetMouseSourceName imgui.lua:9510 + [x] 90% DebugPrintInputEvent imgui.lua:9520 + [x] 78% ImGui::UpdateInputEvents imgui.lua:9540 + [x] 80% ImGui::GetKeyOwner imgui.lua:8895 + [x] 84% ImGui::TestKeyOwner imgui.lua:8709 + [x] 80% ImGui::SetKeyOwner imgui.lua:9704 + [x] 59% ImGui::SetKeyOwnersForKeyChord imgui.lua:9726 + [x] 79% ImGui::SetItemKeyOwner imgui.lua:9754 + [x] 75% ImGui::IsKeyChordPressed imgui.lua:9781 + [x] 76% ImGui::SetNextItemShortcut imgui.lua:9804 + [x] 88% ImGui::ItemHandleShortcut imgui.lua:6516 + [x] 73% ImGui::Shortcut imgui.lua:9817 -- ERROR CHECKING, STATE RECOVERY [ ] ImGui::DebugCheckVersionAndDataLayout - [x] 86% ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries imgui.lua:18928 - [ ] ImGui::ErrorCheckNewFrameSanityChecks - [ ] ImGui::ErrorCheckEndFrameSanityChecks - [x] 100% ImGui::ErrorRecoveryStoreState imgui.lua:19815 - [x] 91% ImGui::ErrorRecoveryTryToRecoverState imgui.lua:19833 - [x] 91% ImGui::ErrorRecoveryTryToRecoverWindowState imgui.lua:19862 - [x] 86% ImGui::ErrorLog imgui.lua:19951 - [x] 80% ImGui::ErrorCheckEndFrameFinalizeErrorTooltip imgui.lua:19995 - [x] 77% ImGui::BeginErrorTooltip imgui.lua:20033 - [x] 100% ImGui::EndErrorTooltip imgui.lua:20055 + [x] 86% ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries imgui.lua:19403 + [x] 73% ImGui::ErrorCheckNewFrameSanityChecks imgui.lua:20289 + [x] 88% ImGui::ErrorCheckEndFrameSanityChecks imgui.lua:20367 + [x] 100% ImGui::ErrorRecoveryStoreState imgui.lua:20383 + [x] 91% ImGui::ErrorRecoveryTryToRecoverState imgui.lua:20401 + [x] 91% ImGui::ErrorRecoveryTryToRecoverWindowState imgui.lua:20430 + [x] 86% ImGui::ErrorLog imgui.lua:20530 + [x] 90% ImGui::ErrorCheckEndFrameFinalizeErrorTooltip imgui.lua:20574 + [x] 77% ImGui::BeginErrorTooltip imgui.lua:20622 + [x] 100% ImGui::EndErrorTooltip imgui.lua:20644 -- ITEM SUBMISSION - [x] 100% ImGui::KeepAliveID imgui.lua:6247 - [x] 49% ImGui::ItemAdd imgui.lua:6371 + [x] 100% ImGui::KeepAliveID imgui.lua:6426 + [x] 52% ImGui::ItemAdd imgui.lua:6550 -- LAYOUT - [x] 39% ImGui::ItemSize imgui.lua:6492 - [x] 72% ImGui::SameLine imgui.lua:6566 - [x] 64% ImGui::GetCursorScreenPos imgui.lua:6701 - [x] 91% ImGui::SetCursorScreenPos imgui.lua:6709 - [x] 56% ImGui::GetCursorPos imgui.lua:6719 - [x] 100% ImGui::GetCursorPosX imgui.lua:6724 - [x] 100% ImGui::GetCursorPosY imgui.lua:6729 - [x] 66% ImGui::SetCursorPos imgui.lua:6735 - [x] 100% ImGui::SetCursorPosX imgui.lua:6743 - [x] 100% ImGui::SetCursorPosY imgui.lua:6751 - [x] 100% ImGui::GetCursorStartPos imgui.lua:6759 - [x] 70% ImGui::Indent imgui.lua:6593 - [x] 70% ImGui::Unindent imgui.lua:6609 - [x] 80% ImGui::SetNextItemWidth imgui.lua:6626 - [x] 67% ImGui::PushItemWidth imgui.lua:6634 - [x] 90% ImGui::PushMultiItemsWidths imgui.lua:6659 - [x] 68% ImGui::PopItemWidth imgui.lua:6645 - [x] 73% ImGui::CalcItemWidth imgui.lua:6913 - [x] 19% ImGui::CalcItemSize imgui.lua:6943 - [x] 100% ImGui::GetTextLineHeight imgui.lua:6974 - [x] 100% ImGui::GetTextLineHeightWithSpacing imgui.lua:6769 - [x] 100% ImGui::GetFrameHeight imgui.lua:6677 - [x] 100% ImGui::GetFrameHeightWithSpacing imgui.lua:6764 - [x] 74% ImGui::GetContentRegionAvail imgui.lua:6685 + [x] 39% ImGui::ItemSize imgui.lua:6685 + [x] 72% ImGui::SameLine imgui.lua:6759 + [x] 64% ImGui::GetCursorScreenPos imgui.lua:6894 + [x] 91% ImGui::SetCursorScreenPos imgui.lua:6902 + [x] 56% ImGui::GetCursorPos imgui.lua:6912 + [x] 100% ImGui::GetCursorPosX imgui.lua:6917 + [x] 100% ImGui::GetCursorPosY imgui.lua:6922 + [x] 66% ImGui::SetCursorPos imgui.lua:6928 + [x] 100% ImGui::SetCursorPosX imgui.lua:6936 + [x] 100% ImGui::SetCursorPosY imgui.lua:6944 + [x] 100% ImGui::GetCursorStartPos imgui.lua:6952 + [x] 70% ImGui::Indent imgui.lua:6786 + [x] 70% ImGui::Unindent imgui.lua:6802 + [x] 80% ImGui::SetNextItemWidth imgui.lua:6819 + [x] 67% ImGui::PushItemWidth imgui.lua:6827 + [x] 90% ImGui::PushMultiItemsWidths imgui.lua:6852 + [x] 68% ImGui::PopItemWidth imgui.lua:6838 + [x] 73% ImGui::CalcItemWidth imgui.lua:7106 + [x] 19% ImGui::CalcItemSize imgui.lua:7136 + [x] 100% ImGui::GetTextLineHeight imgui.lua:7167 + [x] 100% ImGui::GetTextLineHeightWithSpacing imgui.lua:6962 + [x] 100% ImGui::GetFrameHeight imgui.lua:6870 + [x] 100% ImGui::GetFrameHeightWithSpacing imgui.lua:6957 + [x] 74% ImGui::GetContentRegionAvail imgui.lua:6878 [-] ImGui::GetContentRegionMax obsolete [-] ImGui::GetWindowContentRegionMin obsolete [-] ImGui::GetWindowContentRegionMax obsolete - [x] 88% ImGui::BeginGroup imgui.lua:6807 - [x] 91% ImGui::EndGroup imgui.lua:6839 + [x] 88% ImGui::BeginGroup imgui.lua:7000 + [x] 91% ImGui::EndGroup imgui.lua:7032 -- SCROLLING - [x] 100% CalcScrollEdgeSnap imgui.lua:14960 - [x] 89% CalcNextScrollFromScrollTargetAndClamp imgui.lua:14971 - [x] 78% ImGui::ScrollToItem imgui.lua:15097 - [x] 86% ImGui::ScrollToRect imgui.lua:15105 - [x] 88% ImGui::ScrollToRectEx imgui.lua:15003 - [x] 74% ImGui::GetScrollX imgui.lua:15088 - [x] 74% ImGui::GetScrollY imgui.lua:15092 - [x] 74% ImGui::GetScrollMaxX imgui.lua:15084 - [x] 100% ImGui::GetScrollMaxY imgui.lua:15079 - [x] 75% ImGui::SetScrollX imgui.lua:15140 - [x] 75% ImGui::SetScrollY imgui.lua:15149 - [x] 78% ImGui::SetScrollFromPosX imgui.lua:15169 - [x] 78% ImGui::SetScrollFromPosY imgui.lua:15181 - [x] 95% ImGui::SetScrollHereX imgui.lua:15111 - [x] 95% ImGui::SetScrollHereY imgui.lua:15125 + [x] 100% CalcScrollEdgeSnap imgui.lua:15413 + [x] 89% CalcNextScrollFromScrollTargetAndClamp imgui.lua:15424 + [x] 78% ImGui::ScrollToItem imgui.lua:15550 + [x] 86% ImGui::ScrollToRect imgui.lua:15558 + [x] 88% ImGui::ScrollToRectEx imgui.lua:15456 + [x] 74% ImGui::GetScrollX imgui.lua:15541 + [x] 74% ImGui::GetScrollY imgui.lua:15545 + [x] 74% ImGui::GetScrollMaxX imgui.lua:15537 + [x] 100% ImGui::GetScrollMaxY imgui.lua:15532 + [x] 75% ImGui::SetScrollX imgui.lua:15593 + [x] 75% ImGui::SetScrollY imgui.lua:15602 + [x] 78% ImGui::SetScrollFromPosX imgui.lua:15622 + [x] 78% ImGui::SetScrollFromPosY imgui.lua:15634 + [x] 95% ImGui::SetScrollHereX imgui.lua:15564 + [x] 95% ImGui::SetScrollHereY imgui.lua:15578 -- TOOLTIPS - [x] 100% ImGui::BeginTooltip imgui.lua:15249 - [x] 100% ImGui::BeginItemTooltip imgui.lua:15253 - [x] 83% ImGui::BeginTooltipEx imgui.lua:15196 - [x] 73% ImGui::EndTooltip imgui.lua:15260 - [x] 21% ImGui::SetTooltip imgui.lua:15267 - [ ] ImGui::SetTooltipV - [x] 52% ImGui::SetItemTooltip imgui.lua:15279 - [ ] ImGui::SetItemTooltipV + [x] 100% ImGui::BeginTooltip imgui.lua:15702 + [x] 100% ImGui::BeginItemTooltip imgui.lua:15706 + [x] 83% ImGui::BeginTooltipEx imgui.lua:15649 + [x] 73% ImGui::EndTooltip imgui.lua:15713 + [x] 38% ImGui::SetTooltip imgui.lua:15720 + [x] 91% ImGui::SetTooltipV imgui.lua:15725 + [x] 19% ImGui::SetItemTooltip imgui.lua:15737 + [x] 84% ImGui::SetItemTooltipV imgui.lua:15741 -- POPUPS - [x] 73% ImGui::IsPopupOpen imgui.lua:11540 - [x] 82% ImGui::GetTopMostPopupModal imgui.lua:11575 - [x] 81% ImGui::GetTopMostAndVisiblePopupModal imgui.lua:18981 - [x] 79% ImGui::FindBlockingModal imgui.lua:15303 - [x] 26% ImGui::OpenPopup imgui.lua:15336 - [x] 86% ImGui::OpenPopupEx imgui.lua:15357 - [x] 73% ImGui::ClosePopupsOverWindow imgui.lua:15420 - [x] 80% ImGui::ClosePopupsExceptModals imgui.lua:19047 - [x] 62% ImGui::ClosePopupToLevel imgui.lua:15478 - [x] 81% ImGui::CloseCurrentPopup imgui.lua:15514 - [x] 81% ImGui::BeginPopupEx imgui.lua:15554 - [x] 80% ImGui::BeginPopupMenuEx imgui.lua:15577 - [x] 83% ImGui::BeginPopup imgui.lua:15603 - [x] 83% ImGui::BeginPopupModal imgui.lua:19065 - [x] 95% ImGui::EndPopup imgui.lua:15616 - [x] 38% ImGui::GetMouseButtonFromPopupFlags imgui.lua:15837 - [x] 94% ImGui::IsPopupOpenRequestForItem imgui.lua:15849 - [x] 85% ImGui::IsPopupOpenRequestForWindow imgui.lua:19095 - [x] 83% ImGui::OpenPopupOnItemClick imgui.lua:15866 - [x] 83% ImGui::BeginPopupContextItem imgui.lua:15900 - [x] 85% ImGui::BeginPopupContextWindow imgui.lua:19109 - [x] 88% ImGui::BeginPopupContextVoid imgui.lua:19119 - [x] 87% ImGui::FindBestWindowPosForPopupEx imgui.lua:15653 - [x] 87% ImGui::GetPopupAllowedExtentRect imgui.lua:15746 - [x] 92% ImGui::FindBestWindowPosForPopup imgui.lua:15769 + [x] 73% ImGui::IsPopupOpen imgui.lua:11881 + [x] 82% ImGui::GetTopMostPopupModal imgui.lua:11916 + [x] 81% ImGui::GetTopMostAndVisiblePopupModal imgui.lua:19456 + [x] 79% ImGui::FindBlockingModal imgui.lua:15765 + [x] 26% ImGui::OpenPopup imgui.lua:15798 + [x] 86% ImGui::OpenPopupEx imgui.lua:15819 + [x] 73% ImGui::ClosePopupsOverWindow imgui.lua:15882 + [x] 80% ImGui::ClosePopupsExceptModals imgui.lua:19522 + [x] 62% ImGui::ClosePopupToLevel imgui.lua:15940 + [x] 81% ImGui::CloseCurrentPopup imgui.lua:15976 + [x] 81% ImGui::BeginPopupEx imgui.lua:16016 + [x] 80% ImGui::BeginPopupMenuEx imgui.lua:16039 + [x] 83% ImGui::BeginPopup imgui.lua:16065 + [x] 83% ImGui::BeginPopupModal imgui.lua:19540 + [x] 95% ImGui::EndPopup imgui.lua:16078 + [x] 38% ImGui::GetMouseButtonFromPopupFlags imgui.lua:16299 + [x] 94% ImGui::IsPopupOpenRequestForItem imgui.lua:16311 + [x] 85% ImGui::IsPopupOpenRequestForWindow imgui.lua:19570 + [x] 83% ImGui::OpenPopupOnItemClick imgui.lua:16328 + [x] 83% ImGui::BeginPopupContextItem imgui.lua:16362 + [x] 85% ImGui::BeginPopupContextWindow imgui.lua:19584 + [x] 88% ImGui::BeginPopupContextVoid imgui.lua:19594 + [x] 87% ImGui::FindBestWindowPosForPopupEx imgui.lua:16115 + [x] 87% ImGui::GetPopupAllowedExtentRect imgui.lua:16208 + [x] 92% ImGui::FindBestWindowPosForPopup imgui.lua:16231 -- WINDOW FOCUS - [x] 51% ImGui::SetWindowFocus imgui.lua:11016 - [x] 71% ImGui::SetNextWindowFocus imgui.lua:11400 - [x] 87% ImGui::IsWindowFocused imgui.lua:14892 - [x] 94% ImGui::FindWindowFocusIndex imgui.lua:7203 - [x] 81% ImGui::UpdateWindowInFocusOrderList imgui.lua:7238 - [x] 82% ImGui::BringWindowToFocusFront imgui.lua:7263 - [x] 56% ImGui::BringWindowToDisplayFront imgui.lua:7289 - [x] 54% ImGui::BringWindowToDisplayBack imgui.lua:18955 - [x] 35% ImGui::BringWindowToDisplayBehind imgui.lua:7310 - [x] 41% ImGui::FindWindowDisplayIndex imgui.lua:18949 - [x] 87% ImGui::FocusWindow imgui.lua:7124 - [x] 84% ImGui::FocusTopMostWindowUnderOne imgui.lua:7322 + [x] 51% ImGui::SetWindowFocus imgui.lua:11352 + [x] 71% ImGui::SetNextWindowFocus imgui.lua:11741 + [x] 87% ImGui::IsWindowFocused imgui.lua:15345 + [x] 94% ImGui::FindWindowFocusIndex imgui.lua:7396 + [x] 81% ImGui::UpdateWindowInFocusOrderList imgui.lua:7431 + [x] 82% ImGui::BringWindowToFocusFront imgui.lua:7456 + [x] 56% ImGui::BringWindowToDisplayFront imgui.lua:7482 + [x] 54% ImGui::BringWindowToDisplayBack imgui.lua:19430 + [x] 35% ImGui::BringWindowToDisplayBehind imgui.lua:7503 + [x] 41% ImGui::FindWindowDisplayIndex imgui.lua:19424 + [x] 87% ImGui::FocusWindow imgui.lua:7317 + [x] 84% ImGui::FocusTopMostWindowUnderOne imgui.lua:7515 -- KEYBOARD/GAMEPAD NAVIGATION - [x] 93% ImGui::SetNavCursorVisible imgui.lua:19200 - [x] 94% ImGui::SetNavCursorVisibleAfterMove imgui.lua:16022 - [x] 80% ImGui::SetNavWindow imgui.lua:16038 - [x] 100% ImGui::NavHighlightActivated imgui.lua:16118 - [x] 100% ImGui::NavClearPreferredPosForAxis imgui.lua:16052 - [x] 95% ImGui::SetNavID imgui.lua:16061 - [x] 96% ImGui::SetFocusID imgui.lua:7362 - [x] 90% ImGetDirQuadrantFromDelta imgui.lua:17088 - [x] 100% NavScoreItemDistInterval imgui.lua:17095 - [x] 77% ImGui::NavScoreItem imgui.lua:17109 - [x] 93% ImGui::NavApplyItemToResult imgui.lua:17215 - [x] 100% ImGui::NavUpdateCurrentWindowIsScrollPushableX imgui.lua:17542 - [x] 94% ImGui::NavProcessItem imgui.lua:17307 - [x] 90% ImGui::NavProcessItemForTabbingRequest imgui.lua:17247 - [x] 100% ImGui::NavMoveRequestButNoResultYet imgui.lua:17083 - [x] 89% ImGui::NavMoveRequestSubmit imgui.lua:16561 - [x] 92% ImGui::NavMoveRequestResolveWithLastItem imgui.lua:17230 - [x] 92% ImGui::NavMoveRequestResolveWithPastTreeNode imgui.lua:17551 - [x] 93% ImGui::NavMoveRequestCancel imgui.lua:17562 - [x] 95% ImGui::NavMoveRequestForward imgui.lua:17574 - [x] 78% ImGui::NavMoveRequestTryWrapping imgui.lua:17589 - [x] 93% ImGui::NavSaveLastChildNavWindowIntoParent imgui.lua:16079 - [x] 57% ImGui::NavRestoreLastChildNavWindow imgui.lua:16092 - [x] 86% ImGui::NavRestoreLayer imgui.lua:16100 - [x] 100% ImGui::NavUpdateAnyRequestFlag imgui.lua:16124 - [x] 88% ImGui::NavInitWindow imgui.lua:16135 - [x] 97% ImGui::NavCalcPreferredRefPosSource imgui.lua:16167 - [x] 94% ImGui::NavCalcPreferredRefPos imgui.lua:16186 - [x] 91% ImGui::GetNavTweakPressedAmount imgui.lua:16228 - [x] 85% ImGui::NavUpdate imgui.lua:16830 - [x] 88% ImGui::NavInitRequestApplyResult imgui.lua:17381 - [x] 81% NavBiasScoringRect imgui.lua:16590 - [x] 83% ImGui::NavUpdateCreateMoveRequest imgui.lua:16691 - [x] 87% ImGui::NavUpdateCreateTabbingRequest imgui.lua:16801 - [x] 85% ImGui::NavMoveRequestApplyResult imgui.lua:17412 - [x] 91% ImGui::NavUpdateCancelRequest imgui.lua:17038 - [x] 83% ImGui::NavUpdateContextMenuRequest imgui.lua:16526 - [x] 90% ImGui::NavUpdatePageUpPageDown imgui.lua:16622 - [x] 81% ImGui::NavEndFrame imgui.lua:19335 - [x] 83% ImGui::NavUpdateCreateWrappingRequest imgui.lua:19279 - [x] 85% ImGui::IsWindowNavFocusable imgui.lua:7217 - [x] 67% FindWindowNavFocusable imgui.lua:7225 - [x] 86% NavUpdateWindowingTarget imgui.lua:16256 - [x] 92% ImGui::NavUpdateWindowingApplyFocus imgui.lua:16279 - [x] 88% ImGui::NavUpdateWindowing imgui.lua:16317 - [x] 67% GetFallbackWindowNameForWindowingList imgui.lua:19236 - [x] 84% ImGui::NavUpdateWindowingOverlay imgui.lua:19250 + [x] 93% ImGui::SetNavCursorVisible imgui.lua:19675 + [x] 94% ImGui::SetNavCursorVisibleAfterMove imgui.lua:16484 + [x] 80% ImGui::SetNavWindow imgui.lua:16500 + [x] 100% ImGui::NavHighlightActivated imgui.lua:16580 + [x] 100% ImGui::NavClearPreferredPosForAxis imgui.lua:16514 + [x] 95% ImGui::SetNavID imgui.lua:16523 + [x] 96% ImGui::SetFocusID imgui.lua:7555 + [x] 90% ImGetDirQuadrantFromDelta imgui.lua:17550 + [x] 100% NavScoreItemDistInterval imgui.lua:17557 + [x] 77% ImGui::NavScoreItem imgui.lua:17571 + [x] 93% ImGui::NavApplyItemToResult imgui.lua:17677 + [x] 100% ImGui::NavUpdateCurrentWindowIsScrollPushableX imgui.lua:18004 + [x] 94% ImGui::NavProcessItem imgui.lua:17769 + [x] 90% ImGui::NavProcessItemForTabbingRequest imgui.lua:17709 + [x] 100% ImGui::NavMoveRequestButNoResultYet imgui.lua:17545 + [x] 89% ImGui::NavMoveRequestSubmit imgui.lua:17023 + [x] 92% ImGui::NavMoveRequestResolveWithLastItem imgui.lua:17692 + [x] 92% ImGui::NavMoveRequestResolveWithPastTreeNode imgui.lua:18013 + [x] 93% ImGui::NavMoveRequestCancel imgui.lua:18024 + [x] 95% ImGui::NavMoveRequestForward imgui.lua:18036 + [x] 78% ImGui::NavMoveRequestTryWrapping imgui.lua:18051 + [x] 93% ImGui::NavSaveLastChildNavWindowIntoParent imgui.lua:16541 + [x] 57% ImGui::NavRestoreLastChildNavWindow imgui.lua:16554 + [x] 86% ImGui::NavRestoreLayer imgui.lua:16562 + [x] 100% ImGui::NavUpdateAnyRequestFlag imgui.lua:16586 + [x] 88% ImGui::NavInitWindow imgui.lua:16597 + [x] 97% ImGui::NavCalcPreferredRefPosSource imgui.lua:16629 + [x] 94% ImGui::NavCalcPreferredRefPos imgui.lua:16648 + [x] 91% ImGui::GetNavTweakPressedAmount imgui.lua:16690 + [x] 85% ImGui::NavUpdate imgui.lua:17292 + [x] 88% ImGui::NavInitRequestApplyResult imgui.lua:17843 + [x] 81% NavBiasScoringRect imgui.lua:17052 + [x] 83% ImGui::NavUpdateCreateMoveRequest imgui.lua:17153 + [x] 87% ImGui::NavUpdateCreateTabbingRequest imgui.lua:17263 + [x] 85% ImGui::NavMoveRequestApplyResult imgui.lua:17874 + [x] 91% ImGui::NavUpdateCancelRequest imgui.lua:17500 + [x] 83% ImGui::NavUpdateContextMenuRequest imgui.lua:16988 + [x] 90% ImGui::NavUpdatePageUpPageDown imgui.lua:17084 + [x] 81% ImGui::NavEndFrame imgui.lua:19810 + [x] 83% ImGui::NavUpdateCreateWrappingRequest imgui.lua:19754 + [x] 85% ImGui::IsWindowNavFocusable imgui.lua:7410 + [x] 67% FindWindowNavFocusable imgui.lua:7418 + [x] 86% NavUpdateWindowingTarget imgui.lua:16718 + [x] 92% ImGui::NavUpdateWindowingApplyFocus imgui.lua:16741 + [x] 88% ImGui::NavUpdateWindowing imgui.lua:16779 + [x] 67% GetFallbackWindowNameForWindowingList imgui.lua:19711 + [x] 84% ImGui::NavUpdateWindowingOverlay imgui.lua:19725 -- DRAG AND DROP - [x] 55% ImGui::IsDragDropActive imgui.lua:525 - [x] 73% ImGui::ClearDragDrop imgui.lua:529 - [x] 82% ImGui::BeginTooltipHidden imgui.lua:19132 - [x] 88% ImGui::BeginDragDropSource imgui.lua:547 - [x] 86% ImGui::EndDragDropSource imgui.lua:648 - [x] 62% ImGui::SetDragDropPayload imgui.lua:665 - [x] 92% ImGui::BeginDragDropTargetCustom imgui.lua:687 - [x] 89% ImGui::BeginDragDropTargetViewport imgui.lua:711 - [x] 87% ImGui::BeginDragDropTarget imgui.lua:734 - [x] 92% ImGui::IsDragDropPayloadBeingAccepted imgui.lua:760 - [x] 87% ImGui::AcceptDragDropPayload imgui.lua:766 - [x] 88% ImGui::RenderDragDropTargetRectForItem imgui.lua:807 - [x] 83% ImGui::RenderDragDropTargetRectForViewport imgui.lua:819 - [x] 95% ImGui::RenderDragDropTargetRectEx imgui.lua:828 - [x] 88% ImGui::GetDragDropPayload imgui.lua:835 - [x] 94% ImGui::EndDragDropTarget imgui.lua:840 + [x] 55% ImGui::IsDragDropActive imgui.lua:545 + [x] 73% ImGui::ClearDragDrop imgui.lua:549 + [x] 82% ImGui::BeginTooltipHidden imgui.lua:19607 + [x] 88% ImGui::BeginDragDropSource imgui.lua:567 + [x] 86% ImGui::EndDragDropSource imgui.lua:668 + [x] 62% ImGui::SetDragDropPayload imgui.lua:685 + [x] 92% ImGui::BeginDragDropTargetCustom imgui.lua:707 + [x] 89% ImGui::BeginDragDropTargetViewport imgui.lua:731 + [x] 87% ImGui::BeginDragDropTarget imgui.lua:754 + [x] 92% ImGui::IsDragDropPayloadBeingAccepted imgui.lua:780 + [x] 87% ImGui::AcceptDragDropPayload imgui.lua:786 + [x] 88% ImGui::RenderDragDropTargetRectForItem imgui.lua:827 + [x] 83% ImGui::RenderDragDropTargetRectForViewport imgui.lua:839 + [x] 95% ImGui::RenderDragDropTargetRectEx imgui.lua:848 + [x] 88% ImGui::GetDragDropPayload imgui.lua:855 + [x] 94% ImGui::EndDragDropTarget imgui.lua:860 -- LOGGING/CAPTURING - [x] 19% LogTextV imgui.lua:6098 = ImGui . LogText - [x] 45% ImGui::LogText imgui.lua:6093 - [x] 87% ImGui::LogTextV imgui.lua:6098 = ImGui . LogText - [x] 82% ImGui::LogRenderedText imgui.lua:6104 - [x] 83% ImGui::LogBegin imgui.lua:6152 - [x] 100% ImGui::LogSetNextTextDecoration imgui.lua:6168 - [x] 86% ImGui::LogToTTY imgui.lua:6174 - [~] 4% ImGui::LogToFile imgui.lua:6182 stub - [x] 90% ImGui::LogToClipboard imgui.lua:6188 - [x] 90% ImGui::LogToBuffer imgui.lua:6194 - [x] 73% ImGui::LogFinish imgui.lua:6200 - [x] 85% ImGui::LogButtons imgui.lua:6216 + [x] 19% LogTextV imgui.lua:6277 = ImGui . LogText + [x] 45% ImGui::LogText imgui.lua:6272 + [x] 87% ImGui::LogTextV imgui.lua:6277 = ImGui . LogText + [x] 82% ImGui::LogRenderedText imgui.lua:6283 + [x] 83% ImGui::LogBegin imgui.lua:6331 + [x] 100% ImGui::LogSetNextTextDecoration imgui.lua:6347 + [x] 86% ImGui::LogToTTY imgui.lua:6353 + [~] 4% ImGui::LogToFile imgui.lua:6361 stub + [x] 90% ImGui::LogToClipboard imgui.lua:6367 + [x] 90% ImGui::LogToBuffer imgui.lua:6373 + [x] 73% ImGui::LogFinish imgui.lua:6379 + [x] 85% ImGui::LogButtons imgui.lua:6395 -- SETTINGS - [x] 80% ImGui::UpdateSettings imgui.lua:5770 - [x] 82% ImGui::MarkIniSettingsDirty imgui.lua:5790 - [x] 58% ImGui::AddSettingsHandler imgui.lua:5799 - [x] 76% ImGui::RemoveSettingsHandler imgui.lua:5806 - [x] 90% ImGui::FindSettingsHandler imgui.lua:5812 - [x] 79% ImGui::ClearIniSettings imgui.lua:5822 - [x] 48% ImGui::CleanupIniSettings imgui.lua:5830 - [x] 27% ImGui::LoadIniSettingsFromDisk imgui.lua:5841 - [x] 50% ImGui::LoadIniSettingsFromMemory imgui.lua:5851 - [x] 33% ImGui::SaveIniSettingsToDisk imgui.lua:5894 - [x] 59% ImGui::SaveIniSettingsToMemory imgui.lua:5902 - [x] 51% ImGui::CreateNewWindowSettings imgui.lua:5913 - [x] 71% ImGui::FindWindowSettingsByID imgui.lua:5617 - [x] 92% ImGui::FindWindowSettingsByWindow imgui.lua:5605 - [x] 74% ImGui::ClearWindowSettings imgui.lua:5930 - [x] 88% WindowSettingsHandler_ClearAll imgui.lua:5944 - [ ] WindowSettingsHandler_Cleanup - [x] 75% WindowSettingsHandler_ReadOpen imgui.lua:5950 - [x] 41% WindowSettingsHandler_ReadLine imgui.lua:5966 - [x] 71% WindowSettingsHandler_ApplyAll imgui.lua:5990 - [x] 78% WindowSettingsHandler_WriteAll imgui.lua:6001 + [x] 80% ImGui::UpdateSettings imgui.lua:5933 + [x] 82% ImGui::MarkIniSettingsDirty imgui.lua:5953 + [x] 58% ImGui::AddSettingsHandler imgui.lua:5962 + [x] 76% ImGui::RemoveSettingsHandler imgui.lua:5969 + [x] 90% ImGui::FindSettingsHandler imgui.lua:5975 + [x] 79% ImGui::ClearIniSettings imgui.lua:5985 + [x] 48% ImGui::CleanupIniSettings imgui.lua:5993 + [x] 27% ImGui::LoadIniSettingsFromDisk imgui.lua:6004 + [x] 50% ImGui::LoadIniSettingsFromMemory imgui.lua:6014 + [x] 33% ImGui::SaveIniSettingsToDisk imgui.lua:6057 + [x] 59% ImGui::SaveIniSettingsToMemory imgui.lua:6065 + [x] 51% ImGui::CreateNewWindowSettings imgui.lua:6076 + [x] 71% ImGui::FindWindowSettingsByID imgui.lua:5780 + [x] 92% ImGui::FindWindowSettingsByWindow imgui.lua:5768 + [x] 74% ImGui::ClearWindowSettings imgui.lua:6093 + [x] 88% WindowSettingsHandler_ClearAll imgui.lua:6107 + [x] 78% WindowSettingsHandler_Cleanup imgui.lua:6115 + [x] 75% WindowSettingsHandler_ReadOpen imgui.lua:6128 + [x] 41% WindowSettingsHandler_ReadLine imgui.lua:6144 + [x] 71% WindowSettingsHandler_ApplyAll imgui.lua:6168 + [x] 78% WindowSettingsHandler_WriteAll imgui.lua:6179 -- LOCALIZATION - [x] 84% ImGui::LocalizeRegisterEntries imgui.lua:17615 + [x] 84% ImGui::LocalizeRegisterEntries imgui.lua:18077 -- VIEWPORTS, PLATFORM WINDOWS - [x] 83% ImGuiViewport::GetDebugName imgui.lua:17649 - [x] 76% ImGuiPlatformIO::ClearPlatformHandlers imgui.lua:17654 - [x] 69% ImGuiPlatformIO::ClearRendererHandlers imgui.lua:17668 - [x] 78% ImGui::GetMainViewport imgui.lua:17677 - [x] 88% ImGui::FindViewportByID imgui.lua:17686 - [ ] ImGui::FindViewportByPlatformHandle - [x] 98% ImGui::SetCurrentViewport imgui.lua:17698 - [x] 99% ImGui::SetWindowViewport imgui.lua:17726 - [x] 86% ImGui::GetWindowAlwaysWantOwnViewport imgui.lua:17739 - [x] 86% IsViewportAbove imgui.lua:17761 - [x] 89% ImGui::UpdateTryMergeWindowIntoHostViewport imgui.lua:17786 - [x] 83% ImGui::UpdateTryMergeWindowIntoHostViewports imgui.lua:17846 - [x] 88% ImGui::TranslateWindowsInViewport imgui.lua:17858 - [x] 94% ImGui::ScaleWindowsInViewport imgui.lua:14932 - [x] 85% ImGui::FindHoveredViewportFromPlatformWindowStack imgui.lua:17884 - [x] 87% ImGui::UpdateViewportsNewFrame imgui.lua:17901 - [x] 78% ImGui::UpdateViewportsEndFrame imgui.lua:18188 - [x] 84% ImGui::AddUpdateViewport imgui.lua:18222 - [x] 80% ImGui::DestroyViewport imgui.lua:18309 - [x] 93% ImGui::WindowSelectViewport imgui.lua:18335 - [x] 73% ImGui::WindowSyncOwnedViewport imgui.lua:18461 - [x] 88% ImGui::UpdatePlatformWindows imgui.lua:18565 - [x] 85% ImGui::RenderPlatformWindowsDefault imgui.lua:18683 - [x] 87% ImGui::FindPlatformMonitorForPos imgui.lua:18715 - [x] 78% ImGui::FindPlatformMonitorForRect imgui.lua:18731 - [x] 93% ImGui::UpdateViewportPlatformMonitor imgui.lua:18772 - [x] 89% ImGui::GetViewportPlatformMonitor imgui.lua:18779 - [x] 97% ImGui::DestroyPlatformWindow imgui.lua:18791 - [x] 77% ImGui::DestroyPlatformWindows imgui.lua:18817 + [x] 83% ImGuiViewport::GetDebugName imgui.lua:18111 + [x] 76% ImGuiPlatformIO::ClearPlatformHandlers imgui.lua:18116 + [x] 69% ImGuiPlatformIO::ClearRendererHandlers imgui.lua:18131 + [x] 78% ImGui::GetMainViewport imgui.lua:18140 + [x] 88% ImGui::FindViewportByID imgui.lua:18149 + [x] 88% ImGui::FindViewportByPlatformHandle imgui.lua:18161 + [x] 98% ImGui::SetCurrentViewport imgui.lua:18173 + [x] 99% ImGui::SetWindowViewport imgui.lua:18201 + [x] 86% ImGui::GetWindowAlwaysWantOwnViewport imgui.lua:18214 + [x] 86% IsViewportAbove imgui.lua:18236 + [x] 89% ImGui::UpdateTryMergeWindowIntoHostViewport imgui.lua:18261 + [x] 83% ImGui::UpdateTryMergeWindowIntoHostViewports imgui.lua:18321 + [x] 88% ImGui::TranslateWindowsInViewport imgui.lua:18333 + [x] 94% ImGui::ScaleWindowsInViewport imgui.lua:15385 + [x] 85% ImGui::FindHoveredViewportFromPlatformWindowStack imgui.lua:18359 + [x] 87% ImGui::UpdateViewportsNewFrame imgui.lua:18376 + [x] 78% ImGui::UpdateViewportsEndFrame imgui.lua:18663 + [x] 84% ImGui::AddUpdateViewport imgui.lua:18697 + [x] 80% ImGui::DestroyViewport imgui.lua:18784 + [x] 93% ImGui::WindowSelectViewport imgui.lua:18810 + [x] 73% ImGui::WindowSyncOwnedViewport imgui.lua:18936 + [x] 88% ImGui::UpdatePlatformWindows imgui.lua:19040 + [x] 85% ImGui::RenderPlatformWindowsDefault imgui.lua:19158 + [x] 87% ImGui::FindPlatformMonitorForPos imgui.lua:19190 + [x] 78% ImGui::FindPlatformMonitorForRect imgui.lua:19206 + [x] 93% ImGui::UpdateViewportPlatformMonitor imgui.lua:19247 + [x] 89% ImGui::GetViewportPlatformMonitor imgui.lua:19254 + [x] 97% ImGui::DestroyPlatformWindow imgui.lua:19266 + [x] 77% ImGui::DestroyPlatformWindows imgui.lua:19292 -- DOCKING - [x] 61% ImGuiDockRequest::ImGuiDockRequest imgui.lua:1019 - [x] 67% ImGuiDockPreviewData::ImGuiDockPreviewData imgui.lua:1108 - [x] 23% ImGuiDockNodeSettings::ImGuiDockNodeSettings imgui.lua:1032 - [x] 53% DockNodeGetHostWindowTitle imgui.lua:1121 - [x] 96% ImGui::DockContextInitialize imgui.lua:1172 - [x] 26% ImGui::DockContextShutdown imgui.lua:1190 - [x] 67% ImGui::DockContextClearNodes imgui.lua:1197 - [x] 87% ImGui::DockContextRebuildNodes imgui.lua:1204 - [x] 70% ImGui::DockContextNewFrameUpdateUndocking imgui.lua:1214 - [x] 71% ImGui::DockContextNewFrameUpdateDocking imgui.lua:1252 - [x] 76% ImGui::DockContextEndFrame imgui.lua:1287 - [x] 82% ImGui::DockContextFindNodeByID imgui.lua:1302 - [x] 84% ImGui::DockContextGenNodeID imgui.lua:1306 - [x] 82% ImGui::DockContextAddNode imgui.lua:1315 - [x] 87% ImGui::DockContextRemoveNode imgui.lua:1329 - [x] 69% ImGui::DockContextDeleteNode imgui.lua:1353 - [ ] DockNodeComparerDepthMostFirst - [ ] ImGuiDockContextPruneNodeData::ImGuiDockContextPruneNodeData - [x] 58% ImGui::DockContextPruneUnusedSettingsNodes imgui.lua:1360 - [x] 85% ImGui::DockContextBuildNodesFromSettings imgui.lua:1435 - [x] 85% ImGui::DockContextBuildAddWindowsToNodes imgui.lua:1465 - [x] 96% ImGui::DockContextQueueDock imgui.lua:1492 - [x] 91% ImGui::DockContextQueueUndockWindow imgui.lua:1505 - [x] 91% ImGui::DockContextQueueUndockNode imgui.lua:1512 - [x] 73% ImGui::DockContextQueueNotifyRemovedNode imgui.lua:1519 - [x] 88% ImGui::DockContextProcessDock imgui.lua:1525 - [x] 50% FixLargeWindowsWhenUndocking imgui.lua:1650 - [x] 71% ImGui::DockContextProcessUndockWindow imgui.lua:1656 - [x] 84% ImGui::DockContextProcessUndockNode imgui.lua:1673 - [x] 69% ImGui::DockContextCalcDropPosForDocking imgui.lua:1709 - [x] 64% ImGuiDockNode::ImGuiDockNode imgui.lua:1049 + [x] 61% ImGuiDockRequest::ImGuiDockRequest imgui.lua:1039 + [x] 67% ImGuiDockPreviewData::ImGuiDockPreviewData imgui.lua:1128 + [x] 23% ImGuiDockNodeSettings::ImGuiDockNodeSettings imgui.lua:1052 + [x] 53% DockNodeGetHostWindowTitle imgui.lua:1141 + [x] 96% ImGui::DockContextInitialize imgui.lua:1192 + [x] 26% ImGui::DockContextShutdown imgui.lua:1210 + [x] 67% ImGui::DockContextClearNodes imgui.lua:1217 + [x] 87% ImGui::DockContextRebuildNodes imgui.lua:1224 + [x] 70% ImGui::DockContextNewFrameUpdateUndocking imgui.lua:1234 + [x] 71% ImGui::DockContextNewFrameUpdateDocking imgui.lua:1272 + [x] 76% ImGui::DockContextEndFrame imgui.lua:1307 + [x] 82% ImGui::DockContextFindNodeByID imgui.lua:1322 + [x] 84% ImGui::DockContextGenNodeID imgui.lua:1326 + [x] 82% ImGui::DockContextAddNode imgui.lua:1335 + [x] 87% ImGui::DockContextRemoveNode imgui.lua:1349 + [x] 69% ImGui::DockContextDeleteNode imgui.lua:1373 + [x] 33% DockNodeComparerDepthMostFirst imgui.lua:3754 + [x] 77% ImGuiDockContextPruneNodeData::ImGuiDockContextPruneNodeData imgui.lua:1380 + [x] 62% ImGui::DockContextPruneUnusedSettingsNodes imgui.lua:1385 + [x] 85% ImGui::DockContextBuildNodesFromSettings imgui.lua:1460 + [x] 85% ImGui::DockContextBuildAddWindowsToNodes imgui.lua:1490 + [x] 96% ImGui::DockContextQueueDock imgui.lua:1517 + [x] 91% ImGui::DockContextQueueUndockWindow imgui.lua:1530 + [x] 91% ImGui::DockContextQueueUndockNode imgui.lua:1537 + [x] 73% ImGui::DockContextQueueNotifyRemovedNode imgui.lua:1544 + [x] 88% ImGui::DockContextProcessDock imgui.lua:1550 + [x] 50% FixLargeWindowsWhenUndocking imgui.lua:1675 + [x] 71% ImGui::DockContextProcessUndockWindow imgui.lua:1681 + [x] 84% ImGui::DockContextProcessUndockNode imgui.lua:1698 + [x] 69% ImGui::DockContextCalcDropPosForDocking imgui.lua:1734 + [x] 64% ImGuiDockNode::ImGuiDockNode imgui.lua:1069 [-] ImGuiDockNode::~ImGuiDockNode c++-only - [x] 91% ImGui::DockNodeGetTabOrder imgui.lua:1757 - [x] 90% DockNodeHideWindowDuringHostWindowCreation imgui.lua:1764 - [x] 91% ImGui::DockNodeAddWindow imgui.lua:1769 - [x] 83% ImGui::DockNodeRemoveWindow imgui.lua:1822 - [x] 94% ImGui::DockNodeMoveChildNodes imgui.lua:1877 - [x] 88% ImGui::DockNodeMoveWindows imgui.lua:1889 - [x] 89% ImGui::DockNodeApplyPosSizeToWindows imgui.lua:1919 - [x] 92% ImGui::DockNodeHideHostWindow imgui.lua:1926 - [ ] ImGuiDockNodeTreeInfo::ImGuiDockNodeTreeInfo - [x] 93% DockNodeFindInfo imgui.lua:1939 - [x] 90% ImGui::DockNodeFindWindowByID imgui.lua:1954 - [x] 87% ImGui::DockNodeUpdateFlagsAndCollapse imgui.lua:1964 - [x] 96% ImGui::DockNodeUpdateHasCentralNodeChild imgui.lua:2040 - [x] 79% ImGui::DockNodeUpdateVisibleFlag imgui.lua:2053 - [x] 92% ImGui::DockNodeStartMouseMovingWindow imgui.lua:2062 - [x] 86% ImGui::DockNodeUpdateForRootNode imgui.lua:2072 - [x] 100% DockNodeSetupHostWindow imgui.lua:2108 - [x] 86% ImGui::DockNodeUpdate imgui.lua:2121 - [x] 68% TabItemComparerByDockOrder imgui.lua:2415 - [x] 86% ImGui::DockNodeWindowMenuHandler_Default imgui.lua:2428 - [x] 94% ImGui::DockNodeWindowMenuUpdate imgui.lua:2449 - [x] 95% ImGui::DockNodeBeginAmendTabBar imgui.lua:2465 - [x] 75% ImGui::DockNodeEndAmendTabBar imgui.lua:2476 - [x] 77% IsDockNodeTitleBarHighlighted imgui.lua:2482 - [x] 81% ImGui::DockNodeUpdateTabBar imgui.lua:2507 - [x] 96% ImGui::DockNodeAddTabBar imgui.lua:2765 - [x] 86% ImGui::DockNodeRemoveTabBar imgui.lua:2770 - [x] 92% DockNodeIsDropAllowedOne imgui.lua:2775 - [x] 86% ImGui::DockNodeIsDropAllowed imgui.lua:2804 - [x] 83% ImGui::DockNodeCalcTabBarLayout imgui.lua:2817 - [x] 77% ImGui::DockNodeCalcSplitRects imgui.lua:2846 - [x] 85% ImGui::DockNodeCalcDropRectsAndTestMousePos imgui.lua:2882 - [x] 84% ImGui::DockNodePreviewDockSetup imgui.lua:2932 - [x] 79% ImGui::DockNodePreviewDockRender imgui.lua:3019 - [x] 83% ImGui::DockNodeTreeSplit imgui.lua:3139 - [x] 78% ImGui::DockNodeTreeMerge imgui.lua:3186 - [x] 74% ImGui::DockNodeTreeUpdatePosSize imgui.lua:3228 - [x] 96% DockNodeTreeUpdateSplitterFindTouchingNode imgui.lua:3304 - [x] 76% ImGui::DockNodeTreeUpdateSplitter imgui.lua:3324 - [x] 85% ImGui::DockNodeTreeFindFallbackLeafNode imgui.lua:3410 - [x] 80% ImGui::DockNodeTreeFindVisibleNodeByPos imgui.lua:3419 - [x] 87% ImGui::SetWindowDock imgui.lua:3443 - [x] 79% ImGui::DockSpace imgui.lua:3474 - [x] 76% ImGui::DockSpaceOverViewport imgui.lua:3576 - [x] 89% ImGui::DockBuilderDockWindow imgui.lua:3639 - [x] 57% ImGui::DockBuilderGetNode imgui.lua:3657 - [x] 76% ImGui::DockBuilderSetNodePos imgui.lua:3667 - [x] 78% ImGui::DockBuilderSetNodeSize imgui.lua:3674 - [x] 74% ImGui::DockBuilderAddNode imgui.lua:3690 - [x] 87% ImGui::DockBuilderRemoveNode imgui.lua:3708 - [x] 63% ImGui::DockBuilderRemoveNodeChildNodes imgui.lua:3724 - [x] 84% ImGui::DockBuilderRemoveNodeDockedWindows imgui.lua:3792 - [x] 79% ImGui::DockBuilderSplitNode imgui.lua:3823 - [x] 75% DockBuilderCopyNodeRec imgui.lua:3849 - [x] 82% ImGui::DockBuilderCopyNode imgui.lua:3874 - [x] 76% ImGui::DockBuilderCopyWindowSettings imgui.lua:3890 - [x] 66% ImGui::DockBuilderCopyDockSpace imgui.lua:3917 - [x] 50% ImGui::DockBuilderFinish imgui.lua:3989 - [x] 89% ImGui::GetWindowAlwaysWantOwnTabBar imgui.lua:4004 - [x] 95% ImGui::DockContextBindNodeToWindow imgui.lua:4014 - [x] 84% StoreDockStyleForWindow imgui.lua:4062 = StoreDockStyleForWindow - [x] 88% ImGui::BeginDocked imgui.lua:4065 - [x] 89% ImGui::BeginDockableDragDropSource imgui.lua:4178 - [x] 91% ImGui::BeginDockableDragDropTarget imgui.lua:4207 - [x] 62% ImGui::DockSettingsRenameNodeReferences imgui.lua:4302 - [x] 68% ImGui::DockSettingsRemoveNodeReferences imgui.lua:4315 - [x] 46% ImGui::DockSettingsFindNodeSettings imgui.lua:4332 - [x] 91% ImGui::DockSettingsHandler_ClearAll imgui.lua:4341 - [x] 93% ImGui::DockSettingsHandler_ApplyAll imgui.lua:4348 - [x] 63% ImGui::DockSettingsHandler_ReadOpen imgui.lua:4356 - [x] 32% ImGui::DockSettingsHandler_ReadLine imgui.lua:4361 - [x] 80% DockSettingsHandler_DockNodeToSettings imgui.lua:4425 - [x] 52% ImGui::DockSettingsHandler_WriteAll imgui.lua:4442 + [x] 91% ImGui::DockNodeGetTabOrder imgui.lua:1782 + [x] 90% DockNodeHideWindowDuringHostWindowCreation imgui.lua:1789 + [x] 91% ImGui::DockNodeAddWindow imgui.lua:1794 + [x] 83% ImGui::DockNodeRemoveWindow imgui.lua:1847 + [x] 94% ImGui::DockNodeMoveChildNodes imgui.lua:1902 + [x] 88% ImGui::DockNodeMoveWindows imgui.lua:1914 + [x] 89% ImGui::DockNodeApplyPosSizeToWindows imgui.lua:1944 + [x] 92% ImGui::DockNodeHideHostWindow imgui.lua:1951 + [x] 24% ImGuiDockNodeTreeInfo::ImGuiDockNodeTreeInfo imgui.lua:1963 + [x] 93% DockNodeFindInfo imgui.lua:1968 + [x] 90% ImGui::DockNodeFindWindowByID imgui.lua:1983 + [x] 87% ImGui::DockNodeUpdateFlagsAndCollapse imgui.lua:1993 + [x] 96% ImGui::DockNodeUpdateHasCentralNodeChild imgui.lua:2069 + [x] 79% ImGui::DockNodeUpdateVisibleFlag imgui.lua:2082 + [x] 92% ImGui::DockNodeStartMouseMovingWindow imgui.lua:2091 + [x] 89% ImGui::DockNodeUpdateForRootNode imgui.lua:2101 + [x] 100% DockNodeSetupHostWindow imgui.lua:2137 + [x] 86% ImGui::DockNodeUpdate imgui.lua:2150 + [x] 68% TabItemComparerByDockOrder imgui.lua:2444 + [x] 86% ImGui::DockNodeWindowMenuHandler_Default imgui.lua:2457 + [x] 94% ImGui::DockNodeWindowMenuUpdate imgui.lua:2478 + [x] 95% ImGui::DockNodeBeginAmendTabBar imgui.lua:2494 + [x] 75% ImGui::DockNodeEndAmendTabBar imgui.lua:2505 + [x] 77% IsDockNodeTitleBarHighlighted imgui.lua:2511 + [x] 81% ImGui::DockNodeUpdateTabBar imgui.lua:2536 + [x] 96% ImGui::DockNodeAddTabBar imgui.lua:2794 + [x] 86% ImGui::DockNodeRemoveTabBar imgui.lua:2799 + [x] 92% DockNodeIsDropAllowedOne imgui.lua:2804 + [x] 86% ImGui::DockNodeIsDropAllowed imgui.lua:2833 + [x] 83% ImGui::DockNodeCalcTabBarLayout imgui.lua:2846 + [x] 77% ImGui::DockNodeCalcSplitRects imgui.lua:2875 + [x] 85% ImGui::DockNodeCalcDropRectsAndTestMousePos imgui.lua:2911 + [x] 84% ImGui::DockNodePreviewDockSetup imgui.lua:2961 + [x] 79% ImGui::DockNodePreviewDockRender imgui.lua:3048 + [x] 83% ImGui::DockNodeTreeSplit imgui.lua:3168 + [x] 78% ImGui::DockNodeTreeMerge imgui.lua:3215 + [x] 74% ImGui::DockNodeTreeUpdatePosSize imgui.lua:3257 + [x] 96% DockNodeTreeUpdateSplitterFindTouchingNode imgui.lua:3333 + [x] 76% ImGui::DockNodeTreeUpdateSplitter imgui.lua:3353 + [x] 85% ImGui::DockNodeTreeFindFallbackLeafNode imgui.lua:3439 + [x] 80% ImGui::DockNodeTreeFindVisibleNodeByPos imgui.lua:3448 + [x] 87% ImGui::SetWindowDock imgui.lua:3472 + [x] 79% ImGui::DockSpace imgui.lua:3503 + [x] 76% ImGui::DockSpaceOverViewport imgui.lua:3605 + [x] 89% ImGui::DockBuilderDockWindow imgui.lua:3668 + [x] 57% ImGui::DockBuilderGetNode imgui.lua:3686 + [x] 76% ImGui::DockBuilderSetNodePos imgui.lua:3696 + [x] 78% ImGui::DockBuilderSetNodeSize imgui.lua:3703 + [x] 74% ImGui::DockBuilderAddNode imgui.lua:3719 + [x] 87% ImGui::DockBuilderRemoveNode imgui.lua:3737 + [x] 69% ImGui::DockBuilderRemoveNodeChildNodes imgui.lua:3759 + [x] 84% ImGui::DockBuilderRemoveNodeDockedWindows imgui.lua:3825 + [x] 79% ImGui::DockBuilderSplitNode imgui.lua:3856 + [x] 75% DockBuilderCopyNodeRec imgui.lua:3882 + [x] 82% ImGui::DockBuilderCopyNode imgui.lua:3907 + [x] 76% ImGui::DockBuilderCopyWindowSettings imgui.lua:3923 + [x] 66% ImGui::DockBuilderCopyDockSpace imgui.lua:3950 + [x] 50% ImGui::DockBuilderFinish imgui.lua:4022 + [x] 89% ImGui::GetWindowAlwaysWantOwnTabBar imgui.lua:4037 + [x] 95% ImGui::DockContextBindNodeToWindow imgui.lua:4047 + [x] 84% StoreDockStyleForWindow imgui.lua:4095 = StoreDockStyleForWindow + [x] 88% ImGui::BeginDocked imgui.lua:4098 + [x] 89% ImGui::BeginDockableDragDropSource imgui.lua:4211 + [x] 91% ImGui::BeginDockableDragDropTarget imgui.lua:4240 + [x] 62% ImGui::DockSettingsRenameNodeReferences imgui.lua:4335 + [x] 68% ImGui::DockSettingsRemoveNodeReferences imgui.lua:4348 + [x] 46% ImGui::DockSettingsFindNodeSettings imgui.lua:4365 + [x] 91% ImGui::DockSettingsHandler_ClearAll imgui.lua:4374 + [x] 93% ImGui::DockSettingsHandler_ApplyAll imgui.lua:4381 + [x] 63% ImGui::DockSettingsHandler_ReadOpen imgui.lua:4389 + [x] 32% ImGui::DockSettingsHandler_ReadLine imgui.lua:4394 + [x] 80% DockSettingsHandler_DockNodeToSettings imgui.lua:4458 + [x] 52% ImGui::DockSettingsHandler_WriteAll imgui.lua:4475 -- PLATFORM DEPENDENT HELPERS [-] Platform_SetClipboardTextFn_DefaultImpl os-specific [-] Platform_GetClipboardTextFn_DefaultImpl os-specific - [ ] Platform_OpenInShellFn_DefaultImpl + [~] 8% Platform_OpenInShellFn_DefaultImpl imgui.lua:5677 stub [-] Platform_SetImeDataFn_DefaultImpl os-specific - [ ] InitializeDefaultPlatformHandlers + [x] 40% InitializeDefaultPlatformHandlers imgui.lua:5680 -- METRICS/DEBUGGER WINDOW - [x] 97% MetricsHelpMarker imgui.lua:20091 = MetricsHelpMarker - [x] 93% ImGui::DebugRenderViewportThumbnail imgui.lua:18840 - [x] 92% RenderViewportsThumbnails imgui.lua:18879 - [ ] ViewportComparerByLastFocusedStampCount - [ ] ImGui::DebugRenderKeyboardPreview - [x] 52% ImGui::DebugTextEncoding imgui.lua:20998 - [ ] DebugFlashStyleColorStop - [ ] ImGui::DebugFlashStyleColor - [ ] ImGui::UpdateDebugToolFlashStyleColor - [ ] ImGui::DebugTextureIDToU64 - [ ] FormatTextureRefForDebugDisplay - [x] 52% ImGui::ShowFontAtlas imgui.lua:20292 - [x] 84% ImGui::DebugNodeTexture imgui.lua:20259 - [x] 44% ImGui::ShowMetricsWindow imgui.lua:21063 - [ ] ImGui::DebugBreakClearData - [ ] ImGui::DebugBreakButtonTooltip - [ ] ImGui::DebugBreakButton - [x] 87% ImGui::DebugNodeColumns imgui.lua:20637 - [x] 48% DebugNodeDockNodeFlags imgui.lua:20830 - [x] 79% ImGui::DebugNodeDockNode imgui.lua:20847 - [x] 23% ImGui::DebugNodeDrawList imgui.lua:20659 - [ ] ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox - [ ] CalcFontGlyphSrcOverlapMask - [x] 60% ImGui::DebugNodeFont imgui.lua:20182 - [x] 59% ImGui::DebugNodeFontGlyphsForSrcMask imgui.lua:20127 - [x] 89% ImGui::DebugNodeFontGlyph imgui.lua:20113 - [x] 37% ImGui::DebugNodeStorage imgui.lua:20647 - [x] 69% ImGui::DebugNodeTabBar imgui.lua:20725 - [x] 62% ImGui::DebugNodeViewport imgui.lua:20980 - [ ] ImGui::DebugNodePlatformMonitor - [x] 70% ImGui::DebugNodeWindow imgui.lua:20891 - [x] 87% ImGui::DebugNodeWindowSettings imgui.lua:20949 - [x] 73% ImGui::DebugNodeWindowsList imgui.lua:20955 - [x] 67% ImGui::DebugNodeWindowsListByBeginStackParent imgui.lua:20966 + [x] 97% MetricsHelpMarker imgui.lua:20680 = MetricsHelpMarker + [x] 93% ImGui::DebugRenderViewportThumbnail imgui.lua:19315 + [x] 92% RenderViewportsThumbnails imgui.lua:19354 + [x] 54% ViewportComparerByLastFocusedStampCount imgui.lua:20687 + [x] 91% ImGui::DebugRenderKeyboardPreview imgui.lua:20693 + [x] 52% ImGui::DebugTextEncoding imgui.lua:21985 + [x] 81% DebugFlashStyleColorStop imgui.lua:20742 + [x] 94% ImGui::DebugFlashStyleColor imgui.lua:20752 + [x] 49% ImGui::UpdateDebugToolFlashStyleColor imgui.lua:20760 + [~] 12% ImGui::DebugTextureIDToU64 imgui.lua:20777 stub + [x] 37% FormatTextureRefForDebugDisplay imgui.lua:20783 + [x] 52% ImGui::ShowFontAtlas imgui.lua:21041 + [x] 85% ImGui::DebugNodeTexture imgui.lua:21008 + [x] 48% ImGui::ShowMetricsWindow imgui.lua:22050 + [x] 100% ImGui::DebugBreakClearData imgui.lua:22468 + [x] 81% ImGui::DebugBreakButtonTooltip imgui.lua:22478 + [x] 81% ImGui::DebugBreakButton imgui.lua:22495 + [x] 87% ImGui::DebugNodeColumns imgui.lua:21541 + [x] 48% DebugNodeDockNodeFlags imgui.lua:21801 + [x] 79% ImGui::DebugNodeDockNode imgui.lua:21818 + [x] 70% ImGui::DebugNodeDrawList imgui.lua:21564 + [x] 74% ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox imgui.lua:21664 + [x] 63% CalcFontGlyphSrcOverlapMask imgui.lua:20884 + [x] 69% ImGui::DebugNodeFont imgui.lua:20898 + [x] 59% ImGui::DebugNodeFontGlyphsForSrcMask imgui.lua:20827 + [x] 89% ImGui::DebugNodeFontGlyph imgui.lua:20813 + [x] 37% ImGui::DebugNodeStorage imgui.lua:21551 + [x] 69% ImGui::DebugNodeTabBar imgui.lua:21696 + [x] 62% ImGui::DebugNodeViewport imgui.lua:21957 + [x] 100% ImGui::DebugNodePlatformMonitor imgui.lua:21977 + [x] 72% ImGui::DebugNodeWindow imgui.lua:21862 + [x] 87% ImGui::DebugNodeWindowSettings imgui.lua:21926 + [x] 73% ImGui::DebugNodeWindowsList imgui.lua:21932 + [x] 67% ImGui::DebugNodeWindowsListByBeginStackParent imgui.lua:21943 -- DEBUG LOG WINDOW - [x] 5% ImGui::DebugLog imgui.lua:19932 - [ ] ImGui::DebugLogV - [x] 93% SameLineOrWrap imgui.lua:20364 - [x] 61% ShowDebugLogFlag imgui.lua:20371 - [x] 65% ImGui::ShowDebugLogWindow imgui.lua:20384 - [ ] ImGui::DebugTextUnformattedWithLocateItem + [x] 38% ImGui::DebugLog imgui.lua:20500 + [x] 35% ImGui::DebugLogV imgui.lua:20505 + [x] 93% SameLineOrWrap imgui.lua:21113 + [x] 61% ShowDebugLogFlag imgui.lua:21120 + [x] 65% ImGui::ShowDebugLogWindow imgui.lua:21133 + [x] 61% ImGui::DebugTextUnformattedWithLocateItem imgui.lua:21190 -- OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) - [ ] ImGui::DebugDrawCursorPos - [ ] ImGui::DebugDrawLineExtents - [ ] ImGui::DebugDrawItemRect - [ ] ImGui::DebugLocateItem - [ ] ImGui::DebugLocateItemOnHover - [ ] ImGui::DebugLocateItemResolveWithLastItem - [ ] ImGui::DebugStartItemPicker - [ ] ImGui::UpdateDebugToolItemPicker - [x] 75% DebugItemPathQuery_UpdateAndGetHookId imgui.lua:20455 - [x] 49% ImGui::UpdateDebugToolItemPathQuery imgui.lua:20484 - [x] 47% ImGui::DebugHookIdInfo imgui.lua:20496 - [ ] DebugItemPathQuery_FormatLevelInfo - [ ] DebugItemPathQuery_GetResultAsPath - [x] 51% ImGui::ShowIDStackToolWindow imgui.lua:20555 - [x] 78% ImGui::ShowFontSelector imgui.lua:20097 + [x] 88% ImGui::DebugDrawCursorPos imgui.lua:21223 + [x] 90% ImGui::DebugDrawLineExtents imgui.lua:21234 + [x] 78% ImGui::DebugDrawItemRect imgui.lua:21248 + [x] 100% ImGui::DebugLocateItem imgui.lua:21259 + [x] 94% ImGui::DebugLocateItemOnHover imgui.lua:21268 + [x] 84% ImGui::DebugLocateItemResolveWithLastItem imgui.lua:21285 + [x] 100% ImGui::DebugStartItemPicker imgui.lua:21304 + [x] 88% ImGui::UpdateDebugToolItemPicker imgui.lua:21310 + [x] 75% DebugItemPathQuery_UpdateAndGetHookId imgui.lua:21359 + [x] 49% ImGui::UpdateDebugToolItemPathQuery imgui.lua:21388 + [x] 47% ImGui::DebugHookIdInfo imgui.lua:21400 + [x] 52% DebugItemPathQuery_FormatLevelInfo imgui.lua:21435 + [x] 32% DebugItemPathQuery_GetResultAsPath imgui.lua:21444 + [x] 74% ImGui::ShowIDStackToolWindow imgui.lua:21459 + [x] 78% ImGui::ShowFontSelector imgui.lua:20797 ==================================================================================================== imgui_widgets.cpp @@ -915,17 +915,17 @@ imgui_widgets.cpp [x] 29% ImGui::Text imgui_widgets.lua:222 [x] 60% ImGui::TextV imgui_widgets.lua:208 [x] 30% ImGui::TextColored imgui_widgets.lua:233 - [x] 83% ImGui::TextColoredV imgui_widgets.lua:7430 = ImGui . TextColored(...) + [x] 83% ImGui::TextColoredV imgui_widgets.lua:7542 = ImGui . TextColored(...) [x] 17% ImGui::TextDisabled imgui_widgets.lua:241 - [x] 89% ImGui::TextDisabledV imgui_widgets.lua:7431 = ImGui . TextDisabled(...) + [x] 89% ImGui::TextDisabledV imgui_widgets.lua:7543 = ImGui . TextDisabled(...) [x] 10% ImGui::TextWrapped imgui_widgets.lua:250 - [x] 91% ImGui::TextWrappedV imgui_widgets.lua:7432 = ImGui . TextWrapped(...) + [x] 91% ImGui::TextWrappedV imgui_widgets.lua:7544 = ImGui . TextWrapped(...) [x] 2% ImGui::TextAligned imgui_widgets.lua:269 - [x] 67% ImGui::TextAlignedV imgui_widgets.lua:7433 = ImGui . TextAligned(...) + [x] 67% ImGui::TextAlignedV imgui_widgets.lua:7545 = ImGui . TextAligned(...) [x] 4% ImGui::LabelText imgui_widgets.lua:305 - [x] 89% ImGui::LabelTextV imgui_widgets.lua:7434 = ImGui . LabelText(...) + [x] 89% ImGui::LabelTextV imgui_widgets.lua:7546 = ImGui . LabelText(...) [x] 2% ImGui::BulletText imgui_widgets.lua:340 - [x] 77% ImGui::BulletTextV imgui_widgets.lua:7435 = ImGui . BulletText(...) + [x] 77% ImGui::BulletTextV imgui_widgets.lua:7547 = ImGui . BulletText(...) -- Widgets: Main [x] 85% ImGui::ButtonBehavior imgui_widgets.lua:488 @@ -936,7 +936,7 @@ imgui_widgets.cpp [x] 87% ImGui::ArrowButtonEx imgui_widgets.lua:859 [x] 97% ImGui::ArrowButton imgui_widgets.lua:891 [x] 80% ImGui::CloseButton imgui_widgets.lua:900 - [x] 90% ImGui::CollapseButton imgui.lua:4558 + [x] 90% ImGui::CollapseButton imgui.lua:4591 [x] 52% ImGui::GetWindowScrollbarID imgui_widgets.lua:950 [x] 90% ImGui::GetWindowScrollbarRect imgui_widgets.lua:963 [x] 99% ImGui::ExtendHitBoxWhenNearViewportEdge imgui_widgets.lua:986 @@ -964,9 +964,9 @@ imgui_widgets.cpp [x] 87% ImGui::Separator imgui_widgets.lua:1802 [x] 96% ImGui::SeparatorTextEx imgui_widgets.lua:1829 [x] 100% ImGui::SeparatorText imgui_widgets.lua:1890 - [x] 82% ImGui::SplitterBehavior imgui.lua:4592 - [ ] ShrinkWidthItemComparer - [x] 58% ImGui::ShrinkWidths imgui_widgets.lua:10683 + [x] 82% ImGui::SplitterBehavior imgui.lua:4625 + [x] 41% ShrinkWidthItemComparer imgui_widgets.lua:10816 + [x] 61% ImGui::ShrinkWidths imgui_widgets.lua:10824 -- Widgets: ComboBox [x] 100% CalcMaxPopupHeightFromItemCount imgui_widgets.lua:1919 @@ -990,278 +990,278 @@ imgui_widgets.cpp [x] 42% ImGui::DataTypeClamp imgui_widgets.lua:2548 [x] 93% ImGui::DataTypeIsZero imgui_widgets.lua:2564 [x] 53% GetMinimumStepAtDecimalPrecision imgui_widgets.lua:2575 - [x] 58% ImGui::RoundScalarWithFormatT imgui_widgets.lua:2593 + [x] 56% ImGui::RoundScalarWithFormatT imgui_widgets.lua:2593 -- Widgets: DragScalar, DragFloat, DragInt, etc. - [x] 85% ImGui::DragBehaviorT imgui_widgets.lua:3146 - [ ] ShortcutsForCancel - [x] 59% ImGui::DragBehavior imgui_widgets.lua:3302 - [x] 74% TempInputIsClampEnabled imgui_widgets.lua:3349 - [x] 75% ImGui::DragScalar imgui_widgets.lua:3392 - [x] 70% ImGui::DragScalarN imgui_widgets.lua:3535 - [x] 52% ImGui::DragFloat imgui_widgets.lua:3505 - [x] n/a ImGui::DragFloat2 imgui_widgets.lua:3585 = DragFloatN ( 2 ) - [x] n/a ImGui::DragFloat3 imgui_widgets.lua:3586 = DragFloatN ( 3 ) - [x] n/a ImGui::DragFloat4 imgui_widgets.lua:3587 = DragFloatN ( 4 ) - [x] 67% ImGui::DragFloatRange2 imgui_widgets.lua:3632 - [x] 52% ImGui::DragInt imgui_widgets.lua:3524 - [x] n/a ImGui::DragInt2 imgui_widgets.lua:3588 = DragIntN ( 2 ) - [x] n/a ImGui::DragInt3 imgui_widgets.lua:3589 = DragIntN ( 3 ) - [x] n/a ImGui::DragInt4 imgui_widgets.lua:3590 = DragIntN ( 4 ) - [x] 67% ImGui::DragIntRange2 imgui_widgets.lua:3636 + [x] 85% ImGui::DragBehaviorT imgui_widgets.lua:3172 + [x] 95% ShortcutsForCancel imgui_widgets.lua:3319 + [x] 62% ImGui::DragBehavior imgui_widgets.lua:3340 + [x] 74% TempInputIsClampEnabled imgui_widgets.lua:3394 + [x] 75% ImGui::DragScalar imgui_widgets.lua:3437 + [x] 70% ImGui::DragScalarN imgui_widgets.lua:3580 + [x] 52% ImGui::DragFloat imgui_widgets.lua:3550 + [x] n/a ImGui::DragFloat2 imgui_widgets.lua:3630 = DragFloatN ( 2 ) + [x] n/a ImGui::DragFloat3 imgui_widgets.lua:3631 = DragFloatN ( 3 ) + [x] n/a ImGui::DragFloat4 imgui_widgets.lua:3632 = DragFloatN ( 4 ) + [x] 67% ImGui::DragFloatRange2 imgui_widgets.lua:3677 + [x] 52% ImGui::DragInt imgui_widgets.lua:3569 + [x] n/a ImGui::DragInt2 imgui_widgets.lua:3633 = DragIntN ( 2 ) + [x] n/a ImGui::DragInt3 imgui_widgets.lua:3634 = DragIntN ( 3 ) + [x] n/a ImGui::DragInt4 imgui_widgets.lua:3635 = DragIntN ( 4 ) + [x] 67% ImGui::DragIntRange2 imgui_widgets.lua:3681 -- Widgets: SliderScalar, SliderFloat, SliderInt, etc. - [x] 89% ImGui::ScaleRatioFromValueT imgui_widgets.lua:3670 - [x] 89% ImGui::ScaleValueFromRatioT imgui_widgets.lua:3747 - [x] 83% ImGui::SliderBehaviorT imgui_widgets.lua:3835 - [x] 58% ImGui::SliderBehavior imgui_widgets.lua:4014 - [x] 72% ImGui::SliderScalar imgui_widgets.lua:4067 - [x] 74% ImGui::SliderScalarN imgui_widgets.lua:4182 - [x] 71% ImGui::SliderFloat imgui_widgets.lua:4258 - [x] 100% ImGui::SliderFloat2 imgui_widgets.lua:4228 - [x] 100% ImGui::SliderFloat3 imgui_widgets.lua:4238 - [x] 100% ImGui::SliderFloat4 imgui_widgets.lua:4248 - [x] 74% ImGui::SliderAngle imgui_widgets.lua:4273 - [x] 71% ImGui::SliderInt imgui_widgets.lua:4294 - [x] 95% ImGui::SliderInt2 imgui_widgets.lua:4301 - [x] 95% ImGui::SliderInt3 imgui_widgets.lua:4305 - [x] 95% ImGui::SliderInt4 imgui_widgets.lua:4309 - [x] 80% ImGui::VSliderScalar imgui_widgets.lua:4321 - [x] 84% ImGui::VSliderFloat imgui_widgets.lua:4397 - [x] 84% ImGui::VSliderInt imgui_widgets.lua:4410 + [x] 89% ImGui::ScaleRatioFromValueT imgui_widgets.lua:3715 + [x] 89% ImGui::ScaleValueFromRatioT imgui_widgets.lua:3792 + [x] 85% ImGui::SliderBehaviorT imgui_widgets.lua:3880 + [x] 70% ImGui::SliderBehavior imgui_widgets.lua:4050 + [x] 72% ImGui::SliderScalar imgui_widgets.lua:4127 + [x] 74% ImGui::SliderScalarN imgui_widgets.lua:4242 + [x] 71% ImGui::SliderFloat imgui_widgets.lua:4318 + [x] 100% ImGui::SliderFloat2 imgui_widgets.lua:4288 + [x] 100% ImGui::SliderFloat3 imgui_widgets.lua:4298 + [x] 100% ImGui::SliderFloat4 imgui_widgets.lua:4308 + [x] 74% ImGui::SliderAngle imgui_widgets.lua:4333 + [x] 71% ImGui::SliderInt imgui_widgets.lua:4354 + [x] 95% ImGui::SliderInt2 imgui_widgets.lua:4361 + [x] 95% ImGui::SliderInt3 imgui_widgets.lua:4365 + [x] 95% ImGui::SliderInt4 imgui_widgets.lua:4369 + [x] 80% ImGui::VSliderScalar imgui_widgets.lua:4381 + [x] 84% ImGui::VSliderFloat imgui_widgets.lua:4457 + [x] 84% ImGui::VSliderInt imgui_widgets.lua:4470 -- Widgets: InputScalar, InputFloat, InputInt, etc. - [x] 44% ImParseFormatFindStart imgui_widgets.lua:2635 - [x] 46% ImParseFormatFindEnd imgui_widgets.lua:2653 - [x] 55% ImParseFormatTrimDecorations imgui_widgets.lua:2680 - [ ] ImParseFormatSanitizeForPrinting - [x] 61% ImParseFormatSanitizeForScanning imgui_widgets.lua:2696 - [x] 41% ImAtoi imgui_widgets.lua:2726 - [x] 55% ImParseFormatPrecision imgui_widgets.lua:2751 - [x] 88% ImGui::TempInputText imgui_widgets.lua:2792 - [x] 63% ImGui::TempInputScalar imgui_widgets.lua:2836 - [x] 63% ImGui::SetNextItemRefVal imgui_widgets.lua:7439 - [x] 74% ImGui::InputScalar imgui_widgets.lua:2887 - [x] 71% ImGui::InputScalarN imgui_widgets.lua:3004 - [x] 65% ImGui::InputFloat imgui_widgets.lua:3092 - [x] 95% ImGui::InputFloat2 imgui_widgets.lua:3051 - [x] 84% ImGui::InputFloat3 imgui_widgets.lua:3045 - [x] 95% ImGui::InputFloat4 imgui_widgets.lua:3055 - [x] 66% ImGui::InputInt imgui_widgets.lua:3076 - [x] 100% ImGui::InputInt2 imgui_widgets.lua:3059 - [x] 100% ImGui::InputInt3 imgui_widgets.lua:3063 - [x] 100% ImGui::InputInt4 imgui_widgets.lua:3067 - [x] 65% ImGui::InputDouble imgui_widgets.lua:3106 + [x] 44% ImParseFormatFindStart imgui_widgets.lua:2637 + [x] 46% ImParseFormatFindEnd imgui_widgets.lua:2655 + [x] 55% ImParseFormatTrimDecorations imgui_widgets.lua:2682 + [x] 51% ImParseFormatSanitizeForPrinting imgui_widgets.lua:2701 + [x] 61% ImParseFormatSanitizeForScanning imgui_widgets.lua:2722 + [x] 41% ImAtoi imgui_widgets.lua:2752 + [x] 55% ImParseFormatPrecision imgui_widgets.lua:2777 + [x] 88% ImGui::TempInputText imgui_widgets.lua:2818 + [x] 63% ImGui::TempInputScalar imgui_widgets.lua:2862 + [x] 63% ImGui::SetNextItemRefVal imgui_widgets.lua:7551 + [x] 74% ImGui::InputScalar imgui_widgets.lua:2913 + [x] 71% ImGui::InputScalarN imgui_widgets.lua:3030 + [x] 65% ImGui::InputFloat imgui_widgets.lua:3118 + [x] 95% ImGui::InputFloat2 imgui_widgets.lua:3077 + [x] 84% ImGui::InputFloat3 imgui_widgets.lua:3071 + [x] 95% ImGui::InputFloat4 imgui_widgets.lua:3081 + [x] 66% ImGui::InputInt imgui_widgets.lua:3102 + [x] 100% ImGui::InputInt2 imgui_widgets.lua:3085 + [x] 100% ImGui::InputInt3 imgui_widgets.lua:3089 + [x] 100% ImGui::InputInt4 imgui_widgets.lua:3093 + [x] 65% ImGui::InputDouble imgui_widgets.lua:3132 -- Widgets: InputText, InputTextMultiline, InputTextWithHint - [x] 77% ImGui::InputText imgui_widgets.lua:4433 - [x] 80% ImGui::InputTextMultiline imgui_widgets.lua:4455 - [x] 77% ImGui::InputTextWithHint imgui_widgets.lua:6279 - [x] 87% InputTextCalcTextSize imgui_widgets.lua:4475 - [x] 100% STB_TEXTEDIT_STRINGLEN imgui_widgets.lua:4491 - [x] 88% STB_TEXTEDIT_GETCHAR imgui_widgets.lua:4495 - [x] 61% STB_TEXTEDIT_GETWIDTH imgui_widgets.lua:4501 - [x] 86% STB_TEXTEDIT_LAYOUTROW imgui_widgets.lua:4506 - [x] 79% IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL imgui_widgets.lua:4519 - [x] 70% IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL imgui_widgets.lua:4528 - [x] 23% ImCharIsSeparatorW imgui_widgets.lua:4545 - [x] 66% is_word_boundary_from_right imgui_widgets.lua:4558 - [x] 65% is_word_boundary_from_left imgui_widgets.lua:4577 - [x] 71% STB_TEXTEDIT_MOVEWORDLEFT_IMPL imgui_widgets.lua:4595 - [ ] STB_TEXTEDIT_MOVEWORDRIGHT_MAC - [ ] STB_TEXTEDIT_MOVEWORDRIGHT_WIN - [x] 100% STB_TEXTEDIT_MOVEWORDRIGHT_IMPL imgui_widgets.lua:4627 - [x] 68% STB_TEXTEDIT_MOVELINESTART_IMPL imgui_widgets.lua:4640 - [x] 73% STB_TEXTEDIT_MOVELINEEND_IMPL imgui_widgets.lua:4679 - [x] 79% STB_TEXTEDIT_DELETECHARS imgui_widgets.lua:4712 - [x] 87% STB_TEXTEDIT_INSERTCHARS imgui_widgets.lua:4726 - [x] 81% stb_textedit_replace imgui_widgets.lua:4769 - [x] 12% ImGuiInputTextState::ImGuiInputTextState imgui_internal.lua:1717 + [x] 77% ImGui::InputText imgui_widgets.lua:4493 + [x] 80% ImGui::InputTextMultiline imgui_widgets.lua:4515 + [x] 77% ImGui::InputTextWithHint imgui_widgets.lua:6350 + [x] 87% InputTextCalcTextSize imgui_widgets.lua:4535 + [x] 100% STB_TEXTEDIT_STRINGLEN imgui_widgets.lua:4551 + [x] 88% STB_TEXTEDIT_GETCHAR imgui_widgets.lua:4555 + [x] 61% STB_TEXTEDIT_GETWIDTH imgui_widgets.lua:4561 + [x] 86% STB_TEXTEDIT_LAYOUTROW imgui_widgets.lua:4566 + [x] 79% IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL imgui_widgets.lua:4579 + [x] 70% IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL imgui_widgets.lua:4588 + [x] 23% ImCharIsSeparatorW imgui_widgets.lua:4605 + [x] 66% is_word_boundary_from_right imgui_widgets.lua:4618 + [x] 65% is_word_boundary_from_left imgui_widgets.lua:4637 + [x] 71% STB_TEXTEDIT_MOVEWORDLEFT_IMPL imgui_widgets.lua:4655 + [x] 76% STB_TEXTEDIT_MOVEWORDRIGHT_MAC imgui_widgets.lua:4665 + [x] 76% STB_TEXTEDIT_MOVEWORDRIGHT_WIN imgui_widgets.lua:4676 + [x] 83% STB_TEXTEDIT_MOVEWORDRIGHT_IMPL imgui_widgets.lua:4687 + [x] 68% STB_TEXTEDIT_MOVELINESTART_IMPL imgui_widgets.lua:4700 + [x] 73% STB_TEXTEDIT_MOVELINEEND_IMPL imgui_widgets.lua:4739 + [x] 79% STB_TEXTEDIT_DELETECHARS imgui_widgets.lua:4772 + [x] 87% STB_TEXTEDIT_INSERTCHARS imgui_widgets.lua:4786 + [x] 81% stb_textedit_replace imgui_widgets.lua:4829 + [x] 10% ImGuiInputTextState::ImGuiInputTextState imgui_internal.lua:1783 [-] ImGuiInputTextState::~ImGuiInputTextState c++-only - [x] 93% ImGuiInputTextState::OnKeyPressed imgui_widgets.lua:4797 - [x] 63% ImGuiInputTextState::OnCharPressed imgui_widgets.lua:4812 - [x] 100% ImGuiInputTextState::CursorAnimReset imgui_widgets.lua:4824 - [x] 85% ImGuiInputTextState::CursorClamp imgui_widgets.lua:4826 - [x] 94% ImGuiInputTextState::HasSelection imgui_widgets.lua:4832 - [ ] ImGuiInputTextState::ClearSelection - [ ] ImGuiInputTextState::GetCursorPos - [ ] ImGuiInputTextState::GetSelectionStart - [ ] ImGuiInputTextState::GetSelectionEnd - [ ] ImGuiInputTextState::SetSelection - [ ] ImGuiInputTextState::GetPreferredOffsetX - [x] 74% ImGuiInputTextState::SelectAll imgui_widgets.lua:4834 - [ ] ImGuiInputTextState::ReloadUserBufAndSelectAll - [ ] ImGuiInputTextState::ReloadUserBufAndKeepSelection - [ ] ImGuiInputTextState::ReloadUserBufAndMoveToEnd - [x] 18% ImGuiInputTextCallbackData::ImGuiInputTextCallbackData imgui_h.lua:2496 - [x] 61% ImGuiInputTextCallbackData::DeleteChars imgui_h.lua:2500 - [x] 33% ImGuiInputTextCallbackData::InsertChars imgui_h.lua:2517 - [x] 92% ImGui::PushPasswordFont imgui_widgets.lua:4843 - [x] 98% ImGui::PopPasswordFont imgui_widgets.lua:4858 - [x] 80% InputTextFilterCharacter imgui_widgets.lua:4878 - [x] 74% InputTextReconcileUndoState imgui_widgets.lua:5016 - [x] 86% ImGui::InputTextDeactivateHook imgui_widgets.lua:5058 - [x] 74% ImLowerBound imgui_widgets.lua:5160 - [x] 55% InputTextLineIndexBuild imgui_widgets.lua:5092 - [x] 77% InputTextLineIndexGetPosOffset imgui_widgets.lua:5188 - [x] 87% ImGui::InputTextEx imgui_widgets.lua:5233 - [ ] ImGui::DebugNodeInputTextState + [x] 93% ImGuiInputTextState::OnKeyPressed imgui_widgets.lua:4857 + [x] 63% ImGuiInputTextState::OnCharPressed imgui_widgets.lua:4872 + [x] 100% ImGuiInputTextState::CursorAnimReset imgui_widgets.lua:4884 + [x] 85% ImGuiInputTextState::CursorClamp imgui_widgets.lua:4886 + [x] 94% ImGuiInputTextState::HasSelection imgui_widgets.lua:4892 + [x] 85% ImGuiInputTextState::ClearSelection imgui_widgets.lua:4893 + [x] 100% ImGuiInputTextState::GetCursorPos imgui_widgets.lua:4895 + [x] 100% ImGuiInputTextState::GetSelectionStart imgui_widgets.lua:4896 + [x] 100% ImGuiInputTextState::GetSelectionEnd imgui_widgets.lua:4897 + [x] 84% ImGuiInputTextState::SetSelection imgui_widgets.lua:4898 + [x] 55% ImGuiInputTextState::GetPreferredOffsetX imgui_widgets.lua:4899 + [x] 74% ImGuiInputTextState::SelectAll imgui_widgets.lua:4901 + [x] 80% ImGuiInputTextState::ReloadUserBufAndSelectAll imgui_widgets.lua:4908 + [x] 93% ImGuiInputTextState::ReloadUserBufAndKeepSelection imgui_widgets.lua:4909 + [x] 84% ImGuiInputTextState::ReloadUserBufAndMoveToEnd imgui_widgets.lua:4910 + [x] 18% ImGuiInputTextCallbackData::ImGuiInputTextCallbackData imgui_h.lua:2506 + [x] 61% ImGuiInputTextCallbackData::DeleteChars imgui_h.lua:2510 + [x] 33% ImGuiInputTextCallbackData::InsertChars imgui_h.lua:2527 + [x] 92% ImGui::PushPasswordFont imgui_widgets.lua:4914 + [x] 98% ImGui::PopPasswordFont imgui_widgets.lua:4929 + [x] 79% InputTextFilterCharacter imgui_widgets.lua:4949 + [x] 74% InputTextReconcileUndoState imgui_widgets.lua:5087 + [x] 86% ImGui::InputTextDeactivateHook imgui_widgets.lua:5129 + [x] 74% ImLowerBound imgui_widgets.lua:5231 + [x] 55% InputTextLineIndexBuild imgui_widgets.lua:5163 + [x] 77% InputTextLineIndexGetPosOffset imgui_widgets.lua:5259 + [x] 87% ImGui::InputTextEx imgui_widgets.lua:5304 + [x] 78% ImGui::DebugNodeInputTextState imgui_widgets.lua:6359 -- Widgets: ColorEdit, ColorPicker, ColorButton, etc. - [x] 54% ImGui::ColorEdit3 imgui_widgets.lua:6657 - [x] 88% ColorEditRestoreH imgui_widgets.lua:6303 - [x] 87% ColorEditRestoreHS imgui_widgets.lua:6320 - [x] 62% ImGui::ColorEdit4 imgui_widgets.lua:6363 - [x] 70% ImGui::ColorPicker3 imgui_widgets.lua:6665 - [x] 98% RenderArrowsForVerticalBar imgui_widgets.lua:6693 - [x] 80% ImGui::ColorPicker4 imgui_widgets.lua:6712 - [x] 85% ImGui::ColorButton imgui_widgets.lua:7139 + [x] 54% ImGui::ColorEdit3 imgui_widgets.lua:6769 + [x] 88% ColorEditRestoreH imgui_widgets.lua:6415 + [x] 87% ColorEditRestoreHS imgui_widgets.lua:6432 + [x] 62% ImGui::ColorEdit4 imgui_widgets.lua:6475 + [x] 70% ImGui::ColorPicker3 imgui_widgets.lua:6777 + [x] 98% RenderArrowsForVerticalBar imgui_widgets.lua:6805 + [x] 80% ImGui::ColorPicker4 imgui_widgets.lua:6824 + [x] 85% ImGui::ColorButton imgui_widgets.lua:7251 [-] ImGui::SetColorEditOptions obsolete - [x] 73% ImGui::ColorTooltip imgui_widgets.lua:7243 - [x] 72% ImGui::ColorEditOptionsPopup imgui_widgets.lua:7287 - [x] 75% ImGui::ColorPickerOptionsPopup imgui_widgets.lua:7363 + [x] 73% ImGui::ColorTooltip imgui_widgets.lua:7355 + [x] 72% ImGui::ColorEditOptionsPopup imgui_widgets.lua:7399 + [x] 75% ImGui::ColorPickerOptionsPopup imgui_widgets.lua:7475 -- Widgets: TreeNode, CollapsingHeader, etc. - [x] 78% ImGui::TreeNode imgui_widgets.lua:7448 - [x] 89% ImGui::TreeNodeV imgui_widgets.lua:7460 - [x] 69% ImGui::TreeNodeEx imgui_widgets.lua:7467 - [x] 68% ImGui::TreeNodeExV imgui_widgets.lua:7481 - [x] 73% ImGui::TreeNodeGetOpen imgui_widgets.lua:7494 - [x] 79% ImGui::TreeNodeSetOpen imgui_widgets.lua:7502 - [x] 82% ImGui::TreeNodeUpdateNextOpen imgui_widgets.lua:7510 - [x] 86% TreeNodeStoreStackData imgui_widgets.lua:7553 - [x] 82% ImGui::TreeNodeBehavior imgui_widgets.lua:7580 - [x] 91% ImGui::TreeNodeDrawLineToChildNode imgui_widgets.lua:7884 - [x] 98% ImGui::TreeNodeDrawLineToTreePop imgui_widgets.lua:7919 - [x] 67% ImGui::TreePush imgui_widgets.lua:7951 - [x] 74% ImGui::TreePushOverrideID imgui_widgets.lua:7959 - [x] 84% ImGui::TreePop imgui_widgets.lua:7967 - [x] 100% ImGui::GetTreeNodeToLabelSpacing imgui_widgets.lua:8016 - [x] 77% ImGui::SetNextItemOpen imgui_widgets.lua:8003 - [x] 85% ImGui::SetNextItemStorageID imgui_widgets.lua:8023 - [x] 81% ImGui::CollapsingHeader imgui_widgets.lua:8042 + [x] 78% ImGui::TreeNode imgui_widgets.lua:7560 + [x] 89% ImGui::TreeNodeV imgui_widgets.lua:7572 + [x] 69% ImGui::TreeNodeEx imgui_widgets.lua:7579 + [x] 68% ImGui::TreeNodeExV imgui_widgets.lua:7593 + [x] 73% ImGui::TreeNodeGetOpen imgui_widgets.lua:7606 + [x] 79% ImGui::TreeNodeSetOpen imgui_widgets.lua:7614 + [x] 82% ImGui::TreeNodeUpdateNextOpen imgui_widgets.lua:7622 + [x] 86% TreeNodeStoreStackData imgui_widgets.lua:7665 + [x] 82% ImGui::TreeNodeBehavior imgui_widgets.lua:7692 + [x] 91% ImGui::TreeNodeDrawLineToChildNode imgui_widgets.lua:7996 + [x] 98% ImGui::TreeNodeDrawLineToTreePop imgui_widgets.lua:8031 + [x] 67% ImGui::TreePush imgui_widgets.lua:8063 + [x] 74% ImGui::TreePushOverrideID imgui_widgets.lua:8071 + [x] 84% ImGui::TreePop imgui_widgets.lua:8079 + [x] 100% ImGui::GetTreeNodeToLabelSpacing imgui_widgets.lua:8128 + [x] 77% ImGui::SetNextItemOpen imgui_widgets.lua:8115 + [x] 85% ImGui::SetNextItemStorageID imgui_widgets.lua:8135 + [x] 81% ImGui::CollapsingHeader imgui_widgets.lua:8154 -- Widgets: Selectable - [x] 83% ImGui::Selectable imgui_widgets.lua:8099 + [x] 83% ImGui::Selectable imgui_widgets.lua:8211 -- Widgets: Typing-Select support - [x] 74% ImGui::GetTypingSelectRequest imgui_widgets.lua:8330 - [x] 48% ImStrimatchlen imgui_widgets.lua:8432 - [x] 95% ImGui::TypingSelectFindMatch imgui_widgets.lua:8455 - [x] 88% ImGui::TypingSelectFindNextSingleCharMatch imgui_widgets.lua:8472 - [x] 85% ImGui::TypingSelectFindBestLeadingMatch imgui_widgets.lua:8503 - [x] 86% ImGui::DebugNodeTypingSelectState imgui_widgets.lua:8521 + [x] 74% ImGui::GetTypingSelectRequest imgui_widgets.lua:8442 + [x] 48% ImStrimatchlen imgui_widgets.lua:8544 + [x] 95% ImGui::TypingSelectFindMatch imgui_widgets.lua:8567 + [x] 88% ImGui::TypingSelectFindNextSingleCharMatch imgui_widgets.lua:8584 + [x] 85% ImGui::TypingSelectFindBestLeadingMatch imgui_widgets.lua:8615 + [x] 86% ImGui::DebugNodeTypingSelectState imgui_widgets.lua:8633 -- Widgets: Box-Select support - [x] 67% BoxSelectPreStartDrag imgui_widgets.lua:8542 - [x] 89% BoxSelectActivateDrag imgui_widgets.lua:8556 - [x] 99% BoxSelectDeactivateDrag imgui_widgets.lua:8569 - [x] 81% BoxSelectScrollWithMouseDrag imgui_widgets.lua:8579 - [x] 49% ImGui::BeginBoxSelect imgui_widgets.lua:8616 - [x] 90% ImGui::EndBoxSelect imgui_widgets.lua:8712 + [x] 67% BoxSelectPreStartDrag imgui_widgets.lua:8654 + [x] 89% BoxSelectActivateDrag imgui_widgets.lua:8668 + [x] 99% BoxSelectDeactivateDrag imgui_widgets.lua:8681 + [x] 81% BoxSelectScrollWithMouseDrag imgui_widgets.lua:8691 + [x] 49% ImGui::BeginBoxSelect imgui_widgets.lua:8728 + [x] 90% ImGui::EndBoxSelect imgui_widgets.lua:8824 -- Widgets: Multi-Select support - [x] 74% DebugLogMultiSelectRequests imgui_widgets.lua:8756 - [x] 61% CalcScopeRect imgui_widgets.lua:8764 - [x] 80% ImGui::BeginMultiSelect imgui_widgets.lua:8795 - [x] 83% ImGui::EndMultiSelect imgui_widgets.lua:8942 - [x] 73% ImGui::SetNextItemSelectionUserData imgui_widgets.lua:9032 - [x] 84% ImGui::MultiSelectItemHeader imgui_widgets.lua:9063 - [x] 86% ImGui::MultiSelectItemFooter imgui_widgets.lua:9133 - [x] 59% ImGui::MultiSelectAddSetAll imgui_widgets.lua:9347 - [x] 31% ImGui::MultiSelectAddSetRange imgui_widgets.lua:9359 - [x] 84% ImGui::DebugNodeMultiSelectState imgui_widgets.lua:9377 + [x] 74% DebugLogMultiSelectRequests imgui_widgets.lua:8868 + [x] 61% CalcScopeRect imgui_widgets.lua:8876 + [x] 80% ImGui::BeginMultiSelect imgui_widgets.lua:8907 + [x] 83% ImGui::EndMultiSelect imgui_widgets.lua:9054 + [x] 73% ImGui::SetNextItemSelectionUserData imgui_widgets.lua:9144 + [x] 84% ImGui::MultiSelectItemHeader imgui_widgets.lua:9175 + [x] 86% ImGui::MultiSelectItemFooter imgui_widgets.lua:9245 + [x] 59% ImGui::MultiSelectAddSetAll imgui_widgets.lua:9459 + [x] 31% ImGui::MultiSelectAddSetRange imgui_widgets.lua:9471 + [x] 84% ImGui::DebugNodeMultiSelectState imgui_widgets.lua:9489 -- Widgets: Multi-Select helpers - [x] 46% ImGuiSelectionBasicStorage::ImGuiSelectionBasicStorage imgui_widgets.lua:9422 - [x] 61% ImGuiSelectionBasicStorage::Clear imgui_widgets.lua:9434 - [x] 53% ImGuiSelectionBasicStorage::Swap imgui_widgets.lua:9441 - [x] 57% ImGuiSelectionBasicStorage::Contains imgui_widgets.lua:9449 - [x] 12% PairComparerByValueInt imgui_widgets.lua:9454 - [x] 26% ImGuiSelectionBasicStorage::GetNextSelectedItem imgui_widgets.lua:9463 - [x] 50% ImGuiSelectionBasicStorage::SetItemSelected imgui_widgets.lua:9494 - [x] 42% ImGuiSelectionBasicStorage_BatchSetItemSelected imgui_widgets.lua:9507 - [~] 0% ImGuiSelectionBasicStorage_BatchFinish imgui_widgets.lua:9522 stub - [x] 78% ImGuiSelectionBasicStorage::ApplyRequests imgui_widgets.lua:9541 - [x] 48% ImGuiSelectionExternalStorage::ImGuiSelectionExternalStorage imgui_widgets.lua:9606 - [x] 84% ImGuiSelectionExternalStorage::ApplyRequests imgui_widgets.lua:9617 + [x] 46% ImGuiSelectionBasicStorage::ImGuiSelectionBasicStorage imgui_widgets.lua:9534 + [x] 61% ImGuiSelectionBasicStorage::Clear imgui_widgets.lua:9546 + [x] 53% ImGuiSelectionBasicStorage::Swap imgui_widgets.lua:9553 + [x] 57% ImGuiSelectionBasicStorage::Contains imgui_widgets.lua:9561 + [x] 12% PairComparerByValueInt imgui_widgets.lua:9566 + [x] 26% ImGuiSelectionBasicStorage::GetNextSelectedItem imgui_widgets.lua:9575 + [x] 50% ImGuiSelectionBasicStorage::SetItemSelected imgui_widgets.lua:9606 + [x] 42% ImGuiSelectionBasicStorage_BatchSetItemSelected imgui_widgets.lua:9619 + [~] 0% ImGuiSelectionBasicStorage_BatchFinish imgui_widgets.lua:9634 stub + [x] 78% ImGuiSelectionBasicStorage::ApplyRequests imgui_widgets.lua:9653 + [x] 48% ImGuiSelectionExternalStorage::ImGuiSelectionExternalStorage imgui_widgets.lua:9718 + [x] 84% ImGuiSelectionExternalStorage::ApplyRequests imgui_widgets.lua:9729 -- Widgets: ListBox - [x] 92% ImGui::BeginListBox imgui_widgets.lua:9650 - [x] 78% ImGui::EndListBox imgui_widgets.lua:9691 - [x] 63% ImGui::ListBox imgui_widgets.lua:9706 + [x] 92% ImGui::BeginListBox imgui_widgets.lua:9762 + [x] 78% ImGui::EndListBox imgui_widgets.lua:9803 + [x] 63% ImGui::ListBox imgui_widgets.lua:9818 -- Widgets: PlotLines, PlotHistogram - [x] 89% ImGui::PlotEx imgui_widgets.lua:9778 - [x] 86% ImGuiPlotArrayGetterData::ImGuiPlotArrayGetterData imgui_widgets.lua:9908 - [x] 48% Plot_ArrayGetter imgui_widgets.lua:9919 - [x] 41% ImGui::PlotLines imgui_widgets.lua:9933 - [x] 41% ImGui::PlotHistogram imgui_widgets.lua:9959 + [x] 89% ImGui::PlotEx imgui_widgets.lua:9890 + [x] 86% ImGuiPlotArrayGetterData::ImGuiPlotArrayGetterData imgui_widgets.lua:10020 + [x] 48% Plot_ArrayGetter imgui_widgets.lua:10031 + [x] 41% ImGui::PlotLines imgui_widgets.lua:10045 + [x] 41% ImGui::PlotHistogram imgui_widgets.lua:10071 -- Widgets: Value helpers [x] 21% ImGui::Value imgui_widgets.lua:384 -- MenuItem, BeginMenu, EndMenu, etc. - [x] 49% ImGuiMenuColumns::Update imgui_widgets.lua:9991 - [x] 77% ImGuiMenuColumns::CalcNextTotalWidth imgui_widgets.lua:10003 - [x] 64% ImGuiMenuColumns::DeclColumns imgui_widgets.lua:10026 - [x] 91% ImGui::BeginMenuBar imgui_widgets.lua:10039 - [x] 92% ImGui::EndMenuBar imgui_widgets.lua:10073 - [x] 85% ImGui::BeginViewportSideBar imgui_widgets.lua:10136 - [x] 90% ImGui::BeginMainMenuBar imgui_widgets.lua:10172 - [x] 90% ImGui::EndMainMenuBar imgui_widgets.lua:10198 - [x] 91% IsRootOfOpenMenuSet imgui_widgets.lua:10214 - [x] 89% ImGui::BeginMenuEx imgui_widgets.lua:10242 - [x] 67% ImGui::BeginMenu imgui_widgets.lua:10473 - [x] 92% ImGui::EndMenu imgui_widgets.lua:10479 - [x] 85% ImGui::MenuItemEx imgui_widgets.lua:10503 - [x] 67% ImGui::MenuItem imgui_widgets.lua:10610 + [x] 49% ImGuiMenuColumns::Update imgui_widgets.lua:10103 + [x] 77% ImGuiMenuColumns::CalcNextTotalWidth imgui_widgets.lua:10115 + [x] 64% ImGuiMenuColumns::DeclColumns imgui_widgets.lua:10138 + [x] 91% ImGui::BeginMenuBar imgui_widgets.lua:10151 + [x] 92% ImGui::EndMenuBar imgui_widgets.lua:10185 + [x] 85% ImGui::BeginViewportSideBar imgui_widgets.lua:10248 + [x] 90% ImGui::BeginMainMenuBar imgui_widgets.lua:10284 + [x] 90% ImGui::EndMainMenuBar imgui_widgets.lua:10310 + [x] 91% IsRootOfOpenMenuSet imgui_widgets.lua:10326 + [x] 89% ImGui::BeginMenuEx imgui_widgets.lua:10354 + [x] 67% ImGui::BeginMenu imgui_widgets.lua:10585 + [x] 92% ImGui::EndMenu imgui_widgets.lua:10591 + [x] 85% ImGui::MenuItemEx imgui_widgets.lua:10615 + [x] 67% ImGui::MenuItem imgui_widgets.lua:10722 -- Widgets: BeginTabBar, EndTabBar, etc. - [x] 19% ImGuiTabBarSection::ImGuiTabBarSection imgui_widgets.lua:10678 - [x] 16% ImGuiTabBar::ImGuiTabBar imgui_internal.lua:2222 - [x] 65% TabItemGetSectionIdx imgui_widgets.lua:10645 - [ ] TabItemComparerBySection - [ ] TabItemComparerByBeginOrder - [ ] GetTabBarFromTabBarRef - [ ] GetTabBarRefFromTabBar - [x] 60% ImGui::TabBarFindByID imgui_widgets.lua:10766 - [x] 77% ImGui::TabBarRemove imgui_widgets.lua:10772 - [x] 92% ImGui::BeginTabBar imgui_widgets.lua:10777 - [x] 82% ImGui::BeginTabBarEx imgui_widgets.lua:10795 - [x] 90% ImGui::EndTabBar imgui_widgets.lua:10859 - [x] 68% TabBarCalcScrollableWidth imgui_widgets.lua:10671 - [x] 81% ImGui::TabBarLayout imgui_widgets.lua:10894 - [x] 75% ImGui::TabBarCalcTabID imgui_widgets.lua:11165 - [x] 62% ImGui::TabBarCalcMaxTabWidth imgui_widgets.lua:11175 - [x] 71% ImGui::TabBarFindTabByID imgui_widgets.lua:11179 - [x] 90% ImGui::TabBarFindTabByOrder imgui_widgets.lua:11191 - [x] 85% ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow imgui_widgets.lua:11203 - [x] 93% ImGui::TabBarGetCurrentTab imgui_widgets.lua:11214 - [x] 55% ImGui::TabBarGetTabName imgui_widgets.lua:11219 - [x] 89% ImGui::TabBarGetTabPos imgui_widgets.lua:11225 - [x] 92% ImGui::TabBarAddTab imgui_widgets.lua:11234 - [x] 91% ImGui::TabBarRemoveTab imgui_widgets.lua:11251 - [x] 92% ImGui::TabBarCloseTab imgui_widgets.lua:11260 - [x] 97% ImGui::TabBarScrollClamp imgui_widgets.lua:11278 - [x] 89% ImGui::TabBarScrollToTab imgui_widgets.lua:11284 - [x] 67% ImGui::TabBarQueueFocus imgui_widgets.lua:11322 - [x] 100% ImGui::TabBarQueueReorder imgui_widgets.lua:11331 - [x] 85% ImGui::TabBarQueueReorderFromMousePos imgui_widgets.lua:11338 - [x] 64% ImGui::TabBarProcessReorder imgui_widgets.lua:11372 - [x] 85% ImGui::TabBarScrollingButtons imgui_widgets.lua:11395 - [x] 80% ImGui::TabBarTabListPopupButton imgui_widgets.lua:11455 + [x] 19% ImGuiTabBarSection::ImGuiTabBarSection imgui_widgets.lua:10813 + [x] 16% ImGuiTabBar::ImGuiTabBar imgui_internal.lua:2296 + [x] 65% TabItemGetSectionIdx imgui_widgets.lua:10757 + [x] 71% TabItemComparerBySection imgui_widgets.lua:10764 + [x] 54% TabItemComparerByBeginOrder imgui_widgets.lua:10774 + [x] 70% GetTabBarFromTabBarRef imgui_widgets.lua:10778 + [x] 95% GetTabBarRefFromTabBar imgui_widgets.lua:10783 + [x] 60% ImGui::TabBarFindByID imgui_widgets.lua:10904 + [x] 77% ImGui::TabBarRemove imgui_widgets.lua:10910 + [x] 92% ImGui::BeginTabBar imgui_widgets.lua:10915 + [x] 84% ImGui::BeginTabBarEx imgui_widgets.lua:10933 + [x] 91% ImGui::EndTabBar imgui_widgets.lua:10997 + [x] 68% TabBarCalcScrollableWidth imgui_widgets.lua:10806 + [x] 82% ImGui::TabBarLayout imgui_widgets.lua:11032 + [x] 75% ImGui::TabBarCalcTabID imgui_widgets.lua:11303 + [x] 62% ImGui::TabBarCalcMaxTabWidth imgui_widgets.lua:11313 + [x] 71% ImGui::TabBarFindTabByID imgui_widgets.lua:11317 + [x] 90% ImGui::TabBarFindTabByOrder imgui_widgets.lua:11329 + [x] 85% ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow imgui_widgets.lua:11341 + [x] 93% ImGui::TabBarGetCurrentTab imgui_widgets.lua:11352 + [x] 55% ImGui::TabBarGetTabName imgui_widgets.lua:11357 + [x] 89% ImGui::TabBarGetTabPos imgui_widgets.lua:11363 + [x] 92% ImGui::TabBarAddTab imgui_widgets.lua:11372 + [x] 91% ImGui::TabBarRemoveTab imgui_widgets.lua:11389 + [x] 92% ImGui::TabBarCloseTab imgui_widgets.lua:11398 + [x] 97% ImGui::TabBarScrollClamp imgui_widgets.lua:11416 + [x] 89% ImGui::TabBarScrollToTab imgui_widgets.lua:11422 + [x] 67% ImGui::TabBarQueueFocus imgui_widgets.lua:11460 + [x] 100% ImGui::TabBarQueueReorder imgui_widgets.lua:11469 + [x] 85% ImGui::TabBarQueueReorderFromMousePos imgui_widgets.lua:11476 + [x] 64% ImGui::TabBarProcessReorder imgui_widgets.lua:11510 + [x] 85% ImGui::TabBarScrollingButtons imgui_widgets.lua:11533 + [x] 80% ImGui::TabBarTabListPopupButton imgui_widgets.lua:11593 -- Widgets: BeginTabItem, EndTabItem, etc. - [x] 78% ImGui::BeginTabItem imgui_widgets.lua:11503 - [x] 85% ImGui::EndTabItem imgui_widgets.lua:11522 - [x] 81% ImGui::TabItemButton imgui_widgets.lua:11536 - [x] 84% ImGui::TabItemSpacing imgui_widgets.lua:11546 - [x] 79% ImGui::TabItemEx imgui_widgets.lua:11557 - [x] 88% ImGui::SetTabItemClosed imgui_widgets.lua:11843 - [x] 79% ImGui::TabItemCalcSize imgui_widgets.lua:11865 - [x] 93% ImGui::TabItemBackground imgui_widgets.lua:11881 - [x] 86% ImGui::TabItemLabelAndCloseButton imgui_widgets.lua:11902 + [x] 78% ImGui::BeginTabItem imgui_widgets.lua:11641 + [x] 85% ImGui::EndTabItem imgui_widgets.lua:11660 + [x] 81% ImGui::TabItemButton imgui_widgets.lua:11674 + [x] 84% ImGui::TabItemSpacing imgui_widgets.lua:11684 + [x] 79% ImGui::TabItemEx imgui_widgets.lua:11695 + [x] 88% ImGui::SetTabItemClosed imgui_widgets.lua:11981 + [x] 79% ImGui::TabItemCalcSize imgui_widgets.lua:12003 + [x] 93% ImGui::TabItemBackground imgui_widgets.lua:12019 + [x] 86% ImGui::TabItemLabelAndCloseButton imgui_widgets.lua:12040 ==================================================================================================== imgui_draw.cpp @@ -1273,111 +1273,111 @@ imgui_draw.cpp [x] 82% ImGui::StyleColorsLight imgui_draw.lua:270 -- ImDrawList - [x] 30% ImDrawListSharedData::ImDrawListSharedData imgui_internal.lua:1132 + [x] 30% ImDrawListSharedData::ImDrawListSharedData imgui_internal.lua:1194 [-] ImDrawListSharedData::~ImDrawListSharedData c++-only - [x] 57% ImDrawListSharedData::SetCircleTessellationMaxError imgui_draw.lua:4188 + [x] 57% ImDrawListSharedData::SetCircleTessellationMaxError imgui_draw.lua:4224 [x] 6% ImDrawList::ImDrawList imgui_h.lua:657 [-] ImDrawList::~ImDrawList c++-only - [x] 88% ImDrawList::_SetDrawListSharedData imgui_draw.lua:4205 - [x] 43% ImDrawList::_ResetForNewFrame imgui_draw.lua:4218 - [x] 64% ImDrawList::_ClearFreeMemory imgui_draw.lua:4246 - [ ] ImDrawList::CloneOutput - [x] 77% ImDrawList::AddDrawCmd imgui_draw.lua:4265 - [x] 88% ImDrawList::_PopUnusedDrawCmd imgui_draw.lua:4282 - [x] 57% ImDrawList::AddCallback imgui_draw.lua:4296 - [x] 42% ImDrawList::_TryMergeDrawCmds imgui_draw.lua:4371 - [x] 33% ImDrawList::_OnChangedClipRect imgui_draw.lua:4383 - [x] 55% ImDrawList::_OnChangedTexture imgui_draw.lua:4410 - [x] 91% ImDrawList::_OnChangedVtxOffset imgui_draw.lua:4436 - [x] 57% ImDrawList::_CalcCircleAutoSegmentCount imgui_draw.lua:6852 - [x] 86% ImDrawList::PushClipRect imgui_draw.lua:6864 - [x] 60% ImDrawList::PushClipRectFullScreen imgui_draw.lua:6887 - [x] 39% ImDrawList::PopClipRect imgui_draw.lua:6892 - [x] 67% ImDrawList::PushTexture imgui_draw.lua:4652 - [x] 81% ImDrawList::PopTexture imgui_draw.lua:4661 - [x] 62% ImDrawList::PushDrawFlag imgui_draw.lua:4670 - [x] 85% ImDrawList::PopDrawFlag imgui_draw.lua:4682 - [x] 83% ImDrawList::_SetTexture imgui_draw.lua:4689 - [x] 89% ImDrawList::_SetPixelDensity imgui_draw.lua:4699 - [x] 57% ImDrawList::PrimReserve imgui_draw.lua:4739 = PrimReserve - [x] 68% ImDrawList::PrimUnreserve imgui_draw.lua:4742 - [x] 8% ImDrawList::PrimRect imgui_draw.lua:4789 - [x] 13% ImDrawList::PrimRectUV imgui_draw.lua:4798 - [ ] ImDrawList::PrimQuadUV - [x] 83% ImDrawList::_CalculateCenterBiasedOffset imgui_draw.lua:4836 = _CalculateCenterBiasedOffset + [x] 88% ImDrawList::_SetDrawListSharedData imgui_draw.lua:4241 + [x] 43% ImDrawList::_ResetForNewFrame imgui_draw.lua:4254 + [x] 64% ImDrawList::_ClearFreeMemory imgui_draw.lua:4282 + [x] 23% ImDrawList::CloneOutput imgui_draw.lua:4304 + [x] 77% ImDrawList::AddDrawCmd imgui_draw.lua:4324 + [x] 88% ImDrawList::_PopUnusedDrawCmd imgui_draw.lua:4341 + [x] 57% ImDrawList::AddCallback imgui_draw.lua:4355 + [x] 42% ImDrawList::_TryMergeDrawCmds imgui_draw.lua:4430 + [x] 33% ImDrawList::_OnChangedClipRect imgui_draw.lua:4442 + [x] 55% ImDrawList::_OnChangedTexture imgui_draw.lua:4469 + [x] 91% ImDrawList::_OnChangedVtxOffset imgui_draw.lua:4495 + [x] 57% ImDrawList::_CalcCircleAutoSegmentCount imgui_draw.lua:6951 + [x] 86% ImDrawList::PushClipRect imgui_draw.lua:6963 + [x] 60% ImDrawList::PushClipRectFullScreen imgui_draw.lua:6986 + [x] 39% ImDrawList::PopClipRect imgui_draw.lua:6991 + [x] 67% ImDrawList::PushTexture imgui_draw.lua:4711 + [x] 81% ImDrawList::PopTexture imgui_draw.lua:4720 + [x] 62% ImDrawList::PushDrawFlag imgui_draw.lua:4729 + [x] 85% ImDrawList::PopDrawFlag imgui_draw.lua:4741 + [x] 83% ImDrawList::_SetTexture imgui_draw.lua:4748 + [x] 89% ImDrawList::_SetPixelDensity imgui_draw.lua:4758 + [x] 57% ImDrawList::PrimReserve imgui_draw.lua:4798 = PrimReserve + [x] 68% ImDrawList::PrimUnreserve imgui_draw.lua:4801 + [x] 8% ImDrawList::PrimRect imgui_draw.lua:4848 + [x] 13% ImDrawList::PrimRectUV imgui_draw.lua:4857 + [x] 17% ImDrawList::PrimQuadUV imgui_draw.lua:4881 + [x] 83% ImDrawList::_CalculateCenterBiasedOffset imgui_draw.lua:4911 = _CalculateCenterBiasedOffset [x] 77% ImAlphaMultiply imgui_draw.lua:4100 - [x] 72% ImDrawList::_SelectLineTexture imgui_draw.lua:4871 = _SelectLineTexture - [x] 37% ImDrawList::_AddPolyline imgui_draw.lua:4884 - [x] 43% ImDrawList::AddConvexPolyFilled imgui_draw.lua:5254 - [x] 59% CalcCornerArcStepAndCount imgui_draw.lua:4167 - [x] 64% ImDrawList::_PathArcToFastEx imgui_draw.lua:7011 - [x] 63% ImDrawList::_PathArcToN imgui_draw.lua:7031 - [x] 10% ImDrawList::PathArcToFast imgui_draw.lua:7017 - [x] 46% ImDrawList::PathArcTo imgui_draw.lua:7057 - [x] 61% ImDrawList::PathEllipticalArcTo imgui_draw.lua:7647 - [x] 88% ImBezierCubicCalc imgui_draw.lua:7659 - [x] 89% ImBezierQuadraticCalc imgui_draw.lua:7665 - [x] 85% PathBezierCubicCurveToCasteljau imgui_draw.lua:7672 - [x] 90% PathBezierQuadraticCurveToCasteljau imgui_draw.lua:7690 - [x] 91% ImDrawList::PathBezierCubicCurveTo imgui_draw.lua:7704 - [x] 90% ImDrawList::PathBezierQuadraticCurveTo imgui_draw.lua:7716 - [x] 8% ImDrawList::PathRect imgui_draw.lua:5504 - [x] 46% ImDrawList::_AddLine imgui_draw.lua:5636 - [x] 4% ImDrawList::AddLine imgui_draw.lua:5645 - [x] 9% ImDrawList::AddLineH imgui_draw.lua:5673 - [x] 9% ImDrawList::AddLineV imgui_draw.lua:5729 - [x] 18% ImDrawList::_AddRectBaked imgui_draw.lua:5889 - [x] 42% ImDrawList::_AddRectTinyRounding imgui_draw.lua:5906 - [x] 12% ImDrawList::AddRect imgui_draw.lua:6032 - [x] 10% ImDrawList::_AddRectFilledBaked imgui_draw.lua:6250 - [x] 11% ImDrawList::AddRectFilled imgui_draw.lua:6260 - [x] 26% ImDrawList::AddRectFilledMultiColor imgui_draw.lua:6366 - [x] 59% ImDrawList::AddQuad imgui_draw.lua:6389 - [x] 71% ImDrawList::AddQuadFilled imgui_draw.lua:6406 - [x] 59% ImDrawList::AddTriangle imgui_draw.lua:6418 - [x] 73% ImDrawList::AddTriangleFilled imgui_draw.lua:6435 - [x] 100% ApproxApothem imgui_draw.lua:4177 - [x] 47% ImDrawList::AddCircle imgui_draw.lua:6451 - [x] 32% ImDrawList::AddCircleFilled imgui_draw.lua:6516 - [x] 86% ImDrawList::AddNgon imgui_draw.lua:6554 - [x] 95% ImDrawList::AddNgonFilled imgui_draw.lua:6602 - [x] 80% ImDrawList::AddEllipse imgui_draw.lua:6627 - [x] 88% ImDrawList::AddEllipseFilled imgui_draw.lua:6664 - [x] 73% ImDrawList::AddBezierCubic imgui_draw.lua:6705 - [x] 71% ImDrawList::AddBezierQuadratic imgui_draw.lua:6721 - [x] 65% ImDrawList::AddText imgui_draw.lua:6746 - [x] 69% ImDrawList::AddImage imgui_draw.lua:6789 - [ ] ImDrawList::AddImageQuad - [x] 84% ImDrawList::AddImageRounded imgui_draw.lua:6819 + [x] 72% ImDrawList::_SelectLineTexture imgui_draw.lua:4946 = _SelectLineTexture + [x] 37% ImDrawList::_AddPolyline imgui_draw.lua:4959 + [x] 43% ImDrawList::AddConvexPolyFilled imgui_draw.lua:5329 + [x] 59% CalcCornerArcStepAndCount imgui_draw.lua:4203 + [x] 64% ImDrawList::_PathArcToFastEx imgui_draw.lua:7113 + [x] 63% ImDrawList::_PathArcToN imgui_draw.lua:7133 + [x] 10% ImDrawList::PathArcToFast imgui_draw.lua:7119 + [x] 46% ImDrawList::PathArcTo imgui_draw.lua:7159 + [x] 61% ImDrawList::PathEllipticalArcTo imgui_draw.lua:7749 + [x] 88% ImBezierCubicCalc imgui_draw.lua:7761 + [x] 89% ImBezierQuadraticCalc imgui_draw.lua:7767 + [x] 85% PathBezierCubicCurveToCasteljau imgui_draw.lua:7774 + [x] 90% PathBezierQuadraticCurveToCasteljau imgui_draw.lua:7792 + [x] 91% ImDrawList::PathBezierCubicCurveTo imgui_draw.lua:7806 + [x] 90% ImDrawList::PathBezierQuadraticCurveTo imgui_draw.lua:7818 + [x] 8% ImDrawList::PathRect imgui_draw.lua:5579 + [x] 46% ImDrawList::_AddLine imgui_draw.lua:5711 + [x] 4% ImDrawList::AddLine imgui_draw.lua:5720 + [x] 9% ImDrawList::AddLineH imgui_draw.lua:5748 + [x] 9% ImDrawList::AddLineV imgui_draw.lua:5804 + [x] 18% ImDrawList::_AddRectBaked imgui_draw.lua:5964 + [x] 42% ImDrawList::_AddRectTinyRounding imgui_draw.lua:5981 + [x] 12% ImDrawList::AddRect imgui_draw.lua:6107 + [x] 10% ImDrawList::_AddRectFilledBaked imgui_draw.lua:6325 + [x] 11% ImDrawList::AddRectFilled imgui_draw.lua:6335 + [x] 26% ImDrawList::AddRectFilledMultiColor imgui_draw.lua:6441 + [x] 59% ImDrawList::AddQuad imgui_draw.lua:6464 + [x] 71% ImDrawList::AddQuadFilled imgui_draw.lua:6481 + [x] 59% ImDrawList::AddTriangle imgui_draw.lua:6493 + [x] 73% ImDrawList::AddTriangleFilled imgui_draw.lua:6510 + [x] 100% ApproxApothem imgui_draw.lua:4213 + [x] 47% ImDrawList::AddCircle imgui_draw.lua:6526 + [x] 32% ImDrawList::AddCircleFilled imgui_draw.lua:6591 + [x] 86% ImDrawList::AddNgon imgui_draw.lua:6629 + [x] 95% ImDrawList::AddNgonFilled imgui_draw.lua:6677 + [x] 80% ImDrawList::AddEllipse imgui_draw.lua:6702 + [x] 88% ImDrawList::AddEllipseFilled imgui_draw.lua:6739 + [x] 73% ImDrawList::AddBezierCubic imgui_draw.lua:6780 + [x] 71% ImDrawList::AddBezierQuadratic imgui_draw.lua:6796 + [x] 65% ImDrawList::AddText imgui_draw.lua:6821 + [x] 69% ImDrawList::AddImage imgui_draw.lua:6864 + [x] 63% ImDrawList::AddImageQuad imgui_draw.lua:6886 + [x] 84% ImDrawList::AddImageRounded imgui_draw.lua:6918 -- ImTriangulator, ImDrawList concave polygon fill - [x] 35% ImTriangulatorNode::Unlink imgui_draw.lua:7748 - [x] 50% ImTriangulatorNodeSpan::push_back imgui_draw.lua:7761 - [x] 66% ImTriangulatorNodeSpan::find_erase_unsorted imgui_draw.lua:7762 - [x] 84% ImTriangulator::EstimateTriangleCount imgui_draw.lua:7778 - [x] 71% ImTriangulator::EstimateScratchBufferSize imgui_draw.lua:7780 - [x] 38% ImTriangulator::Init imgui_draw.lua:7786 - [x] 45% ImTriangulator::BuildNodes imgui_draw.lua:7811 - [x] 32% ImTriangulator::BuildReflexes imgui_draw.lua:7824 - [x] 38% ImTriangulator::BuildEars imgui_draw.lua:7836 - [x] 53% ImTriangulator::GetNextTriangle imgui_draw.lua:7852 - [x] 65% ImTriangulator::FlipNodeList imgui_draw.lua:7890 - [x] 56% ImTriangulator::IsEar imgui_draw.lua:7913 - [x] 58% ImTriangulator::ReclassifyNode imgui_draw.lua:7928 - [x] 39% ImDrawList::AddConcavePolyFilled imgui_draw.lua:7971 + [x] 35% ImTriangulatorNode::Unlink imgui_draw.lua:7850 + [x] 50% ImTriangulatorNodeSpan::push_back imgui_draw.lua:7863 + [x] 66% ImTriangulatorNodeSpan::find_erase_unsorted imgui_draw.lua:7864 + [x] 84% ImTriangulator::EstimateTriangleCount imgui_draw.lua:7880 + [x] 71% ImTriangulator::EstimateScratchBufferSize imgui_draw.lua:7882 + [x] 38% ImTriangulator::Init imgui_draw.lua:7888 + [x] 45% ImTriangulator::BuildNodes imgui_draw.lua:7913 + [x] 32% ImTriangulator::BuildReflexes imgui_draw.lua:7926 + [x] 38% ImTriangulator::BuildEars imgui_draw.lua:7938 + [x] 53% ImTriangulator::GetNextTriangle imgui_draw.lua:7954 + [x] 65% ImTriangulator::FlipNodeList imgui_draw.lua:7992 + [x] 56% ImTriangulator::IsEar imgui_draw.lua:8015 + [x] 58% ImTriangulator::ReclassifyNode imgui_draw.lua:8030 + [x] 39% ImDrawList::AddConcavePolyFilled imgui_draw.lua:8073 -- ImDrawListSplitter - [x] 58% ImDrawListSplitter::ClearFreeMemory imgui_draw.lua:4471 - [x] 63% ImDrawListSplitter::Split imgui_draw.lua:4489 - [x] 54% ImDrawListSplitter::Merge imgui_draw.lua:4515 - [x] 29% ImDrawListSplitter::SetCurrentChannel imgui_draw.lua:4606 + [x] 58% ImDrawListSplitter::ClearFreeMemory imgui_draw.lua:4530 + [x] 63% ImDrawListSplitter::Split imgui_draw.lua:4548 + [x] 54% ImDrawListSplitter::Merge imgui_draw.lua:4574 + [x] 29% ImDrawListSplitter::SetCurrentChannel imgui_draw.lua:4665 -- ImDrawData [x] 60% ImDrawData::Clear imgui_draw.lua:4118 [x] 68% ImGui::AddDrawListToDrawDataEx imgui_draw.lua:4131 [x] 94% ImDrawData::AddDrawList imgui_draw.lua:4153 - [ ] ImDrawData::DeIndexAllBuffers - [ ] ImDrawData::ScaleClipRects + [x] 48% ImDrawData::DeIndexAllBuffers imgui_draw.lua:4160 + [x] 77% ImDrawData::ScaleClipRects imgui_draw.lua:4184 -- Helpers ShadeVertsXXX functions [x] 36% ImGui::ShadeVertsLinearColorGradientKeepAlpha imgui_draw.lua:351 @@ -1385,7 +1385,7 @@ imgui_draw.cpp [x] 16% ImGui::ShadeVertsTransformPos imgui_draw.lua:378 -- ImFontConfig - [x] 20% ImFontConfig::ImFontConfig imgui_h.lua:957 + [x] 20% ImFontConfig::ImFontConfig imgui_h.lua:967 -- ImTextureData [x] 76% ImTextureDataGetFormatBytesPerPixel imgui_draw.lua:2685 @@ -1395,7 +1395,7 @@ imgui_draw.cpp [x] 71% ImTextureData::DestroyPixels imgui_draw.lua:2680 -- ImFontAtlas, ImFontAtlasBuilder - [x] 39% ImFontAtlas::ImFontAtlas imgui_h.lua:1038 + [x] 39% ImFontAtlas::ImFontAtlas imgui_h.lua:1048 [-] ImFontAtlas::~ImFontAtlas c++-only [x] 93% ImFontAtlas::Clear imgui_draw.lua:571 [x] 76% ImFontAtlas::ClearFonts imgui_draw.lua:616 @@ -1524,9 +1524,9 @@ imgui_draw.cpp [x] 78% ImFontGlyphRangesBuilder::BuildRanges imgui_draw.lua:2768 -- ImFontBaked, ImFont - [x] 12% ImFontBaked::ImFontBaked imgui_h.lua:844 + [x] 12% ImFontBaked::ImFontBaked imgui_h.lua:854 [x] 79% ImFontBaked::ClearOutputData imgui_draw.lua:2788 - [x] 10% ImFont::ImFont imgui_h.lua:901 + [x] 10% ImFont::ImFont imgui_h.lua:911 [-] ImFont::~ImFont c++-only [x] 49% ImFont::ClearOutputData imgui_draw.lua:2842 [x] 58% ImFont::IsGlyphRangeUnused imgui_draw.lua:2855 @@ -1551,27 +1551,27 @@ imgui_draw.cpp [x] 49% ImFontCalcTextSizeEx imgui_draw.lua:3470 [x] 91% ImFont::CalcTextSizeA imgui_draw.lua:3631 [x] 85% ImFont::RenderChar imgui_draw.lua:3644 - [x] 66% ImFont::RenderText imgui_draw.lua:7123 + [x] 66% ImFont::RenderText imgui_draw.lua:7225 -- ImGui Internal Render Helpers - [x] 58% ImGui::RenderArrow imgui_draw.lua:7370 - [x] 88% ImGui::RenderBullet imgui_draw.lua:7402 - [x] 66% ImGui::RenderCheckMark imgui_draw.lua:7414 - [x] 90% ImGui::RenderArrowPointingAt imgui_draw.lua:7439 - [x] 93% ImGui::RenderArrowDockMenu imgui.lua:4551 - [x] 100% ImAcos01 imgui_draw.lua:7452 - [x] 95% ImGui::RenderRectFilledInRangeH imgui_draw.lua:7468 - [x] 80% ImGui::RenderRectFilledWithHole imgui_draw.lua:7625 - [x] 81% ImGui::CalcRoundingFlagsForRectInRect imgui_draw.lua:7523 - [x] 79% ImGui::RenderColorRectWithAlphaCheckerboard imgui_draw.lua:7559 + [x] 58% ImGui::RenderArrow imgui_draw.lua:7472 + [x] 88% ImGui::RenderBullet imgui_draw.lua:7504 + [x] 66% ImGui::RenderCheckMark imgui_draw.lua:7516 + [x] 90% ImGui::RenderArrowPointingAt imgui_draw.lua:7541 + [x] 93% ImGui::RenderArrowDockMenu imgui.lua:4584 + [x] 100% ImAcos01 imgui_draw.lua:7554 + [x] 95% ImGui::RenderRectFilledInRangeH imgui_draw.lua:7570 + [x] 80% ImGui::RenderRectFilledWithHole imgui_draw.lua:7727 + [x] 81% ImGui::CalcRoundingFlagsForRectInRect imgui_draw.lua:7625 + [x] 79% ImGui::RenderColorRectWithAlphaCheckerboard imgui_draw.lua:7661 -- Decompression code - [x] 59% stb_decompress_length imgui_draw.lua:8085 - [x] 49% stb__match imgui_draw.lua:8093 - [x] 80% stb__lit imgui_draw.lua:8109 - [x] 50% stb_decompress_token imgui_draw.lua:8121 - [x] 34% stb_adler32 imgui_draw.lua:8142 - [x] 44% stb_decompress imgui_draw.lua:8164 + [x] 59% stb_decompress_length imgui_draw.lua:8187 + [x] 49% stb__match imgui_draw.lua:8195 + [x] 80% stb__lit imgui_draw.lua:8211 + [x] 50% stb_decompress_token imgui_draw.lua:8223 + [x] 34% stb_adler32 imgui_draw.lua:8244 + [x] 44% stb_decompress imgui_draw.lua:8266 -- Default font data (ProggyClean.ttf) [ ] ImGui_GetDefaultCompressedFontDataProggyClean @@ -1584,143 +1584,143 @@ imgui_tables.cpp ==================================================================================================== -- Tables: Main code - [x] 67% TableFixFlags imgui_tables.lua:392 - [x] 95% ImGui::TableFindByID imgui_tables.lua:431 - [x] 100% ImGui::BeginTable imgui_tables.lua:455 - [x] 77% ImGui::BeginTableEx imgui_tables.lua:460 - [x] 26% ImGui::TableBeginInitMemory imgui_tables.lua:793 - [x] 72% ImGui::TableApplyQueuedRequests imgui_tables.lua:811 - [x] 76% ImGui::TableSetColumnDisplayOrder imgui_tables.lua:871 - [x] 82% TableGetMaxDisplayOrderAllowed imgui_tables.lua:899 - [x] 82% ImGui::TableQueueSetColumnDisplayOrder imgui_tables.lua:925 - [x] 62% TableSetupColumnFlags imgui_tables.lua:937 - [x] 82% ImGui::TableUpdateLayout imgui_tables.lua:996 - [x] 84% ImGui::TableApplyExternalUnclipRect imgui_tables.lua:1555 - [x] 76% ImGui::TableUpdateBorders imgui_tables.lua:1571 - [x] 80% ImGui::EndTable imgui_tables.lua:1633 - [x] 70% ImGui::TableInitColumnDefaults imgui_tables.lua:1851 - [x] 74% TableSetupColumnApply imgui_tables.lua:1881 - [x] 59% ImGui::TableSetupColumn imgui_tables.lua:1913 - [x] 60% ImGui::TableReconcileColumns imgui_tables.lua:1969 - [x] 76% ImGui::TableSetupScrollFreeze imgui_tables.lua:2035 + [x] 67% TableFixFlags imgui_tables.lua:396 + [x] 95% ImGui::TableFindByID imgui_tables.lua:435 + [x] 100% ImGui::BeginTable imgui_tables.lua:459 + [x] 77% ImGui::BeginTableEx imgui_tables.lua:464 + [x] 26% ImGui::TableBeginInitMemory imgui_tables.lua:797 + [x] 72% ImGui::TableApplyQueuedRequests imgui_tables.lua:815 + [x] 76% ImGui::TableSetColumnDisplayOrder imgui_tables.lua:875 + [x] 82% TableGetMaxDisplayOrderAllowed imgui_tables.lua:903 + [x] 82% ImGui::TableQueueSetColumnDisplayOrder imgui_tables.lua:929 + [x] 62% TableSetupColumnFlags imgui_tables.lua:941 + [x] 82% ImGui::TableUpdateLayout imgui_tables.lua:1000 + [x] 84% ImGui::TableApplyExternalUnclipRect imgui_tables.lua:1559 + [x] 76% ImGui::TableUpdateBorders imgui_tables.lua:1575 + [x] 80% ImGui::EndTable imgui_tables.lua:1637 + [x] 70% ImGui::TableInitColumnDefaults imgui_tables.lua:1855 + [x] 74% TableSetupColumnApply imgui_tables.lua:1885 + [x] 59% ImGui::TableSetupColumn imgui_tables.lua:1917 + [x] 60% ImGui::TableReconcileColumns imgui_tables.lua:1973 + [x] 76% ImGui::TableSetupScrollFreeze imgui_tables.lua:2039 -- Tables: Simple accessors - [x] 69% ImGui::TableGetColumnCount imgui_tables.lua:2088 - [x] 53% ImGui::TableGetColumnName imgui_tables.lua:2095 - [x] 83% ImGui::TableSetColumnEnabled imgui_tables.lua:2126 - [x] 78% ImGui::TableGetColumnFlags imgui_tables.lua:2140 - [x] 85% ImGui::TableGetCellBgRect imgui_tables.lua:2162 - [x] 74% ImGui::TableGetColumnResizeID imgui_tables.lua:2176 - [x] 81% ImGui::TableGetHoveredColumn imgui_tables.lua:2184 - [x] 81% ImGui::TableGetHoveredRow imgui_tables.lua:2196 - [x] 78% ImGui::TableSetBgColor imgui_tables.lua:2206 + [x] 69% ImGui::TableGetColumnCount imgui_tables.lua:2092 + [x] 53% ImGui::TableGetColumnName imgui_tables.lua:2099 + [x] 83% ImGui::TableSetColumnEnabled imgui_tables.lua:2130 + [x] 78% ImGui::TableGetColumnFlags imgui_tables.lua:2144 + [x] 85% ImGui::TableGetCellBgRect imgui_tables.lua:2166 + [x] 74% ImGui::TableGetColumnResizeID imgui_tables.lua:2180 + [x] 81% ImGui::TableGetHoveredColumn imgui_tables.lua:2188 + [x] 81% ImGui::TableGetHoveredRow imgui_tables.lua:2200 + [x] 78% ImGui::TableSetBgColor imgui_tables.lua:2210 -- Tables: Row changes - [x] 80% ImGui::TableGetRowIndex imgui_tables.lua:2256 - [x] 64% ImGui::TableNextRow imgui_tables.lua:2268 - [x] 68% ImGui::TableBeginRow imgui_tables.lua:2297 - [x] 74% ImGui::TableEndRow imgui_tables.lua:2341 + [x] 80% ImGui::TableGetRowIndex imgui_tables.lua:2260 + [x] 64% ImGui::TableNextRow imgui_tables.lua:2272 + [x] 68% ImGui::TableBeginRow imgui_tables.lua:2301 + [x] 74% ImGui::TableEndRow imgui_tables.lua:2345 -- Tables: Columns changes - [x] 80% ImGui::TableGetColumnIndex imgui_tables.lua:2508 - [x] 77% ImGui::TableSetColumnIndex imgui_tables.lua:2518 - [x] 59% ImGui::TableNextColumn imgui_tables.lua:2543 - [x] 69% ImGui::TableBeginCell imgui_tables.lua:2572 - [x] 58% ImGui::TableEndCell imgui_tables.lua:2635 + [x] 80% ImGui::TableGetColumnIndex imgui_tables.lua:2512 + [x] 77% ImGui::TableSetColumnIndex imgui_tables.lua:2522 + [x] 59% ImGui::TableNextColumn imgui_tables.lua:2547 + [x] 69% ImGui::TableBeginCell imgui_tables.lua:2576 + [x] 58% ImGui::TableEndCell imgui_tables.lua:2639 -- Tables: Columns width management - [x] 80% ImGui::TableCalcMaxColumnWidth imgui_tables.lua:2678 - [x] 84% ImGui::TableGetColumnWidthAuto imgui_tables.lua:2705 - [x] 88% ImGui::TableSetColumnWidth imgui_tables.lua:2724 - [x] 82% ImGui::TableSetColumnWidthAutoSingle imgui_tables.lua:2810 - [x] 71% ImGui::TableSetColumnWidthAutoAll imgui_tables.lua:2820 - [x] 78% ImGui::TableUpdateColumnsWeightFromWidth imgui_tables.lua:2830 + [x] 80% ImGui::TableCalcMaxColumnWidth imgui_tables.lua:2682 + [x] 84% ImGui::TableGetColumnWidthAuto imgui_tables.lua:2709 + [x] 88% ImGui::TableSetColumnWidth imgui_tables.lua:2728 + [x] 82% ImGui::TableSetColumnWidthAutoSingle imgui_tables.lua:2814 + [x] 71% ImGui::TableSetColumnWidthAutoAll imgui_tables.lua:2824 + [x] 78% ImGui::TableUpdateColumnsWeightFromWidth imgui_tables.lua:2834 -- Tables: Drawing - [x] 79% ImGui::TablePushBackgroundChannel imgui_tables.lua:2874 - [x] 82% ImGui::TablePopBackgroundChannel imgui_tables.lua:2885 - [x] 83% ImGui::TablePushColumnChannel imgui_tables.lua:2896 - [x] 82% ImGui::TablePopColumnChannel imgui_tables.lua:2910 - [x] 69% ImGui::TableSetupDrawChannels imgui_tables.lua:2940 - [x] 53% ImGui::TableMergeDrawChannels imgui_tables.lua:3019 - [x] 81% TableGetColumnBorderCol imgui_tables.lua:3189 - [x] 83% ImGui::TableDrawBorders imgui_tables.lua:3203 + [x] 79% ImGui::TablePushBackgroundChannel imgui_tables.lua:2878 + [x] 82% ImGui::TablePopBackgroundChannel imgui_tables.lua:2889 + [x] 83% ImGui::TablePushColumnChannel imgui_tables.lua:2900 + [x] 82% ImGui::TablePopColumnChannel imgui_tables.lua:2914 + [x] 69% ImGui::TableSetupDrawChannels imgui_tables.lua:2944 + [x] 53% ImGui::TableMergeDrawChannels imgui_tables.lua:3023 + [x] 81% TableGetColumnBorderCol imgui_tables.lua:3193 + [x] 83% ImGui::TableDrawBorders imgui_tables.lua:3207 -- Tables: Sorting - [x] 71% ImGui::TableGetSortSpecs imgui_tables.lua:3311 - [x] 74% TableGetColumnAvailSortDirection imgui_tables.lua:3327 - [x] 90% ImGui::TableFixColumnSortDirection imgui_tables.lua:3333 - [x] 91% ImGui::TableGetColumnNextSortDirection imgui_tables.lua:3344 - [x] 82% ImGui::TableSetColumnSortDirection imgui_tables.lua:3360 - [x] 73% ImGui::TableSortSpecsSanitize imgui_tables.lua:3397 - [x] 66% ImGui::TableSortSpecsBuild imgui_tables.lua:3469 + [x] 71% ImGui::TableGetSortSpecs imgui_tables.lua:3315 + [x] 74% TableGetColumnAvailSortDirection imgui_tables.lua:3331 + [x] 90% ImGui::TableFixColumnSortDirection imgui_tables.lua:3337 + [x] 91% ImGui::TableGetColumnNextSortDirection imgui_tables.lua:3348 + [x] 82% ImGui::TableSetColumnSortDirection imgui_tables.lua:3364 + [x] 73% ImGui::TableSortSpecsSanitize imgui_tables.lua:3401 + [x] 66% ImGui::TableSortSpecsBuild imgui_tables.lua:3473 -- Tables: Headers - [x] 79% ImGui::TableGetHeaderRowHeight imgui_tables.lua:3521 - [x] 77% ImGui::TableGetHeaderAngledMaxLabelWidth imgui_tables.lua:3539 - [x] 81% ImGui::TableHeadersRow imgui_tables.lua:3560 - [x] 80% ImGui::TableHeader imgui_tables.lua:3602 - [x] 79% ImGui::TableAngledHeadersRow imgui_tables.lua:3749 - [x] 87% ImGui::TableAngledHeadersRowEx imgui_tables.lua:3796 + [x] 79% ImGui::TableGetHeaderRowHeight imgui_tables.lua:3525 + [x] 77% ImGui::TableGetHeaderAngledMaxLabelWidth imgui_tables.lua:3543 + [x] 81% ImGui::TableHeadersRow imgui_tables.lua:3564 + [x] 80% ImGui::TableHeader imgui_tables.lua:3606 + [x] 79% ImGui::TableAngledHeadersRow imgui_tables.lua:3753 + [x] 87% ImGui::TableAngledHeadersRowEx imgui_tables.lua:3800 -- Tables: Context Menu - [x] 78% ImGui::TableOpenContextMenu imgui_tables.lua:3943 - [x] 83% ImGui::TableBeginContextMenuPopup imgui_tables.lua:3963 - [x] 88% MenuItemForColumnReorder imgui_tables.lua:3976 - [x] 78% ImGui::TableDrawDefaultContextMenu imgui_tables.lua:4012 + [x] 78% ImGui::TableOpenContextMenu imgui_tables.lua:3947 + [x] 83% ImGui::TableBeginContextMenuPopup imgui_tables.lua:3967 + [x] 88% MenuItemForColumnReorder imgui_tables.lua:3980 + [x] 78% ImGui::TableDrawDefaultContextMenu imgui_tables.lua:4016 -- Tables: Settings (.ini data) - [x] 62% TableSettingsInit imgui_tables.lua:4160 + [x] 62% TableSettingsInit imgui_tables.lua:4164 [ ] TableSettingsCalcChunkSize - [x] 88% ImGui::TableSettingsCreate imgui_tables.lua:4171 - [x] 65% ImGui::TableSettingsFindByID imgui_tables.lua:4188 - [x] 86% ImGui::TableGetBoundSettings imgui_tables.lua:4205 - [x] 79% ImGui::TableResetSettings imgui_tables.lua:4216 - [x] 77% ImGui::TableSaveSettings imgui_tables.lua:4223 - [x] 73% ImGui::TableLoadSettings imgui_tables.lua:4285 - [x] 76% ImGui::TableLoadSettingsForColumns imgui_tables.lua:4312 - [x] 85% ImGui::TableLoadSettingsForColumn imgui_tables.lua:4373 - [ ] TableFixDisplayOrderComparer - [x] 40% ImGui::TableFixDisplayOrder imgui_tables.lua:4398 - [x] 65% TableSettingsHandler_ClearAll imgui_tables.lua:4437 - [ ] TableSettingsHandler_Cleanup - [x] 64% TableSettingsHandler_ApplyAll imgui_tables.lua:4444 - [x] 65% TableSettingsHandler_ReadOpen imgui_tables.lua:4452 - [x] 35% TableSettingsHandler_ReadLine imgui_tables.lua:4467 - [x] 80% TableSettingsHandler_WriteAll imgui_tables.lua:4507 - [x] 90% ImGui::TableSettingsAddSettingsHandler imgui_tables.lua:4546 + [x] 88% ImGui::TableSettingsCreate imgui_tables.lua:4175 + [x] 65% ImGui::TableSettingsFindByID imgui_tables.lua:4192 + [x] 86% ImGui::TableGetBoundSettings imgui_tables.lua:4209 + [x] 79% ImGui::TableResetSettings imgui_tables.lua:4220 + [x] 77% ImGui::TableSaveSettings imgui_tables.lua:4227 + [x] 73% ImGui::TableLoadSettings imgui_tables.lua:4289 + [x] 76% ImGui::TableLoadSettingsForColumns imgui_tables.lua:4316 + [x] 85% ImGui::TableLoadSettingsForColumn imgui_tables.lua:4377 + [x] 31% TableFixDisplayOrderComparer imgui_tables.lua:4402 + [x] 55% ImGui::TableFixDisplayOrder imgui_tables.lua:4413 + [x] 65% TableSettingsHandler_ClearAll imgui_tables.lua:4463 + [x] 77% TableSettingsHandler_Cleanup imgui_tables.lua:4435 + [x] 64% TableSettingsHandler_ApplyAll imgui_tables.lua:4470 + [x] 65% TableSettingsHandler_ReadOpen imgui_tables.lua:4478 + [x] 35% TableSettingsHandler_ReadLine imgui_tables.lua:4493 + [x] 80% TableSettingsHandler_WriteAll imgui_tables.lua:4533 + [x] 85% ImGui::TableSettingsAddSettingsHandler imgui_tables.lua:4572 -- Tables: Garbage Collection - [x] 79% ImGui::TableRemove imgui_tables.lua:4567 - [x] 60% ImGui::TableGcCompactTransientBuffers imgui_tables.lua:4577 - [x] 36% ImGui::TableGcCompactSettings imgui_tables.lua:4601 + [x] 79% ImGui::TableRemove imgui_tables.lua:4594 + [x] 60% ImGui::TableGcCompactTransientBuffers imgui_tables.lua:4604 + [x] 36% ImGui::TableGcCompactSettings imgui_tables.lua:4628 -- Tables: Debugging - [ ] DebugNodeTableGetSizingPolicyDesc - [x] 16% ImGui::DebugNodeTable imgui.lua:20783 - [x] 69% ImGui::DebugNodeTableSettings imgui.lua:20765 + [x] 89% DebugNodeTableGetSizingPolicyDesc imgui_tables.lua:4650 + [x] 16% ImGui::DebugNodeTable imgui.lua:21754 + [x] 69% ImGui::DebugNodeTableSettings imgui.lua:21736 -- Columns, BeginColumns, EndColumns, etc. - [x] 24% ImGui::SetWindowClipRectBeforeSetChannel imgui_tables.lua:2070 - [x] 92% ImGui::GetColumnIndex imgui_tables.lua:4642 - [x] 92% ImGui::GetColumnsCount imgui_tables.lua:4647 - [x] 100% ImGui::GetColumnOffsetFromNorm imgui_tables.lua:4652 - [x] 100% ImGui::GetColumnNormFromOffset imgui_tables.lua:4656 - [x] 96% GetDraggedColumnOffset imgui_tables.lua:4662 - [x] 89% ImGui::GetColumnOffset imgui_tables.lua:4679 - [x] 64% GetColumnWidthEx imgui_tables.lua:4697 - [x] 72% ImGui::GetColumnWidth imgui_tables.lua:4712 - [x] 93% ImGui::SetColumnOffset imgui_tables.lua:4728 - [x] 97% ImGui::SetColumnWidth imgui_tables.lua:4752 - [x] 92% ImGui::PushColumnClipRect imgui_tables.lua:4763 - [x] 93% ImGui::PushColumnsBackground imgui_tables.lua:4775 - [x] 97% ImGui::PopColumnsBackground imgui_tables.lua:4788 - [x] 55% ImGui::FindOrCreateColumns imgui_tables.lua:4800 - [x] 80% ImGui::GetColumnsID imgui_tables.lua:4814 - [x] 94% ImGui::BeginColumns imgui_tables.lua:4826 - [x] 95% ImGui::NextColumn imgui_tables.lua:4901 - [x] 88% ImGui::EndColumns imgui_tables.lua:4955 - [x] 83% ImGui::Columns imgui_tables.lua:5034 + [x] 24% ImGui::SetWindowClipRectBeforeSetChannel imgui_tables.lua:2074 + [x] 92% ImGui::GetColumnIndex imgui_tables.lua:4683 + [x] 92% ImGui::GetColumnsCount imgui_tables.lua:4688 + [x] 100% ImGui::GetColumnOffsetFromNorm imgui_tables.lua:4693 + [x] 100% ImGui::GetColumnNormFromOffset imgui_tables.lua:4697 + [x] 96% GetDraggedColumnOffset imgui_tables.lua:4703 + [x] 89% ImGui::GetColumnOffset imgui_tables.lua:4720 + [x] 64% GetColumnWidthEx imgui_tables.lua:4738 + [x] 72% ImGui::GetColumnWidth imgui_tables.lua:4753 + [x] 93% ImGui::SetColumnOffset imgui_tables.lua:4769 + [x] 97% ImGui::SetColumnWidth imgui_tables.lua:4793 + [x] 92% ImGui::PushColumnClipRect imgui_tables.lua:4804 + [x] 93% ImGui::PushColumnsBackground imgui_tables.lua:4816 + [x] 97% ImGui::PopColumnsBackground imgui_tables.lua:4829 + [x] 55% ImGui::FindOrCreateColumns imgui_tables.lua:4841 + [x] 80% ImGui::GetColumnsID imgui_tables.lua:4855 + [x] 94% ImGui::BeginColumns imgui_tables.lua:4867 + [x] 95% ImGui::NextColumn imgui_tables.lua:4942 + [x] 88% ImGui::EndColumns imgui_tables.lua:4996 + [x] 83% ImGui::Columns imgui_tables.lua:5075 ==================================================================================================== imgui_demo.cpp @@ -1735,125 +1735,125 @@ imgui_demo.cpp [x] 22% ImGui::ShowDemoWindow imgui_demo.lua:287 -- DemoWindowMenuBar() - [x] 60% DemoWindowMenuBar imgui_demo.lua:652 + [x] 57% DemoWindowMenuBar imgui_demo.lua:652 -- Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) - [x] 52% ExampleTree_CreateNode imgui_demo.lua:760 - [x] 67% ExampleTree_DestroyNode imgui_demo.lua:772 - [x] 65% ExampleTree_CreateDemoTree imgui_demo.lua:786 + [x] 52% ExampleTree_CreateNode imgui_demo.lua:759 + [x] 67% ExampleTree_DestroyNode imgui_demo.lua:771 + [x] 65% ExampleTree_CreateDemoTree imgui_demo.lua:785 -- Helpers: ExampleImageViewer - [x] 89% ExampleImageViewer_DrawOptions imgui_demo.lua:839 - [x] 93% ExampleImageViewer_DrawCanvas imgui_demo.lua:852 + [x] 89% ExampleImageViewer_DrawOptions imgui_demo.lua:838 + [x] 93% ExampleImageViewer_DrawCanvas imgui_demo.lua:851 -- DemoWindowWidgetsBasic() - [x] 77% DemoWindowWidgetsBasic imgui_demo.lua:935 + [x] 72% DemoWindowWidgetsBasic imgui_demo.lua:934 -- DemoWindowWidgetsBullets() - [x] 97% DemoWindowWidgetsBullets imgui_demo.lua:1135 + [x] 87% DemoWindowWidgetsBullets imgui_demo.lua:1134 -- DemoWindowWidgetsCollapsingHeaders() - [x] 68% DemoWindowWidgetsCollapsingHeaders imgui_demo.lua:1158 + [x] 65% DemoWindowWidgetsCollapsingHeaders imgui_demo.lua:1157 -- DemoWindowWidgetsColorAndPickers() - [x] 73% DemoWindowWidgetsColorAndPickers imgui_demo.lua:1206 + [x] 71% DemoWindowWidgetsColorAndPickers imgui_demo.lua:1205 -- DemoWindowWidgetsComboBoxes() - [x] 70% DemoWindowWidgetsComboBoxes imgui_demo.lua:1411 + [x] 69% DemoWindowWidgetsComboBoxes imgui_demo.lua:1410 -- DemoWindowWidgetsDataTypes() - [x] 65% DemoWindowWidgetsDataTypes imgui_demo.lua:1532 + [x] 64% DemoWindowWidgetsDataTypes imgui_demo.lua:1531 -- DemoWindowWidgetsDisableBlocks() - [x] 84% DemoWindowWidgetsDisableBlocks imgui_demo.lua:1648 + [x] 72% DemoWindowWidgetsDisableBlocks imgui_demo.lua:1647 -- DemoWindowWidgetsDragAndDrop() - [x] 76% DemoWindowWidgetsDragAndDrop imgui_demo.lua:1675 + [x] 73% DemoWindowWidgetsDragAndDrop imgui_demo.lua:1674 -- DemoWindowWidgetsDragsAndSliders() - [x] 79% DemoWindowWidgetsDragsAndSliders imgui_demo.lua:1817 + [x] 78% DemoWindowWidgetsDragsAndSliders imgui_demo.lua:1816 -- DemoWindowWidgetsFonts() - [x] 94% DemoWindowWidgetsFonts imgui_demo.lua:1867 + [x] 77% DemoWindowWidgetsFonts imgui_demo.lua:1866 -- DemoWindowWidgetsImages() - [x] 89% DemoWindowWidgetsImages imgui_demo.lua:1885 + [x] 87% DemoWindowWidgetsImages imgui_demo.lua:1884 -- DemoWindowWidgetsListBoxes() - [x] 82% DemoWindowWidgetsListBoxes imgui_demo.lua:1970 + [x] 80% DemoWindowWidgetsListBoxes imgui_demo.lua:1969 -- DemoWindowWidgetsLiveEdit() - [x] 81% DemoWindowWidgetsLiveEdit imgui_demo.lua:2040 + [x] 79% DemoWindowWidgetsLiveEdit imgui_demo.lua:2039 -- DemoWindowWidgetsMixedValues() - [x] 66% DemoWindowWidgetsMixedValues imgui_demo.lua:2079 + [x] 66% DemoWindowWidgetsMixedValues imgui_demo.lua:2078 -- DemoWindowWidgetsMultiComponents() - [x] 86% DemoWindowWidgetsMultiComponents imgui_demo.lua:2147 + [x] 86% DemoWindowWidgetsMultiComponents imgui_demo.lua:2146 -- DemoWindowWidgetsPlotting() - [x] 70% DemoWindowWidgetsPlotting imgui_demo.lua:2213 + [x] 69% DemoWindowWidgetsPlotting imgui_demo.lua:2212 -- DemoWindowWidgetsProgressBars() - [x] 78% DemoWindowWidgetsProgressBars imgui_demo.lua:2283 + [x] 76% DemoWindowWidgetsProgressBars imgui_demo.lua:2282 -- DemoWindowWidgetsQueryingStatuses() - [x] 74% DemoWindowWidgetsQueryingStatuses imgui_demo.lua:2334 + [x] 74% DemoWindowWidgetsQueryingStatuses imgui_demo.lua:2333 -- DemoWindowWidgetsSelectables() - [x] 66% DemoWindowWidgetsSelectables imgui_demo.lua:2584 + [x] 64% DemoWindowWidgetsSelectables imgui_demo.lua:2583 -- DemoWindowWidgetsSelectionAndMultiSelect() - [x] 87% ExampleSelectionWithDeletion::ApplyDeletionPreLoop imgui_demo.lua:2774 - [x] 84% ExampleSelectionWithDeletion::ApplyDeletionPostLoop imgui_demo.lua:2807 - [x] 74% ExampleDualListBox::MoveAll imgui_demo.lua:2841 - [x] 59% ExampleDualListBox::MoveSelected imgui_demo.lua:2851 - [x] 74% ExampleDualListBox::ApplySelectionRequests imgui_demo.lua:2871 - [x] 29% ExampleDualListBox::CompareItemsByValue imgui_demo.lua:2878 - [x] 36% ExampleDualListBox::SortItems imgui_demo.lua:2881 - [x] 90% ExampleDualListBox::Show imgui_demo.lua:2886 - [x] 71% DemoWindowWidgetsSelectionAndMultiSelect imgui_demo.lua:3130 + [x] 87% ExampleSelectionWithDeletion::ApplyDeletionPreLoop imgui_demo.lua:2773 + [x] 84% ExampleSelectionWithDeletion::ApplyDeletionPostLoop imgui_demo.lua:2806 + [x] 74% ExampleDualListBox::MoveAll imgui_demo.lua:2840 + [x] 59% ExampleDualListBox::MoveSelected imgui_demo.lua:2850 + [x] 74% ExampleDualListBox::ApplySelectionRequests imgui_demo.lua:2870 + [x] 29% ExampleDualListBox::CompareItemsByValue imgui_demo.lua:2877 + [x] 36% ExampleDualListBox::SortItems imgui_demo.lua:2880 + [x] 90% ExampleDualListBox::Show imgui_demo.lua:2885 + [x] 70% DemoWindowWidgetsSelectionAndMultiSelect imgui_demo.lua:3129 -- DemoWindowWidgetsTabs() - [x] 58% EditTabBarFittingPolicyFlags imgui_demo.lua:3755 - [x] 70% DemoWindowWidgetsTabs imgui_demo.lua:3785 + [x] 58% EditTabBarFittingPolicyFlags imgui_demo.lua:3754 + [x] 68% DemoWindowWidgetsTabs imgui_demo.lua:3784 -- DemoWindowWidgetsText() - [x] 89% DemoWindowWidgetsText imgui_demo.lua:3941 + [x] 85% DemoWindowWidgetsText imgui_demo.lua:3940 -- DemoWindowWidgetsTextFilter() - [x] 84% DemoWindowWidgetsTextFilter imgui_demo.lua:4055 + [x] 81% DemoWindowWidgetsTextFilter imgui_demo.lua:4054 -- DemoWindowWidgetsTextInput() - [x] 75% DemoWindowWidgetsTextInput imgui_demo.lua:4130 + [x] 73% DemoWindowWidgetsTextInput imgui_demo.lua:4129 -- DemoWindowWidgetsTooltips() - [x] 84% DemoWindowWidgetsTooltips imgui_demo.lua:4314 + [x] 83% DemoWindowWidgetsTooltips imgui_demo.lua:4313 -- DemoWindowWidgetsTreeNodes() - [x] 75% DemoWindowWidgetsTreeNodes imgui_demo.lua:4421 + [x] 72% DemoWindowWidgetsTreeNodes imgui_demo.lua:4420 -- DemoWindowWidgetsVerticalSliders() - [x] 83% DemoWindowWidgetsVerticalSliders imgui_demo.lua:4602 + [x] 82% DemoWindowWidgetsVerticalSliders imgui_demo.lua:4601 -- DemoWindowWidgets() - [x] 97% DemoWindowWidgets imgui_demo.lua:4670 + [x] 97% DemoWindowWidgets imgui_demo.lua:4669 -- DemoWindowLayout() - [x] 81% DemoWindowLayout imgui_demo.lua:4777 + [x] 80% DemoWindowLayout imgui_demo.lua:4776 -- DemoWindowPopups() - [x] 59% DemoWindowPopups imgui_demo.lua:5621 - [x] 36% MyItem::SortWithSortSpecs imgui_demo.lua:5939 - [x] 68% MyItem::CompareWithSortSpecs imgui_demo.lua:5956 - [x] 96% PushStyleCompact imgui_demo.lua:5983 - [x] 100% PopStyleCompact imgui_demo.lua:5989 - [x] 69% EditTableSizingFlags imgui_demo.lua:5996 - [x] 74% EditTableColumnsFlags imgui_demo.lua:6048 - [x] 100% ShowTableColumnsStatusFlags imgui_demo.lua:6078 + [x] 56% DemoWindowPopups imgui_demo.lua:5620 + [x] 36% MyItem::SortWithSortSpecs imgui_demo.lua:5938 + [x] 68% MyItem::CompareWithSortSpecs imgui_demo.lua:5955 + [x] 96% PushStyleCompact imgui_demo.lua:5982 + [x] 100% PopStyleCompact imgui_demo.lua:5988 + [x] 69% EditTableSizingFlags imgui_demo.lua:5995 + [x] 74% EditTableColumnsFlags imgui_demo.lua:6047 + [x] 100% ShowTableColumnsStatusFlags imgui_demo.lua:6077 -- DemoWindowTables() - [x] 41% DemoWindowTables imgui_demo.lua:6224 + [x] 41% DemoWindowTables imgui_demo.lua:6223 ==================================================================================================== imgui.h @@ -1864,7 +1864,7 @@ imgui.h [x] 0% ImVec4::ImVec4 imgui_h.lua:357 -- Texture identifiers (ImTextureID, ImTextureRef) - [x] 60% IM_MSVC_RUNTIME_CHECKS_OFF::ImTextureRef imgui_h.lua:807 + [x] 55% IM_MSVC_RUNTIME_CHECKS_OFF::ImTextureRef imgui_h.lua:810 -- Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) [x] 35% ImGuiTableSortSpecs::ImGuiTableSortSpecs imgui_tables.lua:232 @@ -1909,35 +1909,35 @@ imgui.h [ ] IM_MSVC_RUNTIME_CHECKS_OFF::index_from_ptr -- Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) - [x] 80% ImGuiInputTextCallbackData::SelectAll imgui_h.lua:2546 - [ ] ImGuiInputTextCallbackData::SetSelection - [x] 83% ImGuiInputTextCallbackData::ClearSelection imgui_h.lua:2547 - [x] 89% ImGuiInputTextCallbackData::HasSelection imgui_h.lua:2548 - [x] 29% ImGuiWindowClass::ImGuiWindowClass imgui_h.lua:2412 - [x] 0% ImGuiPayload::ImGuiPayload imgui_h.lua:2756 - [x] 61% ImGuiPayload::Clear imgui_h.lua:2752 - [x] 55% ImGuiPayload::IsDataType imgui_h.lua:2753 - [x] 100% ImGuiPayload::IsPreview imgui_h.lua:2754 - [x] 100% ImGuiPayload::IsDelivery imgui_h.lua:2755 + [x] 84% ImGuiInputTextCallbackData::SelectAll imgui_h.lua:2556 + [x] 77% ImGuiInputTextCallbackData::SetSelection imgui_h.lua:2557 + [x] 83% ImGuiInputTextCallbackData::ClearSelection imgui_h.lua:2558 + [x] 89% ImGuiInputTextCallbackData::HasSelection imgui_h.lua:2559 + [x] 29% ImGuiWindowClass::ImGuiWindowClass imgui_h.lua:2422 + [x] 0% ImGuiPayload::ImGuiPayload imgui_h.lua:2767 + [x] 61% ImGuiPayload::Clear imgui_h.lua:2763 + [x] 55% ImGuiPayload::IsDataType imgui_h.lua:2764 + [x] 100% ImGuiPayload::IsPreview imgui_h.lua:2765 + [x] 100% ImGuiPayload::IsDelivery imgui_h.lua:2766 -- Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) - [ ] ImGuiOnceUponAFrame::ImGuiOnceUponAFrame + [x] 57% ImGuiOnceUponAFrame::ImGuiOnceUponAFrame imgui_internal.lua:3803 [-] ImGuiOnceUponAFrame::operatorbool c++-only - [x] 80% ImGuiTextFilter::Clear imgui.lua:19388 - [x] 100% ImGuiTextFilter::IsActive imgui.lua:19389 + [x] 80% ImGuiTextFilter::Clear imgui.lua:19863 + [x] 100% ImGuiTextFilter::IsActive imgui.lua:19864 [-] ImGuiTextFilter::Draw obsolete - [x] 0% ImGuiTextBuffer::ImGuiTextBuffer imgui_h.lua:2773 + [x] 0% ImGuiTextBuffer::ImGuiTextBuffer imgui_h.lua:2784 [ ] ImGuiTextBuffer::begin [ ] ImGuiTextBuffer::end - [x] 14% ImGuiTextBuffer::size imgui_h.lua:2779 - [x] 33% ImGuiTextBuffer::empty imgui_h.lua:2775 - [x] 40% ImGuiTextBuffer::clear imgui_h.lua:2774 + [x] 14% ImGuiTextBuffer::size imgui_h.lua:2790 + [x] 33% ImGuiTextBuffer::empty imgui_h.lua:2786 + [x] 40% ImGuiTextBuffer::clear imgui_h.lua:2785 [ ] ImGuiTextBuffer::resize [ ] ImGuiTextBuffer::reserve - [x] 31% ImGuiTextBuffer::c_str imgui_h.lua:2778 + [x] 31% ImGuiTextBuffer::c_str imgui_h.lua:2789 [ ] ImGuiStoragePair::ImGuiStoragePair [ ] ImGuiStorage::Clear - [x] 100% ImGuiListClipper::IncludeItemByIndex imgui.lua:19619 + [x] 100% ImGuiListClipper::IncludeItemByIndex imgui.lua:20094 [-] operator+ c++-only [-] operator- c++-only [-] operator* c++-only @@ -1948,32 +1948,32 @@ imgui.h [-] operator/= c++-only [-] operator== c++-only [-] operator!= c++-only - [x] n/a IM_MSVC_RUNTIME_CHECKS_RESTORE::ImColor imgui_h.lua:2789 = setmetatable ( { } , { + [x] n/a IM_MSVC_RUNTIME_CHECKS_RESTORE::ImColor imgui_h.lua:2800 = setmetatable ( { } , { [-] IM_MSVC_RUNTIME_CHECKS_RESTORE::operatorImU32 c++-only [-] IM_MSVC_RUNTIME_CHECKS_RESTORE::operatorImVec4 c++-only [ ] IM_MSVC_RUNTIME_CHECKS_RESTORE::SetHSV [ ] IM_MSVC_RUNTIME_CHECKS_RESTORE::HSV -- Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiSelectionRequestType, ImGuiSelectionRequest, ImGuiMultiSelectIO, ImGuiSelectionBasicStorage) - [x] 100% ImGuiSelectionBasicStorage::GetStorageIdFromIndex imgui_widgets.lua:9503 + [x] 100% ImGuiSelectionBasicStorage::GetStorageIdFromIndex imgui_widgets.lua:9615 -- Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawList, ImDrawData) - [x] 14% ImDrawCmd::ImDrawCmd imgui_h.lua:507 + [x] 13% ImDrawCmd::ImDrawCmd imgui_h.lua:507 [x] 18% ImDrawListSplitter::ImDrawListSplitter imgui_h.lua:594 [-] ImDrawListSplitter::~ImDrawListSplitter c++-only - [x] 92% ImDrawListSplitter::Clear imgui_draw.lua:4466 - [ ] ImDrawList::GetClipRectMin - [ ] ImDrawList::GetClipRectMax - [x] 80% ImDrawList::AddPolyline imgui_internal.lua:1089 - [x] 100% ImDrawList::PathClear imgui_internal.lua:1041 - [x] 16% ImDrawList::PathLineTo imgui_internal.lua:1045 - [x] 48% ImDrawList::PathLineToMergeDuplicate imgui_internal.lua:1055 - [x] 94% ImDrawList::PathFillConvex imgui_internal.lua:1065 - [x] 94% ImDrawList::PathFillConcave imgui_draw.lua:8065 - [x] 75% ImDrawList::PathStroke imgui_internal.lua:1073 - [x] 89% ImDrawList::ChannelsSplit imgui_draw.lua:4647 - [x] 80% ImDrawList::ChannelsMerge imgui_draw.lua:4648 - [x] 89% ImDrawList::ChannelsSetCurrent imgui_draw.lua:4650 + [x] 92% ImDrawListSplitter::Clear imgui_draw.lua:4525 + [x] 92% ImDrawList::GetClipRectMin imgui_draw.lua:7003 + [x] 92% ImDrawList::GetClipRectMax imgui_draw.lua:7004 + [x] 80% ImDrawList::AddPolyline imgui_internal.lua:1151 + [x] 100% ImDrawList::PathClear imgui_internal.lua:1103 + [x] 16% ImDrawList::PathLineTo imgui_internal.lua:1107 + [x] 48% ImDrawList::PathLineToMergeDuplicate imgui_internal.lua:1117 + [x] 94% ImDrawList::PathFillConvex imgui_internal.lua:1127 + [x] 94% ImDrawList::PathFillConcave imgui_draw.lua:8167 + [x] 75% ImDrawList::PathStroke imgui_internal.lua:1135 + [x] 89% ImDrawList::ChannelsSplit imgui_draw.lua:4706 + [x] 80% ImDrawList::ChannelsMerge imgui_draw.lua:4707 + [x] 89% ImDrawList::ChannelsSetCurrent imgui_draw.lua:4709 [x] 16% ImDrawList::PrimWriteVtx imgui_h.lua:631 [x] 44% ImDrawList::PrimWriteIdx imgui_h.lua:641 [x] 89% ImDrawList::PrimVtx imgui_h.lua:649 @@ -1985,43 +1985,43 @@ imgui.h -- Texture API (ImTextureFormat, ImTextureStatus, ImTextureRect, ImTextureData) [x] 14% ImTextureData::ImTextureData imgui_h.lua:751 [-] ImTextureData::~ImTextureData c++-only - [ ] ImTextureData::GetPixels - [x] 58% ImTextureData::GetPixelsAt imgui_h.lua:778 - [ ] ImTextureData::GetSizeInBytes - [x] 86% ImTextureData::GetPitch imgui_h.lua:782 - [ ] ImTextureData::GetTexRef - [x] 100% ImTextureData::GetTexID imgui_h.lua:783 - [x] 100% ImTextureData::SetTexID imgui_h.lua:786 - [x] 95% ImTextureData::SetStatus imgui_h.lua:789 + [x] 71% ImTextureData::GetPixels imgui_h.lua:778 + [x] 58% ImTextureData::GetPixelsAt imgui_h.lua:779 + [x] 80% ImTextureData::GetSizeInBytes imgui_h.lua:783 + [x] 86% ImTextureData::GetPitch imgui_h.lua:784 + [x] 76% ImTextureData::GetTexRef imgui_h.lua:785 + [x] 100% ImTextureData::GetTexID imgui_h.lua:786 + [x] 100% ImTextureData::SetTexID imgui_h.lua:789 + [x] 95% ImTextureData::SetStatus imgui_h.lua:792 -- Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont) - [x] 21% ImFontGlyph::ImFontGlyph imgui_h.lua:1126 - [x] 13% ImFontGlyphRangesBuilder::ImFontGlyphRangesBuilder imgui_h.lua:1150 - [x] 63% ImFontGlyphRangesBuilder::Clear imgui_h.lua:1156 - [x] 68% ImFontGlyphRangesBuilder::GetBit imgui_h.lua:1163 - [x] 51% ImFontGlyphRangesBuilder::SetBit imgui_h.lua:1165 - [x] 100% ImFontGlyphRangesBuilder::AddChar imgui_h.lua:1167 - [x] 14% ImFontAtlasRect::ImFontAtlasRect imgui_h.lua:1098 + [x] 21% ImFontGlyph::ImFontGlyph imgui_h.lua:1136 + [x] 13% ImFontGlyphRangesBuilder::ImFontGlyphRangesBuilder imgui_h.lua:1160 + [x] 63% ImFontGlyphRangesBuilder::Clear imgui_h.lua:1166 + [x] 68% ImFontGlyphRangesBuilder::GetBit imgui_h.lua:1173 + [x] 51% ImFontGlyphRangesBuilder::SetBit imgui_h.lua:1175 + [x] 100% ImFontGlyphRangesBuilder::AddChar imgui_h.lua:1177 + [x] 14% ImFontAtlasRect::ImFontAtlasRect imgui_h.lua:1108 [-] ImFontAtlas::SetTexID obsolete [-] ImFontAtlas::IsBuilt obsolete [-] ImFontAtlas::AddCustomRectRegular obsolete [-] ImFontAtlas::GetCustomRectByIndex obsolete [-] ImFontAtlas::CalcCustomRectUV obsolete - [x] 100% ImFont::IsLoaded imgui_h.lua:896 - [x] 58% ImFont::GetDebugName imgui_h.lua:897 + [x] 100% ImFont::IsLoaded imgui_h.lua:906 + [x] 58% ImFont::GetDebugName imgui_h.lua:907 [-] ImFont::CalcWordWrapPositionA obsolete - [ ] ImTextureRef::GetTexID - [ ] ImDrawCmd::GetTexID + [x] 63% ImTextureRef::GetTexID imgui_h.lua:820 + [x] 76% ImDrawCmd::GetTexID imgui_h.lua:522 -- Viewports - [x] 7% ImGuiViewport::ImGuiViewport imgui_h.lua:1519 + [x] 7% ImGuiViewport::ImGuiViewport imgui_h.lua:1529 [-] ImGuiViewport::~ImGuiViewport c++-only - [x] 90% ImGuiViewport::GetCenter imgui_h.lua:1509 - [x] 90% ImGuiViewport::GetWorkCenter imgui_h.lua:1513 + [x] 90% ImGuiViewport::GetCenter imgui_h.lua:1519 + [x] 90% ImGuiViewport::GetWorkCenter imgui_h.lua:1523 -- ImGuiPlatformIO + other Platform Dependent Interfaces (ImGuiPlatformMonitor, ImGuiPlatformImeData) - [x] 42% ImGuiPlatformMonitor::ImGuiPlatformMonitor imgui_h.lua:1613 - [x] 24% ImGuiPlatformImeData::ImGuiPlatformImeData imgui_h.lua:1419 + [x] 42% ImGuiPlatformMonitor::ImGuiPlatformMonitor imgui_h.lua:1623 + [x] 24% ImGuiPlatformImeData::ImGuiPlatformImeData imgui_h.lua:1429 -- Obsolete functions and types [-] PushFont obsolete @@ -2042,11 +2042,11 @@ imgui_internal.h [x] 62% ImToUpper imgui_internal.lua:403 [x] 75% ImCharIsBlankA imgui_internal.lua:704 [x] 83% ImCharIsBlankW imgui_internal.lua:707 - [ ] ImCharIsXdigitA - [x] 0% ImFileOpen imgui.lua:4702 - [x] 0% ImFileClose imgui.lua:4719 - [x] 67% ImFileGetSize imgui.lua:4720 - [x] 4% ImFileRead imgui.lua:4725 + [x] 75% ImCharIsXdigitA imgui_internal.lua:710 + [x] 0% ImFileOpen imgui.lua:4735 + [x] 0% ImFileClose imgui.lua:4752 + [x] 67% ImFileGetSize imgui.lua:4753 + [x] 4% ImFileRead imgui.lua:4758 [ ] ImFileWrite [x] n/a ImPow imgui_internal.lua:150 = math . pow [x] n/a ImLog imgui_internal.lua:151 = math . log @@ -2063,64 +2063,64 @@ imgui_internal.h [x] 45% ImLerp imgui_internal.lua:229 [x] 77% ImSaturate imgui_internal.lua:393 [x] 67% ImLengthSqr imgui_internal.lua:440 - [ ] ImInvLength + [x] 100% ImInvLength imgui_internal.lua:714 [x] 24% ImTrunc imgui_internal.lua:242 [~] 25% ImFloor imgui_internal.lua:272 stub [x] 15% ImTrunc64 imgui_internal.lua:248 = _Trunc - [ ] ImRoundPositive64 - [ ] ImRoundSigned64 + [x] 40% ImRoundPositive64 imgui_internal.lua:715 + [x] 38% ImRoundSigned64 imgui_internal.lua:716 [x] 42% ImCeilFast imgui_internal.lua:252 - [ ] ImModPositive + [x] 77% ImModPositive imgui_internal.lua:718 [x] 100% ImDot imgui_internal.lua:453 [x] 98% ImRotate imgui_internal.lua:447 - [x] 100% ImLinearSweep imgui_widgets.lua:10639 + [x] 100% ImLinearSweep imgui_widgets.lua:10751 [x] 100% ImLinearRemapClamp imgui_internal.lua:399 [x] 97% ImMul imgui_internal.lua:460 - [ ] ImIsFloatAboveGuaranteedIntegerPrecision + [x] 100% ImIsFloatAboveGuaranteedIntegerPrecision imgui_internal.lua:719 [x] 71% ImExponentialMovingAverage imgui_internal.lua:308 [x] 60% ImIsTruncated imgui_internal.lua:264 [x] 60% ImIsTruncated4 imgui_internal.lua:266 [x] 100% ImTriangleArea imgui_internal.lua:468 [x] 100% ImTriangleIsClockwise imgui_internal.lua:474 - [x] 0% IM_MSVC_RUNTIME_CHECKS_OFF::ImVec1 imgui_internal.lua:809 - [ ] ImVec2i::ImVec2i - [ ] ImVec2ih::ImVec2ih - [x] 0% ImRect::ImRect imgui_internal.lua:839 - [x] 90% ImRect::GetCenter imgui_internal.lua:869 - [x] 89% ImRect::GetSize imgui_internal.lua:874 - [x] 94% ImRect::GetWidth imgui_internal.lua:870 - [x] 94% ImRect::GetHeight imgui_internal.lua:871 - [x] 91% ImRect::GetArea imgui_internal.lua:963 - [x] 33% ImRect::GetTL imgui_internal.lua:877 - [x] 89% ImRect::GetTR imgui_internal.lua:879 - [x] 89% ImRect::GetBL imgui_internal.lua:881 - [x] 33% ImRect::GetBR imgui_internal.lua:883 - [x] 43% ImRect::Contains imgui_internal.lua:846 - [x] 96% ImRect::ContainsWithPad imgui_internal.lua:858 - [x] 14% ImRect::Overlaps imgui_internal.lua:864 - [x] 59% ImRect::Add imgui_internal.lua:908 - [x] 96% ImRect::AddX imgui_internal.lua:924 - [x] 96% ImRect::AddY imgui_internal.lua:925 - [x] 38% ImRect::Expand imgui_internal.lua:929 - [x] 64% ImRect::Translate imgui_internal.lua:946 - [x] 55% ImRect::TranslateX imgui_internal.lua:952 - [x] 55% ImRect::TranslateY imgui_internal.lua:957 - [x] 22% ImRect::ClipWith imgui_internal.lua:888 - [x] 20% ImRect::ClipWithFull imgui_internal.lua:898 - [x] 91% ImRect::IsInverted imgui_internal.lua:961 - [x] 94% ImRect::ToVec4 imgui_internal.lua:940 - [x] 36% ImRect::AsVec4 imgui_internal.lua:966 - [ ] ImBitArrayGetStorageSizeInBytes - [ ] ImBitArrayClearAllBits - [ ] ImBitArrayTestBit - [ ] ImBitArrayClearBit - [x] 34% ImBitArraySetBit imgui_internal.lua:1001 - [ ] ImBitArraySetBitRange - [ ] ImBitVector::Create - [ ] ImBitVector::Clear - [ ] ImBitVector::TestBit - [ ] ImBitVector::SetBit - [ ] ImBitVector::ClearBit + [x] 0% IM_MSVC_RUNTIME_CHECKS_OFF::ImVec1 imgui_internal.lua:830 + [x] 0% ImVec2i::ImVec2i imgui_internal.lua:723 + [x] 0% ImVec2ih::ImVec2ih imgui_internal.lua:725 + [x] 0% ImRect::ImRect imgui_internal.lua:860 + [x] 90% ImRect::GetCenter imgui_internal.lua:890 + [x] 89% ImRect::GetSize imgui_internal.lua:895 + [x] 94% ImRect::GetWidth imgui_internal.lua:891 + [x] 94% ImRect::GetHeight imgui_internal.lua:892 + [x] 91% ImRect::GetArea imgui_internal.lua:984 + [x] 33% ImRect::GetTL imgui_internal.lua:898 + [x] 89% ImRect::GetTR imgui_internal.lua:900 + [x] 89% ImRect::GetBL imgui_internal.lua:902 + [x] 33% ImRect::GetBR imgui_internal.lua:904 + [x] 43% ImRect::Contains imgui_internal.lua:867 + [x] 96% ImRect::ContainsWithPad imgui_internal.lua:879 + [x] 14% ImRect::Overlaps imgui_internal.lua:885 + [x] 59% ImRect::Add imgui_internal.lua:929 + [x] 96% ImRect::AddX imgui_internal.lua:945 + [x] 96% ImRect::AddY imgui_internal.lua:946 + [x] 38% ImRect::Expand imgui_internal.lua:950 + [x] 64% ImRect::Translate imgui_internal.lua:967 + [x] 55% ImRect::TranslateX imgui_internal.lua:973 + [x] 55% ImRect::TranslateY imgui_internal.lua:978 + [x] 22% ImRect::ClipWith imgui_internal.lua:909 + [x] 20% ImRect::ClipWithFull imgui_internal.lua:919 + [x] 91% ImRect::IsInverted imgui_internal.lua:982 + [x] 94% ImRect::ToVec4 imgui_internal.lua:961 + [x] 36% ImRect::AsVec4 imgui_internal.lua:987 + [x] 67% ImBitArrayGetStorageSizeInBytes imgui_internal.lua:1030 + [x] 18% ImBitArrayClearAllBits imgui_internal.lua:1033 + [x] 60% ImBitArrayTestBit imgui_internal.lua:1034 + [x] 33% ImBitArrayClearBit imgui_internal.lua:1035 + [x] 34% ImBitArraySetBit imgui_internal.lua:1022 + [x] 55% ImBitArraySetBitRange imgui_internal.lua:1037 + [x] 61% ImBitVector::Create imgui_internal.lua:1093 + [x] 80% ImBitVector::Clear imgui_internal.lua:1094 + [x] 46% ImBitVector::TestBit imgui_internal.lua:1096 + [x] 77% ImBitVector::SetBit imgui_internal.lua:1097 + [x] 77% ImBitVector::ClearBit imgui_internal.lua:1098 [ ] IM_MSVC_RUNTIME_CHECKS_RESTORE::ImSpan [ ] IM_MSVC_RUNTIME_CHECKS_RESTORE::set [ ] IM_MSVC_RUNTIME_CHECKS_RESTORE::clear @@ -2166,123 +2166,123 @@ imgui_internal.h [ ] template::offset_from_ptr [ ] template::ptr_from_offset [ ] template::swap - [x] 83% ImGuiTextIndex::clear imgui_internal.lua:1831 - [x] 100% ImGuiTextIndex::size imgui_internal.lua:1833 - [x] 71% ImGuiTextIndex::get_line_begin imgui_internal.lua:1835 - [x] 76% ImGuiTextIndex::get_line_end imgui_internal.lua:1839 - [ ] ImGuiTextFilterItem::ImGuiTextFilterItem - [ ] ImGuiPackedDate::ImGuiPackedDate - [ ] ImGuiPackedDate::IsValid - [ ] ImGuiPackedDate::Unpack - [ ] ImGuiPackedDate::SubtractMonths + [x] 83% ImGuiTextIndex::clear imgui_internal.lua:1905 + [x] 100% ImGuiTextIndex::size imgui_internal.lua:1907 + [x] 71% ImGuiTextIndex::get_line_begin imgui_internal.lua:1909 + [x] 76% ImGuiTextIndex::get_line_end imgui_internal.lua:1913 + [x] 68% ImGuiTextFilterItem::ImGuiTextFilterItem imgui_internal.lua:3810 + [x] 47% ImGuiPackedDate::ImGuiPackedDate imgui_internal.lua:3817 + [x] 60% ImGuiPackedDate::IsValid imgui_internal.lua:3826 + [x] 49% ImGuiPackedDate::Unpack imgui_internal.lua:3827 + [x] 60% ImGuiPackedDate::SubtractMonths imgui_internal.lua:3828 -- ImDrawList support - [x] 27% ImDrawDataBuilder::ImDrawDataBuilder imgui_internal.lua:3028 + [x] 27% ImDrawDataBuilder::ImDrawDataBuilder imgui_internal.lua:3102 -- Style support - [ ] ImGuiStyleVarInfo::GetVarPtr - [x] 39% ImGuiStyleMod::ImGuiStyleMod imgui_internal.lua:1280 + [x] 50% ImGuiStyleVarInfo::GetVarPtr imgui_internal.lua:1337 + [x] 39% ImGuiStyleMod::ImGuiStyleMod imgui_internal.lua:1346 -- Widgets support: flags, enums, data structures - [x] 21% ImGuiComboPreviewData::ImGuiComboPreviewData imgui_internal.lua:1677 - [x] 12% ImGuiMenuColumns::ImGuiMenuColumns imgui_internal.lua:2695 - [x] 20% ImGuiInputTextDeactivatedState::ImGuiInputTextDeactivatedState imgui_internal.lua:1763 - [ ] ImGuiInputTextDeactivatedState::ClearFreeMemory - [ ] ImGuiInputTextState::ClearText - [ ] ImGuiInputTextState::ClearFreeMemory - [ ] ImGuiInputTextState::GetText - [x] 3% ImGuiNextWindowData::ImGuiNextWindowData imgui_internal.lua:1445 - [ ] ImGuiNextWindowData::ClearFlags - [x] 20% ImGuiNextItemData::ImGuiNextItemData imgui_internal.lua:1397 - [ ] ImGuiNextItemData::ClearFlags - [x] 11% ImGuiLastItemData::ImGuiLastItemData imgui_internal.lua:1317 - [x] 8% ImGuiErrorRecoveryState::ImGuiErrorRecoveryState imgui.lua:19808 - [ ] ImGuiPtrOrIndex::ImGuiPtrOrIndex + [x] 21% ImGuiComboPreviewData::ImGuiComboPreviewData imgui_internal.lua:1743 + [x] 12% ImGuiMenuColumns::ImGuiMenuColumns imgui_internal.lua:2769 + [x] 18% ImGuiInputTextDeactivatedState::ImGuiInputTextDeactivatedState imgui_internal.lua:1837 + [x] 84% ImGuiInputTextDeactivatedState::ClearFreeMemory imgui_internal.lua:1829 + [x] 74% ImGuiInputTextState::ClearText imgui_internal.lua:1816 + [x] 55% ImGuiInputTextState::ClearFreeMemory imgui_internal.lua:1817 + [x] 40% ImGuiInputTextState::GetText imgui_internal.lua:1818 + [x] 3% ImGuiNextWindowData::ImGuiNextWindowData imgui_internal.lua:1511 + [x] 100% ImGuiNextWindowData::ClearFlags imgui_internal.lua:1505 + [x] 19% ImGuiNextItemData::ImGuiNextItemData imgui_internal.lua:1463 + [x] 95% ImGuiNextItemData::ClearFlags imgui_internal.lua:1456 + [x] 11% ImGuiLastItemData::ImGuiLastItemData imgui_internal.lua:1383 + [x] 8% ImGuiErrorRecoveryState::ImGuiErrorRecoveryState imgui.lua:20283 + [x] 41% ImGuiPtrOrIndex::ImGuiPtrOrIndex imgui_internal.lua:3832 -- Popup support - [x] 36% ImGuiPopupData::ImGuiPopupData imgui_internal.lua:3582 + [x] 36% ImGuiPopupData::ImGuiPopupData imgui_internal.lua:3658 -- Inputs support - [x] 9% ImGuiInputEvent::ImGuiInputEvent imgui_internal.lua:3376 - [x] 73% ImGuiKeyRoutingData::ImGuiKeyRoutingData imgui_internal.lua:1784 - [x] 10% ImGuiKeyRoutingTable::ImGuiKeyRoutingTable imgui_internal.lua:1811 - [ ] ImGuiKeyRoutingTable::Clear + [x] 9% ImGuiInputEvent::ImGuiInputEvent imgui_internal.lua:3450 + [x] 73% ImGuiKeyRoutingData::ImGuiKeyRoutingData imgui_internal.lua:1858 + [x] 9% ImGuiKeyRoutingTable::ImGuiKeyRoutingTable imgui_internal.lua:1885 + [x] 54% ImGuiKeyRoutingTable::Clear imgui_internal.lua:1878 [x] 64% ImGuiKeyOwnerData::ImGuiKeyOwnerData imgui_internal.lua:659 -- Clipper support - [ ] ImGuiListClipperRange::FromIndices - [ ] ImGuiListClipperRange::FromPositions - [ ] ImGuiListClipperData::ImGuiListClipperData - [ ] ImGuiListClipperData::Reset + [x] 59% ImGuiListClipperRange::FromIndices imgui_internal.lua:3840 + [x] 34% ImGuiListClipperRange::FromPositions imgui_internal.lua:3841 + [x] 20% ImGuiListClipperData::ImGuiListClipperData imgui_internal.lua:3847 + [x] 81% ImGuiListClipperData::Reset imgui_internal.lua:3848 -- Navigation support - [x] 13% ImGuiNavItemData::ImGuiNavItemData imgui_internal.lua:1917 - [ ] ImGuiNavItemData::Clear + [x] 12% ImGuiNavItemData::ImGuiNavItemData imgui_internal.lua:1991 + [x] 75% ImGuiNavItemData::Clear imgui_internal.lua:1979 -- Typing-select support - [x] 7% ImGuiTypingSelectState::ImGuiTypingSelectState imgui_internal.lua:1961 - [x] 71% ImGuiTypingSelectState::Clear imgui_internal.lua:1964 + [x] 7% ImGuiTypingSelectState::ImGuiTypingSelectState imgui_internal.lua:2035 + [x] 71% ImGuiTypingSelectState::Clear imgui_internal.lua:2038 -- Columns support - [x] 19% ImGuiOldColumnData::ImGuiOldColumnData imgui_tables.lua:340 - [x] 5% ImGuiOldColumns::ImGuiOldColumns imgui_tables.lua:345 + [x] 19% ImGuiOldColumnData::ImGuiOldColumnData imgui_tables.lua:344 + [x] 5% ImGuiOldColumns::ImGuiOldColumns imgui_tables.lua:349 -- Box-select support - [x] 6% ImGuiBoxSelectState::ImGuiBoxSelectState imgui_internal.lua:1988 + [x] 6% ImGuiBoxSelectState::ImGuiBoxSelectState imgui_internal.lua:2062 -- Multi-select support - [x] 9% ImGuiMultiSelectTempData::ImGuiMultiSelectTempData imgui_internal.lua:2034 - [x] 10% ImGuiMultiSelectTempData::Clear imgui_internal.lua:2040 - [x] 67% ImGuiMultiSelectTempData::ClearIO imgui_internal.lua:2058 - [x] 72% ImGuiMultiSelectState::ImGuiMultiSelectState imgui_internal.lua:2071 + [x] 9% ImGuiMultiSelectTempData::ImGuiMultiSelectTempData imgui_internal.lua:2108 + [x] 10% ImGuiMultiSelectTempData::Clear imgui_internal.lua:2114 + [x] 67% ImGuiMultiSelectTempData::ClearIO imgui_internal.lua:2132 + [x] 72% ImGuiMultiSelectState::ImGuiMultiSelectState imgui_internal.lua:2145 -- Docking support - [x] 100% ImGuiDockNode::IsRootNode imgui.lua:1095 - [x] 88% ImGuiDockNode::IsDockSpace imgui.lua:1096 - [x] 88% ImGuiDockNode::IsFloatingNode imgui.lua:1097 - [x] 88% ImGuiDockNode::IsCentralNode imgui.lua:1098 - [x] 88% ImGuiDockNode::IsHiddenTabBar imgui.lua:1099 - [x] 88% ImGuiDockNode::IsNoTabBar imgui.lua:1100 - [x] 100% ImGuiDockNode::IsSplitNode imgui.lua:1101 - [x] 100% ImGuiDockNode::IsLeafNode imgui.lua:1102 - [x] 96% ImGuiDockNode::IsEmpty imgui.lua:1103 - [x] 92% ImGuiDockNode::Rect imgui.lua:1104 - [x] 100% ImGuiDockNode::SetLocalFlags imgui.lua:1105 - [x] 67% ImGuiDockNode::UpdateMergedFlags imgui.lua:1106 - [x] 20% ImGuiDockContext::ImGuiDockContext imgui.lua:1040 + [x] 100% ImGuiDockNode::IsRootNode imgui.lua:1115 + [x] 88% ImGuiDockNode::IsDockSpace imgui.lua:1116 + [x] 88% ImGuiDockNode::IsFloatingNode imgui.lua:1117 + [x] 88% ImGuiDockNode::IsCentralNode imgui.lua:1118 + [x] 88% ImGuiDockNode::IsHiddenTabBar imgui.lua:1119 + [x] 88% ImGuiDockNode::IsNoTabBar imgui.lua:1120 + [x] 100% ImGuiDockNode::IsSplitNode imgui.lua:1121 + [x] 100% ImGuiDockNode::IsLeafNode imgui.lua:1122 + [x] 96% ImGuiDockNode::IsEmpty imgui.lua:1123 + [x] 92% ImGuiDockNode::Rect imgui.lua:1124 + [x] 100% ImGuiDockNode::SetLocalFlags imgui.lua:1125 + [x] 67% ImGuiDockNode::UpdateMergedFlags imgui.lua:1126 + [x] 20% ImGuiDockContext::ImGuiDockContext imgui.lua:1060 -- Viewport support - [x] 36% ImGuiViewportP::ImGuiViewportP imgui_internal.lua:3115 + [x] 36% ImGuiViewportP::ImGuiViewportP imgui_internal.lua:3189 [-] ImGuiViewportP::~ImGuiViewportP c++-only - [x] 78% ImGuiViewportP::ClearRequestFlags imgui_internal.lua:3070 - [x] 94% ImGuiViewportP::CalcWorkRectPos imgui_internal.lua:3077 - [x] 98% ImGuiViewportP::CalcWorkRectSize imgui_internal.lua:3081 - [x] 87% ImGuiViewportP::UpdateWorkRect imgui_internal.lua:3086 - [x] 92% ImGuiViewportP::GetMainRect imgui_internal.lua:3093 - [x] 92% ImGuiViewportP::GetWorkRect imgui_internal.lua:3100 - [x] 96% ImGuiViewportP::GetBuildWorkRect imgui_internal.lua:3107 + [x] 78% ImGuiViewportP::ClearRequestFlags imgui_internal.lua:3144 + [x] 94% ImGuiViewportP::CalcWorkRectPos imgui_internal.lua:3151 + [x] 98% ImGuiViewportP::CalcWorkRectSize imgui_internal.lua:3155 + [x] 87% ImGuiViewportP::UpdateWorkRect imgui_internal.lua:3160 + [x] 92% ImGuiViewportP::GetMainRect imgui_internal.lua:3167 + [x] 92% ImGuiViewportP::GetWorkRect imgui_internal.lua:3174 + [x] 96% ImGuiViewportP::GetBuildWorkRect imgui_internal.lua:3181 -- Settings support - [x] 18% ImGuiWindowSettings::ImGuiWindowSettings imgui_internal.lua:2662 - [ ] ImGuiWindowSettings::GetName - [x] 13% ImGuiSettingsHandler::ImGuiSettingsHandler imgui_h.lua:2926 + [x] 17% ImGuiWindowSettings::ImGuiWindowSettings imgui_internal.lua:2736 + [x] 40% ImGuiWindowSettings::GetName imgui_internal.lua:2732 + [x] 13% ImGuiSettingsHandler::ImGuiSettingsHandler imgui_h.lua:2937 -- Metrics, Debug Tools - [x] 7% ImGuiDebugAllocInfo::ImGuiDebugAllocInfo imgui_internal.lua:1865 - [ ] ImGuiStackLevelInfo::ImGuiStackLevelInfo - [ ] ImGuiDebugItemPathQuery::ImGuiDebugItemPathQuery - [ ] ImGuiIDStackTool::ImGuiIDStackTool + [x] 7% ImGuiDebugAllocInfo::ImGuiDebugAllocInfo imgui_internal.lua:1939 + [x] 57% ImGuiStackLevelInfo::ImGuiStackLevelInfo imgui_internal.lua:3850 + [x] 12% ImGuiDebugItemPathQuery::ImGuiDebugItemPathQuery imgui_internal.lua:3851 + [x] 59% ImGuiIDStackTool::ImGuiIDStackTool imgui_internal.lua:3852 -- Generic context hooks - [ ] ImGuiContextHook::ImGuiContextHook + [x] 15% ImGuiContextHook::ImGuiContextHook imgui.lua:14755 -- ImGuiWindowTempData, ImGuiWindow - [x] 92% ImGuiWindow::Rect imgui_internal.lua:2836 - [x] 84% ImGuiWindow::TitleBarRect imgui_internal.lua:2842 - [x] 91% ImGuiWindow::MenuBarRect imgui_internal.lua:2848 + [x] 92% ImGuiWindow::Rect imgui_internal.lua:2910 + [x] 84% ImGuiWindow::TitleBarRect imgui_internal.lua:2916 + [x] 91% ImGuiWindow::MenuBarRect imgui_internal.lua:2922 -- Tab bar, Tab item support - [x] 50% ImGuiTabItem::ImGuiTabItem imgui_internal.lua:2203 + [x] 50% ImGuiTabItem::ImGuiTabItem imgui_internal.lua:2277 -- Table support + internal API [x] 28% ImGuiTableColumn::ImGuiTableColumn imgui_tables.lua:240 @@ -2291,114 +2291,81 @@ imgui_internal.h [-] ImGuiTable::~ImGuiTable c++-only [x] 14% ImGuiTableTempData::ImGuiTableTempData imgui_tables.lua:280 [x] 85% ImGuiTableColumnSettings::ImGuiTableColumnSettings imgui_tables.lua:327 - [x] 11% ImGuiTableSettings::ImGuiTableSettings imgui_tables.lua:334 - [ ] ImGuiTableSettings::GetColumnSettings - [ ] GetCurrentTable - [x] 73% TableGetInstanceData imgui_tables.lua:438 - [x] 86% TableGetInstanceID imgui_tables.lua:445 + [x] 10% ImGuiTableSettings::ImGuiTableSettings imgui_tables.lua:336 + [x] 33% ImGuiTableSettings::GetColumnSettings imgui_tables.lua:340 + [x] 100% GetCurrentTable imgui_internal.lua:3859 + [x] 73% TableGetInstanceData imgui_tables.lua:442 + [x] 86% TableGetInstanceID imgui_tables.lua:449 -- ImGui internal API - [x] 100% GetScale imgui.lua:13586 - [x] 100% GetCurrentWindowRead imgui.lua:13592 - [x] 100% GetCurrentWindow imgui.lua:13599 - [ ] SetWindowParentWindowForFocusRoute + [x] 100% GetScale imgui.lua:13934 + [x] 100% GetCurrentWindowRead imgui.lua:13940 + [x] 100% GetCurrentWindow imgui.lua:13947 + [x] 100% SetWindowParentWindowForFocusRoute imgui_internal.lua:3862 [x] 99% WindowRectAbsToRel imgui_internal.lua:676 [x] 99% WindowRectRelToAbs imgui_internal.lua:681 [x] 98% WindowPosAbsToRel imgui_internal.lua:694 [x] 98% WindowPosRelToAbs imgui_internal.lua:700 - [ ] GetPixelDensity + [x] 75% GetPixelDensity imgui_internal.lua:3863 [x] 55% GetRoundedFontSize imgui_internal.lua:670 - [x] 15% GetForegroundDrawList imgui.lua:13675 - [x] 80% LocalizeGetMsg imgui_internal.lua:3686 - [ ] ScrollToBringRectIntoView - [ ] GetItemStatusFlags - [ ] GetActiveID - [ ] GetFocusID - [x] 2% ItemSize imgui.lua:6492 + [x] 15% GetForegroundDrawList imgui.lua:14023 + [x] 80% LocalizeGetMsg imgui_internal.lua:3762 + [x] 100% ScrollToBringRectIntoView imgui_internal.lua:3864 + [x] 100% GetItemStatusFlags imgui_internal.lua:3865 + [x] 100% GetActiveID imgui_internal.lua:3866 + [x] 100% GetFocusID imgui_internal.lua:3867 + [x] 2% ItemSize imgui.lua:6685 [x] 100% IsNamedKey imgui_internal.lua:584 [x] 75% IsNamedKeyOrMod imgui_internal.lua:615 - [ ] IsLegacyKey + [x] 60% IsLegacyKey imgui_internal.lua:3868 [x] 60% IsKeyboardKey imgui_internal.lua:589 [x] 60% IsGamepadKey imgui_internal.lua:594 [x] 60% IsMouseKey imgui_internal.lua:599 [x] 60% IsAliasKey imgui_internal.lua:604 [x] 100% IsLRModKey imgui_internal.lua:609 [x] 76% ConvertSingleModFlagToKey imgui_internal.lua:621 - [x] 17% GetKeyData imgui.lua:8440 + [x] 17% GetKeyData imgui.lua:8678 [x] 97% MouseButtonToKey imgui_internal.lua:581 [x] 81% IsActiveIdUsingNavDir imgui_internal.lua:685 [x] 88% GetKeyOwnerData imgui_internal.lua:647 - [x] 100% DockNodeGetRootNode imgui.lua:4488 - [x] 100% DockNodeIsInHierarchyOf imgui.lua:4493 - [x] 86% DockNodeGetDepth imgui.lua:4501 - [x] 89% DockNodeGetWindowMenuButtonId imgui.lua:4507 - [ ] GetWindowDockNode - [x] 97% DockBuilderGetCentralNode imgui.lua:3661 - [ ] GetCurrentFocusScope - [x] 91% GetBoxSelectState imgui_internal.lua:2077 - [x] 95% GetMultiSelectState imgui_internal.lua:2080 - [ ] GetCurrentTabBar - [x] 35% TabBarGetTabOrder imgui_widgets.lua:11197 + [x] 100% DockNodeGetRootNode imgui.lua:4521 + [x] 100% DockNodeIsInHierarchyOf imgui.lua:4526 + [x] 86% DockNodeGetDepth imgui.lua:4534 + [x] 89% DockNodeGetWindowMenuButtonId imgui.lua:4540 + [x] 100% GetWindowDockNode imgui_internal.lua:3869 + [x] 97% DockBuilderGetCentralNode imgui.lua:3690 + [x] 100% GetCurrentFocusScope imgui_internal.lua:3870 + [x] 91% GetBoxSelectState imgui_internal.lua:2151 + [x] 95% GetMultiSelectState imgui_internal.lua:2154 + [x] 100% GetCurrentTabBar imgui_internal.lua:3871 + [x] 35% TabBarGetTabOrder imgui_widgets.lua:11335 [-] RenderNavHighlight obsolete - [x] 100% TempInputIsActive imgui_internal.lua:3693 - [x] 88% GetInputTextState imgui_internal.lua:3701 - [ ] IsItemActiveAsInputText - [x] 80% SetNextItemColorMarker imgui_internal.lua:1095 + [x] 100% TempInputIsActive imgui_internal.lua:3769 + [x] 88% GetInputTextState imgui_internal.lua:3777 + [x] 100% IsItemActiveAsInputText imgui_internal.lua:3873 + [x] 80% SetNextItemColorMarker imgui_internal.lua:1157 -- ImFontLoader - [x] 6% ImFontLoader::ImFontLoader imgui_internal.lua:3177 + [x] 6% ImFontLoader::ImFontLoader imgui_internal.lua:3251 -- ImFontAtlas internal API [-] operator== c++-only [-] operator!= c++-only - [x] 75% ImFontAtlasRectId_GetIndex imgui_internal.lua:3229 - [x] 62% ImFontAtlasRectId_GetGeneration imgui_internal.lua:3233 - [x] 77% ImFontAtlasRectId_Make imgui_internal.lua:3238 - [x] 18% ImFontAtlasBuilder::ImFontAtlasBuilder imgui_internal.lua:1196 + [x] 75% ImFontAtlasRectId_GetIndex imgui_internal.lua:3303 + [x] 62% ImFontAtlasRectId_GetGeneration imgui_internal.lua:3307 + [x] 77% ImFontAtlasRectId_Make imgui_internal.lua:3312 + [x] 18% ImFontAtlasBuilder::ImFontAtlasBuilder imgui_internal.lua:1258 ==================================================================================================== API declarations not ported (by upstream line) ==================================================================================================== - Public API (imgui.h, namespace ImGui): 368 / 376 + Public API (imgui.h, namespace ImGui): 374 / 376 -- Dear ImGui end-user API functions - [ ] ImGui::SetTooltipV - [ ] ImGui::SetItemTooltipV - [ ] ImGui::DebugFlashStyleColor - [ ] ImGui::DebugStartItemPicker [ ] ImGui::DebugCheckVersionAndDataLayout - [ ] ImGui::DebugLogV [ ] ImGui::GetAllocatorFunctions - [ ] ImGui::FindViewportByPlatformHandle - Internal API (imgui_internal.h, namespace ImGui): 417 / 443 - -- ImGui internal API - [ ] ImGui::RegisterUserTexture - [ ] ImGui::UnregisterUserTexture - [ ] ImGui::SetPixelDensity - [ ] ImGui::SetContextName - [ ] ImGui::AddContextHook - [ ] ImGui::RemoveContextHook - [ ] ImGui::CallContextHooks - [ ] ImGui::TestShortcutRouting - [ ] ImGui::GetWindowResizeCornerID - [ ] ImGui::GetWindowResizeBorderID - [ ] ImGui::DemoMarker - [ ] ImGui::DebugDrawCursorPos - [ ] ImGui::DebugDrawLineExtents - [ ] ImGui::DebugDrawItemRect - [ ] ImGui::DebugTextUnformattedWithLocateItem - [ ] ImGui::DebugLocateItem - [ ] ImGui::DebugLocateItemOnHover - [ ] ImGui::DebugLocateItemResolveWithLastItem - [ ] ImGui::DebugBreakClearData - [ ] ImGui::DebugBreakButton - [ ] ImGui::DebugBreakButtonTooltip - [ ] ImGui::DebugTextureIDToU64 - [ ] ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox - [ ] ImGui::DebugNodeInputTextState - [ ] ImGui::DebugNodePlatformMonitor - [ ] ImGui::DebugRenderKeyboardPreview + Internal API (imgui_internal.h, namespace ImGui): 443 / 443 ==================================================================================================== Enums (values ported / total; missing listed) @@ -2527,14 +2494,14 @@ Struct fields (name found in the port / total; missing listed). Field names are ImGuiBoxSelectState 16 / 16 ImGuiColorMod 2 / 2 ImGuiComboPreviewData 6 / 9 missing: BackupWorkRectMaxX, BackupContentRectMaxX, WithinPreview - ImGuiContext 313 / 338 missing: TestEngineHookItems, CurrentPixelDensity, TestEngine, InputEventsTrail, DebugBreakInShortcutRouting, DebugLocateId, NavJustMovedToIsInit, DragDropPayloadBufHeap, DragDropPayloadBufLocal, ClipboardHandlerData, SessionDate, DemoMarkerCallback, DebugLogIndex, DebugLogSkippedErrors, DebugLocateFrames, DebugBreakInLocateId, DebugBreakKeyChord, DebugItemPickerActive, DebugItemPickerMouseButton, DebugItemPickerBreakId, DebugFlashStyleColorTime, DebugFlashStyleColorBackup, DebugDrawIdConflictsAliveCount, DebugDrawIdConflictsHighlightSet, TempKeychordName - ImGuiContextHook 2 / 5 missing: HookId, Owner, Callback + ImGuiContext 323 / 338 missing: TestEngineHookItems, CurrentPixelDensity, TestEngine, InputEventsTrail, NavJustMovedToIsInit, DragDropPayloadBufHeap, DragDropPayloadBufLocal, ClipboardHandlerData, SessionDate, DemoMarkerCallback, DebugLogIndex, DebugLogSkippedErrors, DebugDrawIdConflictsAliveCount, DebugDrawIdConflictsHighlightSet, TempKeychordName + ImGuiContextHook 5 / 5 ImGuiDataTypeInfo 4 / 4 ImGuiDataTypeStorage 1 / 1 ImGuiDeactivatedItemData 4 / 4 ImGuiDebugAllocEntry 3 / 3 ImGuiDebugAllocInfo 4 / 4 - ImGuiDebugItemPathQuery 5 / 7 missing: ResultsDescBuf, ResultPathBuf + ImGuiDebugItemPathQuery 7 / 7 ImGuiDemoWindowData 25 / 25 ImGuiDockContext 4 / 4 ImGuiDockContextPruneNodeData 4 / 4 @@ -2558,7 +2525,7 @@ Struct fields (name found in the port / total; missing listed). Field names are ImGuiInputEventText 1 / 1 ImGuiInputTextCallbackData 15 / 15 ImGuiInputTextDeactivatedState 3 / 3 - ImGuiInputTextState 21 / 24 missing: ValidatedThisFrame, ReloadSelectionStart, ReloadSelectionEnd + ImGuiInputTextState 23 / 24 missing: ValidatedThisFrame ImGuiKeyData 4 / 4 ImGuiKeyOwnerData 4 / 4 ImGuiKeyRoutingData 6 / 6 @@ -2578,15 +2545,15 @@ Struct fields (name found in the port / total; missing listed). Field names are ImGuiNextWindowData 25 / 25 ImGuiOldColumnData 4 / 4 ImGuiOldColumns 17 / 17 - ImGuiOnceUponAFrame 0 / 1 missing: RefFrame - ImGuiPackedDate 0 / 3 missing: Year, Month, Day + ImGuiOnceUponAFrame 1 / 1 + ImGuiPackedDate 3 / 3 ImGuiPayload 8 / 8 ImGuiPlatformIO 10 / 15 missing: Platform_SessionDate, DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest, DrawCallback_SetSamplerFromTex ImGuiPlatformImeData 5 / 5 ImGuiPlatformMonitor 6 / 6 ImGuiPlotArrayGetterData 2 / 2 ImGuiPopupData 8 / 8 - ImGuiPtrOrIndex 1 / 2 missing: Ptr + ImGuiPtrOrIndex 2 / 2 ImGuiResizeBorderDef 4 / 4 ImGuiResizeGripDef 4 / 4 ImGuiSelectionBasicStorage 5 / 5 @@ -2596,7 +2563,7 @@ Struct fields (name found in the port / total; missing listed). Field names are ImGuiSettingsHandler 3 / 3 ImGuiShrinkWidthItem 3 / 3 ImGuiSizeCallbackData 4 / 4 - ImGuiStackLevelInfo 4 / 5 missing: DescOffset + ImGuiStackLevelInfo 5 / 5 ImGuiStorage 1 / 1 ImGuiStoragePair 1 / 4 missing: val_i, val_f, val_p ImGuiStyleMod 1 / 3 missing: BackupInt, BackupFloat @@ -2618,7 +2585,7 @@ Struct fields (name found in the port / total; missing listed). Field names are ImGuiTableTempData 18 / 18 ImGuiTextBuffer 1 / 2 missing: EmptyString ImGuiTextFilter 3 / 3 - ImGuiTextFilterItem 1 / 4 missing: Begin, Len, MatchIncludesMask + ImGuiTextFilterItem 2 / 4 missing: Begin, Len ImGuiTextIndex 2 / 2 ImGuiTreeNodeStackData 7 / 7 ImGuiTypingSelectRequest 6 / 6 diff --git a/imgui.lua b/imgui.lua index 91ef3ab..958354f 100644 --- a/imgui.lua +++ b/imgui.lua @@ -431,6 +431,15 @@ IMGUI_DISABLE_DEBUG_TOOLS = false -- Disable metrics/debugger and other debug to --- @type ImGuiContext? local GImGui = nil +-- [Luau] IM_DEBUG_BREAK() (imgui_internal.h macro): Lua can't break into a debugger. It calls the optional user hook +-- g.DebugBreakCallback(g) instead (a context field added by this port; the library can't be patched from outside the bundle). +local function IM_DEBUG_BREAK() + local g = GImGui + if g ~= nil and g.DebugBreakCallback ~= nil then + g.DebugBreakCallback(g) + end +end + ImGui = {} ImStd = {} -- Contains functions that originally don't belong to cpp namespaces @@ -477,6 +486,17 @@ function ImGui.MemFree(owner, field) return GImAllocatorFreeFunc(owner, field, GImAllocatorUserData) end +-- [Luau] g.DemoMarkerCallback (fun(file, line, section)) is not in ImGuiContext() yet: nil unless set by the user. +--- @param file string +--- @param line int +--- @param section string +function ImGui.DemoMarker(file, line, section) + local g = GImGui + if g.DemoMarkerCallback ~= nil then + g.DemoMarkerCallback(file, line, section) + end +end + -- We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames" --- @param info ImGuiDebugAllocInfo --- @param frame_count int @@ -1356,6 +1376,11 @@ function ImGui.DockContextDeleteNode(ctx, node) dc.Nodes[node.ID] = nil end +-- Pre C++0x doesn't allow us to use a function-local type (without linkage) as template parameter, so we moved this here. +local function ImGuiDockContextPruneNodeData() + return { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 } +end + -- Garbage collect unused nodes (run once at init time) function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local g = ctx @@ -1365,7 +1390,7 @@ function ImGui.DockContextPruneUnusedSettingsNodes(ctx) local pool = {} local function GetOrAdd(id) local d = pool[id] - if not d then d = { CountWindows = 0, CountChildWindows = 0, CountChildNodes = 0, RootId = 0 }; pool[id] = d end + if not d then d = ImGuiDockContextPruneNodeData(); pool[id] = d end return d end @@ -1935,6 +1960,10 @@ function ImGui.DockNodeHideHostWindow(node) if node.TabBar then ImGui.DockNodeRemoveTabBar(node) end end +local function ImGuiDockNodeTreeInfo() + return { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } +end + -- Search function called once by root node in DockNodeUpdate() local function DockNodeFindInfo(node, info) if node.Windows.Size > 0 then @@ -2075,7 +2104,7 @@ function ImGui.DockNodeUpdateForRootNode(node) -- - Setup central node pointers -- - Find if there's only a single visible window in the hierarchy (in which case we need to display a regular title bar -> FIXME-DOCK: that last part is not done yet!) -- Cannot merge this with DockNodeUpdateFlagsAndCollapse() because FirstNodeWithWindows is found after window removal and child collapsing - local info = { CentralNode = nil, FirstNodeWithWindows = nil, CountNodesWithWindows = 0 } + local info = ImGuiDockNodeTreeInfo() DockNodeFindInfo(node, info) node.CentralNode = info.CentralNode node.OnlyNodeWithWindows = (info.CountNodesWithWindows == 1) and info.FirstNodeWithWindows or nil @@ -3720,6 +3749,12 @@ function ImGui.DockBuilderRemoveNode(node_id) ImGui.DockContextRemoveNode(g, node, true) end +--- @param a ImGuiDockNode +--- @param b ImGuiDockNode +local function DockNodeComparerDepthMostFirst(a, b) -- [Luau] table.sort() "less than" predicate + return ImGui.DockNodeGetDepth(a) > ImGui.DockNodeGetDepth(b) +end + -- root_id = 0 to remove all, root_id != 0 to remove child of given node. function ImGui.DockBuilderRemoveNodeChildNodes(root_id) local g = ImGui.GetCurrentContext() @@ -3772,9 +3807,7 @@ function ImGui.DockBuilderRemoveNodeChildNodes(root_id) -- Not really efficient, but easier to destroy a whole hierarchy considering DockContextRemoveNode is attempting to merge nodes if #nodes_to_remove > 1 then - local depth = {} - for _, n in ipairs(nodes_to_remove) do depth[n] = ImGui.DockNodeGetDepth(n) end - table.sort(nodes_to_remove, function(a, b) return depth[a] > depth[b] end) + table.sort(nodes_to_remove, DockNodeComparerDepthMostFirst) end for _, n in ipairs(nodes_to_remove) do ImGui.DockContextRemoveNode(g, n, false) @@ -5122,6 +5155,79 @@ function ImStd.ImTextFindValidUtf8CodepointEnd(text, in_text_start, in_text_end, return prev end +------------------------------------------------------------------------------- +-- [SECTION] MISC HELPERS/UTILITIES (Geometry functions) +------------------------------------------------------------------------------- + +--- @param p1 ImVec2 +--- @param p2 ImVec2 +--- @param p3 ImVec2 +--- @param p4 ImVec2 +--- @param p ImVec2 +--- @param num_segments int +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPoint(p1, p2, p3, p4, p, num_segments) + IM_ASSERT(num_segments > 0) -- Use ImBezierCubicClosestPointCasteljau() + local p_last = p1 + local p_closest = ImVec2(0, 0) + local p_closest_dist2 = FLT_MAX + local t_step = 1.0 / num_segments + for i_step = 1, num_segments do + local p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step) + local p_line = ImStd.ImLineClosestPoint(p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < p_closest_dist2 then + p_closest = p_line + p_closest_dist2 = dist2 + end + p_last = p_current + end + return ImVec2(p_closest.x, p_closest.y) +end + +-- Closely mimics PathBezierToCasteljau() in imgui_draw.cpp +-- [Luau] p_closest / p_last / p_closest_dist2 are C++ references: kept in the `st` table. +local function ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x2, y2, x3, y3, x4, y4, max_error_sqr, level) + local dx = x4 - x1 + local dy = y4 - y1 + local d2 = ((x2 - x4) * dy - (y2 - y4) * dx) + local d3 = ((x3 - x4) * dy - (y3 - y4) * dx) + d2 = (d2 >= 0) and d2 or -d2 + d3 = (d3 >= 0) and d3 or -d3 + if (d2 + d3) * (d2 + d3) < max_error_sqr * (dx * dx + dy * dy) then + local p_current = ImVec2(x4, y4) + local p_line = ImStd.ImLineClosestPoint(st.p_last, p_current, p) + local dist2 = ImLengthSqr(p - p_line) + if dist2 < st.p_closest_dist2 then + st.p_closest = p_line + st.p_closest_dist2 = dist2 + end + st.p_last = p_current + elseif level < 10 then + local x12, y12 = (x1 + x2) * 0.5, (y1 + y2) * 0.5 + local x23, y23 = (x2 + x3) * 0.5, (y2 + y3) * 0.5 + local x34, y34 = (x3 + x4) * 0.5, (y3 + y4) * 0.5 + local x123, y123 = (x12 + x23) * 0.5, (y12 + y23) * 0.5 + local x234, y234 = (x23 + x34) * 0.5, (y23 + y34) * 0.5 + local x1234, y1234 = (x123 + x234) * 0.5, (y123 + y234) * 0.5 + ImBezierCubicClosestPointCasteljauStep(p, st, x1, y1, x12, y12, x123, y123, x1234, y1234, max_error_sqr, level + 1) + ImBezierCubicClosestPointCasteljauStep(p, st, x1234, y1234, x234, y234, x34, y34, x4, y4, max_error_sqr, level + 1) + end +end + +-- tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationMaxError +-- Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. +--- @return ImVec2 +--- @nodiscard +function ImBezierCubicClosestPointCasteljau(p1, p2, p3, p4, p, max_error) + IM_ASSERT(max_error > 0.0) + local st = { p_last = p1, p_closest = ImVec2(0, 0), p_closest_dist2 = FLT_MAX } + local max_error_sqr = max_error * max_error + ImBezierCubicClosestPointCasteljauStep(p, st, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, max_error_sqr, 0) + return ImVec2(st.p_closest.x, st.p_closest.y) +end + --- @param a ImVec2 --- @param b ImVec2 --- @param p ImVec2 @@ -5309,6 +5415,20 @@ function ImGui.UpdateCurrentFontSize(restore_font_size_after_scaling) g.DrawListSharedData.FontScale = g.FontBakedScale end +-- Exposed in case user may want to override setting density. +-- IMPORTANT: Begin()/End() is overriding density. Be considerate of this you change it. +-- [Luau] upstream g.CurrentPixelDensity is g.FontRasterizerDensity in this port. +--- @param pixel_density float +function ImGui.SetPixelDensity(pixel_density) + local g = GImGui + IM_ASSERT(bit32.band(g.IO.BackendFlags, ImGuiBackendFlags.RendererHasTextures) ~= 0) + if g.FontRasterizerDensity == pixel_density then + return + end + g.FontRasterizerDensity = pixel_density + ImGui.UpdateCurrentFontSize(0.0) +end + -- Use ImDrawList:_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList. -- - Whereas ImDrawList:PushTexture()/PopTexture() is not to be used across Begin() calls. -- - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did... @@ -5453,6 +5573,22 @@ function ImGui.GetDefaultFont() return g.IO.FontDefault and g.IO.FontDefault or atlas.Fonts[1] end +-- EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates. Textures logic will be automatically be updated in NewFrame(). +--- @param tex ImTextureData +function ImGui.RegisterUserTexture(tex) + local g = GImGui + tex.RefCount = tex.RefCount + 1 + g.UserTextures:push_back(tex) +end + +--- @param tex ImTextureData +function ImGui.UnregisterUserTexture(tex) + local g = GImGui + IM_ASSERT(tex.RefCount > 0) + tex.RefCount = tex.RefCount - 1 + g.UserTextures:find_erase(tex) +end + --- @param atlas ImFontAtlas function ImGui.RegisterFontAtlas(atlas) local g = GImGui @@ -5535,6 +5671,16 @@ local GLocalizationEntriesEnUS = { ImGuiLocEntry(ImGuiLocKey.DockingDragToUndockOrMoveNode, "Click and drag to move or undock whole node."), } +-- [Luau] Default platform handlers (upstream: next to the metrics section; defined here so Initialize() can see the local). +-- Roblox has no shell: IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS path. Default clipboard/IME handlers are OS-specific: left nil +-- (the backends install their own clipboard handlers). +local function Platform_OpenInShellFn_DefaultImpl(ctx, path) return false end + +-- Setup default ImGuiPlatformIO clipboard/IME handlers +local function InitializeDefaultPlatformHandlers(platform_io) + platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl +end + function ImGui.Initialize() local g = GImGui IM_ASSERT(not g.Initialized and not g.SettingsLoaded) @@ -5547,6 +5693,23 @@ function ImGui.Initialize() -- Setup default localization table ImGui.LocalizeRegisterEntries(GLocalizationEntriesEnUS, #GLocalizationEntriesEnUS) + -- Setup default ImGuiPlatformIO clipboard/IME handlers. + InitializeDefaultPlatformHandlers(g.PlatformIO) + + -- [Luau] Debug tools context fields not (yet) in ImGuiContext() (imgui_internal.lua): initialized here. + if g.DebugItemPickerActive == nil then g.DebugItemPickerActive = false end -- Item picker is active (started with DebugStartItemPicker()) + if g.DebugItemPickerMouseButton == nil then g.DebugItemPickerMouseButton = ImGuiMouseButton.Left end + if g.DebugItemPickerBreakId == nil then g.DebugItemPickerBreakId = 0 end -- Will call IM_DEBUG_BREAK() when encountering this ID + if g.DebugFlashStyleColorTime == nil then g.DebugFlashStyleColorTime = 0.0 end + if g.DebugFlashStyleColorBackup == nil then g.DebugFlashStyleColorBackup = ImVec4(0, 0, 0, 0) end + if g.DebugLocateId == nil then g.DebugLocateId = 0 end -- Storage for DebugLocateItem(): ID to locate + if g.DebugLocateFrames == nil then g.DebugLocateFrames = 0 end -- Storage for DebugLocateItem(): number of frames to display + if g.DebugBreakInLocateId == nil then g.DebugBreakInLocateId = false end -- Debug break in ItemAdd() call for g.DebugLocateId. + if g.DebugBreakKeyChord == nil then g.DebugBreakKeyChord = ImGuiKey.Pause end -- = ImGuiKey_Pause + if g.DebugBreakInShortcutRouting == nil then g.DebugBreakInShortcutRouting = ImGuiKey.None end + if g.DebugLogAutoDisableFrames == nil then g.DebugLogAutoDisableFrames = 0 end + if g.DebugLogAutoDisableFlags == nil then g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags.None end + -- Create default viewport local viewport = ImGuiViewportP() viewport.ID = IMGUI_VIEWPORT_DEFAULT_ID @@ -5947,6 +6110,21 @@ local function WindowSettingsHandler_ClearAll(ctx, handler) g.SettingsWindows:clear() end +-- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD number, 0 = invalid), so ImGuiPackedDate::IsValid()/Unpack() are inlined. +-- g.SessionDate doesn't exist in this port's context yet (no Platform_SessionDate support): treated as 0. +local function WindowSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for _, settings in g.SettingsWindows:iter() do + local is_valid = (settings.LastUsedDate or 0) ~= 0 + if ((args._DiscardOlderThanDate or 0) ~= 0 and (settings.LastUsedDate or 0) < args._DiscardOlderThanDate) or (args.DiscardWhenMissingDate and not is_valid) then + settings.WantDelete = true + end + if args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate or 0 + end + end +end + local function WindowSettingsHandler_ReadOpen(ctx, handler, name) local id = ImHashStr(name) local settings = ImGui.FindWindowSettingsByID(id) @@ -6062,6 +6240,7 @@ function ImGui.WindowSettingsAddSettingsHandler() ini_handler.TypeName = "Window" ini_handler.TypeHash = ImHashStr("Window") ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll + ini_handler.CleanupFn = WindowSettingsHandler_Cleanup ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll @@ -6437,6 +6616,20 @@ function ImGui.ItemAdd(bb, id, nav_bb_arg, extra_flags) end end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + if id == g.DebugLocateId then + ImGui.DebugLocateItemResolveWithLastItem() + end + + -- [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". + -- Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". + -- READ THE FAQ: https://dearimgui.com/faq + IM_ASSERT(id ~= window.ID, "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!") + end +end + if id ~= 0 and g.DeactivatedItemData.ID == id then g.DeactivatedItemData.ElapseFrame = g.FrameCount end @@ -7922,6 +8115,21 @@ end return false end +if not IMGUI_DISABLE_DEBUG_TOOLS then + if id ~= 0 then + -- [DEBUG] Item Picker tool! + -- We perform the check here because reaching is path is rare (1~ time a frame), + -- making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered + -- items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost. + if g.DebugItemPickerActive and g.HoveredIdPreviousFrame == id then + ImGui.GetForegroundDrawList():AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)) + end + if g.DebugItemPickerBreakId == id then + IM_DEBUG_BREAK() + end + end +end + if g.NavHighlightItemUnderNav and (bit32.band(item_flags, ImGuiItemFlags.NoNavDisableMouseHover) == 0) then return false end @@ -8029,6 +8237,19 @@ function MT.ImGuiIO:AddInputCharacterUTF16(c) self:AddInputCharacter(cp) end +--- @param str string +function MT.ImGuiIO:AddInputCharactersUTF8(str) + if not self.AppAcceptingEvents then + return + end + local p, str_end = 1, #str + 1 + while p < str_end and string.byte(str, p) ~= 0 do + local len, c = ImStd.ImTextCharFromUtf8(str, p, str_end) + p = p + len + self:AddInputCharacter(c) + end +end + -- Clear all incoming events. function MT.ImGuiIO:ClearEventsQueue() IM_ASSERT(self.Ctx ~= nil) @@ -8081,7 +8302,7 @@ end --- @param type ImGuiInputEventType --- @param arg? int --- @return ImGuiInputEvent? -function MT.ImGuiIO:FindLatestInputEvent(ctx, type, arg) +local function FindLatestInputEvent(ctx, type, arg) if arg == nil then arg = -1 end local g = ctx @@ -8131,7 +8352,7 @@ function MT.ImGuiIO:AddKeyAnalogEvent(key, down, analog_value) end -- Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed) - local latest_event = self:FindLatestInputEvent(g, ImGuiInputEventType.Key, key) + local latest_event = FindLatestInputEvent(g, ImGuiInputEventType.Key, key) local key_data = ImGui.GetKeyData(g, key) local latest_key_down = latest_event and latest_event.Key.Down or key_data.Down local latest_key_analog = latest_event and latest_event.Key.AnalogValue or key_data.AnalogValue @@ -8161,6 +8382,23 @@ function MT.ImGuiIO:AddKeyEvent(key, down) self:AddKeyAnalogEvent(key, down, (down and 1.0 or 0.0)) end +-- [Optional] Call after AddKeyEvent(). +-- Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices. +-- If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. +--- @param key ImGuiKey +--- @param native_keycode int +--- @param native_scancode int +--- @param native_legacy_index? int +function MT.ImGuiIO:SetKeyEventNativeData(key, native_keycode, native_scancode, native_legacy_index) + if native_legacy_index == nil then native_legacy_index = -1 end + if key == ImGuiKey.None then + return + end + IM_ASSERT(ImGui.IsNamedKey(key)) -- >= 512 + IM_ASSERT(native_legacy_index == -1 or (native_legacy_index >= 0 and native_legacy_index < 512)) -- [Luau] inline IsLegacyKey(): >= 0 && <= 511 + -- Yet unused: key, native_keycode, native_scancode, native_legacy_index +end + -- 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. --- @param accepting_events bool function MT.ImGuiIO:SetAppAcceptingEvents(accepting_events) @@ -8186,7 +8424,7 @@ function MT.ImGuiIO:AddMouseViewportEvent(viewport_id) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, ImGuiInputEventType.MouseViewport) + local latest_event = FindLatestInputEvent(g, ImGuiInputEventType.MouseViewport) local latest_viewport_id if latest_event then latest_viewport_id = latest_event.MouseViewport.HoveredViewportID @@ -8211,7 +8449,7 @@ function MT.ImGuiIO:AddFocusEvent(focused) local g = self.Ctx -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, ImGuiInputEventType.Focus) + local latest_event = FindLatestInputEvent(g, ImGuiInputEventType.Focus) local latest_focused = latest_event and latest_event.AppFocused.Focused or (not g.IO.AppFocusLost) if latest_focused == focused or (self.ConfigDebugIgnoreFocusLoss and not focused) then return @@ -8248,7 +8486,7 @@ function MT.ImGuiIO:AddMousePosEvent(x, y) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, ImGuiInputEventType.MousePos) + local latest_event = FindLatestInputEvent(g, ImGuiInputEventType.MousePos) local latest_pos = latest_event and ImVec2(latest_event.MousePos.PosX, latest_event.MousePos.PosY) or self.MousePos if latest_pos.x == x_val and latest_pos.y == y_val then return @@ -8286,7 +8524,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) end -- Filter duplicate - local latest_event = self:FindLatestInputEvent(g, ImGuiInputEventType.MouseButton, mouse_button) + local latest_event = FindLatestInputEvent(g, ImGuiInputEventType.MouseButton, mouse_button) local latest_button_down = latest_event and latest_event.MouseButton.Down or self.MouseDown[mouse_button] if latest_button_down == down then return @@ -8296,7 +8534,7 @@ function MT.ImGuiIO:AddMouseButtonEvent(mouse_button, down) -- - Note that this is actual physical Ctrl which is ImGuiMod_Super for us. -- - At this point we want from !down to down, so this is handling the initial press. if self.ConfigMacOSXBehaviors and mouse_button == 0 and down then - local latest_super_event = self:FindLatestInputEvent(g, ImGuiInputEventType.Key, ImGuiMod_Super) + local latest_super_event = FindLatestInputEvent(g, ImGuiInputEventType.Key, ImGuiMod_Super) if latest_super_event and latest_super_event.Key.Down or self.KeySuper then -- IMGUI_DEBUG_LOG_IO("[io] Super+Left Click aliased into Right Click\n") self.MouseCtrlLeftAsRightClick = true @@ -8946,7 +9184,7 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) -- [DEBUG] Debug break requested by user if g.DebugBreakInShortcutRouting == key_chord then - -- IM_DEBUG_BREAK() + IM_DEBUG_BREAK() end if bit32.band(flags, ImGuiInputFlags.RouteUnlessBgFocused) ~= 0 then @@ -9017,6 +9255,18 @@ function ImGui.SetShortcutRouting(key_chord, flags, owner_id) return routing_data.RoutingCurr == owner_id end +-- Currently unused by core (but used by tests) +-- Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. +--- @param key_chord ImGuiKeyChord +--- @param owner_id ImGuiID +--- @return bool +function ImGui.TestShortcutRouting(key_chord, owner_id) + local routing_id = GetRoutingIdFromOwnerId(owner_id) + key_chord = ImGui.FixupKeyChord(key_chord) + local routing_data = ImGui.GetShortcutRoutingData(key_chord) -- FIXME: Could avoid creating entry. + return routing_data.RoutingCurr == routing_id +end + -- We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position. --- @param mouse_pos? ImVec2 function ImGui.IsMousePosValid(mouse_pos) @@ -9245,6 +9495,39 @@ function ImGui.ResetMouseDragDelta(button) ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos) end +--- @param source ImGuiInputSource +--- @return string +local function GetInputSourceName(source) + local input_source_names = { "None", "Mouse", "Keyboard", "Gamepad" } + IM_ASSERT(#input_source_names == ImGuiInputSource.COUNT) + if source < 0 or source >= ImGuiInputSource.COUNT then + return "Unknown" + end + return input_source_names[source + 1] +end +--- @param source ImGuiMouseSource +--- @return string +local function GetMouseSourceName(source) + local mouse_source_names = { "Mouse", "TouchScreen", "Pen" } + IM_ASSERT(#mouse_source_names == ImGuiMouseSource.COUNT) + if source < 0 or source >= ImGuiMouseSource.COUNT then + return "Unknown" + end + return mouse_source_names[source + 1] +end +--- @param prefix string +--- @param e ImGuiInputEvent +local function DebugPrintInputEvent(prefix, e) + local T = ImGuiInputEventType + if e.Type == T.MousePos then if e.MousePos.PosX == -FLT_MAX and e.MousePos.PosY == -FLT_MAX then IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix) else IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix, e.MousePos.PosX, e.MousePos.PosY, GetMouseSourceName(e.MousePos.MouseSource)) end return end + if e.Type == T.MouseButton then IMGUI_DEBUG_LOG_IO("[io] %s: MouseButton %d %s (%s)\n", prefix, e.MouseButton.Button, e.MouseButton.Down and "Down" or "Up", GetMouseSourceName(e.MouseButton.MouseSource)) return end + if e.Type == T.MouseWheel then IMGUI_DEBUG_LOG_IO("[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix, e.MouseWheel.WheelX, e.MouseWheel.WheelY, GetMouseSourceName(e.MouseWheel.MouseSource)) return end + if e.Type == T.MouseViewport then IMGUI_DEBUG_LOG_IO("[io] %s: MouseViewport (0x%08X)\n", prefix, e.MouseViewport.HoveredViewportID) return end + if e.Type == T.Key then IMGUI_DEBUG_LOG_IO("[io] %s: Key \"%s\" %s\n", prefix, ImGui.GetKeyName(e.Key.Key), e.Key.Down and "Down" or "Up") return end + if e.Type == T.Text then IMGUI_DEBUG_LOG_IO("[io] %s: Text: '%s' (U+%08X)\n", prefix, utf8.char(e.Text.Char), e.Text.Char) return end -- [Luau] utf8.char() instead of ImTextCharToUtf8() + if e.Type == T.Focus then IMGUI_DEBUG_LOG_IO("[io] %s: AppFocused %d\n", prefix, e.AppFocused.Focused and 1 or 0) return end +end + do local key_changed_mask = ImBitArray(ImGuiKey.NamedKey_COUNT) @@ -9377,6 +9660,15 @@ function ImGui.UpdateInputEvents(trickle_fast_inputs) event_n = event_n + 1 end + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if event_n ~= 1 and bit32.band(g.DebugLogFlags, ImGuiDebugLogFlags.EventIO) ~= 0 then -- [Luau] event_n is the 1-based next index: processed count = event_n - 1 + for n = 1, g.InputEventsQueue.Size do + DebugPrintInputEvent((n < event_n) and "Processed" or "Remaining", g.InputEventsQueue.Data[n]) + end + end +end + -- Remaining events will be processed on the next frame -- FIXME-MULTITHREADING: io.AddKeyEvent() etc. calls are mostly thread-safe apart from the fact they push to this -- queue which may be resized here. Could potentially rework this to narrow down the section needing a mutex? (#5772) @@ -9573,6 +9865,12 @@ end --- @param window ImGuiWindow --- @nodiscard +--- @param window ImGuiWindow +--- @return ImGuiWindow +local function GetWindowForTitleAndMenuHeight(window) + return (window.DockNodeAsHost and window.DockNodeAsHost.VisibleWindow) and window.DockNodeAsHost.VisibleWindow or window +end + local function CalcWindowMinSize(window) -- We give windows non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) -- FIXME: Essentially we want to restrict manual resizing to WindowMinSize+Decoration, and allow api resizing to be smaller. @@ -9608,7 +9906,7 @@ local function CalcWindowMinSize(window) end -- Reduce artifacts with very small windows - local window_for_height = window + local window_for_height = GetWindowForTitleAndMenuHeight(window) size_min.y = ImMax(size_min.y, window_for_height.TitleBarHeight + window_for_height.MenuBarHeight + ImMax(0, g.Style.WindowRounding - 1)) return size_min @@ -9796,6 +10094,29 @@ end --- @param resize_grip_col table --- @param visibility_rect ImRect --- @return int, int, int +--- @param window ImGuiWindow +--- @param n int +--- @return ImGuiID +function ImGui.GetWindowResizeCornerID(window, n) + IM_ASSERT(n >= 0 and n < 4) + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] ImHashData(&n, sizeof(int), id): same hashing as window:GetID(n) used by UpdateWindowManualResize() + return id +end + +--- @param window ImGuiWindow +--- @param dir ImGuiDir +--- @return ImGuiID +function ImGui.GetWindowResizeBorderID(window, dir) + IM_ASSERT(dir >= 0 and dir < 4) + local n = dir + 4 + local id = window.DockIsActive and window.DockNode.HostWindow.ID or window.ID + id = ImHashStr("#RESIZE", nil, id) + id = ImHashData(n, -1, id) -- [Luau] see GetWindowResizeCornerID() + return id +end + local function UpdateWindowManualResize(window, resize_grip_count, resize_grip_col, visibility_rect) local g = GImGui local flags = window.Flags @@ -10427,6 +10748,21 @@ end --- @param border_n int --- @param border_col ImU32 --- @param border_size float +--- @param window ImGuiWindow +--- @param visibility_rect ImRect +local function ClampWindowPos(window, visibility_rect) + local size_for_clamping = ImVec2(window.Size.x, window.Size.y) + local move_from_title_bar_only = bit32.band(window.BgClickFlags, ImGuiWindowBgClickFlags.Move) == 0 + if move_from_title_bar_only and window.DockNodeAsHost then + size_for_clamping.y = ImGui.GetFrameHeight() -- Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here. + elseif move_from_title_bar_only and bit32.band(window.Flags, ImGuiWindowFlags.NoTitleBar) == 0 then + size_for_clamping.y = window.TitleBarHeight + end + -- [Luau] in place (window.Pos may be referenced elsewhere): window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max) + window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - size_for_clamping.x, visibility_rect.Max.x) + window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping.y, visibility_rect.Max.y) +end + local function RenderWindowOuterSingleBorder(window, border_n, border_col, border_size) local def = ImGuiResizeBorderDef[border_n + 1] local rounding = window.WindowRounding @@ -11094,6 +11430,11 @@ function ImGui.GetWindowDrawList() return window.DrawList end +--- @return ImFontBaked +function ImGui.GetFontBaked() + return GImGui.FontBaked +end + function ImGui.GetFont() return GImGui.Font end @@ -11716,6 +12057,11 @@ function ImGui.Begin(name, open, flags) window = CreateNewWindow(name, flags) --- @cast window ImGuiWindow end + -- [DEBUG] Debug break requested by user + if g.DebugBreakInWindow == window.ID then + IM_DEBUG_BREAK() + end + if bit32.band(g.NextWindowData.HasFlags, ImGuiNextWindowDataFlags.HasWindowFlags) ~= 0 then flags = bit32.band(bit32.bor(flags, g.NextWindowData.WindowFlagsSet), bit32.bnot(g.NextWindowData.WindowFlagsClear)) end @@ -12214,12 +12560,7 @@ function ImGui.Begin(name, open, flags) -- FIXME: Similar to code in GetWindowAllowedExtentRect() if not window_pos_set_by_api and bit32.band(flags, ImGuiWindowFlags.ChildWindow) == 0 then if not window.ViewportOwned and viewport_rect:GetWidth() > 0 and viewport_rect:GetHeight() > 0.0 then - local size_for_clamping_y = window.Size.y - if bit32.band(window.BgClickFlags, ImGuiWindowBgClickFlags.Move) == 0 and bit32.band(window.Flags, ImGuiWindowFlags.NoTitleBar) == 0 then - size_for_clamping_y = window.TitleBarHeight - end - window.Pos.x = ImClamp(window.Pos.x, visibility_rect.Min.x - window.Size.x, visibility_rect.Max.x) - window.Pos.y = ImClamp(window.Pos.y, visibility_rect.Min.y - size_for_clamping_y, visibility_rect.Max.y) + ClampWindowPos(window, visibility_rect) end end window.Pos.x = ImTrunc(window.Pos.x) window.Pos.y = ImTrunc(window.Pos.y) @@ -12654,6 +12995,13 @@ function ImGui.Begin(name, open, flags) window.DC.WindowItemStatusFlags = bit32.bor(window.DC.WindowItemStatusFlags, ImGuiItemStatusFlags.HoveredRect) end ImGui.SetLastItemDataForWindow(window, title_bar_rect) + + -- [DEBUG] +if not IMGUI_DISABLE_DEBUG_TOOLS then + if g.DebugLocateId ~= 0 and (window.ID == g.DebugLocateId or window.MoveId == g.DebugLocateId) then + ImGui.DebugLocateItemResolveWithLastItem() + end +end else -- Skip refresh always mark active if (window.SkipRefresh) then @@ -13770,14 +14118,19 @@ function ImGui.NewFrame() IM_ASSERT(GImGui ~= nil, "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?") local g = GImGui - g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame - -- [Luau] ErrorCheckNewFrameSanityChecks() is not ported; only the parts below are inlined. - IM_ASSERT(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") - -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) - if g.Style.CurveTessellationTol ~= 0.0 then - g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + -- Remove pending delete hooks before frame start. + -- This deferred removal avoid issues of removal while iterating the hook vector + for n = g.Hooks.Size, 1, -1 do + if g.Hooks.Data[n].Type == ImGuiContextHookType.PendingRemoval_ then + g.Hooks:erase(n) + end end - g.Style.CurveTessellationTol = 0.0 + + ImGui.CallContextHooks(g, ImGuiContextHookType.NewFramePre) + + -- Check and assert for various common IO and Configuration mistakes + g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame + ImGui.ErrorCheckNewFrameSanityChecks() g.ConfigFlagsCurrFrame = g.IO.ConfigFlags -- Load settings on first frame, save settings when modified (after a delay) @@ -14048,12 +14401,31 @@ function ImGui.NewFrame() g.CurrentItemFlags = g.ItemFlagsStack:back() g.GroupStack:resize(0) - -- [DEBUG] ID Stack Tool query - ImGui.UpdateDebugToolItemPathQuery() - -- Docking ImGui.DockContextNewFrameUpdateDocking(g) + -- [DEBUG] Update debug features +if not IMGUI_DISABLE_DEBUG_TOOLS then + ImGui.UpdateDebugToolItemPicker() + ImGui.UpdateDebugToolItemPathQuery() + ImGui.UpdateDebugToolFlashStyleColor() + if g.DebugLocateFrames > 0 then + g.DebugLocateFrames = g.DebugLocateFrames - 1 + if g.DebugLocateFrames == 0 then + g.DebugLocateId = 0 + g.DebugBreakInLocateId = false + end + end + if (g.DebugLogAutoDisableFrames or 0) > 0 then + g.DebugLogAutoDisableFrames = g.DebugLogAutoDisableFrames - 1 + if g.DebugLogAutoDisableFrames == 0 then + ImGui.DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n") + g.DebugLogFlags = bit32.band(g.DebugLogFlags, bit32.bnot(g.DebugLogAutoDisableFlags)) + g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags.None + end + end +end + -- Create implicit/fallback window - which we will only render it if the user has added something to it. -- We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. -- This fallback is particularly important as it prevents ImGui:: calls from crashing. @@ -14074,6 +14446,8 @@ function ImGui.NewFrame() else g.DebugBeginReturnValueCullDepth = -1 end + + ImGui.CallContextHooks(g, ImGuiContextHookType.NewFramePost) end -- This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. @@ -14087,10 +14461,13 @@ function ImGui.EndFrame() end IM_ASSERT_USER_ERROR(g.WithinFrameScope, "Forgot to call ImGui::NewFrame()?") + ImGui.CallContextHooks(g, ImGuiContextHookType.EndFramePre) + -- [EXPERIMENTAL] Recover from errors if g.IO.ConfigErrorRecovery and g.StackSizesInNewFrame then ImGui.ErrorRecoveryTryToRecoverState(g.StackSizesInNewFrame) end + ImGui.ErrorCheckEndFrameSanityChecks() ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) @@ -14182,6 +14559,8 @@ function ImGui.EndFrame() g.IO.MouseWheel = 0.0 g.IO.MouseWheelH = 0.0 g.IO.InputQueueCharacters:resize(0) + + ImGui.CallContextHooks(g, ImGuiContextHookType.EndFramePost) end -- TODO: @@ -14199,6 +14578,7 @@ function ImGui.Render() g.FrameCountRendered = g.FrameCount g.IO.MetricsRenderWindows = 0 + ImGui.CallContextHooks(g, ImGuiContextHookType.RenderPre) -- Add background ImDrawList (for each active viewport) for _, viewport in g.Viewports:iter() do @@ -14251,6 +14631,8 @@ function ImGui.Render() g.IO.MetricsRenderVertices = g.IO.MetricsRenderVertices + draw_data.TotalVtxCount g.IO.MetricsRenderIndices = g.IO.MetricsRenderIndices + draw_data.TotalIdxCount end + + ImGui.CallContextHooks(g, ImGuiContextHookType.RenderPost) end -- Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. @@ -14333,13 +14715,16 @@ function ImGui.Shutdown() end g.DrawListSharedData.TempBuffer:clear() - -- Shutdown extensions - ImGui.DockContextShutdown(g) - -- Cleanup of other data are conditional on actually having initialized Dear ImGui. if not g.Initialized then return end + + -- Shutdown extensions + ImGui.DockContextShutdown(g) + + ImGui.CallContextHooks(g, ImGuiContextHookType.Shutdown) + -- TODO: -- Clear everything else @@ -14348,6 +14733,74 @@ function ImGui.Shutdown() g.MenusIdSubmittedThisFrame:clear() end +-- When using multiple context it can be helpful to give name a name. +-- (A) Will be visible in debugger, (B) Will be included in all IMGUI_DEBUG_LOG() calls, (C) Should be <= 15 characters long. +--- @param ctx ImGuiContext +--- @param name string +function ImGui.SetContextName(ctx, name) + ctx.ContextName = string.sub(name, 1, 15) -- [Luau] ImStrncpy() into char[16] +end + +-- [Luau] ImGuiContextHookType / ImGuiContextHook are not defined in imgui_internal.lua yet: defined here. +--- @enum ImGuiContextHookType +ImGuiContextHookType = ImGuiContextHookType or { NewFramePre = 0, NewFramePost = 1, EndFramePre = 2, EndFramePost = 3, RenderPre = 4, RenderPost = 5, Shutdown = 6, PendingRemoval_ = 7 } + +--- @class ImGuiContextHook +--- @field HookId ImGuiID -- A unique ID assigned by AddContextHook() +--- @field Type ImGuiContextHookType +--- @field Owner ImGuiID +--- @field Callback fun(ctx: ImGuiContext, hook: ImGuiContextHook)? +--- @field UserData any +if ImGuiContextHook == nil then + function ImGuiContextHook() + return { HookId = 0, Type = ImGuiContextHookType.NewFramePre, Owner = 0, Callback = nil, UserData = nil } + end +end + +-- No specific ordering/dependency support, will see as needed +--- @param ctx ImGuiContext +--- @param hook ImGuiContextHook +--- @return ImGuiID +function ImGui.AddContextHook(ctx, hook) + local g = ctx + IM_ASSERT(hook.Callback ~= nil and (hook.HookId or 0) == 0 and hook.Type ~= ImGuiContextHookType.PendingRemoval_) + local copy = ImGuiContextHook() -- [Luau] g.Hooks.push_back(*hook): store a copy + copy.Type = hook.Type; copy.Owner = hook.Owner or 0; copy.Callback = hook.Callback; copy.UserData = hook.UserData + g.Hooks:push_back(copy) + g.HookIdNext = g.HookIdNext + 1 + g.Hooks:back().HookId = g.HookIdNext + return g.HookIdNext +end + +-- Deferred removal, avoiding issue with changing vector while iterating it +--- @param ctx ImGuiContext +--- @param hook_id ImGuiID +function ImGui.RemoveContextHook(ctx, hook_id) + local g = ctx + IM_ASSERT(hook_id ~= 0) + for _, hook in g.Hooks:iter() do + if hook.HookId == hook_id then + hook.Type = ImGuiContextHookType.PendingRemoval_ + end + end +end + +-- Call context hooks (used by e.g. test engine) +-- We assume a small number of hooks so all stored in same array +--- @param ctx ImGuiContext +--- @param hook_type ImGuiContextHookType +function ImGui.CallContextHooks(ctx, hook_type) + local g = ctx + local hooks = g.Hooks + if hooks.Size == 0 then return end -- [Luau] fast path + for n = 1, hooks.Size do + local hook = hooks.Data[n] + if hook.Type == hook_type then + hook.Callback(g, hook) + end + end +end + -- A conformant backend should return nil on failure (e.g. clipboard data is not text). --- @return string? function ImGui.GetClipboardText() @@ -15265,6 +15718,11 @@ end --- @param fmt string --- @param ... any function ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()) +function ImGui.SetTooltipV(fmt, ...) if not ImGui.BeginTooltipEx(ImGuiTooltipFlags.OverridePrevious, ImGuiWindowFlags.None) then return end @@ -15277,8 +15735,12 @@ end --- @param fmt string --- @param ... any function ImGui.SetItemTooltip(fmt, ...) + ImGui.SetItemTooltipV(fmt, ...) +end + +function ImGui.SetItemTooltipV(fmt, ...) if ImGui.IsItemHovered(ImGuiHoveredFlags.ForTooltip) then - ImGui.SetTooltip(fmt, ...) + ImGui.SetTooltipV(fmt, ...) end end @@ -17663,6 +18125,7 @@ function MT.ImGuiPlatformIO:ClearPlatformHandlers() self.Platform_SetWindowTitle = nil; self.Platform_SetWindowAlpha = nil; self.Platform_UpdateWindow = nil self.Platform_RenderWindow = nil; self.Platform_SwapBuffers = nil; self.Platform_GetWindowDpiScale = nil self.Platform_OnChangedViewport = nil; self.Platform_GetWindowWorkAreaInsets = nil; self.Platform_CreateVkSurface = nil + InitializeDefaultPlatformHandlers(self) -- Prevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation. end function MT.ImGuiPlatformIO:ClearRendererHandlers() @@ -17693,6 +18156,18 @@ function ImGui.FindViewportByID(viewport_id) return nil end +--- @param platform_handle any +--- @return ImGuiViewportP? +function ImGui.FindViewportByPlatformHandle(platform_handle) + local g = GImGui + for _, viewport in g.Viewports:iter() do + if viewport.PlatformHandle == platform_handle then + return viewport + end + end + return nil +end + --- @param current_window? ImGuiWindow --- @param viewport? ImGuiViewportP function ImGui.SetCurrentViewport(current_window, viewport) @@ -19811,6 +20286,99 @@ function ImGuiErrorRecoveryState() SizeOfBeginPopupStack = 0, SizeOfDisabledStack = 0 } end +function ImGui.ErrorCheckNewFrameSanityChecks() + local g = GImGui + + -- [Luau] C++-only check of the user's IM_ASSERT macro definition dropped. + + -- Check user data + -- (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) + IM_ASSERT(g.Initialized) + IM_ASSERT(g.IO.DeltaTime > 0.0 or g.FrameCount == 0, "Need a positive DeltaTime!") + IM_ASSERT(g.FrameCount == 0 or g.FrameCountEnded == g.FrameCount, "Forgot to call Render() or EndFrame() at the end of the previous frame?") + IM_ASSERT(g.IO.DisplaySize.x >= 0.0 and g.IO.DisplaySize.y >= 0.0, "Invalid DisplaySize value!") + IM_ASSERT(g.Style.CurveTessellationMaxError > 0.0, "Invalid style setting!") + IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0, "Invalid style setting!") + IM_ASSERT(g.Style.Alpha >= 0.0 and g.Style.Alpha <= 1.0, "Invalid style setting!") -- Allows us to avoid a few clamps in color computations + IM_ASSERT(g.Style.WindowMinSize.x >= 1.0 and g.Style.WindowMinSize.y >= 1.0, "Invalid style setting!") + IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0, "Invalid style setting!") -- Required otherwise cannot resize from borders. + IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir.None or g.Style.WindowMenuButtonPosition == ImGuiDir.Left or g.Style.WindowMenuButtonPosition == ImGuiDir.Right) + IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir.Left or g.Style.ColorButtonPosition == ImGuiDir.Right) + IM_ASSERT(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, ImGuiColorEditFlags.DisplayMask_))) -- Check only 1 option is selected + IM_ASSERT(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, ImGuiColorEditFlags.DataTypeMask_))) -- " + IM_ASSERT(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, ImGuiColorEditFlags.PickerMask_))) -- " + IM_ASSERT(ImIsPowerOfTwo(bit32.band(g.IO.ConfigColorEditFlags, ImGuiColorEditFlags.InputMask_))) -- " + + IM_ASSERT(g.Style.TreeLinesFlags == ImGuiTreeNodeFlags.DrawLinesNone or g.Style.TreeLinesFlags == ImGuiTreeNodeFlags.DrawLinesFull or g.Style.TreeLinesFlags == ImGuiTreeNodeFlags.DrawLinesToNodes) + IM_ASSERT(g.IO.MouseSingleClickDelay > g.IO.MouseDoubleClickTime) + + -- Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way. + if g.IO.ConfigErrorRecovery then + IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert or g.IO.ConfigErrorRecoveryEnableDebugLog or g.IO.ConfigErrorRecoveryEnableTooltip or g.ErrorCallback ~= nil) + end + + -- [Luau] Obsolete io.FontGlobalScale, ImGuiConfigFlags_NavEnableSetMousePos/NavNoCaptureKeyboard/DpiEnableScaleXXX and + -- io.Get/SetClipboardTextFn don't exist in this port: their remaps are dropped. + + -- Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026) + if g.Style.CurveTessellationTol ~= 0.0 then + g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol) + end + g.Style.CurveTessellationTol = 0.0 + + -- Perform simple check: error if Docking or Viewport are enabled _exactly_ on frame 1 (instead of frame 0 or later), which is a common error leading to loss of .ini data. + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, ImGuiConfigFlags.DockingEnable) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, ImGuiConfigFlags.DockingEnable) == 0 then + IM_ASSERT(false, "Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + if g.FrameCount == 1 and bit32.band(g.IO.ConfigFlags, ImGuiConfigFlags.ViewportsEnable) ~= 0 and bit32.band(g.ConfigFlagsLastFrame, ImGuiConfigFlags.ViewportsEnable) == 0 then + IM_ASSERT(false, "Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your .ini settings!") + end + + -- Perform simple checks: multi-viewport and platform windows support + if bit32.band(g.IO.ConfigFlags, ImGuiConfigFlags.ViewportsEnable) ~= 0 then + if bit32.band(g.IO.BackendFlags, ImGuiBackendFlags.PlatformHasViewports) ~= 0 and bit32.band(g.IO.BackendFlags, ImGuiBackendFlags.RendererHasViewports) ~= 0 then + local pio = g.PlatformIO + IM_ASSERT(g.FrameCount == 0 or g.FrameCount == g.FrameCountPlatformEnded, "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.") + IM_ASSERT(pio.Platform_CreateWindow ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Platform_DestroyWindow ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Platform_GetWindowPos ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Platform_SetWindowPos ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Platform_GetWindowSize ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Platform_SetWindowSize ~= nil, "Platform init didn't install handlers?") + IM_ASSERT(pio.Monitors.Size > 0, "Platform init didn't setup Monitors list?") + IM_ASSERT(g.Viewports.Data[1].PlatformUserData ~= nil or g.Viewports.Data[1].PlatformHandle ~= nil, "Platform init didn't setup main viewport.") + if g.IO.ConfigDockingTransparentPayload and bit32.band(g.IO.ConfigFlags, ImGuiConfigFlags.DockingEnable) ~= 0 then + IM_ASSERT(pio.Platform_SetWindowAlpha ~= nil, "Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!") + end + else + -- Disable feature, our backends do not support it + g.IO.ConfigFlags = bit32.band(g.IO.ConfigFlags, bit32.bnot(ImGuiConfigFlags.ViewportsEnable)) + end + + -- Perform simple checks on platform monitor data + compute a total bounding box for quick early outs + for _, mon in g.PlatformIO.Monitors:iter() do + IM_ASSERT(mon.MainSize.x > 0.0 and mon.MainSize.y > 0.0, "Monitor main bounds not setup properly.") + IM_ASSERT(ImRect(mon.MainPos, mon.MainPos + mon.MainSize):Contains(ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)), "Monitor work bounds not setup properly. If you don't have work area information, just copy MainPos/MainSize into them.") + IM_ASSERT(mon.DpiScale > 0.0 and mon.DpiScale < 99.0, "Monitor DpiScale is invalid.") -- Typical correct values would be between 1.0f and 4.0f + end + end +end + +function ImGui.ErrorCheckEndFrameSanityChecks() + -- Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() + -- One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). + -- It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will + -- send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. + -- We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), + -- while still correctly asserting on mid-frame key press events. + local g = GImGui + local key_mods = ImGui.GetMergedModsFromKeys() + IM_ASSERT(key_mods == 0 or g.IO.KeyMods == key_mods, "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods") + + IM_ASSERT(g.CurrentWindowStack.Size == 1) + IM_ASSERT(g.CurrentWindowStack.Data[1].Window.IsFallbackWindow) +end + -- Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery. function ImGui.ErrorRecoveryStoreState(state_out) local g = GImGui @@ -19930,9 +20498,20 @@ end -- Lines are stored in g.DebugLogBuf (one chunk per call) function ImGui.DebugLog(fmt, ...) + ImGui.DebugLogV(fmt, ...) +end + +-- [Luau] va_list -> varargs (same convention as TextV()). Without arguments `fmt` is used verbatim. +function ImGui.DebugLogV(fmt, ...) local g = GImGui g.DebugLogBuf = g.DebugLogBuf or ImGuiTextBuffer() - local str = string.format("[%05d] ", g.FrameCount) .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) + local prefix + if g.ContextName ~= nil and g.ContextName ~= "" then + prefix = string.format("[%s] [%05d] ", g.ContextName, g.FrameCount) + else + prefix = string.format("[%05d] ", g.FrameCount) + end + local str = prefix .. ((select("#", ...) > 0) and string.format(fmt, ...) or fmt) g.DebugLogBuf:append(str) -- Line index (upstream: g.DebugLogIndex). Lines are complete strings without '\n'. local lines = g.DebugLogLines @@ -20004,7 +20583,17 @@ function ImGui.ErrorCheckEndFrameFinalizeErrorTooltip() -- ImGui.BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags.AllowDuplicateId, true); ... PopItemFlag()") -- Not making this too visible for fear of it being abused. ImGui.BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds.") ImGui.Separator() - ImGui.Text("(Hold Ctrl to: ") + if g.IO.ConfigDebugHighlightIdConflictsShowItemPicker then + ImGui.Text("(Hold Ctrl to: use ") + ImGui.SameLine(0.0, 0.0) + if ImGui.SmallButton("Item Picker") then + ImGui.DebugStartItemPicker() + end + ImGui.SameLine(0.0, 0.0) + ImGui.Text(" to break in item call-stack, or ") + else + ImGui.Text("(Hold Ctrl to: ") + end ImGui.SameLine(0.0, 0.0) ImGui.TextLinkOpenURL("read FAQ \"About ID Stack System\"", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage") ImGui.SameLine(0.0, 0.0) @@ -20092,6 +20681,117 @@ ImGui.MetricsHelpMarker = MetricsHelpMarker local function U8(c) return (c and c > 0) and utf8.char(c) or "" end +-- [Luau] table.sort() "less than" predicate (upstream: ImQsort() comparer returning b - a) +--- @param a ImGuiViewportP +--- @param b ImGuiViewportP +local function ViewportComparerByLastFocusedStampCount(a, b) + return b.LastFocusedStampCount < a.LastFocusedStampCount +end + +-- Draw an arbitrary US keyboard layout to visualize translated keys +--- @param draw_list ImDrawList +function ImGui.DebugRenderKeyboardPreview(draw_list) + local scale = ImGui.GetFontSize() / 13.0 + local key_size = ImVec2(35.0, 35.0) * scale + local key_rounding = 3.0 * scale + local key_face_size = ImVec2(25.0, 25.0) * scale + local key_face_pos = ImVec2(5.0, 3.0) * scale + local key_face_rounding = 2.0 * scale + local key_label_pos = ImVec2(7.0, 4.0) * scale + local key_step = ImVec2(key_size.x - 1.0, key_size.y - 1.0) + local key_row_offset = 9.0 * scale + + local board_min = ImGui.GetCursorScreenPos() + local board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0, board_min.y + 3 * key_step.y + 10.0) + local start_pos = ImVec2(board_min.x + 5.0 - key_step.x, board_min.y) + + local K = ImGuiKey + local keys_to_display = { -- { Row, Col, Label, Key } + { 0, 0, "", K.Tab }, { 0, 1, "Q", K.Q }, { 0, 2, "W", K.W }, { 0, 3, "E", K.E }, { 0, 4, "R", K.R }, + { 1, 0, "", K.CapsLock }, { 1, 1, "A", K.A }, { 1, 2, "S", K.S }, { 1, 3, "D", K.D }, { 1, 4, "F", K.F }, + { 2, 0, "", K.LeftShift }, { 2, 1, "Z", K.Z }, { 2, 2, "X", K.X }, { 2, 3, "C", K.C }, { 2, 4, "V", K.V }, + } + + -- Elements rendered manually via ImDrawList API are not clipped automatically. + -- While not strictly necessary, here IsItemVisible() is used to avoid rendering these shapes when they are out of view. + ImGui.Dummy(board_max - board_min) + if not ImGui.IsItemVisible() then + return + end + draw_list:PushClipRect(board_min, board_max, true) + for n = 1, #keys_to_display do + local key_data = keys_to_display[n] + local key_min = ImVec2(start_pos.x + key_data[2] * key_step.x + key_data[1] * key_row_offset, start_pos.y + key_data[1] * key_step.y) + local key_max = key_min + key_size + draw_list:AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding) + draw_list:AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding) + local face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y) + local face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y) + draw_list:AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0) + draw_list:AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding) + local label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y) + draw_list:AddText(label_min, IM_COL32(64, 64, 64, 255), key_data[3]) + if ImGui.IsKeyDown(key_data[4]) then + draw_list:AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding) + end + end + draw_list:PopClipRect() +end + +-- [Luau] g.DebugFlashStyleColorIdx == nil stands for ImGuiCol_COUNT (see ImGuiContext() in imgui_internal.lua). +local function DebugFlashStyleColorStop() + local g = GImGui + if g.DebugFlashStyleColorIdx ~= nil then + ImVec4_Copy(g.Style.Colors[g.DebugFlashStyleColorIdx], g.DebugFlashStyleColorBackup) + end + g.DebugFlashStyleColorIdx = nil +end + +-- Flash a given style color for some + inhibit modifications of this color via PushStyleColor() calls. +--- @param idx ImGuiCol +function ImGui.DebugFlashStyleColor(idx) + local g = GImGui + DebugFlashStyleColorStop() + g.DebugFlashStyleColorTime = 0.5 + g.DebugFlashStyleColorIdx = idx + ImVec4_Copy(g.DebugFlashStyleColorBackup, g.Style.Colors[idx]) +end + +function ImGui.UpdateDebugToolFlashStyleColor() + local g = GImGui + if g.DebugFlashStyleColorTime <= 0.0 then + return + end + local col = g.Style.Colors[g.DebugFlashStyleColorIdx] + col.x, col.y, col.z = ImGui.ColorConvertHSVtoRGB(math.cos(g.DebugFlashStyleColorTime * 6.0) * 0.5 + 0.5, 0.5, 0.5) + col.w = 1.0 + g.DebugFlashStyleColorTime = g.DebugFlashStyleColorTime - g.IO.DeltaTime + if g.DebugFlashStyleColorTime <= 0.0 then + DebugFlashStyleColorStop() + end +end + +-- [Luau] ImTextureID can be any Lua value here: numbers are returned as is, anything else is returned unchanged too +-- (there is no memcpy into an ImU64); FormatTextureRefForDebugDisplay() formats non-numbers with tostring(). +--- @param tex_id ImTextureID +function ImGui.DebugTextureIDToU64(tex_id) + return tex_id +end + +--- @param tex_ref ImTextureRef +--- @return string +local function FormatTextureRefForDebugDisplay(tex_ref) + local buf = "" + if tex_ref._TexData ~= nil then + buf = string.format("#%03d: ", tex_ref._TexData.UniqueID) + end + local v = ImGui.DebugTextureIDToU64(tex_ref:GetTexID()) + if type(v) == "number" and v >= 0 and v == math.floor(v) then + return buf .. string.format("0x%X", v) + end + return buf .. tostring(v) +end + -- Demo helper function to select among loaded fonts. -- Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one. function ImGui.ShowFontSelector(label) @@ -20179,6 +20879,22 @@ function ImGui.DebugNodeFontGlyphsForSrcMask(font, baked, src_mask) end -- [DEBUG] Display details for a single font, called by ShowStyleEditor(). +-- [DEBUG] Compute mask of inputs with the same codepoint. +-- [Luau] the port's font loaders expose FontSrcContainsGlyph() (pre-1.93 loader API) instead of FontSrcGetGlyphIndexFromCodepoint() != 0. +local function CalcFontGlyphSrcOverlapMask(atlas, font, codepoint) + local mask, count = 0, 0 + for src_n = 0, font.Sources.Size - 1 do repeat + local src = font.Sources.Data[src_n + 1] + local loader = src.FontLoader or atlas.FontLoader + if not (loader.FontSrcContainsGlyph ~= nil and loader.FontSrcContainsGlyph(atlas, src, codepoint)) then + break -- continue + end + mask = bit32.bor(mask, bit32.lshift(1, src_n)) + count = count + 1 + until true end + return (count > 1) and mask or 0 +end + function ImGui.DebugNodeFont(font) local g = ImGui.GetCurrentContext() local cfg = g.DebugMetricsConfig @@ -20223,6 +20939,39 @@ function ImGui.DebugNodeFont(font) ImGui.TreePop() end end + if font.Sources.Size > 1 and ImGui.TreeNode("Input Glyphs Overlap Detection Tool") then + ImGui.TextWrapped("- First Input that contains the glyph is used.\n" .. + "- Use ImFontConfig::GlyphExcludeRanges[] to specify ranges to ignore glyph in given Input.\n- Prefer using a small number of ranges as the list is scanned every time a new glyph is loaded,\n - e.g. GlyphExcludeRanges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };\n- This tool doesn't cache results and is slow, don't keep it open!") + if ImGui.BeginTable("table", 2) then + local c = 0 + while c < 0x10000 do + local overlap_mask = CalcFontGlyphSrcOverlapMask(atlas, font, c) + if overlap_mask ~= 0 then + local c_end = c + 1 + while c_end < 0x10000 and CalcFontGlyphSrcOverlapMask(atlas, font, c_end) == overlap_mask do + c_end = c_end + 1 + end + if ImGui.TableNextColumn() and ImGui.TreeNode(c, "U+%04X-U+%04X: %d codepoints in %d inputs", c, c_end - 1, c_end - c, ImCountSetBits(overlap_mask)) then + for n = c, c_end - 1 do + ImGui.BulletText("Codepoint U+%04X (%s)", n, U8(n)) + end + ImGui.TreePop() + end + ImGui.TableNextColumn() + for src_n = 0, font.Sources.Size - 1 do + if bit32.band(overlap_mask, bit32.lshift(1, src_n)) ~= 0 then + ImGui.Text("%d ", src_n) + ImGui.SameLine() + end + end + c = c_end - 1 + end + c = c + 1 + end + ImGui.EndTable() + end + ImGui.TreePop() + end -- Display all glyphs of the fonts in separate pages of 256 characters local builder = atlas.Builder @@ -20282,7 +21031,7 @@ function ImGui.DebugNodeTexture(tex, int_id, highlight_rect) end ImGui.PopStyleVar() ImGui.Text("Status = %s (%d), Format = %s (%d), UseColors = %d", StatusNames[tex.Status] or "?", tex.Status, FormatNames[tex.Format] or "?", tex.Format, tex.UseColors and 1 or 0) - ImGui.Text("TexID = %s", tostring(tex.TexID)) + ImGui.Text("TexRef = %s, BackendUserData = %s", FormatTextureRefForDebugDisplay(tex:GetTexRef()), tostring(tex.BackendUserData)) ImGui.TreePop() end ImGui.PopID() @@ -20427,7 +21176,7 @@ function ImGui.ShowDebugLogWindow(p_open) local clipper = ImGuiListClipper() clipper:Begin(count) while clipper:Step() do - for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.TextUnformatted(lines[line_no + 1]) end + for line_no = clipper.DisplayStart, clipper.DisplayEnd - 1 do ImGui.DebugTextUnformattedWithLocateItem(lines[line_no + 1]) end end g.DebugLogFlags = backup_log_flags if ImGui.GetScrollY() >= ImGui.GetScrollMaxY() then ImGui.SetScrollHereY(1.0) end @@ -20436,10 +21185,165 @@ function ImGui.ShowDebugLogWindow(p_open) return p_open end +-- Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered. +-- [Luau] line_begin is the line string, line_end its optional exclusive end byte position (default: whole string). +function ImGui.DebugTextUnformattedWithLocateItem(line_begin, line_end) + if line_end == nil then line_end = #line_begin + 1 end + ImGui.TextUnformatted(line_begin, line_end) + if not ImGui.IsItemHovered(bit32.bor(ImGuiHoveredFlags.AllowWhenBlockedByPopup, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem)) then + return + end + local g = GImGui + local text_rect = ImRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max) -- [Luau] copy (LastItemData.Rect is overwritten below) + local p = 1 + while p <= line_end - 10 do repeat -- [Luau] 1-based (C: p <= line_end - 10 with 0-based offsets) + local b0, b1 = string.byte(line_begin, p, p + 1) + local hex = string.match(line_begin, "^%x+", p + 2) + if b0 ~= 48 or (b1 ~= 120 and b1 ~= 88) or hex == nil or string.find(string.sub(line_begin, p + 10, p + 10), "^%x") then -- '0', 'x', 'X' + p = p + 1 + break -- continue + end + local id = tonumber(hex, 16) -- [Luau] sscanf("%X") + local p0 = ImGui.CalcTextSizeEx(line_begin, 1, p) + local p1 = ImGui.CalcTextSizeEx(line_begin, p, p + 10) + g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)) + if ImGui.IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true) then + ImGui.DebugLocateItemOnHover(id) + end + p = p + 11 -- p += 10, then the loop's p++ + until true end +end + ------------------------------------------------------------------------------- -- [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) ------------------------------------------------------------------------------- +-- Draw a small cross at current CursorPos in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawCursorPos(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local pos = window.DC.CursorPos + window.DrawList:AddLineV(pos.x, pos.y - 3.0, pos.y + 4.0, col, 1.0) + window.DrawList:AddLineH(pos.x - 3.0, pos.x + 4.0, pos.y, col, 1.0) +end + +-- Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList +--- @param col? ImU32 +function ImGui.DebugDrawLineExtents(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + local curr_x = window.DC.CursorPos.x + local line_y1 = window.DC.IsSameLine and window.DC.CursorPosPrevLine.y or window.DC.CursorPos.y + local line_y2 = line_y1 + (window.DC.IsSameLine and window.DC.PrevLineSize.y or window.DC.CurrLineSize.y) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y1, col, 1.0) + window.DrawList:AddLineV(curr_x, line_y1, line_y2, col, 1.0) + window.DrawList:AddLineH(curr_x - 4.0, curr_x + 5.0, line_y2, col, 1.0) +end + +-- Draw last item rect in ForegroundDrawList (so it is always visible) +--- @param col? ImU32 +function ImGui.DebugDrawItemRect(col) + if col == nil then col = IM_COL32(255, 0, 0, 255) end + local g = GImGui + local window = g.CurrentWindow + ImGui.GetForegroundDrawList(window.Viewport):AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col) +end + +-- [DEBUG] Locate item position/rectangle given an ID. +local DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255) -- Green + +--- @param target_id ImGuiID +function ImGui.DebugLocateItem(target_id) + local g = GImGui + g.DebugLocateId = target_id + g.DebugLocateFrames = 2 + g.DebugBreakInLocateId = false +end + +-- FIXME: Doesn't work over through a modal window, because they clear HoveredWindow. +--- @param target_id ImGuiID +function ImGui.DebugLocateItemOnHover(target_id) + if target_id == 0 or not ImGui.IsItemHovered(bit32.bor(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.AllowWhenBlockedByPopup)) then + return + end + local g = GImGui + ImGui.DebugLocateItem(target_id) + ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport):AddRect(g.LastItemData.Rect.Min - ImVec2(3.0, 3.0), g.LastItemData.Rect.Max + ImVec2(3.0, 3.0), DEBUG_LOCATE_ITEM_COLOR) + + -- Can't easily use a context menu here because it will mess with focus, active id etc. + if g.IO.ConfigDebugIsDebuggerPresent and g.MouseStationaryTimer > 1.0 then + ImGui.DebugBreakButtonTooltip(false, "in ItemAdd()") + if ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) then + g.DebugBreakInLocateId = true + end + end +end + +function ImGui.DebugLocateItemResolveWithLastItem() + local g = GImGui + + -- [DEBUG] Debug break requested by user + if g.DebugBreakInLocateId then + IM_DEBUG_BREAK() + end + + local item_data = g.LastItemData + g.DebugLocateId = 0 + local draw_list = ImGui.GetForegroundDrawList(g.CurrentWindow.Viewport) + local r = ImRect(item_data.Rect.Min, item_data.Rect.Max) -- [Luau] copy + r:Expand(3.0) + local p1 = g.IO.MousePos + local p2 = ImVec2((p1.x < r.Min.x) and r.Min.x or ((p1.x > r.Max.x) and r.Max.x or p1.x), (p1.y < r.Min.y) and r.Min.y or ((p1.y > r.Max.y) and r.Max.y or p1.y)) + draw_list:AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR) + draw_list:AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR) +end + +function ImGui.DebugStartItemPicker() + local g = GImGui + g.DebugItemPickerActive = true +end + +-- [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. +function ImGui.UpdateDebugToolItemPicker() + local g = GImGui + g.DebugItemPickerBreakId = 0 + if not g.DebugItemPickerActive then + return + end + + local hovered_id = g.HoveredIdPreviousFrame + ImGui.SetMouseCursor(ImGuiMouseCursor.Hand) + if ImGui.IsKeyPressed(ImGuiKey.Escape) then + g.DebugItemPickerActive = false + end + local change_mapping = g.IO.KeyMods == bit32.bor(ImGuiMod_Ctrl, ImGuiMod_Shift) + if not change_mapping and ImGui.IsMouseClicked(g.DebugItemPickerMouseButton) and hovered_id ~= 0 then + g.DebugItemPickerBreakId = hovered_id + g.DebugItemPickerActive = false + end + for mouse_button = 0, 2 do + if change_mapping and ImGui.IsMouseClicked(mouse_button) then + g.DebugItemPickerMouseButton = mouse_button + end + end + ImGui.SetNextWindowBgAlpha(0.70) + if not ImGui.BeginTooltip() then + return + end + ImGui.Text("HoveredId: 0x%08X", hovered_id) + ImGui.Text("Press ESC to abort picking.") + local mouse_button_names = { "Left", "Right", "Middle" } + if change_mapping then + ImGui.Text("Remap w/ Ctrl+Shift: click anywhere to select new mouse button.") + else + ImGui.TextColored(ImGui.GetStyleColorVec4((hovered_id ~= 0) and ImGuiCol.Text or ImGuiCol.TextDisabled), "Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[g.DebugItemPickerMouseButton + 1]) + end + ImGui.EndTooltip() +end + local function PathQuery(g) local q = g.DebugItemPathQuery if q == nil then @@ -20528,7 +21432,7 @@ local function SkipUncontributingPrefix(label) return label end -local function FormatLevelInfo(g, query, n, format_for_ui) +local function DebugItemPathQuery_FormatLevelInfo(query, n, format_for_ui) local info = query.Results[n + 1] local window = (info.Desc == nil and n == 0) and ImGui.FindWindowByID(info.ID) or nil if window then return string.format(format_for_ui and "\"%s\" [window]" or "%s", SkipUncontributingPrefix(window.Name)) end -- Source: window name (because the root ID don't call GetID() and so doesn't get hooked) @@ -20537,10 +21441,10 @@ local function FormatLevelInfo(g, query, n, format_for_ui) return "???" end -local function GetResultAsPath(g, query, hex_encode_non_ascii_chars) +local function DebugItemPathQuery_GetResultAsPath(query, hex_encode_non_ascii_chars) local out = {} for n = 0, #query.Results - 1 do - local desc = FormatLevelInfo(g, query, n, false) + local desc = DebugItemPathQuery_FormatLevelInfo(query, n, false) out[#out + 1] = (n == 0) and "//" or "/" desc = string.gsub(desc, "/", "\\/") if hex_encode_non_ascii_chars then @@ -20566,7 +21470,7 @@ function ImGui.ShowIDStackToolWindow(p_open) local query = PathQuery(g) local tool = g.DebugIDStackTool tool.LastActiveFrame = g.FrameCount - local result_path = GetResultAsPath(g, query, tool.OptHexEncodeNonAsciiChars) + local result_path = DebugItemPathQuery_GetResultAsPath(query, tool.OptHexEncodeNonAsciiChars) ImGui.Text("0x%08X", query.MainID) ImGui.SameLine() MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.") @@ -20599,7 +21503,7 @@ function ImGui.ShowIDStackToolWindow(p_open) ImGui.TableNextColumn() ImGui.Text("0x%08X", (n > 0) and query.Results[n].ID or 0) ImGui.TableNextColumn() - ImGui.TextUnformatted(FormatLevelInfo(g, query, n, true)) + ImGui.TextUnformatted(DebugItemPathQuery_FormatLevelInfo(query, n, true)) ImGui.TableNextColumn() ImGui.Text("0x%08X", info.ID) if n == #query.Results - 1 then ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, ImGui.GetColorU32(ImGuiCol.Header)) end @@ -20650,6 +21554,7 @@ function ImGui.DebugNodeStorage(storage, label) if not ImGui.TreeNode(label, "%s: %d entries", label, n) then return end for k, v in pairs(storage) do ImGui.BulletText("Key 0x%08X Value { %s }", tonumber(k) or 0, tostring(v)) + ImGui.DebugLocateItemOnHover(tonumber(k) or 0) end ImGui.TreePop() end @@ -20677,50 +21582,116 @@ function ImGui.DebugNodeDrawList(window, viewport, draw_list, label) if not node_open then return end if window and not window.WasActive then ImGui.TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!") end - local vtx, idx = draw_list.VtxBuffer.Buf, draw_list.IdxBuffer.Data - for cmd_n = 1, cmd_count do + for cmd_n = 1, cmd_count do repeat local pcmd = draw_list.CmdBuffer.Data[cmd_n] if pcmd.UserCallback then - ImGui.BulletText("Callback %s", tostring(pcmd.UserCallback)) - else - local cr = pcmd.ClipRect - local open = ImGui.TreeNode(cmd_n, "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", math.floor(pcmd.ElemCount / 3), tostring(pcmd.TexRef and (pcmd.TexRef._TexID or pcmd.TexRef._TexData)), cr.x, cr.y, cr.z, cr.w) - local function ShowMeshImpl(show_mesh, show_aabb) - local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) - local vtxs_rect = ImRect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX) - local base = pcmd.IdxOffset - for i = base, base + pcmd.ElemCount - 1, 3 do - local tri = {} - for n = 0, 2 do - local vi = idx[i + n + 1] + pcmd.VtxOffset - if vi > draw_list.VtxBuffer.Size then return end - tri[n + 1] = ImVec2(ImDrawVtx_Pos(vtx, vi)) - vtxs_rect:Add(tri[n + 1]) - end - if show_mesh then fg_draw_list:AddPolyline(tri, 3, IM_COL32(255, 255, 0, 255), 1.0, ImDrawFlags.Closed) end -- In yellow: mesh triangles - end - if show_aabb then - fg_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU - fg_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles - end + ImGui.BulletText("Callback %s, user_data %s", tostring(pcmd.UserCallback), tostring(pcmd.UserCallbackData)) + break -- continue + end + + local texid_desc = FormatTextureRefForDebugDisplay(pcmd.TexRef) + local cr = pcmd.ClipRect + local buf = string.format("DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + math.floor(pcmd.ElemCount / 3), texid_desc, cr.x, cr.y, cr.z, cr.w) + local pcmd_node_open = ImGui.TreeNode(cmd_n - 1, "%s", buf) + if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) + end + if not pcmd_node_open then + break -- continue + end + + -- Calculate approximate coverage area (touched pixel count) + -- This will be in pixels squared as long there's no post-scaling happening to the renderer output. + -- [Luau] index values are 1-based vertex indices relative to VtxOffset (see ImDrawVtx_Pos()) + local idx_buffer = draw_list.IdxBuffer.Data + local vtx_buffer = draw_list.VtxBuffer.Buf + local total_area = 0.0 + local idx_n = pcmd.IdxOffset + while idx_n < pcmd.IdxOffset + pcmd.ElemCount do + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + pcmd.VtxOffset)) + idx_n = idx_n + 1 end - local function ShowMesh(show_mesh, show_aabb) -- DebugNodeDrawCmdShowMeshAndBoundingBox() - if not fg_draw_list then return end - fg_draw_list:PushDrawFlag(ImDrawFlags.AALines, false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. - ShowMeshImpl(show_mesh, show_aabb) - fg_draw_list:PopDrawFlag() - end - if ImGui.IsItemHovered() and (cfg.ShowDrawCmdMesh or cfg.ShowDrawCmdBoundingBoxes) then ShowMesh(cfg.ShowDrawCmdMesh, cfg.ShowDrawCmdBoundingBoxes) end - if open then - ImGui.Selectable(string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset)) - if ImGui.IsItemHovered() then ShowMesh(true, false) end - ImGui.TreePop() + total_area = total_area + ImTriangleArea(triangle[1], triangle[2], triangle[3]) + end + + -- Display vertex information summary. Hover to get all triangles drawn in wire-frame + buf = string.format("Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd.ElemCount, pcmd.VtxOffset, pcmd.IdxOffset, total_area) + ImGui.Selectable(buf) + if ImGui.IsItemHovered() and fg_draw_list then + ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false) + end + + -- Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. + local clipper = ImGuiListClipper() + clipper:Begin(math.floor(pcmd.ElemCount / 3)) -- Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while clipper:Step() do + local idx_i = pcmd.IdxOffset + clipper.DisplayStart * 3 + for prim = clipper.DisplayStart, clipper.DisplayEnd - 1 do + local lines = {} + local triangle = {} + for n = 1, 3 do + local vi = idx_buffer[idx_i + 1] + pcmd.VtxOffset + local o = (vi - 1) * VTX_STRIDE -- [Luau] packed vertex: f64 pos.x, pos.y, uv.x, uv.y, u32 col + local px, py = ImDrawVtx_Pos(vtx_buffer, vi) + triangle[n] = ImVec2(px, py) + lines[n] = string.format("%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", + (n == 1) and "Vert:" or " ", idx_i, px, py, buffer.readf64(vtx_buffer, o + 16), buffer.readf64(vtx_buffer, o + 24), ImDrawVtx_Col(vtx_buffer, vi)) + idx_i = idx_i + 1 + end + + ImGui.Selectable(table.concat(lines), false) + if fg_draw_list and ImGui.IsItemHovered() then + fg_draw_list:PushDrawFlag(ImDrawFlags.AALines, false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + fg_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, ImDrawFlags.Closed) + fg_draw_list:PopDrawFlag() + end end end - end + ImGui.TreePop() + until true end ImGui.TreePop() end +-- [DEBUG] Display mesh/aabb of a ImDrawCmd +--- @param out_draw_list ImDrawList +--- @param draw_list ImDrawList +--- @param draw_cmd ImDrawCmd +--- @param show_mesh bool +--- @param show_aabb bool +function ImGui.DebugNodeDrawCmdShowMeshAndBoundingBox(out_draw_list, draw_list, draw_cmd, show_mesh, show_aabb) + IM_ASSERT(show_mesh or show_aabb) + + -- Draw wire-frame version of all triangles + local cr = draw_cmd.ClipRect + local clip_rect = ImRect(cr.x, cr.y, cr.z, cr.w) + local vtxs_rect = ImRect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX) + out_draw_list:PushDrawFlag(ImDrawFlags.AALines, false) -- Disable AA on triangle outlines is more readable for very large and thin triangles. + local idx_n, idx_end = draw_cmd.IdxOffset, draw_cmd.IdxOffset + draw_cmd.ElemCount + while idx_n < idx_end do + local idx_buffer = draw_list.IdxBuffer.Data -- We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list + local vtx_buffer = draw_list.VtxBuffer.Buf + + local triangle = {} + for n = 1, 3 do + triangle[n] = ImVec2(ImDrawVtx_Pos(vtx_buffer, idx_buffer[idx_n + 1] + draw_cmd.VtxOffset)) + vtxs_rect:Add(triangle[n]) + idx_n = idx_n + 1 + end + if show_mesh then + out_draw_list:AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0, ImDrawFlags.Closed) -- In yellow: mesh triangles + end + end + -- Draw bounding boxes + if show_aabb then + out_draw_list:AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)) -- In pink: clipping rectangle submitted to GPU + out_draw_list:AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)) -- In cyan: bounding box of triangles + end + out_draw_list:PopDrawFlag() +end + -- [DEBUG] Display contents of ImGuiTabBar function ImGui.DebugNodeTabBar(tab_bar, label) -- Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. @@ -20902,6 +21873,11 @@ function ImGui.DebugNodeWindow(window, label) if ImGui.IsItemHovered() and is_active then YellowRect(window, window.Pos, window.Pos + window.Size) end if not open then return end if window.MemoryCompacted then ImGui.TextDisabled("Note: some memory buffers have been compacted/freed.") end + + if g.IO.ConfigDebugIsDebuggerPresent and ImGui.DebugBreakButton("**DebugBreak**", "in Begin()") then + g.DebugBreakInWindow = window.ID + end + local W = ImGuiWindowFlags local flags = window.Flags local function F(f, s) return (bit32.band(flags, f) ~= 0) and s or "" end @@ -20926,6 +21902,7 @@ function ImGui.DebugNodeWindow(window, label) else ImGui.BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window.NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y) end + ImGui.DebugLocateItemOnHover(window.NavLastIds[layer]) end ImGui.BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window.DC.NavLayersActiveMask, window.NavLastChildNavWindow and window.NavLastChildNavWindow.Name or "NULL") ImGui.BulletText("Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window.Viewport and (window.Viewport.Idx or 0) or -1, window.ViewportOwned and " (Owned)" or "", window.ViewportId or 0, window.ViewportPos.x, window.ViewportPos.y) @@ -20994,6 +21971,16 @@ function ImGui.DebugNodeViewport(viewport) end end +--- @param monitor ImGuiPlatformMonitor +--- @param label string +--- @param idx int +function ImGui.DebugNodePlatformMonitor(monitor, label, idx) + ImGui.BulletText("%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin (%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)", + label, idx, monitor.DpiScale * 100.0, + monitor.MainPos.x, monitor.MainPos.y, monitor.MainPos.x + monitor.MainSize.x, monitor.MainPos.y + monitor.MainSize.y, monitor.MainSize.x, monitor.MainSize.y, + monitor.WorkPos.x, monitor.WorkPos.y, monitor.WorkPos.x + monitor.WorkSize.x, monitor.WorkPos.y + monitor.WorkSize.y, monitor.WorkSize.x, monitor.WorkSize.y) +end + -- Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. function ImGui.DebugTextEncoding(str) ImGui.Text("Text: \"%s\"", str) @@ -21074,8 +22061,15 @@ function ImGui.ShowMetricsWindow(p_open) return p_open end + -- [DEBUG] Clear debug breaks hooks after exactly one cycle. + ImGui.DebugBreakClearData() + -- Basic info ImGui.Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM) + if g.ContextName ~= nil and g.ContextName ~= "" then + ImGui.SameLine() + ImGui.Text("(Context Name: \"%s\")", g.ContextName) + end ImGui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / math.max(io.Framerate, 0.0001), io.Framerate) ImGui.Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, math.floor(io.MetricsRenderIndices / 3)) ImGui.Text("%d visible windows, %d current allocations", io.MetricsRenderWindows, g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount) @@ -21086,6 +22080,18 @@ function ImGui.ShowMetricsWindow(p_open) -- Tools if ImGui.TreeNode("Tools") then + -- Debug Break features + -- The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. + ImGui.SeparatorTextEx(0, "Debug breaks", nil, ImGui.CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x) + ImGui.SameLine() + MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.") + local picker_toggled + picker_toggled, g.DebugItemPickerActive = ImGui.Checkbox("Show Item Picker", g.DebugItemPickerActive) + if picker_toggled and g.DebugItemPickerActive then + ImGui.DebugStartItemPicker() + end + _, io.ConfigDebugIsDebuggerPresent = ImGui.Checkbox("Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", io.ConfigDebugIsDebuggerPresent) + ImGui.SeparatorText("Visualize") _, cfg.ShowDebugLog = ImGui.Checkbox("Show Debug Log", cfg.ShowDebugLog == true) ImGui.SameLine(); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code.") @@ -21166,12 +22172,47 @@ function ImGui.ShowMetricsWindow(p_open) -- Viewports if ImGui.TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size) then + cfg.HighlightMonitorIdx = -1 + local open = ImGui.TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size) + ImGui.SameLine() + MetricsHelpMarker("Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors.") + if open then + for i = 1, g.PlatformIO.Monitors.Size do + ImGui.DebugNodePlatformMonitor(g.PlatformIO.Monitors.Data[i], "Monitor", i - 1) + if ImGui.IsItemHovered() then + cfg.HighlightMonitorIdx = i - 1 -- 0-based, like Monitors:index_from_ptr() + end + end + if g.FallbackMonitor then ImGui.DebugNodePlatformMonitor(g.FallbackMonitor, "Fallback", 0) end + ImGui.TreePop() + end + ImGui.SetNextItemOpen(true, ImGuiCond.Once) if ImGui.TreeNode("Windows Minimap") then ImGui.RenderViewportsThumbnails() ImGui.TreePop() end cfg.HighlightViewportID = 0 + + ImGui.BulletText("MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)", g.MouseViewport and g.MouseViewport.ID or 0, g.IO.MouseHoveredViewport or 0, g.MouseLastHoveredViewport and g.MouseLastHoveredViewport.ID or 0) + if ImGui.TreeNode("Inferred Z order (front-to-back)") then + local viewports = {} + for n = 1, g.Viewports.Size do viewports[n] = g.Viewports.Data[n] end + if #viewports > 1 then + table.sort(viewports, ViewportComparerByLastFocusedStampCount) + end + for _, viewport in ipairs(viewports) do + ImGui.BulletText("Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"", + viewport.Idx, viewport.ID, viewport.LastFocusedStampCount, + (g.PlatformIO.Platform_GetWindowFocus and viewport.PlatformWindowCreated) and (g.PlatformIO.Platform_GetWindowFocus(viewport) and "1" or "0") or "N/A", + viewport.Window and viewport.Window.Name or "N/A") + if ImGui.IsItemHovered() then + cfg.HighlightViewportID = viewport.ID + end + end + ImGui.TreePop() + end + for _, viewport in g.Viewports:iter() do ImGui.DebugNodeViewport(viewport) end ImGui.TreePop() end @@ -21316,6 +22357,12 @@ function ImGui.ShowMetricsWindow(p_open) if ImGui.IsKeyReleased(key) then ImGui.SameLine(); ImGui.Text("\"%s\"", ImGui.GetKeyName(key)) end end ImGui.Text("Keys mods: %s%s%s%s", io.KeyCtrl and "Ctrl " or "", io.KeyShift and "Shift " or "", io.KeyAlt and "Alt " or "", io.KeySuper and "Super " or "") + ImGui.Text("Chars queue:") + for i = 1, io.InputQueueCharacters.Size do + local c = io.InputQueueCharacters.Data[i] + ImGui.SameLine(); ImGui.Text("'%s' (0x%04X)", (c > 32 and c <= 255) and string.char(c) or "?", c) -- FIXME: We should convert 'c' to UTF-8 here but the functions are not public. + end + ImGui.DebugRenderKeyboardPreview(ImGui.GetWindowDrawList()) ImGui.Unindent() ImGui.Text("MOUSE STATE") ImGui.Indent() @@ -21329,6 +22376,7 @@ function ImGui.ShowMetricsWindow(p_open) for i = 0, 2 do if ImGui.IsMouseReleased(i) then ImGui.SameLine(); ImGui.Text("b%d", i) end end ImGui.Text("Mouse wheel: %.1f", io.MouseWheel) ImGui.Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer) + ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource or ImGuiMouseSource.Mouse)) -- [Luau] field may be unset (C++: zero-initialized) ImGui.Unindent() ImGui.Text("MOUSE WHEELING") ImGui.Indent() @@ -21352,16 +22400,20 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.Unindent() ImGui.Text("ITEMS") ImGui.Indent() - ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap)) + ImGui.Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, B(g.ActiveIdAllowOverlap), GetInputSourceName(g.ActiveIdSource or ImGuiInputSource.None)) -- [Luau] field may be unset (C++: zero-initialized) + ImGui.DebugLocateItemOnHover(g.ActiveId) ImGui.Text("ActiveIdWindow: '%s'", N(g.ActiveIdWindow)) ImGui.Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, B(g.HoveredIdAllowOverlap)) -- Not displaying g.HoveredId as it is update mid-frame ImGui.Text("HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId or 0, g.HoverItemDelayTimer or 0, g.HoverItemDelayClearTimer or 0) ImGui.Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\"", B(g.DragDropActive), g.DragDropPayload.SourceId or 0, tostring(g.DragDropPayload.DataType or "")) + ImGui.DebugLocateItemOnHover(g.DragDropPayload.SourceId or 0) ImGui.Unindent() ImGui.Text("NAV,FOCUS") ImGui.Indent() ImGui.Text("NavWindow: '%s'", N(g.NavWindow)) ImGui.Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer) + ImGui.DebugLocateItemOnHover(g.NavId) + ImGui.Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource or ImGuiInputSource.None)) ImGui.Text("NavLastValidSelectionUserData = %s", tostring(g.NavLastValidSelectionUserData)) -- [Port] any Lua value: tostring() instead of %lld (0x%llX) ImGui.Text("NavActive: %d, NavVisible: %d", B(io.NavActive), B(io.NavVisible)) ImGui.Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId or 0, g.NavActivatePressedId or 0) @@ -21412,6 +22464,68 @@ function ImGui.ShowMetricsWindow(p_open) ImGui.End() return p_open end + +function ImGui.DebugBreakClearData() + -- Those fields are scattered in their respective subsystem to stay in hot-data locations + local g = GImGui + g.DebugBreakInWindow = 0 + g.DebugBreakInTable = 0 + g.DebugBreakInShortcutRouting = ImGuiKey.None +end + +--- @param keyboard_only bool +--- @param description_of_location string +function ImGui.DebugBreakButtonTooltip(keyboard_only, description_of_location) + if not ImGui.BeginItemTooltip() then + return + end + ImGui.Text("To call IM_DEBUG_BREAK() %s:", description_of_location) + ImGui.Separator() + ImGui.TextUnformatted(keyboard_only and "- Press 'Pause/Break' on keyboard." or "- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space.") + ImGui.Separator() + ImGui.TextUnformatted("Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!") -- [Luau] IM_DEBUG_BREAK() calls g.DebugBreakCallback (if set) instead + ImGui.EndTooltip() +end + +-- Special button that doesn't take focus, doesn't take input owner, and can be activated without a click etc. +-- In order to reduce interferences with the contents we are trying to debug into. +--- @param label string +--- @param description_of_location string +--- @return bool +function ImGui.DebugBreakButton(label, description_of_location) + local window = ImGui.GetCurrentWindow() + if window.SkipItems then + return false + end + + local g = GImGui + local id = window:GetID(label) + local label_size = ImGui.CalcTextSize(label, nil, true) + local pos = window.DC.CursorPos + ImVec2(0.0, window.DC.CurrLineTextBaseOffset) + local size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0, label_size.y) + + local bb = ImRect(pos, pos + size) + ImGui.ItemSize(size, 0.0) + if not ImGui.ItemAdd(bb, id) then + return false + end + + -- WE DO NOT USE ButtonEx() or ButtonBehavior() in order to reduce our side-effects. + local hovered = ImGui.ItemHoverable(bb, id, g.CurrentItemFlags) + local pressed = hovered and (ImGui.IsKeyChordPressed(g.DebugBreakKeyChord) or ImGui.IsMouseClicked(0) or g.NavActivateId == id) + ImGui.DebugBreakButtonTooltip(false, description_of_location) + + local src = ImGui.GetStyleColorVec4(hovered and ImGuiCol.ButtonHovered or ImGuiCol.Button) + local col4f = ImVec4(src.x, src.y, src.z, src.w) -- [Luau] copy + local h, s, v = ImGui.ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z) + col4f.x, col4f.y, col4f.z = ImGui.ColorConvertHSVtoRGB(h + 0.20, s, v) + + ImGui.RenderNavCursor(bb, id) + ImGui.RenderFrame(bb.Min, bb.Max, ImGui.GetColorU32(col4f), true, g.Style.FrameRounding) + ImGui.RenderTextClipped(bb.Min, bb.Max, label, nil, label_size, g.Style.ButtonTextAlign, bb) + + return pressed +end end --[[ [SECTION] METRICS/DEBUGGER WINDOW, DEBUG LOG, ID STACK TOOL, FONT DEBUG ]] return true -- [Roblox] ModuleScripts must return exactly one value diff --git a/imgui_demo.lua b/imgui_demo.lua index af216b6..0b399b4 100644 --- a/imgui_demo.lua +++ b/imgui_demo.lua @@ -214,7 +214,7 @@ function ShowDockingDisabledMessage() end -- Helper to wire demo markers located in code to an interactive browser (e.g. https://pthom.github.io/imgui_explorer) -function IMGUI_DEMO_MARKER(section) end -- [Port] no ImGui.DemoMarker() hook in this port: no-op +function IMGUI_DEMO_MARKER(section) ImGui.DemoMarker("imgui_demo.lua", 0, section) end -- [Port] no __LINE__ in Lua: line is 0 -- Sneakily forward declare functions which aren't worth putting in public API yet -- [Port] ImGui.ShowFontAtlas(atlas) and ImGui.TreeNodeSetOpen(storage_id, is_open) are already public here. @@ -698,8 +698,7 @@ function DemoWindowMenuBar(demo_data) _, demo_data.ShowDebugLog = ImGui.MenuItem("Debug Log", nil, demo_data.ShowDebugLog, has_debug_tools) _, demo_data.ShowIDStackTool = ImGui.MenuItem("ID Stack Tool", nil, demo_data.ShowIDStackTool, has_debug_tools) local is_debugger_present = io.ConfigDebugIsDebuggerPresent - local has_item_picker = ImGui.DebugStartItemPicker ~= nil -- [Port] ImGui.DebugStartItemPicker() is not ported yet: menu item disabled until it is - if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools and has_item_picker) then -- and is_debugger_present + if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools) then -- and is_debugger_present ImGui.DebugStartItemPicker() end if not is_debugger_present then @@ -8904,7 +8903,7 @@ function ImGui.ShowStyleEditor(ref) end ImGui.PushID(i) if ImGui.Button("?") then - if ImGui.DebugFlashStyleColor then ImGui.DebugFlashStyleColor(i) end -- [Port] DebugFlashStyleColor() is not in the library yet + ImGui.DebugFlashStyleColor(i) end ImGui.SetItemTooltip("Flash given color to identify places where it is used.") ImGui.SameLine() diff --git a/imgui_draw.lua b/imgui_draw.lua index fa43184..3a1e1f7 100644 --- a/imgui_draw.lua +++ b/imgui_draw.lua @@ -4155,6 +4155,42 @@ function MT.ImDrawData:AddDrawList(draw_list) ImGui.AddDrawListToDrawDataEx(self, self.CmdLists, draw_list) end +-- For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! +-- [Luau] IdxBuffer values are 1-based vertex indices +function MT.ImDrawData:DeIndexAllBuffers() + local new_vtx_buffer = ImDrawVtxBuffer() + self.TotalVtxCount = 0; self.TotalIdxCount = 0 + for i = 1, self.CmdLists.Size do + repeat + local draw_list = self.CmdLists.Data[i] + if draw_list.IdxBuffer.Size == 0 then + break -- continue + end + new_vtx_buffer:resize(draw_list.IdxBuffer.Size) + local src, dst, idx = draw_list.VtxBuffer.Buf, new_vtx_buffer.Buf, draw_list.IdxBuffer.Data + for j = 1, draw_list.IdxBuffer.Size do + buffer.copy(dst, (j - 1) * VTX_STRIDE, src, (idx[j] - 1) * VTX_STRIDE, VTX_STRIDE) + end + draw_list.VtxBuffer, new_vtx_buffer = new_vtx_buffer, draw_list.VtxBuffer -- swap() + draw_list.IdxBuffer:resize(0) + self.TotalVtxCount = self.TotalVtxCount + draw_list.VtxBuffer.Size + until true + end +end + +-- Helper to scale the ClipRect field of each ImDrawCmd. +-- Use if your final output buffer is at a different scale than draw_data->DisplaySize, +-- or if there is a difference between your window resolution and framebuffer resolution. +function MT.ImDrawData:ScaleClipRects(fb_scale) + for i = 1, self.CmdLists.Size do + local draw_list = self.CmdLists.Data[i] + for j = 1, draw_list.CmdBuffer.Size do + local cmd = draw_list.CmdBuffer.Data[j] + cmd.ClipRect = ImVec4(cmd.ClipRect.x * fb_scale.x, cmd.ClipRect.y * fb_scale.y, cmd.ClipRect.z * fb_scale.x, cmd.ClipRect.w * fb_scale.y) + end + end +end + local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN = 4 local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX = 512 @@ -4262,6 +4298,29 @@ function MT.ImDrawList:_ClearFreeMemory() self._Splitter:ClearFreeMemory() end +-- Note: For multi-threaded rendering, consider using `imgui_threaded_rendering` from https://github.com/ocornut/imgui_club +-- [Luau] C++ copies the vectors by value: copy the ImDrawCmd structs and the vertex buffer bytes +--- @return ImDrawList +function MT.ImDrawList:CloneOutput() + local dst = ImDrawList(nil) + for i = 1, self.CmdBuffer.Size do + local src_cmd = self.CmdBuffer.Data[i] + local cmd = ImDrawCmd() + for k, v in pairs(src_cmd) do cmd[k] = v end + cmd.ClipRect = ImVec4(src_cmd.ClipRect.x, src_cmd.ClipRect.y, src_cmd.ClipRect.z, src_cmd.ClipRect.w) + if src_cmd.TexRef then cmd.TexRef = ImTextureRef(src_cmd.TexRef._TexID); cmd.TexRef._TexData = src_cmd.TexRef._TexData end + dst.CmdBuffer:push_back(cmd) + end + if self.IdxBuffer.Size > 0 then + dst.IdxBuffer:resize(self.IdxBuffer.Size) + table.move(self.IdxBuffer.Data, 1, self.IdxBuffer.Size, 1, dst.IdxBuffer.Data) + end + dst.VtxBuffer:resize(self.VtxBuffer.Size) + buffer.copy(dst.VtxBuffer.Buf, 0, self.VtxBuffer.Buf, 0, self.VtxBuffer.Size * VTX_STRIDE) + dst.Flags = self.Flags + return dst +end + function MT.ImDrawList:AddDrawCmd() local draw_cmd = ImDrawCmd() @@ -4819,6 +4878,22 @@ function MT.ImDrawList:PrimRectUV(a, c, uv_a, uv_c, col) self._IdxWritePtr = idx_write_ptr + 6 end +function MT.ImDrawList:PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col) + local idx = self._VtxCurrentIdx + local idx_data = self.IdxBuffer.Data; local vtx_data = self.VtxBuffer.Buf + local idx_write_ptr = self._IdxWritePtr + idx_data[idx_write_ptr + 0] = idx; idx_data[idx_write_ptr + 1] = idx + 1; idx_data[idx_write_ptr + 2] = idx + 2 + idx_data[idx_write_ptr + 3] = idx; idx_data[idx_write_ptr + 4] = idx + 2; idx_data[idx_write_ptr + 5] = idx + 3 + local vtx_write_ptr = self._VtxWritePtr + WV(vtx_data, vtx_write_ptr + 0, a.x, a.y, uv_a.x, uv_a.y, col) + WV(vtx_data, vtx_write_ptr + 1, b.x, b.y, uv_b.x, uv_b.y, col) + WV(vtx_data, vtx_write_ptr + 2, c.x, c.y, uv_c.x, uv_c.y, col) + WV(vtx_data, vtx_write_ptr + 3, d.x, d.y, uv_d.x, uv_d.y, col) + self._VtxWritePtr = vtx_write_ptr + 4 + self._VtxCurrentIdx = idx + 4 + self._IdxWritePtr = idx_write_ptr + 6 +end + --- @param thickness float --- @return float -- [Luau] local function (also MT.ImDrawList._CalculateCenterBiasedOffset) @@ -6808,6 +6883,30 @@ function MT.ImDrawList:AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col) end end +function MT.ImDrawList:AddImageQuad(tex_ref, p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + if uv1 == nil then uv1 = ImVec2(0, 0) end + if uv2 == nil then uv2 = ImVec2(1, 0) end + if uv3 == nil then uv3 = ImVec2(1, 1) end + if uv4 == nil then uv4 = ImVec2(0, 1) end + if col == nil then col = IM_COL32_WHITE end + + if bit32.band(col, IM_COL32_A_MASK) == 0 then + return + end + + local push_texture_id = tex_ref ~= self._CmdHeader.TexRef + if push_texture_id then + self:PushTexture(tex_ref) + end + + self:PrimReserve(6, 4) + self:PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) + + if push_texture_id then + self:PopTexture() + end +end + --- @param tex_ref ImTextureRef --- @param p_min ImVec2 --- @param p_max ImVec2 @@ -6901,6 +7000,9 @@ function MT.ImDrawList:PopClipRect() self:_OnChangedClipRect() end +function MT.ImDrawList:GetClipRectMin() local cr = self._ClipRectStack:back(); return ImVec2(cr.x, cr.y) end +function MT.ImDrawList:GetClipRectMax() local cr = self._ClipRectStack:back(); return ImVec2(cr.z, cr.w) end + --- @param center ImVec2 --- @param radius float --- @param a_min_sample int diff --git a/imgui_h.lua b/imgui_h.lua index 3de8e67..983c120 100644 --- a/imgui_h.lua +++ b/imgui_h.lua @@ -499,8 +499,8 @@ end --- @field UserCallbackData any --- @field UserCallbackDataSize int --- @field UserCallbackDataOffset int -local IM_DRAWCMD = {} -IM_DRAWCMD.__index = IM_DRAWCMD +MT.ImDrawCmd = {} +MT.ImDrawCmd.__index = MT.ImDrawCmd --- @return ImDrawCmd --- @nodiscard @@ -515,11 +515,11 @@ function ImDrawCmd() UserCallbackData = nil, -- 4-8 -- Callback user data (when UserCallback != nil). If called AddCallback() with size == 0, this is a copy of the AddCallback() argument. If called AddCallback() with size > 0, this is pointing to a buffer where data is stored. UserCallbackDataSize = 0, -- 4 -- Size of callback user data when using storage, otherwise 0. UserCallbackDataOffset = 0 -- 4 -- [Internal] Offset of callback user data when using storage, otherwise -1. - }, IM_DRAWCMD) + }, MT.ImDrawCmd) end --- @return ImTextureID -function IM_DRAWCMD:GetTexID() +function MT.ImDrawCmd:GetTexID() local tex_id = (self.TexRef._TexData) and self.TexRef._TexData.TexID or self.TexRef._TexID if self.TexRef._TexData ~= nil then IM_ASSERT(tex_id ~= ImTextureID_Invalid, "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!") @@ -775,11 +775,14 @@ end --- @param x int --- @param y int +function MT.ImTextureData:GetPixels() IM_ASSERT(self.Pixels ~= nil); return self.Pixels end function MT.ImTextureData:GetPixelsAt(x, y) return self.Pixels, (x + y * self.Width) * self.BytesPerPixel + 1 end +function MT.ImTextureData:GetSizeInBytes() return self.Width * self.Height * self.BytesPerPixel end function MT.ImTextureData:GetPitch() return self.Width * self.BytesPerPixel end +function MT.ImTextureData:GetTexRef() local tex_ref = ImTextureRef(); tex_ref._TexData = self; tex_ref._TexID = ImTextureID_Invalid; return tex_ref end function MT.ImTextureData:GetTexID() return self.TexID end --- @param tex_id ImTextureID @@ -799,8 +802,8 @@ function MT.ImTextureData:SetStatus(status) self.Status = status if (status == I --- @class ImTextureRef --- @field _TexData? ImTextureData --- @field _TexID ImTextureID -local IM_TEXTURE_REF = {} -IM_TEXTURE_REF.__index = IM_TEXTURE_REF +MT.ImTextureRef = {} +MT.ImTextureRef.__index = MT.ImTextureRef --- @return ImTextureRef --- @nodiscard @@ -809,7 +812,14 @@ function ImTextureRef(tex_id) -- Members (either are set, never both!) _TexData = nil, -- A texture, generally owned by a ImFontAtlas. Will convert to ImTextureID during render loop, after texture has been uploaded. _TexID = tex_id or ImTextureID_Invalid -- _OR_ Low-level backend texture identifier, if already uploaded or created by user/app. Generally provided to e.g. ImGui.Image() calls. - }, IM_TEXTURE_REF) + }, MT.ImTextureRef) +end + +-- This is provided for consistency (but we don't actually use this) +--- @return ImTextureID +function MT.ImTextureRef:GetTexID() + IM_ASSERT(not (self._TexData ~= nil and self._TexID ~= ImTextureID_Invalid)) + if self._TexData then return self._TexData.TexID else return self._TexID end end ------------------------------------------------------------------------------- @@ -2543,7 +2553,8 @@ function MT.ImGuiInputTextCallbackData:InsertChars(pos, new_text) self.SelectionStart = self.CursorPos; self.SelectionEnd = self.CursorPos end -function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.CursorPos = self.BufTextLen; self.SelectionEnd = self.BufTextLen end +function MT.ImGuiInputTextCallbackData:SetSelection(s, e) IM_ASSERT(s >= 0 and s <= self.BufTextLen); IM_ASSERT(e >= 0 and e <= self.BufTextLen); self.SelectionStart = s; self.CursorPos = e; self.SelectionEnd = e end function MT.ImGuiInputTextCallbackData:ClearSelection() self.SelectionStart = self.BufTextLen; self.SelectionEnd = self.BufTextLen end function MT.ImGuiInputTextCallbackData:HasSelection() return self.SelectionStart ~= self.SelectionEnd end diff --git a/imgui_internal.lua b/imgui_internal.lua index 4d7781a..72d1565 100644 --- a/imgui_internal.lua +++ b/imgui_internal.lua @@ -706,6 +706,27 @@ function ImCharIsBlankA(c) return c == 32 or c == 9 end --- @param c char function ImCharIsBlankW(c) return c == 32 or c == 9 or c == 0x3000 end +--- @param c char +function ImCharIsXdigitA(c) return (c >= 48 and c <= 57) or (c >= 65 and c <= 70) or (c >= 97 and c <= 102) end + +--- @param lhs ImVec2 +--- @param fail_value float +function ImInvLength(lhs, fail_value) local d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if d > 0.0 then return ImRsqrt(d) end; return fail_value end +function ImRoundPositive64(f) return _Trunc(f + 0.5) end -- Positive values only. +function ImRoundSigned64(f) if f >= 0.0 then return _Trunc(f + 0.5) else return _Trunc(f - 0.5) end end +-- [Luau] C '%' truncates toward zero; math.fmod matches it +function ImModPositive(a, b) return math.fmod(a + b, b) end +function ImIsFloatAboveGuaranteedIntegerPrecision(f) return f <= -16777216 or f >= 16777216 end + +-- Helper: ImVec2i (2D vector, integer) / ImVec2ih (2D vector, half-size integer, for long-term packed storage) +-- [Luau] both are plain ImVec2 holding whole numbers +function ImVec2i(x, y) return ImVec2(x or 0, y or 0) end +--- @overload fun(rhs: ImVec2): ImVec2 +function ImVec2ih(x, y) + if type(x) == "table" then return ImVec2(_Trunc(x.x), _Trunc(x.y)) end + return ImVec2(x or 0, y or 0) +end + --- @enum ImGuiNavMoveFlags ImGuiNavMoveFlags = { @@ -1004,6 +1025,28 @@ function ImBitArraySetBit(arr, n) arr[idx] = bitOr(arr[idx], mask) end +-- [Luau] bit arrays are ImU32[] tables with 1-based word indices; bit indices 'n' are 1-based like the functions above +--- @param bitcount int +function ImBitArrayGetStorageSizeInBytes(bitcount) return bitLShift(bitRShift(bitcount + 31, 5), 2) end +--- @param arr ImU32[] +--- @param bitcount int +function ImBitArrayClearAllBits(arr, bitcount) for i = 1, bitRShift(bitcount + 31, 5) do arr[i] = 0 end end +function ImBitArrayTestBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); return bitAnd(arr[bitRShift(n - 1, 5) + 1], mask) ~= 0 end +function ImBitArrayClearBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)); local idx = bitRShift(n - 1, 5) + 1; arr[idx] = bitAnd(arr[idx], bitNot(mask)) end +-- Works on range [n..n2) +function ImBitArraySetBitRange(arr, n, n2) + n = n - 1; n2 = n2 - 1 -- [Luau] to 0-based + n2 = n2 - 1 + while n <= n2 do + local a_mod = bitAnd(n, 31) + local b_mod = ((n2 > bitOr(n, 31)) and 31 or bitAnd(n2, 31)) + 1 + local mask = bitAnd(2 ^ b_mod - 1, bitNot(2 ^ a_mod - 1)) + local idx = bitRShift(n, 5) + 1 + arr[idx] = bitOr(arr[idx], mask) + n = bitAnd(n + 32, bitNot(31)) + end +end + -- Bit array for named keys --- @alias ImBitArrayForNamedKeys ImBitArray @@ -1030,11 +1073,30 @@ function ImBitArray(BITCOUNT, OFFSET) --- @param n int # 1-based this.SetBit = function(self, n) n = n + OFFSET; IM_ASSERT(n >= 1 and n <= BITCOUNT); ImBitArraySetBit(self.Data, n); end + --- @param n int # 1-based + this.ClearBit = function(self, n) n = n + OFFSET; IM_ASSERT(n >= 1 and n <= BITCOUNT); ImBitArrayClearBit(self.Data, n); end + --- @param n int # 1-based, range [n..n2) + this.SetBitRange = function(self, n, n2) n = n + OFFSET; n2 = n2 + OFFSET; IM_ASSERT(n >= 1 and n <= BITCOUNT and n2 > n and n2 <= BITCOUNT + 1); ImBitArraySetBitRange(self.Data, n, n2); end + this:ClearAllBits() return this end +-- Helper: ImBitVector +-- Store 1-bit per value. +--- @class ImBitVector +--- @field Storage ImVector +MT.ImBitVector = {} +MT.ImBitVector.__index = MT.ImBitVector +function ImBitVector() return setmetatable({ Storage = ImVector() }, MT.ImBitVector) end +function MT.ImBitVector:Create(sz) self.Storage:resize(bitRShift(sz + 31, 5)); for i = 1, self.Storage.Size do self.Storage.Data[i] = 0 end end +function MT.ImBitVector:Clear() self.Storage:clear() end +--- @param n int # 1-based +function MT.ImBitVector:TestBit(n) IM_ASSERT(n <= bitLShift(self.Storage.Size, 5)); return IM_BITARRAY_TESTBIT(self.Storage.Data, n) end +function MT.ImBitVector:SetBit(n) IM_ASSERT(n <= bitLShift(self.Storage.Size, 5)); ImBitArraySetBit(self.Storage.Data, n) end +function MT.ImBitVector:ClearBit(n) IM_ASSERT(n <= bitLShift(self.Storage.Size, 5)); ImBitArrayClearBit(self.Storage.Data, n) end + -- Stateful path API, add points then finish with PathFillConvex() or PathStroke() -- - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. -- so e.g. 'PathArcTo(center, radius, PI * -0.5, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5)' won't have correct anti-aliasing when followed by PathFillConvex(). @@ -1266,9 +1328,13 @@ end --- @param key string --- @return ImGuiStyleVarInfo --- @nodiscard +MT.ImGuiStyleVarInfo = {} +MT.ImGuiStyleVarInfo.__index = MT.ImGuiStyleVarInfo function ImGuiStyleVarInfo(count, data_type, key) - return { Count = count, DataType = data_type, Key = key } + return setmetatable({ Count = count, DataType = data_type, Key = key }, MT.ImGuiStyleVarInfo) end +-- [Luau] no pointers: returns the field value (number, or the live ImVec2 table) of 'parent' (e.g. ImGuiStyle) +function MT.ImGuiStyleVarInfo:GetVarPtr(parent) return parent[self.Key] end -- Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. --- @class ImGuiStyleMod @@ -1383,11 +1449,11 @@ end --- @field RefVal any --- @field StorageId ImGuiID --- @field ColorMarker ImU32 -local IMGUI_NEXT_ITEM_DATA = {} -IMGUI_NEXT_ITEM_DATA.__index = IMGUI_NEXT_ITEM_DATA +MT.ImGuiNextItemData = {} +MT.ImGuiNextItemData.__index = MT.ImGuiNextItemData -- Also cleared manually by ItemAdd()! -function IMGUI_NEXT_ITEM_DATA:ClearFlags() +function MT.ImGuiNextItemData:ClearFlags() self.HasFlags = ImGuiNextItemDataFlags.None self.ItemFlagsSet = ImGuiItemFlags.None end @@ -1410,7 +1476,7 @@ function ImGuiNextItemData() RefVal = 0, -- Not exposed yet, for ImGuiInputTextFlags.ParseEmptyAsRefVal StorageId = 0, -- Set by SetNextItemStorageID() ColorMarker = 0 -- Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags.ColorMarkers. - }, IMGUI_NEXT_ITEM_DATA) + }, MT.ImGuiNextItemData) end -- Storage for SetNexWindow** functions @@ -1433,10 +1499,10 @@ end --- @field BgAlphaVal number? --- @field MenuBarOffsetMinVal ImVec2? --- @field RefreshFlagsVal int? -local IMGUI_NEXT_WINDOW_DATA = {} -IMGUI_NEXT_WINDOW_DATA.__index = IMGUI_NEXT_WINDOW_DATA +MT.ImGuiNextWindowData = {} +MT.ImGuiNextWindowData.__index = MT.ImGuiNextWindowData -function IMGUI_NEXT_WINDOW_DATA:ClearFlags() +function MT.ImGuiNextWindowData:ClearFlags() self.HasFlags = ImGuiNextWindowDataFlags.None end @@ -1475,7 +1541,7 @@ function ImGuiNextWindowData() RefreshFlagsVal = nil, CacheKeySet = false, -- [Port] SetNextWindowCached() CacheKeyVal = nil - }, IMGUI_NEXT_WINDOW_DATA) + }, MT.ImGuiNextWindowData) end --- @enum ImGuiWindowBgClickFlags @@ -1738,21 +1804,29 @@ local function ImGuiInputTextState() SelectedAllMouseLock = false, -- after a double-click to select all, we ignore further mouse drags to update selection EditedBefore = false, -- edited since activated EditedThisFrame = false, -- edited this frame + WantReloadUserBuf = false, -- force a reload of user buf so it may be modified externally. may be automatic in future version. + LastMoveDirectionLR = ImGuiDir.Left, -- ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s + ReloadSelectionStart = 0, + ReloadSelectionEnd = 0, } return setmetatable(this, MT.ImGuiInputTextState) end +function MT.ImGuiInputTextState:ClearText() self.TextLen = 0; self.TextA.Data[1] = 0; self:CursorClamp() end +function MT.ImGuiInputTextState:ClearFreeMemory() self.TextA:clear(); self.TextToRevertTo:clear() end +function MT.ImGuiInputTextState:GetText() if self.TextA.Data then return self.TextA.Data else return { 0 } end end -- [Luau] byte table (char[]) + -- Internal temporary state for deactivating InputText() instances. -- Store as part of ImGuiDeactivatedItemData? --- @class ImGuiInputTextDeactivatedState --- @field ID ImGuiID # widget id owning the text state (which just got deactivated) --- @field ElapseFrame int --- @field TextA ImVector # text buffer -local IMGUI_INPUT_TEXT_DEACTIVATED_STATE = {} -IMGUI_INPUT_TEXT_DEACTIVATED_STATE.__index = IMGUI_INPUT_TEXT_DEACTIVATED_STATE +MT.ImGuiInputTextDeactivatedState = {} +MT.ImGuiInputTextDeactivatedState.__index = MT.ImGuiInputTextDeactivatedState -function IMGUI_INPUT_TEXT_DEACTIVATED_STATE:ClearFreeMemory() +function MT.ImGuiInputTextDeactivatedState:ClearFreeMemory() self.ID = 0 self.ElapseFrame = 0 self.TextA:clear() @@ -1765,7 +1839,7 @@ local function ImGuiInputTextDeactivatedState() ID = 0, -- widget id owning the text state (which just got deactivated) ElapseFrame = 0, TextA = ImVector() -- text buffer - }, IMGUI_INPUT_TEXT_DEACTIVATED_STATE) + }, MT.ImGuiInputTextDeactivatedState) end --- @alias ImGuiKeyRoutingIndex ImS16 @@ -1798,10 +1872,10 @@ end --- @field Index ImGuiKeyRoutingIndex[] # Index of first entry in Entries[] --- @field Entries ImVector --- @field EntriesNext ImVector # Double-buffer to avoid reallocation (could use a shared buffer) -local _ImGuiKeyRoutingTable = {} -_ImGuiKeyRoutingTable.__index = _ImGuiKeyRoutingTable +MT.ImGuiKeyRoutingTable = {} +MT.ImGuiKeyRoutingTable.__index = MT.ImGuiKeyRoutingTable -function _ImGuiKeyRoutingTable:Clear() +function MT.ImGuiKeyRoutingTable:Clear() for n = 1, ImGuiKey.NamedKey_COUNT do self.Index[n] = -1 end self.Entries:clear() self.EntriesNext:clear() @@ -1813,7 +1887,7 @@ local function ImGuiKeyRoutingTable() Index = {}, -- Index of first entry in Entries[] Entries = ImVector(), EntriesNext = ImVector() -- Double-buffer to avoid reallocation (could use a shared buffer) - }, _ImGuiKeyRoutingTable) + }, MT.ImGuiKeyRoutingTable) this:Clear() @@ -1899,10 +1973,10 @@ end --- @field DistBox float # Move -- Best candidate box distance to current NavId --- @field DistCenter float # Move -- Best candidate center distance to current NavId --- @field DistAxial float # Move -- Best candidate axial distance to current NavId -local IMGUI_NAV_ITEM_DATA = {} -IMGUI_NAV_ITEM_DATA.__index = IMGUI_NAV_ITEM_DATA +MT.ImGuiNavItemData = {} +MT.ImGuiNavItemData.__index = MT.ImGuiNavItemData -function IMGUI_NAV_ITEM_DATA:Clear() +function MT.ImGuiNavItemData:Clear() self.Window = nil self.ID = 0 self.FocusScopeId = 0 @@ -1915,7 +1989,7 @@ end --- @return ImGuiNavItemData local function ImGuiNavItemData() - local this = setmetatable({ }, IMGUI_NAV_ITEM_DATA) + local this = setmetatable({ }, MT.ImGuiNavItemData) this.RectRel = ImRect() this:Clear() return this @@ -2488,7 +2562,7 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct DockContext = ImGuiDockContext(), DockNodeWindowMenuHandler = nil, DebugHoveredDockNode = nil, -- Hovered dock node. - CurrentTabBarStack = ImVector(), -- holds ImGuiTabBar references directly (no ImGuiPtrOrIndex needed in Lua) + CurrentTabBarStack = ImVector(), -- ImVector ShrinkWidthBuffer = ImVector(), -- ImGuiShrinkWidthItem -- Multi-Select state @@ -2652,10 +2726,10 @@ end --- @field WantApply bool # Set when loaded from .ini data --- @field WantDelete bool # Set to invalidate/delete the settings entry --- @field Name string # Window name -local IMGUI_WINDOW_SETTINGS = {} -IMGUI_WINDOW_SETTINGS.__index = IMGUI_WINDOW_SETTINGS +MT.ImGuiWindowSettings = {} +MT.ImGuiWindowSettings.__index = MT.ImGuiWindowSettings -function IMGUI_WINDOW_SETTINGS:GetName() +function MT.ImGuiWindowSettings:GetName() return self.Name end @@ -2675,7 +2749,7 @@ function ImGuiWindowSettings() DockOrder = -1, -- Order of the last time the window was visible within its DockNode. This is used to reorder windows that are reappearing on the same frame. Same value between windows that were active and windows that were none are possible. ClassId = 0, -- ID of window class if specified LastUsedDate = 0, - }, IMGUI_WINDOW_SETTINGS) + }, MT.ImGuiWindowSettings) end -- Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. @@ -3391,6 +3465,8 @@ function ImGuiInputEvent() end -- [Internal] Key ranges +ImGuiKey_LegacyNativeKey_BEGIN = 0 +ImGuiKey_LegacyNativeKey_END = 512 ImGuiKey_Keyboard_BEGIN = ImGuiKey.NamedKey_BEGIN ImGuiKey_Keyboard_END = ImGuiKey.GamepadStart ImGuiKey_Gamepad_BEGIN = ImGuiKey.GamepadStart @@ -3715,5 +3791,86 @@ end --- @nodiscard function ImGuiFocusScopeData() return { ID = nil, WindowID = nil } end +------------------------------------------------------------------------------- +-- [Luau] Inline struct helpers / constructors from imgui.h + imgui_internal.h +------------------------------------------------------------------------------- + +-- Helper for running a block of code not more than once a frame +-- [Luau] no operator bool(): call the object, e.g. 'if once() then ... end' +MT.ImGuiOnceUponAFrame = {} +MT.ImGuiOnceUponAFrame.__index = MT.ImGuiOnceUponAFrame +MT.ImGuiOnceUponAFrame.__call = function(self) local current_frame = ImGui.GetFrameCount(); if self.RefFrame == current_frame then return false end; self.RefFrame = current_frame; return true end +function ImGuiOnceUponAFrame() return setmetatable({ RefFrame = -1 }, MT.ImGuiOnceUponAFrame) end + +-- [Internal] ImGuiTextFilter item +-- [Luau] stores the item text as a Lua string (upstream: Begin pointer + Len) +--- @param buf string +--- @param b int # 1-based +--- @param e int # exclusive +function ImGuiTextFilterItem(buf, b, e) IM_ASSERT(e > b); return { Text = string.sub(buf, b, e - 1), CountInclude = 0, MatchIncludesMask = 0 } end + +-- A date in YYYYMMDD format packed into 16-bits +--- @class ImGuiPackedDate +MT.ImGuiPackedDate = {} +MT.ImGuiPackedDate.__index = MT.ImGuiPackedDate +--- @param yyyymmdd? int +function ImGuiPackedDate(yyyymmdd) + local this = setmetatable({ Year = 0, Month = 0, Day = 0 }, MT.ImGuiPackedDate) + if yyyymmdd ~= nil then -- Pack + this.Year = bitAnd(math.floor(yyyymmdd / 10000) - 2000, 0x7F) -- Year since 2000 (7 bits) + this.Month = bitAnd(math.floor(yyyymmdd / 100) % 100, 0x0F) -- Month (1-12) (4 bits) + this.Day = bitAnd(yyyymmdd % 100, 0x1F) -- Day (1-31) (5 bits) + end + return this +end +function MT.ImGuiPackedDate:IsValid() return self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 end +function MT.ImGuiPackedDate:Unpack() if self.Year ~= 0 and self.Month ~= 0 and self.Day ~= 0 then return ((self.Year + 2000) * 10000) + (self.Month * 100) + self.Day end; return 0 end -- Unpack +function MT.ImGuiPackedDate:SubtractMonths(m) while m > 0 do if self.Month == 1 then self.Year = bitAnd(self.Year - 1, 0x7F) end; self.Month = (self.Month == 1) and 12 or self.Month - 1; m = m - 1 end end -- FIXME-OPT: Stupid but enough for what we do with it. + +-- Pointer or index, e.g. g.CurrentTabBarStack[] +-- [Luau] overload by argument type: number = index, otherwise pointer +function ImGuiPtrOrIndex(ptr_or_index) + if type(ptr_or_index) == "number" then return { Ptr = nil, Index = ptr_or_index } end + return { Ptr = ptr_or_index, Index = -1 } +end + +-- Note that Max is exclusive, so perhaps should be using a Begin/End convention. +--- @class ImGuiListClipperRange +MT.ImGuiListClipperRange = {} +function MT.ImGuiListClipperRange.FromIndices(min, max) return { Min = min, Max = max, PosToIndexConvert = false, PosToIndexOffsetMin = 0, PosToIndexOffsetMax = 0 } end +function MT.ImGuiListClipperRange.FromPositions(y1, y2, off_min, off_max) return { Min = _Trunc(y1), Max = _Trunc(y2), PosToIndexConvert = true, PosToIndexOffsetMin = off_min, PosToIndexOffsetMax = off_max } end + +-- Temporary clipper data, buffers shared/reused between instances +--- @class ImGuiListClipperData +MT.ImGuiListClipperData = {} +MT.ImGuiListClipperData.__index = MT.ImGuiListClipperData +function ImGuiListClipperData() return setmetatable({ ListClipper = nil, LossynessOffset = 0.0, StepNo = 0, ItemsFrozen = 0, Ranges = ImVector() }, MT.ImGuiListClipperData) end +function MT.ImGuiListClipperData:Reset(clipper) self.ListClipper = clipper; self.StepNo = 0; self.ItemsFrozen = 0; self.Ranges:resize(0) end + +function ImGuiStackLevelInfo() return { ID = 0, QueryFrameCount = 0, QuerySuccess = false, DataType = -1, DescOffset = -1 } end +function ImGuiDebugItemPathQuery() return { MainID = 0, Active = false, Complete = false, Step = 0, Results = ImVector(), ResultsDescBuf = ImGuiTextBuffer(), ResultPathBuf = ImGuiTextBuffer() } end +function ImGuiIDStackTool() return { OptHexEncodeNonAsciiChars = true, OptCopyToClipboardOnCtrlC = false, LastActiveFrame = -1, CopyToClipboardLastTime = -FLT_MAX } end +function ImGuiContextHook() return { HookId = 0, Type = 0, Owner = 0, Callback = nil, UserData = nil } end + +------------------------------------------------------------------------------- +-- [Luau] ImGui:: inline helpers from imgui_internal.h +------------------------------------------------------------------------------- + +function ImGui.GetCurrentTable() local g = GImGui; return g.CurrentTable end +--- @param window ImGuiWindow +--- @param parent_window ImGuiWindow? +function ImGui.SetWindowParentWindowForFocusRoute(window, parent_window) window.ParentWindowForFocusRoute = parent_window end -- You may also use SetNextWindowClass()'s FocusRouteParentWindowId field. +function ImGui.GetPixelDensity() return GImGui.FontRasterizerDensity end -- [Luau] g.FontRasterizerDensity == upstream g.CurrentPixelDensity +function ImGui.ScrollToBringRectIntoView(window, rect) ImGui.ScrollToRect(window, rect, ImGuiScrollFlags.KeepVisibleEdgeY) end +function ImGui.GetItemStatusFlags() local g = GImGui; return g.LastItemData.StatusFlags end +function ImGui.GetActiveID() local g = GImGui; return g.ActiveId end +function ImGui.GetFocusID() local g = GImGui; return g.NavId end +function ImGui.IsLegacyKey(key) return key >= ImGuiKey_LegacyNativeKey_BEGIN and key < ImGuiKey_LegacyNativeKey_END end +function ImGui.GetWindowDockNode() local g = GImGui; return g.CurrentWindow.DockNode end +function ImGui.GetCurrentFocusScope() local g = GImGui; return g.CurrentFocusScopeId end -- Focus scope we are outputting into, set by PushFocusScope() +function ImGui.GetCurrentTabBar() local g = GImGui; return g.CurrentTabBar end +-- This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. +function ImGui.IsItemActiveAsInputText() local g = GImGui; return g.ActiveId ~= 0 and g.ActiveId == g.LastItemData.ID and g.InputTextState.ID == g.LastItemData.ID end + return true -- [Roblox] ModuleScripts must return exactly one value diff --git a/imgui_tables.lua b/imgui_tables.lua index 9d82042..1a7a34c 100644 --- a/imgui_tables.lua +++ b/imgui_tables.lua @@ -331,9 +331,13 @@ end -- Storage for a table .ini settings --- @class ImGuiTableSettings +MT.ImGuiTableSettings = {} +MT.ImGuiTableSettings.__index = MT.ImGuiTableSettings function ImGuiTableSettings() - return { ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} } + return setmetatable({ ID = 0, SaveFlags = 0, RefScale = 0.0, ColumnsCount = 0, ColumnsCountMax = 0, LastUsedDate = 0, WantApply = false, Columns = {} }, MT.ImGuiTableSettings) end +-- [Luau] column settings are stored in a 0-based .Columns table (upstream: allocated right after the struct) +function MT.ImGuiTableSettings:GetColumnSettings() return self.Columns end -- Storage data for a single column for legacy Columns() api --- @class ImGuiOldColumnData @@ -4394,6 +4398,17 @@ function ImGui.TableLoadSettingsForColumn(column, column_settings, load_flags) column.SortDirection = column_settings.SortDirection end +-- [Luau] boolean "less than" for table.sort; takes (table, lhs column idx, rhs column idx) instead of ImGuiTableFixDisplayOrderColumnData +local function TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) + -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. + local lhs_order, rhs_order = table_.Columns[lhs_idx].DisplayOrder, table_.Columns[rhs_idx].DisplayOrder + if lhs_order < 0 then lhs_order = lhs_order + 0x10000 end + if rhs_order < 0 then rhs_order = rhs_order + 0x10000 end + local order_delta = lhs_order - rhs_order + if order_delta ~= 0 then return order_delta < 0 end + return lhs_idx < rhs_idx +end + -- Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2) function ImGui.TableFixDisplayOrder(table_) if band(table_.Flags, ImGuiTableFlags.Reorderable) == 0 then @@ -4408,17 +4423,7 @@ function ImGui.TableFixDisplayOrder(table_) fdo_columns[n + 1] = n end -- Sort by DisplayOrder and then Index - -- Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after. - local function key(idx) - local o = table_.Columns[idx].DisplayOrder - if o < 0 then o = o + 0x10000 end - return o - end - table.sort(fdo_columns, function(lhs_idx, rhs_idx) - local a, b = key(lhs_idx), key(rhs_idx) - if a ~= b then return a < b end - return lhs_idx < rhs_idx - end) + table.sort(fdo_columns, function(lhs_idx, rhs_idx) return TableFixDisplayOrderComparer(table_, lhs_idx, rhs_idx) end) for n = 0, table_.ColumnsCount - 1 do table_.Columns[fdo_columns[n + 1]].DisplayOrder = n end @@ -4427,6 +4432,27 @@ function ImGui.TableFixDisplayOrder(table_) end end +local function TableSettingsHandler_Cleanup(ctx, handler, args) + local g = ctx + for i = 0, g.Tables:GetMapSize() - 1 do + local table_ = g.Tables:GetByIndex(i) + if table_ then + table_.SettingsOffset = -1 + end + end + -- [Luau] settings.LastUsedDate is stored unpacked (YYYYMMDD int, 0 = none); g.SessionDate is an ImGuiPackedDate when set + for _, settings in g.SettingsTables:iter() do + local is_valid = ImGuiPackedDate(settings.LastUsedDate):IsValid() + if args._DiscardOlderThanDate ~= 0 and settings.LastUsedDate < args._DiscardOlderThanDate then + settings.ID = 0 + elseif args.DiscardWhenMissingDate and not is_valid then + settings.ID = 0 + elseif args.SetCurrentSessionDateToAll or (args.SetCurrentSessionDateWhenMissingDate and not is_valid) then + settings.LastUsedDate = g.SessionDate and g.SessionDate:Unpack() or 0 + end + end +end + local function ForEachTable(g, fn) for i = 0, g.Tables:GetMapSize() - 1 do local t = g.Tables:GetByIndex(i) @@ -4552,6 +4578,7 @@ function ImGui.TableSettingsAddSettingsHandler() ini_handler.ReadLineFn = TableSettingsHandler_ReadLine ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll ini_handler.WriteAllFn = TableSettingsHandler_WriteAll + ini_handler.CleanupFn = TableSettingsHandler_Cleanup ImGui.AddSettingsHandler(ini_handler) end @@ -4615,6 +4642,20 @@ function ImGui.TableGcCompactSettings() ForEachTable(g, function(t) t.SettingsOffset = -1 end) end +------------------------------------------------------------------------------- +-- [SECTION] Tables: Debugging +------------------------------------------------------------------------------- +-- [Luau] global (upstream: static) so ImGui.DebugNodeTable() in imgui.lua can use it + +function DebugNodeTableGetSizingPolicyDesc(sizing_policy) + sizing_policy = band(sizing_policy, ImGuiTableFlags.SizingMask_) + if sizing_policy == ImGuiTableFlags.SizingFixedFit then return "FixedFit" end + if sizing_policy == ImGuiTableFlags.SizingFixedSame then return "FixedSame" end + if sizing_policy == ImGuiTableFlags.SizingStretchProp then return "StretchProp" end + if sizing_policy == ImGuiTableFlags.SizingStretchSame then return "StretchSame" end + return "N/A" +end + ------------------------------------------------------------------------------- -- [SECTION] Columns, BeginColumns, EndColumns, etc. -- (This is a legacy API, prefer using BeginTable/EndTable!) diff --git a/imgui_widgets.lua b/imgui_widgets.lua index 458a38f..886fb4c 100644 --- a/imgui_widgets.lua +++ b/imgui_widgets.lua @@ -2598,12 +2598,14 @@ function ImGui.RoundScalarWithFormatT(format, data_type, v) return v -- Don't apply if the value is not visible in the format string end - -- TODO: Sanitize format + -- Sanitize format + local fmt_sanitized = ImParseFormatSanitizeForPrinting(string.sub(format, fmt_start), nil, 32) -- Format value with our rounding, and read back - local str = ImFormatString(format, v) + local v_str = ImFormatString(fmt_sanitized, v) + -- [Luau] leading spaces: ImAtof() skips them - v = ImAtof(str) or v + v = ImAtof(v_str) or v return v end @@ -2689,6 +2691,30 @@ local function ImParseFormatTrimDecorations(fmt) return string.sub(fmt, fmt_start, fmt_end - 1) end +-- Sanitize format +-- - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi +-- - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. +-- [Luau] fmt_out is a byte table (may be nil); returns the sanitized format as a string +--- @param fmt_in string +--- @param fmt_out char[]? +--- @param fmt_out_size size_t +function ImParseFormatSanitizeForPrinting(fmt_in, fmt_out, fmt_out_size) + local fmt_end = ImParseFormatFindEnd(fmt_in, 1) + -- IM_UNUSED(fmt_out_size) + IM_ASSERT(fmt_end < fmt_out_size) -- Format is too long, let us know if this happens to you! + fmt_out = fmt_out or {} + local n = 0 + for i = 1, fmt_end - 1 do + local c = string.byte(fmt_in, i) + if c ~= 39 and c ~= 36 and c ~= 95 then -- Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. + n = n + 1 + fmt_out[n] = c + end + end + fmt_out[n + 1] = 0 -- Zero-terminate + return string.char(unpack(fmt_out, 1, n)) +end + -- - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" --- @param fmt_in string --- @param fmt_out char[] @@ -3290,6 +3316,18 @@ function ImGui.DragBehaviorT(TYPE, SIGNEDTYPE, data_type, v, v_speed, v_min, v_m return v, true end +local function ShortcutsForCancel(id) + local g = GImGui + local is_cancel_with_keyboard = ImGui.Shortcut(ImGuiKey.Escape, ImGuiInputFlags.None, id) + -- [Luau] ImGuiKey_NavGamepadCancel macro inlined (io.ConfigNavSwapGamepadButtons is not ported: always FaceRight) + local is_cancel_with_gamepad = bit32.band(g.IO.ConfigFlags, ImGuiConfigFlags.NavEnableGamepad) ~= 0 and bit32.band(g.IO.BackendFlags, ImGuiBackendFlags.HasGamepad) ~= 0 and ImGui.Shortcut(ImGuiKey.GamepadFaceRight, ImGuiInputFlags.None, id) + local is_cancel_with_mouse = ImGui.IsMouseReleased(ImGuiMouseButton.Right, id) + if is_cancel_with_mouse then + ImGui.SetKeyOwner(ImGuiKey.MouseRight, id) + end + return is_cancel_with_keyboard or is_cancel_with_gamepad or is_cancel_with_mouse +end + --- @param id ImGuiID --- @param data_type ImGuiDataType --- @param v number @@ -3311,6 +3349,13 @@ function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags) elseif (g.ActiveIdSource == ImGuiInputSource.Keyboard or g.ActiveIdSource == ImGuiInputSource.Gamepad) and g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then ImGui.ClearActiveID() end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end end if g.ActiveId ~= id then return v, false @@ -3869,9 +3914,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ local set_new_value = false local clicked_t = 0.0 if g.ActiveIdSource == ImGuiInputSource.Mouse then - if not g.IO.MouseDown[0] then - ImGui.ClearActiveID() - else + do local mouse_abs_pos = g.IO.MousePos[axis_k] if g.ActiveIdIsJustActivated then local grab_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) @@ -3891,11 +3934,6 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ set_new_value = true end elseif g.ActiveIdSource == ImGuiInputSource.Keyboard or g.ActiveIdSource == ImGuiInputSource.Gamepad then - if g.ActiveIdIsJustActivated then - g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation - g.SliderCurrentAccumDirty = false - end - local input_delta = (axis == ImGuiAxis.X) and ImGui.GetNavTweakPressedAmount(axis) or -ImGui.GetNavTweakPressedAmount(axis) if input_delta ~= 0.0 then local tweak_slow = ImGui.IsKeyDown((g.NavInputSource == ImGuiInputSource.Gamepad) and ImGuiKey.NavGamepadTweakSlow or ImGuiKey.NavKeyboardTweakSlow) @@ -3922,9 +3960,7 @@ function ImGui.SliderBehaviorT(TYPE, SIGNEDTYPE, bb, id, data_type, v, v_min, v_ end local delta = g.SliderCurrentAccum - if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then - ImGui.ClearActiveID() - elseif g.SliderCurrentAccumDirty then + if g.SliderCurrentAccumDirty then clicked_t = ImGui.ScaleRatioFromValueT(data_type, v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize) if (clicked_t >= 1.0 and delta > 0.0) or (clicked_t <= 0.0 and delta < 0.0) then -- This is to avoid applying the saturation when already past the limits @@ -4016,6 +4052,30 @@ function ImGui.SliderBehavior(bb, id, data_type, v, min, max, format, flags, out 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.") IM_ASSERT(bit32.band(flags, ImGuiSliderFlags.WrapAround) == 0) -- Not supported by SliderXXX(), only by DragXXX() + -- Things we can do easily outside the SliderBehaviorT<> template, saves code generation. + local g = GImGui + if g.ActiveId == id then + if g.ActiveIdSource == ImGuiInputSource.Mouse and not g.IO.MouseDown[0] then + ImGui.ClearActiveID() + end + if g.ActiveIdSource == ImGuiInputSource.Keyboard or g.ActiveIdSource == ImGuiInputSource.Gamepad then + if g.ActiveIdIsJustActivated then + g.SliderCurrentAccum = 0.0 -- Reset any stored nav delta upon activation + g.SliderCurrentAccumDirty = false + end + if g.NavActivatePressedId == id and not g.ActiveIdIsJustActivated then + ImGui.ClearActiveID() + end + end + if ShortcutsForCancel(id) and g.ActiveId == id then + -- Canceling action reverts to initial value + local value_changed = (v ~= g.ActiveIdValueOnActivation) + v = g.ActiveIdValueOnActivation + ImGui.ClearActiveID() + return v, value_changed + end + end + if data_type == ImGuiDataType.S8 then local v32 = (ImS32)((ImS8)(v)); local r v32, r = ImGui.SliderBehaviorT(ImS32, ImS32, bb, id, ImGuiDataType.S32, v32, min, max, format, flags, out_grab_bb) @@ -4602,7 +4662,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) local len = obj.TextLen idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) while idx <= len and not ImStb.is_word_boundary_from_left(obj, idx) do @@ -4613,7 +4673,7 @@ end --- @param obj ImGuiInputTextState --- @param idx int -local function STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) +function ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) idx = ImStb.TEXTEDIT_GETNEXTCHARINDEX(obj, idx) local len = obj.TextLen while idx <= len and not ImStb.is_word_boundary_from_right(obj, idx) do @@ -4627,9 +4687,9 @@ end function ImStb.TEXTEDIT_MOVEWORDRIGHT(obj, idx) local g = obj.Ctx if g.IO.ConfigMacOSXBehaviors then - return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx) else - return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) + return ImStb.TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx) end end @@ -4830,6 +4890,13 @@ function MT.ImGuiInputTextState:CursorClamp() end function MT.ImGuiInputTextState:HasSelection() return self.Stb.select_start ~= self.Stb.select_end end +function MT.ImGuiInputTextState:ClearSelection() self.Stb.select_start = self.Stb.cursor; self.Stb.select_end = self.Stb.cursor end +-- [Luau] positions are 1-based byte indices (upstream: 0-based) +function MT.ImGuiInputTextState:GetCursorPos() return self.Stb.cursor end +function MT.ImGuiInputTextState:GetSelectionStart() return self.Stb.select_start end +function MT.ImGuiInputTextState:GetSelectionEnd() return self.Stb.select_end end +function MT.ImGuiInputTextState:SetSelection(start, _end) self.Stb.select_start = start; self.Stb.cursor = _end; self.Stb.select_end = _end end +function MT.ImGuiInputTextState:GetPreferredOffsetX() if self.Stb.has_preferred_x then return self.Stb.preferred_x else return -1 end end function MT.ImGuiInputTextState:SelectAll() self.Stb.select_start = 1 @@ -4838,6 +4905,10 @@ function MT.ImGuiInputTextState:SelectAll() self.Stb.has_preferred_x = false end +function MT.ImGuiInputTextState:ReloadUserBufAndSelectAll() self.WantReloadUserBuf = true; self.ReloadSelectionStart = 1; self.ReloadSelectionEnd = INT_MAX end +function MT.ImGuiInputTextState:ReloadUserBufAndKeepSelection() self.WantReloadUserBuf = true; self.ReloadSelectionStart = self.Stb.select_start; self.ReloadSelectionEnd = self.Stb.select_end end +function MT.ImGuiInputTextState:ReloadUserBufAndMoveToEnd() self.WantReloadUserBuf = true; self.ReloadSelectionStart = INT_MAX; self.ReloadSelectionEnd = INT_MAX end + end function ImGui.PushPasswordFont() @@ -4989,9 +5060,9 @@ local function InputTextFilterCharacter(ctx, state, char, callback, user_data, i callback_data.EventFlag = ImGuiInputTextFlags.CallbackCharFilter callback_data.EventChar = c callback_data.EventActivated = (state ~= nil and g.ActiveId == state.ID and g.ActiveIdIsJustActivated) - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 callback_data.UserData = user_data if callback(callback_data) ~= 0 then return char, false @@ -5573,7 +5644,7 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback if not stbte.HAS_SELECTION(state.Stb) then stbte.prep_selection_at_cursor(state.Stb) end - state.Stb.cursor = STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) + state.Stb.cursor = ImStb.TEXTEDIT_MOVEWORDRIGHT_MAC(state, state.Stb.cursor) state.Stb.select_end = state.Stb.cursor stbte.clamp(state, state.Stb) else @@ -5902,9 +5973,9 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback callback_data.BufTextLen = state.TextLen callback_data.BufSize = state.BufCapacity callback_data.BufDirty = false - callback_data.CursorPos = state.Stb.cursor - callback_data.SelectionStart = state.Stb.select_start - callback_data.SelectionEnd = state.Stb.select_end + callback_data.CursorPos = state.Stb.cursor - 1 -- [Luau] callback positions are 0-based, stb ones 1-based + callback_data.SelectionStart = state.Stb.select_start - 1 + callback_data.SelectionEnd = state.Stb.select_end - 1 -- Call user code callback(callback_data) @@ -5914,12 +5985,12 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback IM_ASSERT(callback_data.Buf == callback_buf) -- Invalid to modify those fields IM_ASSERT(callback_data.BufSize == state.BufCapacity) IM_ASSERT(callback_data.Flags == flags) - if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor then + if callback_data.BufDirty or callback_data.CursorPos ~= state.Stb.cursor - 1 then state.CursorFollow = true end - state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) - state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) - state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + state.Stb.cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen) + 1 + state.Stb.select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen) + 1 + state.Stb.select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen) + 1 if callback_data.BufDirty then -- Callback may update buffer and thus set buf_dirty even in read-only mode. IM_ASSERT(callback_data.BufTextLen == ImStd.ImStrlen(callback_data.Buf)) -- You need to maintain BufTextLen if you change the text! @@ -6283,6 +6354,47 @@ function ImGui.InputTextWithHint(label, hint, buf, buf_size, flags, callback, us return ImGui.InputTextEx(label, hint, buf, buf_size, ImVec2(0, 0), flags, callback, user_data) end +-- [Luau] stb positions/undo indices are 1-based in this port (displayed as-is) +--- @param state ImGuiInputTextState +function ImGui.DebugNodeInputTextState(state) + local g = GImGui + local stb_state = state.Stb + local undo_state = stb_state.undostate + ImGui.Text("ID: 0x%08X, ActiveID: 0x%08X", state.ID, g.ActiveId) + if ImGui.DebugLocateItemOnHover then ImGui.DebugLocateItemOnHover(state.ID) end -- [Luau] not ported yet + local wrap_dir = "" + if bit32.band(state.Flags, ImGuiInputTextFlags.WordWrap) ~= 0 then + if state.LastMoveDirectionLR == ImGuiDir.Left then wrap_dir = " (L)" else wrap_dir = " (R)" end + end + ImGui.Text("TextLen: %d, Cursor: %d%s, Selection: %d..%d", state.TextLen, stb_state.cursor, wrap_dir, stb_state.select_start, stb_state.select_end) + ImGui.Text("BufCapacity: %d, LineCount: %d", state.BufCapacity, state.LineCount) + ImGui.Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state.TextA.Size, state.TextA.Capacity) + ImGui.Text("has_preferred_x: %d (%.2f)", stb_state.has_preferred_x and 1 or 0, stb_state.preferred_x) + ImGui.Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state.undo_point, undo_state.redo_point, undo_state.undo_char_point, undo_state.redo_char_point) + if ImGui.BeginChild("undopoints", ImVec2(0.0, ImGui.GetTextLineHeight() * 10), bit32.bor(ImGuiChildFlags.Borders, ImGuiChildFlags.ResizeY)) then -- Visualize undo state + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ImVec2(0, 0)) + for n = 1, IMSTB_TEXTEDIT_UNDOSTATECOUNT do + local undo_rec = undo_state.undo_rec[n] + local undo_rec_type = (n < undo_state.undo_point) and "u" or ((n >= undo_state.redo_point) and "r" or " ") + if undo_rec_type == " " then + ImGui.BeginDisabled() + end + local buf_preview_len = (undo_rec_type ~= " " and undo_rec.char_storage ~= -1) and undo_rec.insert_length or 0 + local buf_preview_str = "" + if buf_preview_len > 0 then + buf_preview_str = string.char(unpack(undo_state.undo_char, undo_rec.char_storage, undo_rec.char_storage + buf_preview_len - 1)) + end + ImGui.Text("%s [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%s\"", + undo_rec_type, n, undo_rec.where, undo_rec.insert_length, undo_rec.delete_length, undo_rec.char_storage, buf_preview_str) + if undo_rec_type == " " then + ImGui.EndDisabled() + end + end + ImGui.PopStyleVar() + end + ImGui.EndChild() +end + ------------------------------------------------------------------------------- -- [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. ------------------------------------------------------------------------------- @@ -10648,14 +10760,37 @@ local function TabItemGetSectionIdx(tab) return 1 end +-- [Luau] comparers return a boolean "less than" for table.sort (upstream: ImQsort int comparers) +local function TabItemComparerBySection(a, b) + if a == nil or b == nil then return false end + local a_section = TabItemGetSectionIdx(a) + local b_section = TabItemGetSectionIdx(b) + if a_section ~= b_section then + return a_section < b_section + end + return a.IndexDuringLayout < b.IndexDuringLayout +end + +local function TabItemComparerByBeginOrder(a, b) + return a.BeginOrder < b.BeginOrder +end + +local function GetTabBarFromTabBarRef(ref) + local g = GImGui + if ref.Ptr then return ref.Ptr else return g.TabBars:GetByIndex(ref.Index) end +end + +local function GetTabBarRefFromTabBar(tab_bar) + local g = GImGui + if g.TabBars:Contains(tab_bar) then + return ImGuiPtrOrIndex(g.TabBars:GetIndex(tab_bar)) + end + return ImGuiPtrOrIndex(tab_bar) +end + -- Stable sorts (C++ ImQsort is not stable, but the comparers are total orders in practice) local function SortTabsBySection(tab_bar) - table.sort(tab_bar.Tabs.Data, function(a, b) - if a == nil or b == nil then return false end - local sa, sb = TabItemGetSectionIdx(a), TabItemGetSectionIdx(b) - if sa ~= sb then return sa < sb end - return a.IndexDuringLayout < b.IndexDuringLayout - end) + table.sort(tab_bar.Tabs.Data, TabItemComparerBySection) end local function SortTabsByBeginOrder(tab_bar) @@ -10663,7 +10798,7 @@ local function SortTabsByBeginOrder(tab_bar) if not data then return end local arr = {} for i = 1, tab_bar.Tabs.Size do arr[i] = data[i] end - table.sort(arr, function(a, b) return a.BeginOrder < b.BeginOrder end) + table.sort(arr, TabItemComparerByBeginOrder) for i = 1, tab_bar.Tabs.Size do data[i] = arr[i] end end @@ -10677,6 +10812,12 @@ end -- Spacing: Horizontal spacing at the end of the section. local function ImGuiTabBarSection() return { TabCount = 0, Width = 0.0, WidthAfterShrinkMinWidth = 0.0, Spacing = 0.0 } end +-- [Luau] boolean "less than" for table.sort. Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects +local function ShrinkWidthItemComparer(a, b) + if a.Width ~= b.Width then return a.Width > b.Width end + return a.Index > b.Index -- b->Index - a->Index +end + -- Shrink excess width from a set of item, by removing width from the larger items first. -- Set items Width to -1.0f to disable shrinking this item. -- items: 1-based array of ImGuiShrinkWidthItem, `first` = 1-based index of first item, `count` items @@ -10690,10 +10831,7 @@ function ImGui.ShrinkWidths(items, first, count, width_excess, width_min) -- Sort largest first, smallest last. local slice = {} for n = 1, count do slice[n] = items[first + n - 1] end - table.sort(slice, function(a, b) - if a.Width ~= b.Width then return a.Width > b.Width end - return a.Index > b.Index -- ShrinkWidthItemComparer: b->Index - a->Index (Width compared exactly: upstream's (int) truncation isn't a strict weak order, which table.sort rejects) - end) + table.sort(slice, ShrinkWidthItemComparer) for n = 1, count do items[first + n - 1] = slice[n] end local it = slice local count_same_width = 1 @@ -10804,7 +10942,7 @@ function ImGui.BeginTabBarEx(tab_bar, tab_bar_bb, flags) end -- Add to stack - g.CurrentTabBarStack:push_back(tab_bar) + g.CurrentTabBarStack:push_back(GetTabBarRefFromTabBar(tab_bar)) g.CurrentTabBar = tab_bar tab_bar.Window = window @@ -10886,7 +11024,7 @@ function ImGui.EndTabBar() end g.CurrentTabBarStack:pop_back() - if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = g.CurrentTabBarStack.Data[g.CurrentTabBarStack.Size] end + if g.CurrentTabBarStack.Size == 0 then g.CurrentTabBar = nil else g.CurrentTabBar = GetTabBarFromTabBarRef(g.CurrentTabBarStack:back()) end end -- This is called only once a frame before by the first call to ItemTab() diff --git a/tools/test/check_all.sh b/tools/test/check_all.sh index baca1fc..43ae769 100755 --- a/tools/test/check_all.sh +++ b/tools/test/check_all.sh @@ -13,6 +13,8 @@ CHECKS=( "readme-min|README OK|MINIFY=1 $R --main tools/test/scripts/t_readme.luau --frames 30" "cached|CACHED OK|$R --main tools/test/scripts/t_cached_window.luau --frames 130" "fixes|FIXES OK|$R --main tools/test/scripts/t_fixes.luau --frames 55" +"debugtools|DEBUGTOOLS OK|$R --main tools/test/scripts/t_debugtools.luau --frames 65" +"helpers|HELPERS OK|$R --main tools/test/scripts/t_helpers.luau --frames 35" "multiselect|MULTISELECT OK|$R --main tools/test/scripts/t_multiselect.luau --frames 380" "nodemo|NODEMO OK|NO_DEMO=1 $R --main tools/test/scripts/t_nodemo.luau --frames 25" "widgets|OK|$R --main tools/test/scripts/t_widgets.luau --frames 80" diff --git a/tools/test/scripts/t_debugtools.luau b/tools/test/scripts/t_debugtools.luau new file mode 100644 index 0000000..feceb9c --- /dev/null +++ b/tools/test/scripts/t_debugtools.luau @@ -0,0 +1,79 @@ +-- Debug tools + misc imgui.cpp ports: item picker, DebugFlashStyleColor, DebugLocateItem, context hooks, AddInputCharactersUTF8, ImBezierCubicClosestPoint +local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui")) +local ImGui, ImVec2 = G.ImGui, G.ImVec2 +local ctx = ImGui.CreateContext(); 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 + +-- ImBezierCubicClosestPoint: straight-line cubic (0,0)-(30,0)-(60,0)-(90,0): closest point to (45,10) is (45,0) +local p1, p2, p3, p4 = ImVec2(0, 0), ImVec2(30, 0), ImVec2(60, 0), ImVec2(90, 0) +local cp = G.ImBezierCubicClosestPoint(p1, p2, p3, p4, ImVec2(45, 10), 20) +check(math.abs(cp.x - 45) < 1e-3 and math.abs(cp.y) < 1e-6, ("ImBezierCubicClosestPoint %g,%g"):format(cp.x, cp.y)) +-- Curved: result must lie on the curve (distance to a dense sampling of the curve ~0) and beat the endpoints +local q1, q2, q3, q4 = ImVec2(0, 0), ImVec2(0, 100), ImVec2(100, 100), ImVec2(100, 0) +local target = ImVec2(50, 120) +for _, r in { G.ImBezierCubicClosestPoint(q1, q2, q3, q4, target, 64), G.ImBezierCubicClosestPointCasteljau(q1, q2, q3, q4, target, 0.25) } do + check(math.abs(r.x - 50) < 0.5 and math.abs(r.y - 75) < 0.5, ("closest point on curve %g,%g (expected ~50,75)"):format(r.x, r.y)) +end + +-- AddInputCharactersUTF8 queues one Text event per codepoint +io:AddInputCharactersUTF8("a\u{e9}\u{20ac}\u{1F600}") +local chars = {} +for _, e in ctx.InputEventsQueue.Data do if e.Type == G.ImGuiInputEventType.Text then table.insert(chars, e.Text.Char) end end +-- (this build has IM_UNICODE_CODEPOINT_MAX = 0xFFFF like upstream's default ImWchar16: U+1F600 becomes IM_UNICODE_CODEPOINT_INVALID) +check(#chars == 4 and chars[1] == 0x61 and chars[2] == 0xE9 and chars[3] == 0x20AC and chars[4] == ((G.IM_UNICODE_CODEPOINT_MAX >= 0x1F600) and 0x1F600 or 0xFFFD), "AddInputCharactersUTF8 " .. table.concat(chars, ",")) + +-- Context hooks +local log = {} +local function hook(t, name) + local h = G.ImGuiContextHook(); h.Type = t; h.Callback = function(c, hk) table.insert(log, name) end + return ImGui.AddContextHook(ctx, h) +end +local T = G.ImGuiContextHookType +hook(T.NewFramePre, "nfpre"); hook(T.NewFramePost, "nfpost"); hook(T.RenderPre, "rpre"); local rpost = hook(T.RenderPost, "rpost") + +-- Style color flash +local col = ImGui.GetStyle().Colors[G.ImGuiCol.Button] +local orig = { col.x, col.y, col.z, col.w } + +local f, rect, picked, broke, button_id = 0, nil, nil, 0, 0 +ctx.DebugBreakCallback = function() broke += 1 end +game:GetService("RunService").Stepped:Connect(function() + f += 1 + G.ImGui_ImplRoblox.NewFrame() + if rect and f == 5 then io:AddMousePosEvent((rect[1].x + rect[2].x) / 2, (rect[1].y + rect[2].y) / 2) end + if f == 6 then ImGui.DebugStartItemPicker() end + if f == 8 then io:AddMouseButtonEvent(0, true) elseif f == 9 then io:AddMouseButtonEvent(0, false) end + ImGui.NewFrame() + if f == 1 then check(table.concat(log, " ") == "nfpre nfpost", "hooks after NewFrame: " .. table.concat(log, " ")) end + if f == 8 then picked = ctx.DebugItemPickerBreakId end + if f == 3 then ImGui.DebugFlashStyleColor(G.ImGuiCol.Button) end + ImGui.SetNextWindowPos(ImVec2(10, 10), G.ImGuiCond.Always) + ImGui.Begin("DebugTools") + ImGui.Button("Target") + if f == 2 then local a, b = ImGui.GetItemRectMin(), ImGui.GetItemRectMax(); rect = { ImVec2(a.x, a.y), ImVec2(b.x, b.y) } end + local target_id = ctx.LastItemData.ID + button_id = target_id + if f == 12 then ImGui.DebugLocateItem(target_id) end + if f == 13 then check(ctx.DebugLocateId == 0, "DebugLocateItem resolved by ItemAdd()") end + ImGui.DebugDrawItemRect(); ImGui.DebugDrawCursorPos(); ImGui.DebugDrawLineExtents() + ImGui.DebugTextUnformattedWithLocateItem(("id 0x%08X here"):format(target_id)) + ImGui.End() + ImGui.SetNextWindowPos(ImVec2(400, 10), G.ImGuiCond.Always); ImGui.ShowMetricsWindow() + ImGui.SetNextWindowPos(ImVec2(400, 300), G.ImGuiCond.Always); ImGui.ShowDebugLogWindow() + if f == 4 then + local c = ImGui.GetStyle().Colors[G.ImGuiCol.Button] + check(c.w == 1.0 and ctx.DebugFlashStyleColorIdx == G.ImGuiCol.Button, "flash active") + end + ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData()) + if f == 1 then check(table.concat(log, " ") == "nfpre nfpost rpre rpost", "hooks after Render: " .. table.concat(log, " ")); ImGui.RemoveContextHook(ctx, rpost) end + if f == 2 then check(table.concat(log, " ") == "nfpre nfpost rpre rpost nfpre nfpost rpre", "RemoveContextHook: " .. table.concat(log, " ")) end + if f == 60 then + local c = ImGui.GetStyle().Colors[G.ImGuiCol.Button] + check(c.x == orig[1] and c.y == orig[2] and c.z == orig[3] and c.w == orig[4] and ctx.DebugFlashStyleColorIdx == nil, "flash restored color exactly") + check(picked ~= nil and picked ~= 0 and picked == button_id, ("item picker set DebugItemPickerBreakId (%s vs %s)"):format(tostring(picked), tostring(button_id))) + check(not ctx.DebugItemPickerActive and broke >= 1, ("item picker break hook called (%d)"):format(broke)) + if #failed == 0 then print("DEBUGTOOLS OK") end + end +end) diff --git a/tools/test/scripts/t_helpers.luau b/tools/test/scripts/t_helpers.luau new file mode 100644 index 0000000..ef41e6f --- /dev/null +++ b/tools/test/scripts/t_helpers.luau @@ -0,0 +1,142 @@ +-- Small upstream helpers: ImGuiInputTextState selection API + ReloadUserBuf*, ImGuiInputTextCallbackData:SetSelection, ImDrawList AddImageQuad/PrimQuadUV/ +-- CloneOutput, ImDrawData DeIndexAllBuffers/ScaleClipRects, ImBitVector/ImBitArray*, ImGuiPackedDate, ImParseFormatSanitizeForPrinting, drag cancel (ShortcutsForCancel) +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 failed = {} +local function check(ok, msg) if not ok then table.insert(failed, msg); print("FAIL " .. msg) end end + +-- Pure helpers +check(G.ImParseFormatSanitizeForPrinting("%.3f%%", nil, 32) == "%.3f", "sanitize %.3f%%") +check(G.ImParseFormatSanitizeForPrinting("%'_5.2f units", nil, 32) == "%5.2f", "sanitize stb flags: " .. G.ImParseFormatSanitizeForPrinting("%'_5.2f units", nil, 32)) +local d = G.ImGuiPackedDate(20260315) +check(d:IsValid() and d:Unpack() == 20260315, "PackedDate round trip " .. d:Unpack()) +d:SubtractMonths(3) +check(d:Unpack() == 20251215, "PackedDate SubtractMonths " .. d:Unpack()) +check(not G.ImGuiPackedDate():IsValid() and G.ImGuiPackedDate():Unpack() == 0, "PackedDate empty") +local bv = G.ImBitVector() +bv:Create(70) +check(bv.Storage.Size == 3, "ImBitVector size") +bv:SetBit(1); bv:SetBit(70); bv:SetBit(33) +check(bv:TestBit(1) and bv:TestBit(70) and bv:TestBit(33) and not bv:TestBit(2) and not bv:TestBit(69), "ImBitVector SetBit/TestBit") +bv:ClearBit(33) +check(not bv:TestBit(33) and bv:TestBit(70), "ImBitVector ClearBit") +local arr = {} +G.ImBitArrayClearAllBits(arr, 96) +G.ImBitArraySetBitRange(arr, 3, 70) -- [3..70) +local ok_range = true +for n = 1, 96 do if G.ImBitArrayTestBit(arr, n) ~= (n >= 3 and n < 70) then ok_range = false end end +check(ok_range, "ImBitArraySetBitRange") +check(G.ImBitArrayGetStorageSizeInBytes(70) == 12, "ImBitArrayGetStorageSizeInBytes") +check(G.ImModPositive(-1, 5) == 4 and G.ImRoundSigned64(-1.5) == -2 and G.ImCharIsXdigitA(string.byte("F")), "math helpers") + +local buf = ImGui.NewTextBuffer("hello world", 64) +local cbuf = ImGui.NewTextBuffer("abcdef", 64) +local cb_calls = 0 +local function cb(data) + cb_calls += 1 + if cb_calls == 1 then data:SetSelection(1, 3) end + return 0 +end +local df, rect_df = 10.0, nil +local f = 0 +local function center(r) return (r[1].x + r[2].x) / 2, (r[1].y + r[2].y) / 2 end + +local function vtx(dl, i) -- 1-based vertex + local b, o = dl.VtxBuffer.Buf, (i - 1) * G.VTX_STRIDE + return buffer.readf64(b, o), buffer.readf64(b, o + 8), buffer.readf64(b, o + 16), buffer.readf64(b, o + 24), buffer.readu32(b, o + 32) +end + +game:GetService("RunService").Stepped:Connect(function() + f += 1 + G.ImGui_ImplRoblox.NewFrame() + -- drag + Escape cancels and reverts (ShortcutsForCancel) + if f == 20 then io:AddMousePosEvent(center(rect_df)) end + if f == 21 then io:AddMouseButtonEvent(0, true) end + if f == 22 then local x, y = center(rect_df); io:AddMousePosEvent(x + 40, y) end + if f == 24 then io:AddKeyEvent(G.ImGuiKey.Escape, true) end + if f == 25 then io:AddKeyEvent(G.ImGuiKey.Escape, false) end + if f == 26 then io:AddMouseButtonEvent(0, false) end + ImGui.NewFrame() + ImGui.SetNextWindowPos(ImVec2(10, 10)); ImGui.SetNextWindowSize(ImVec2(400, 300)) + ImGui.Begin("H") + if f == 2 then ImGui.SetKeyboardFocusHere() end + ImGui.InputText("##t", buf, 64) + local id = ImGui.GetItemID() + local st = ImGui.GetInputTextState(id) + if f == 5 then + check(st ~= nil, "InputText active") + if st then + st:SetSelection(3, 6) + check(st:GetSelectionStart() == 3 and st:GetSelectionEnd() == 6 and st:GetCursorPos() == 6 and st:HasSelection(), "SetSelection/Get*") + st:ClearSelection() + check(st:GetSelectionStart() == 6 and st:GetSelectionEnd() == 6 and not st:HasSelection(), "ClearSelection") + check(st:GetPreferredOffsetX() == -1, "GetPreferredOffsetX") + -- modify the user buffer externally then reload + local s = "bye"; for i = 1, #s do buf[i] = string.byte(s, i) end; buf[#s + 1] = 0 + st:ReloadUserBufAndSelectAll() + end + end + if f == 7 and st then + check(G.ImGui._ByteArrayToString(st:GetText(), 1, st.TextLen + 1) == "bye", "ReloadUserBufAndSelectAll text") + check(st:GetSelectionStart() == 1 and st:GetSelectionEnd() == 4, ("ReloadUserBufAndSelectAll sel %d..%d"):format(st:GetSelectionStart(), st:GetSelectionEnd())) + st:SetSelection(2, 3); st:ReloadUserBufAndKeepSelection() + end + if f == 9 and st then + check(st:GetSelectionStart() == 2 and st:GetSelectionEnd() == 3, "ReloadUserBufAndKeepSelection") + st:ReloadUserBufAndMoveToEnd() + end + if f == 11 and st then + check(st:GetCursorPos() == 4 and not st:HasSelection(), "ReloadUserBufAndMoveToEnd " .. st:GetCursorPos()) + end + -- callback SetSelection (0-based callback positions -> 1-based stb) + if f == 12 then ImGui.SetKeyboardFocusHere() end + ImGui.InputText("##c", cbuf, 64, G.ImGuiInputTextFlags.CallbackAlways, cb) + if f == 15 then + local cst = ImGui.GetInputTextState(ImGui.GetItemID()) + check(cst ~= nil and cb_calls > 0 and cst:GetSelectionStart() == 2 and cst:GetSelectionEnd() == 4, "callback SetSelection " .. (cst and (cst:GetSelectionStart() .. ".." .. cst:GetSelectionEnd()) or "nil")) + end + df = ImGui.DragFloat("##df", df, 1.0) + local a, b = ImGui.GetItemRectMin(), ImGui.GetItemRectMax(); rect_df = { ImVec2(a.x, a.y), ImVec2(b.x, b.y) } + if f == 23 then check(df ~= 10.0, "drag changed value " .. df) end + if f == 25 then check(df == 10.0 and ImGui.GetActiveID() == 0, "Escape reverts drag " .. df) end + + if f == 30 then + local dl = ImGui.GetWindowDrawList() + local v0, i0 = dl.VtxBuffer.Size, dl.IdxBuffer.Size + local tex = G.ImTextureRef(1234) + dl:AddImageQuad(tex, ImVec2(10, 10), ImVec2(50, 12), ImVec2(48, 60), ImVec2(8, 58), ImVec2(0, 0), ImVec2(1, 0), ImVec2(1, 1), ImVec2(0, 1), 0xFF00FF00) + check(dl.VtxBuffer.Size == v0 + 4 and dl.IdxBuffer.Size == i0 + 6, "AddImageQuad counts") + local x, y, u, v, col = vtx(dl, v0 + 3) + check(x == 48 and y == 60 and u == 1 and v == 1 and col == 0xFF00FF00, ("PrimQuadUV vertex %s %s %s %s %x"):format(x, y, u, v, col)) + local idx = dl.IdxBuffer.Data + check(idx[i0 + 1] == v0 + 1 and idx[i0 + 5] == v0 + 3 and idx[i0 + 6] == v0 + 4, "PrimQuadUV indices") + local cmin, cmax = dl:GetClipRectMin(), dl:GetClipRectMax() + check(cmax.x > cmin.x and cmax.y > cmin.y, "GetClipRectMin/Max") + + local clone = dl:CloneOutput() + check(clone.VtxBuffer.Size == dl.VtxBuffer.Size and clone.IdxBuffer.Size == dl.IdxBuffer.Size and clone.CmdBuffer.Size == dl.CmdBuffer.Size + and clone.VtxBuffer.Buf ~= dl.VtxBuffer.Buf and clone.CmdBuffer.Data[1] ~= dl.CmdBuffer.Data[1], "CloneOutput copies buffers") + local cx = vtx(clone, v0 + 3) + check(cx == 48, "CloneOutput vertex data") + + local dd = G.ImDrawData() + dd.CmdLists:push_back(clone) + local n_idx = clone.IdxBuffer.Size + local ex, ey = vtx(clone, clone.IdxBuffer.Data[n_idx]) + dd:DeIndexAllBuffers() + check(clone.IdxBuffer.Size == 0 and clone.VtxBuffer.Size == n_idx and dd.TotalVtxCount == n_idx and dd.TotalIdxCount == 0, "DeIndexAllBuffers counts") + local lx, ly = vtx(clone, n_idx) + check(lx == ex and ly == ey, "DeIndexAllBuffers vertex data") + + local cr = clone.CmdBuffer.Data[1].ClipRect + local x1, y1, z1, w1 = cr.x, cr.y, cr.z, cr.w + dd:ScaleClipRects(ImVec2(2, 3)) + local cr2 = clone.CmdBuffer.Data[1].ClipRect + check(cr2.x == x1 * 2 and cr2.y == y1 * 3 and cr2.z == z1 * 2 and cr2.w == w1 * 3 and dl.CmdBuffer.Data[1].ClipRect.z == z1, "ScaleClipRects") + end + ImGui.End() + ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData()) + if f == 32 and #failed == 0 then print("HELPERS OK") end +end)