Port leftovers: BringWindowToDisplayBehind, ImGuiSizeCallbackData + CalcWindowSizeAfterConstraint, ErrorCheckUsingSetCursorPosToExtendParentBoundaries, PopFocusScope user error (+ SetCurrentWindow stack sizes fix), log text decorations (Button/Menu/TreeNode/Drag/Slider/InputText/Checkbox/Radio), DataTypeFormatString display, ImGuiDataType S64/U64 (upstream enum layout; doubles), sscanf %u/length modifiers, mouse arrays sized ImGuiMouseButton.COUNT, AddCallback userdata copy; TODO.txt refreshed

This commit is contained in:
4DBug
2026-10-15 10:51:20 -05:00
parent b71e62b4d9
commit dad1a0c0f1
15 changed files with 2161 additions and 1591 deletions
+1 -1
View File
@@ -1 +1 @@
[[46, "imgui.lua"], [22668, "imgui_demo.lua"], [34519, "imgui_draw.lua"], [42824, "imgui_h.lua"], [45800, "imgui_impl_roblox.lua"], [47452, "imgui_impl_roblox_fonts.lua"], [53855, "imgui_internal.lua"], [57827, "imgui_tables.lua"], [62919, "imgui_widgets.lua"], [75061, "imstb_rectpack.lua"], [75725, "imstb_textedit.lua"], [77267, "imstb_truetype.lua"], [80055, "imstd_minstdio.lua"]] [[46, "imgui.lua"], [22675, "imgui_demo.lua"], [34533, "imgui_draw.lua"], [42860, "imgui_h.lua"], [45857, "imgui_impl_roblox.lua"], [47509, "imgui_impl_roblox_fonts.lua"], [53912, "imgui_internal.lua"], [57884, "imgui_tables.lua"], [62976, "imgui_widgets.lua"], [75210, "imstb_rectpack.lua"], [75874, "imstb_textedit.lua"], [77416, "imstb_truetype.lua"], [80204, "imstd_minstdio.lua"]]
+365 -195
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
[[183, "imgui.lua"], [22805, "imgui_demo.lua"], [34656, "imgui_draw.lua"], [42961, "imgui_h.lua"], [45937, "imgui_impl_love.lua"], [46481, "imgui_internal.lua"], [50453, "imgui_tables.lua"], [55545, "imgui_widgets.lua"], [67687, "imstb_rectpack.lua"], [68351, "imstb_textedit.lua"], [69893, "imstb_truetype.lua"], [72681, "imstd_minstdio.lua"]] [[183, "imgui.lua"], [22812, "imgui_demo.lua"], [34670, "imgui_draw.lua"], [42997, "imgui_h.lua"], [45994, "imgui_impl_love.lua"], [46538, "imgui_internal.lua"], [50510, "imgui_tables.lua"], [55602, "imgui_widgets.lua"], [67836, "imstb_rectpack.lua"], [68500, "imstb_textedit.lua"], [70042, "imstb_truetype.lua"], [72830, "imstd_minstdio.lua"]]
+365 -195
View File
File diff suppressed because it is too large Load Diff
+1033 -1033
View File
File diff suppressed because it is too large Load Diff
+13 -25
View File
@@ -6,26 +6,16 @@ Re-check with: python3 tools/test/missing.py [imgui|widgets|tables|draw] and p
which exist as ImGui.DragFloat2 = DragFloatN(2) etc. Those are NOT gaps.) which exist as ImGui.DragFloat2 = DragFloatN(2) etc. Those are NOT gaps.)
FEATURES NOT PORTED FEATURES NOT PORTED / PARTIAL
------------------- -----------------------------
- Multi-select / box-select: BeginMultiSelect, EndMultiSelect, MultiSelectItemHeader/Footer, MultiSelectAddSetAll, - ImFont::AddRemapCodepointToGlyphIndex / FontSrcGetGlyphIndexFromCodepoint (needs the 1.93 font loader split).
MultiSelectAddSetRange, SetNextItemSelectionUserData, BeginBoxSelect/EndBoxSelect, DebugNodeMultiSelectState. - Default compressed font data (GetDefaultCompressedFontDataTTF / ProggyClean/ProggyForever embedded data):
(Selectable/TreeNode call sites are stubbed with TODOs; the demo "Selection State & Multi-Select" section is not ported.) AddFontFromMemoryCompressedTTF works, but the default font comes from fonts/ instead.
- Typing-select (type to jump in lists): GetTypingSelectRequest, TypingSelectFind*, DebugNodeTypingSelectState. - DebugLogSkippedErrors / DebugDrawIdConflicts* (Metrics error-recovery and ID-conflict debug tools).
- Examples > Assets Browser (needs multi-select + box-select). - ImGuiDataType.S64/U64: supported, but values are Luau doubles: exact only within +-2^53 (LLONG_MAX/ULLONG_MAX
- Metrics > Tools > Item Picker (UpdateDebugToolItemPicker). round up to 2^63/2^64; U64 max prints as 18446744073709551615 via a special case).
- DebugFlashStyleColor / UpdateDebugToolFlashStyleColor (Style Editor "?" flash button). - ImDrawList::AddCallback(userdata_size > 0): "copy" = shallow copy of a table userdata (no raw bytes in Lua).
- DebugNodeInputTextState (Metrics > Internal state > InputText). - stb_truetype: cmap format 2 (high-byte mapping) asserts -- same as upstream stb_truetype ("@TODO").
- BringWindowToDisplayBehind: stub, does nothing.
- ColorEdit4 / ColorPicker4: drag & drop target (dropping a color onto a color widget).
- ImFontAtlas:AddFontFromMemoryCompressedTTF: stub (binary_to_compressed_c fonts can't be loaded).
- ImGuiSizeCallbackData: SetNextWindowSizeConstraints custom callbacks only partially supported
(Examples > Constrained Resize).
- LogSetNextTextDecoration (Selectable "[ ]" decoration in log/clipboard output).
- stb_truetype: cmap high-byte mapping (some CJK fonts assert).
- Context hooks removal (RemoveContextHook), SetContextName.
- RegisterUserTexture / UnregisterUserTexture.
- ErrorCheckNewFrameSanityChecks / ErrorCheckEndFrameSanityChecks (fewer usage-error asserts than upstream).
- GetAllocatorFunctions (n/a in Luau). - GetAllocatorFunctions (n/a in Luau).
WON'T DO (platform) WON'T DO (platform)
@@ -41,11 +31,9 @@ NOT VERIFIED LINE BY LINE AGAINST UPSTREAM
KNOWN ISSUES KNOWN ISSUES
------------ ------------
- Tables > "Columns flags": disabling every column asserts in TableUpdateLayout (upstream asserts too). - Tables > "Columns flags": disabling every column asserts in TableUpdateLayout (upstream asserts too).
- Style Editor > Colors uses a ListClipper (port-only change, upstream submits every row). - ImTriangulator ([Luau] deviation, imgui_draw.lua ImTriangulator_IsReflex): only strictly counter-clockwise corners are
reflex (upstream: also collinear/duplicate points), so polygons with duplicate points triangulate differently (no
PERFORMANCE IDEAS (not done) overlapping-triangle fallback).
----------------------------
- Cheaper visible ColorEdit4 rows; cheaper Begin() for child windows.
PLANNED EXTENSIONS PLANNED EXTENSIONS
------------------ ------------------
+41 -34
View File
@@ -6489,7 +6489,7 @@ function ImGui.IsMouseDragPastThreshold(button, lock_threshold)
if lock_threshold == nil then lock_threshold = -1.0 end if lock_threshold == nil then lock_threshold = -1.0 end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) -- IM_COUNTOF(g.IO.MouseDown) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
if lock_threshold < 0.0 then if lock_threshold < 0.0 then
lock_threshold = g.IO.MouseDragThreshold lock_threshold = g.IO.MouseDragThreshold
end end
@@ -6502,7 +6502,7 @@ function ImGui.IsMouseDragging(button, lock_threshold)
if lock_threshold == nil then lock_threshold = -1.0 end if lock_threshold == nil then lock_threshold = -1.0 end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) -- IM_COUNTOF(g.IO.MouseDown) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
if not g.IO.MouseDown[button] then if not g.IO.MouseDown[button] then
return false return false
end end
@@ -7048,7 +7048,7 @@ function ImGui.EndGroup()
IM_ASSERT(group_data.WindowID == window.ID) -- EndGroup() in wrong window? IM_ASSERT(group_data.WindowID == window.ID) -- EndGroup() in wrong window?
if (window.DC.IsSetPos) then if (window.DC.IsSetPos) then
-- TODO: ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries() ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
end end
-- Include LastItemData.Rect.Max as a workaround for e.g. EndTable() undershooting with CursorMaxPos report. (#7543) -- Include LastItemData.Rect.Max as a workaround for e.g. EndTable() undershooting with CursorMaxPos report. (#7543)
@@ -7515,7 +7515,16 @@ function ImGui.BringWindowToDisplayBehind(window, behind_window)
local g = GImGui local g = GImGui
window = window.RootWindow window = window.RootWindow
behind_window = behind_window.RootWindow behind_window = behind_window.RootWindow
-- TODO: local pos_wnd = ImGui.FindWindowDisplayIndex(window) + 1 -- 1-based
local pos_beh = ImGui.FindWindowDisplayIndex(behind_window) + 1
local data = g.Windows.Data
if pos_wnd < pos_beh then
for i = pos_wnd, pos_beh - 2 do data[i] = data[i + 1] end -- memmove
data[pos_beh - 1] = window
else
for i = pos_wnd, pos_beh + 1, -1 do data[i] = data[i - 1] end -- memmove
data[pos_beh] = window
end
end end
--- @param under_this_window? ImGuiWindow --- @param under_this_window? ImGuiWindow
@@ -8298,7 +8307,7 @@ function MT.ImGuiIO:ClearInputMouse()
self.MousePos = ImVec2(-FLT_MAX, -FLT_MAX) self.MousePos = ImVec2(-FLT_MAX, -FLT_MAX)
for n = 0, 2 do -- IM_COUNTOF(MouseDown) for n = 0, ImGuiMouseButton.COUNT - 1 do
self.MouseDown[n] = false self.MouseDown[n] = false
self.MouseDownDuration[n] = -1.0 self.MouseDownDuration[n] = -1.0
self.MouseDownDurationPrev[n] = -1.0 self.MouseDownDurationPrev[n] = -1.0
@@ -8841,7 +8850,6 @@ function ImGui.IsKeyPressedEx(key, flags, owner_id)
return true return true
end end
-- TODO:
-- Return untranslated names: on macOS, Cmd key will show as Ctrl, Ctrl key will show as super. -- Return untranslated names: on macOS, Cmd key will show as Ctrl, Ctrl key will show as super.
function ImGui.GetKeyChordName(key_chord) function ImGui.GetKeyChordName(key_chord)
local key = bit32.band(key_chord, bit32.bnot(ImGuiMod_Mask_)) local key = bit32.band(key_chord, bit32.bnot(ImGuiMod_Mask_))
@@ -9290,7 +9298,7 @@ end
--- @return bool --- @return bool
function ImGui.IsAnyMouseDown() function ImGui.IsAnyMouseDown()
local g = GImGui local g = GImGui
for n = 0, 2 do -- IM_COUNTOF(g.IO.MouseDown) - 1 for n = 0, ImGuiMouseButton.COUNT - 1 do
if g.IO.MouseDown[n] then if g.IO.MouseDown[n] then
return true return true
end end
@@ -9304,7 +9312,7 @@ function ImGui.IsMouseDown(button, owner_id)
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) -- IM_COUNTOF(g.IO.MouseDown) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
return g.IO.MouseDown[button] and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id) -- Should be same as IsKeyDown(MouseButtonToKey(button), owner_id), but this allows legacy code hijacking the io.Mousedown[] array. return g.IO.MouseDown[button] and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id) -- Should be same as IsKeyDown(MouseButtonToKey(button), owner_id), but this allows legacy code hijacking the io.Mousedown[] array.
end end
@@ -9324,7 +9332,7 @@ function ImGui.IsMouseClickedEx(button, flags, owner_id)
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) -- IM_COUNTOF(g.IO.MouseDown) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
if not g.IO.MouseDown[button] then -- In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership) if not g.IO.MouseDown[button] then -- In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership)
return false return false
@@ -9355,7 +9363,7 @@ function ImGui.IsMouseReleased(button, owner_id)
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) -- IM_COUNTOF(g.IO.MouseDown) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
return g.IO.MouseReleased[button] and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id) -- Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id) return g.IO.MouseReleased[button] and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id) -- Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id)
end end
@@ -9368,7 +9376,7 @@ end
function ImGui.IsMouseReleasedWithDelay(button, delay) function ImGui.IsMouseReleasedWithDelay(button, delay)
if delay == nil then delay = -1.0 end if delay == nil then delay = -1.0 end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
if ImGui.IsMouseDown(button) then if ImGui.IsMouseDown(button) then
return false return false
end end
@@ -9384,14 +9392,14 @@ end
function ImGui.IsMouseDoubleClicked(button, owner_id) function ImGui.IsMouseDoubleClicked(button, owner_id)
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
return g.IO.MouseClickedCount[button] == 2 and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id) return g.IO.MouseClickedCount[button] == 2 and ImGui.TestKeyOwner(ImGui.MouseButtonToKey(button), owner_id)
end end
--- @param button ImGuiMouseButton --- @param button ImGuiMouseButton
function ImGui.GetMouseClickedCount(button) function ImGui.GetMouseClickedCount(button)
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
return g.IO.MouseClickedCount[button] return g.IO.MouseClickedCount[button]
end end
@@ -9482,7 +9490,7 @@ function ImGui.GetMouseDragDelta(button, lock_threshold)
if button == nil then button = 0 end if button == nil then button = 0 end
if lock_threshold == nil then lock_threshold = -1.0 end if lock_threshold == nil then lock_threshold = -1.0 end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
if lock_threshold < 0.0 then if lock_threshold < 0.0 then
lock_threshold = g.IO.MouseDragThreshold lock_threshold = g.IO.MouseDragThreshold
end end
@@ -9500,7 +9508,7 @@ end
function ImGui.ResetMouseDragDelta(button) function ImGui.ResetMouseDragDelta(button)
if button == nil then button = 0 end if button == nil then button = 0 end
local g = GImGui local g = GImGui
IM_ASSERT(button >= 0 and button < 3) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) -- IM_COUNTOF(g.IO.MouseDown)
-- NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr -- NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos) ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos)
end end
@@ -9945,14 +9953,13 @@ local function CalcWindowSizeAfterConstraint(window, size_desired)
new_size.x = (cr.Min.x >= 0 and cr.Max.x >= 0) and ImClamp(new_size.x, cr.Min.x, cr.Max.x) or window.SizeFull.x new_size.x = (cr.Min.x >= 0 and cr.Max.x >= 0) and ImClamp(new_size.x, cr.Min.x, cr.Max.x) or window.SizeFull.x
new_size.y = (cr.Min.y >= 0 and cr.Max.y >= 0) and ImClamp(new_size.y, cr.Min.y, cr.Max.y) or window.SizeFull.y new_size.y = (cr.Min.y >= 0 and cr.Max.y >= 0) and ImClamp(new_size.y, cr.Min.y, cr.Max.y) or window.SizeFull.y
if g.NextWindowData.SizeCallback then if g.NextWindowData.SizeCallback then
local data = {} -- TODO: ImGuiSizeCallbackData local data = ImGuiSizeCallbackData()
data.UserData = g.NextWindowData.SizeCallbackUserData data.UserData = g.NextWindowData.SizeCallbackUserData
data.Pos = ImVec2(window.Pos.x, window.Pos.y) ImVec2_Copy(data.Pos, window.Pos)
data.CurrentSize = ImVec2(window.SizeFull.x, window.SizeFull.y) ImVec2_Copy(data.CurrentSize, window.SizeFull)
data.DesiredSize = ImVec2(new_size.x, new_size.y) ImVec2_Copy(data.DesiredSize, new_size)
g.NextWindowData.SizeCallback(data) g.NextWindowData.SizeCallback(data)
new_size.x = data.DesiredSize.x ImVec2_Copy(new_size, data.DesiredSize)
new_size.y = data.DesiredSize.y
end end
new_size.x = IM_TRUNC(new_size.x) new_size.x = IM_TRUNC(new_size.x)
new_size.y = IM_TRUNC(new_size.y) new_size.y = IM_TRUNC(new_size.y)
@@ -11161,6 +11168,7 @@ local function SetCurrentWindow(window)
local g = GImGui local g = GImGui
--- @diagnostic disable-next-line --- @diagnostic disable-next-line
g.CurrentWindow = window g.CurrentWindow = window
g.StackSizesInBeginForCurrentWindow = window and g.CurrentWindowStack:back().StackSizesInBegin or nil
g.CurrentTable = (window and window.DC.CurrentTableIdx ~= -1) and g.Tables:GetByIndex(window.DC.CurrentTableIdx) or nil g.CurrentTable = (window and window.DC.CurrentTableIdx ~= -1) and g.Tables:GetByIndex(window.DC.CurrentTableIdx) or nil
if window then if window then
@@ -11177,7 +11185,6 @@ local function SetCurrentWindow(window)
end end
end end
-- TODO:
function ImGui.GcCompactTransientMiscBuffers() function ImGui.GcCompactTransientMiscBuffers()
local g = GImGui local g = GImGui
g.ItemFlagsStack:clear() g.ItemFlagsStack:clear()
@@ -13399,7 +13406,6 @@ local function FindHoveredWindowEx(pos, find_first_and_in_any_viewport)
return hovered_window, hovered_window_under_moving_window return hovered_window, hovered_window_under_moving_window
end end
-- TODO:
-- The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) -- The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
function ImGui.UpdateHoveredWindowAndCaptureFlags(mouse_pos) function ImGui.UpdateHoveredWindowAndCaptureFlags(mouse_pos)
local g = GImGui local g = GImGui
@@ -13436,7 +13442,7 @@ function ImGui.UpdateHoveredWindowAndCaptureFlags(mouse_pos)
local mouse_earliest_down = -1 local mouse_earliest_down = -1
local mouse_any_down = false local mouse_any_down = false
for i = 0, 2 do -- IM_COUNTOF(io.MouseDown) for i = 0, ImGuiMouseButton.COUNT - 1 do
if io.MouseClicked[i] then if io.MouseClicked[i] then
io.MouseDownOwned[i] = (g.HoveredWindow ~= nil) or has_open_popup io.MouseDownOwned[i] = (g.HoveredWindow ~= nil) or has_open_popup
io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow ~= nil) or has_open_modal io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow ~= nil) or has_open_modal
@@ -13525,7 +13531,7 @@ function ImGui.UpdateKeyboardInputs()
end end
-- Update aliases -- Update aliases
for n = 0, 2 do -- TODO: ImGuiMouseButton.COUNT - 1 for n = 0, ImGuiMouseButton.COUNT - 1 do
ImGui.UpdateAliasKey(ImGui.MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] and 1.0 or 0.0) ImGui.UpdateAliasKey(ImGui.MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] and 1.0 or 0.0)
end end
ImGui.UpdateAliasKey(ImGuiKey.MouseWheelX, io.MouseWheelH ~= 0.0, io.MouseWheelH) ImGui.UpdateAliasKey(ImGuiKey.MouseWheelX, io.MouseWheelH ~= 0.0, io.MouseWheelH)
@@ -13633,7 +13639,7 @@ function ImGui.UpdateMouseInputs()
g.NavHighlightItemUnderNav = false g.NavHighlightItemUnderNav = false
end end
for i = 0, 2 do -- IM_COUNTOF(io.MouseDown) for i = 0, ImGuiMouseButton.COUNT - 1 do
io.MouseClicked[i] = io.MouseDown[i] and (io.MouseDownDuration[i] < 0.0) io.MouseClicked[i] = io.MouseDown[i] and (io.MouseDownDuration[i] < 0.0)
io.MouseClickedCount[i] = 0 -- Will be filled below io.MouseClickedCount[i] = 0 -- Will be filled below
io.MouseReleased[i] = not io.MouseDown[i] and (io.MouseDownDuration[i] >= 0.0) io.MouseReleased[i] = not io.MouseDown[i] and (io.MouseDownDuration[i] >= 0.0)
@@ -14585,7 +14591,6 @@ function ImGui.EndFrame()
ImGui.CallContextHooks(g, ImGuiContextHookType.EndFramePost) ImGui.CallContextHooks(g, ImGuiContextHookType.EndFramePost)
end end
-- TODO:
-- Prepare the data for rendering so you can call GetDrawData() -- Prepare the data for rendering so you can call GetDrawData()
-- (As with anything within the ImGui:: namespace this doesn't touch your GPU or graphics API at all: -- (As with anything within the ImGui:: namespace this doesn't touch your GPU or graphics API at all:
-- it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend) -- it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend)
@@ -16452,7 +16457,7 @@ end
function ImGui.PopFocusScope() function ImGui.PopFocusScope()
local g = GImGui local g = GImGui
-- TODO: IM_ASSERT_USER_ERROR_RET(g.FocusScopeStack.Size > g.StackSizesInBeginForCurrentWindow.SizeOfFocusScopeStack, "Calling PopFocusScope() too many times!") IM_ASSERT_USER_ERROR_RET(g.FocusScopeStack.Size > g.StackSizesInBeginForCurrentWindow.SizeOfFocusScopeStack, "Calling PopFocusScope() too many times!")
g.FocusScopeStack:pop_back() g.FocusScopeStack:pop_back()
if g.FocusScopeStack.Size > 0 then if g.FocusScopeStack.Size > 0 then
g.CurrentFocusScopeId = g.FocusScopeStack:back().ID g.CurrentFocusScopeId = g.FocusScopeStack:back().ID
@@ -19467,9 +19472,10 @@ function ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
window.DC.IsSetPos = false window.DC.IsSetPos = false
if window.DC.CursorPos.x <= window.DC.CursorMaxPos.x and window.DC.CursorPos.y <= window.DC.CursorMaxPos.y then return end if window.DC.CursorPos.x <= window.DC.CursorMaxPos.x and window.DC.CursorPos.y <= window.DC.CursorMaxPos.y then return end
if window.SkipItems then return end if window.SkipItems then return end
-- Upstream asserts (user error): "Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. IM_ASSERT_USER_ERROR(false, "Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries.\nPlease submit an item e.g. Dummy() afterwards in order to grow window/parent boundaries.")
-- Please submit an item e.g. Dummy() afterwards". We keep the old, tolerant behavior instead of erroring.
window.DC.CursorMaxPos = ImMax(window.DC.CursorMaxPos, window.DC.CursorPos) -- For reference, the old behavior was essentially:
--window.DC.CursorMaxPos = ImMax(window.DC.CursorMaxPos, window.DC.CursorPos)
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -22456,11 +22462,12 @@ function ImGui.ShowMetricsWindow(p_open)
if ImGui.IsMousePosValid() then ImGui.Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y) else ImGui.Text("Mouse pos: <INVALID>") end if ImGui.IsMousePosValid() then ImGui.Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y) else ImGui.Text("Mouse pos: <INVALID>") end
ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y) ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y)
ImGui.Text("Mouse down:") ImGui.Text("Mouse down:")
for i = 0, 2 do if ImGui.IsMouseDown(i) then ImGui.SameLine(); ImGui.Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]) end end local count = ImGuiMouseButton.COUNT -- IM_COUNTOF(io.MouseDown)
for i = 0, count - 1 do if ImGui.IsMouseDown(i) then ImGui.SameLine(); ImGui.Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]) end end
ImGui.Text("Mouse clicked:") ImGui.Text("Mouse clicked:")
for i = 0, 2 do if ImGui.IsMouseClicked(i) then ImGui.SameLine(); ImGui.Text("b%d (%d)", i, io.MouseClickedCount[i]) end end for i = 0, count - 1 do if ImGui.IsMouseClicked(i) then ImGui.SameLine(); ImGui.Text("b%d (%d)", i, io.MouseClickedCount[i]) end end
ImGui.Text("Mouse released:") ImGui.Text("Mouse released:")
for i = 0, 2 do if ImGui.IsMouseReleased(i) then ImGui.SameLine(); ImGui.Text("b%d", i) end end for i = 0, count - 1 do if ImGui.IsMouseReleased(i) then ImGui.SameLine(); ImGui.Text("b%d", i) end end
ImGui.Text("Mouse wheel: %.1f", io.MouseWheel) ImGui.Text("Mouse wheel: %.1f", io.MouseWheel)
ImGui.Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer) ImGui.Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer)
ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource)) ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource))
+19 -12
View File
@@ -1520,7 +1520,8 @@ S.DemoWindowWidgetsDataTypes = {
u16_v = 65535, u16_v = 65535,
s32_v = -1, s32_v = -1,
u32_v = 4294967295, -- (ImU32)-1 u32_v = 4294967295, -- (ImU32)-1
-- [Port] s64_v / u64_v: 64-bit integer types are not supported (Lua numbers are doubles) s64_v = -1,
u64_v = 18446744073709551615, -- (ImU64)-1 [Port] Lua numbers are doubles: 64-bit values are exact only within +-2^53
f32_v = 0.123, f32_v = 0.123,
f64_v = 90000.01234567890123456789, f64_v = 90000.01234567890123456789,
drag_clamp = false, drag_clamp = false,
@@ -1551,14 +1552,15 @@ function DemoWindowWidgetsDataTypes()
-- Setup limits (as helper variables so we can take their address, as explained above) -- Setup limits (as helper variables so we can take their address, as explained above)
-- Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2. -- Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
-- [Port] LLONG_MIN/LLONG_MAX/ULLONG_MAX fallback block dropped: no 64-bit integer types local LLONG_MIN, LLONG_MAX, ULLONG_MAX = -9223372036854775808, 9223372036854775807, 18446744073709551615 -- [Port] doubles (LLONG_MAX/ULLONG_MAX round up)
local s8_zero, s8_one, s8_fifty, s8_min, s8_max = 0, 1, 50, -128, 127 local s8_zero, s8_one, s8_fifty, s8_min, s8_max = 0, 1, 50, -128, 127
local u8_zero, u8_one, u8_fifty, u8_min, u8_max = 0, 1, 50, 0, 255 local u8_zero, u8_one, u8_fifty, u8_min, u8_max = 0, 1, 50, 0, 255
local s16_zero, s16_one, s16_fifty, s16_min, s16_max = 0, 1, 50, -32768, 32767 local s16_zero, s16_one, s16_fifty, s16_min, s16_max = 0, 1, 50, -32768, 32767
local u16_zero, u16_one, u16_fifty, u16_min, u16_max = 0, 1, 50, 0, 65535 local u16_zero, u16_one, u16_fifty, u16_min, u16_max = 0, 1, 50, 0, 65535
local s32_zero, s32_one, s32_fifty, s32_min, s32_max, s32_hi_a, s32_hi_b = 0, 1, 50, -1073741824, 1073741823, 1073741823 - 100, 1073741823 -- INT_MIN/2, INT_MAX/2 local s32_zero, s32_one, s32_fifty, s32_min, s32_max, s32_hi_a, s32_hi_b = 0, 1, 50, -1073741824, 1073741823, 1073741823 - 100, 1073741823 -- INT_MIN/2, INT_MAX/2
local u32_zero, u32_one, u32_fifty, u32_min, u32_max, u32_hi_a, u32_hi_b = 0, 1, 50, 0, 2147483647, 2147483647 - 100, 2147483647 -- UINT_MAX/2 local u32_zero, u32_one, u32_fifty, u32_min, u32_max, u32_hi_a, u32_hi_b = 0, 1, 50, 0, 2147483647, 2147483647 - 100, 2147483647 -- UINT_MAX/2
-- [Port] s64_* / u64_* limits: ImGuiDataType.S64/U64 are not supported local s64_zero, s64_one, s64_fifty, s64_min, s64_max, s64_hi_a, s64_hi_b = 0, 1, 50, LLONG_MIN / 2, LLONG_MAX / 2, LLONG_MAX / 2 - 100, LLONG_MAX / 2
local u64_zero, u64_one, u64_fifty, u64_min, u64_max, u64_hi_a, u64_hi_b = 0, 1, 50, 0, ULLONG_MAX / 2, ULLONG_MAX / 2 - 100, ULLONG_MAX / 2
local f32_zero, f32_one, f32_lo_a, f32_hi_a = 0.0, 1.0, -10000000000.0, 10000000000.0 local f32_zero, f32_one, f32_lo_a, f32_hi_a = 0.0, 1.0, -10000000000.0, 10000000000.0
local f64_zero, f64_one, f64_lo_a, f64_hi_a = 0.0, 1.0, -1000000000000000.0, 1000000000000000.0 local f64_zero, f64_one, f64_lo_a, f64_hi_a = 0.0, 1.0, -1000000000000000.0, 1000000000000000.0
@@ -1580,8 +1582,8 @@ function DemoWindowWidgetsDataTypes()
s.s32_v = ImGui.DragScalar("drag s32", ImGuiDataType.S32, s.s32_v, drag_speed, drag_clamp and s32_zero or nil, drag_clamp and s32_fifty or nil) s.s32_v = ImGui.DragScalar("drag s32", ImGuiDataType.S32, s.s32_v, drag_speed, drag_clamp and s32_zero or nil, drag_clamp and s32_fifty or nil)
s.s32_v = ImGui.DragScalar("drag s32 hex", ImGuiDataType.S32, s.s32_v, drag_speed, drag_clamp and s32_zero or nil, drag_clamp and s32_fifty or nil, "0x%08X") s.s32_v = ImGui.DragScalar("drag s32 hex", ImGuiDataType.S32, s.s32_v, drag_speed, drag_clamp and s32_zero or nil, drag_clamp and s32_fifty or nil, "0x%08X")
s.u32_v = ImGui.DragScalar("drag u32", ImGuiDataType.U32, s.u32_v, drag_speed, drag_clamp and u32_zero or nil, drag_clamp and u32_fifty or nil, "%u ms") s.u32_v = ImGui.DragScalar("drag u32", ImGuiDataType.U32, s.u32_v, drag_speed, drag_clamp and u32_zero or nil, drag_clamp and u32_fifty or nil, "%u ms")
-- [Port] ImGui.DragScalar("drag s64", ImGuiDataType.S64, s64_v, ...) -- 64-bit types not supported s.s64_v = ImGui.DragScalar("drag s64", ImGuiDataType.S64, s.s64_v, drag_speed, drag_clamp and s64_zero or nil, drag_clamp and s64_fifty or nil)
-- [Port] ImGui.DragScalar("drag u64", ImGuiDataType.U64, u64_v, ...) -- 64-bit types not supported s.u64_v = ImGui.DragScalar("drag u64", ImGuiDataType.U64, s.u64_v, drag_speed, drag_clamp and u64_zero or nil, drag_clamp and u64_fifty or nil)
s.f32_v = ImGui.DragScalar("drag float", ImGuiDataType.Float, s.f32_v, 0.005, f32_zero, f32_one, "%f") s.f32_v = ImGui.DragScalar("drag float", ImGuiDataType.Float, s.f32_v, 0.005, f32_zero, f32_one, "%f")
s.f32_v = ImGui.DragScalar("drag float log", ImGuiDataType.Float, s.f32_v, 0.005, f32_zero, f32_one, "%f", ImGuiSliderFlags.Logarithmic) s.f32_v = ImGui.DragScalar("drag float log", ImGuiDataType.Float, s.f32_v, 0.005, f32_zero, f32_one, "%f", ImGuiSliderFlags.Logarithmic)
s.f64_v = ImGui.DragScalar("drag double", ImGuiDataType.Double, s.f64_v, 0.0005, f64_zero, nil, "%.10f grams") s.f64_v = ImGui.DragScalar("drag double", ImGuiDataType.Double, s.f64_v, 0.0005, f64_zero, nil, "%.10f grams")
@@ -1600,8 +1602,12 @@ function DemoWindowWidgetsDataTypes()
s.u32_v = ImGui.SliderScalar("slider u32 low", ImGuiDataType.U32, s.u32_v, u32_zero, u32_fifty,"%u") s.u32_v = ImGui.SliderScalar("slider u32 low", ImGuiDataType.U32, s.u32_v, u32_zero, u32_fifty,"%u")
s.u32_v = ImGui.SliderScalar("slider u32 high", ImGuiDataType.U32, s.u32_v, u32_hi_a, u32_hi_b, "%u") s.u32_v = ImGui.SliderScalar("slider u32 high", ImGuiDataType.U32, s.u32_v, u32_hi_a, u32_hi_b, "%u")
s.u32_v = ImGui.SliderScalar("slider u32 full", ImGuiDataType.U32, s.u32_v, u32_min, u32_max, "%u") s.u32_v = ImGui.SliderScalar("slider u32 full", ImGuiDataType.U32, s.u32_v, u32_min, u32_max, "%u")
-- [Port] "slider s64 low" / "slider s64 high" / "slider s64 full" (ImGuiDataType.S64): 64-bit types not supported s.s64_v = ImGui.SliderScalar("slider s64 low", ImGuiDataType.S64, s.s64_v, s64_zero, s64_fifty,"%lld") -- "%" PRId64
-- [Port] "slider u64 low" / "slider u64 high" / "slider u64 full" (ImGuiDataType.U64): 64-bit types not supported s.s64_v = ImGui.SliderScalar("slider s64 high", ImGuiDataType.S64, s.s64_v, s64_hi_a, s64_hi_b, "%lld")
s.s64_v = ImGui.SliderScalar("slider s64 full", ImGuiDataType.S64, s.s64_v, s64_min, s64_max, "%lld")
s.u64_v = ImGui.SliderScalar("slider u64 low", ImGuiDataType.U64, s.u64_v, u64_zero, u64_fifty,"%llu ms") -- "%" PRIu64 " ms"
s.u64_v = ImGui.SliderScalar("slider u64 high", ImGuiDataType.U64, s.u64_v, u64_hi_a, u64_hi_b, "%llu ms")
s.u64_v = ImGui.SliderScalar("slider u64 full", ImGuiDataType.U64, s.u64_v, u64_min, u64_max, "%llu ms")
s.f32_v = ImGui.SliderScalar("slider float low", ImGuiDataType.Float, s.f32_v, f32_zero, f32_one) s.f32_v = ImGui.SliderScalar("slider float low", ImGuiDataType.Float, s.f32_v, f32_zero, f32_one)
s.f32_v = ImGui.SliderScalar("slider float low log", ImGuiDataType.Float, s.f32_v, f32_zero, f32_one, "%.10f", ImGuiSliderFlags.Logarithmic) s.f32_v = ImGui.SliderScalar("slider float low log", ImGuiDataType.Float, s.f32_v, f32_zero, f32_one, "%.10f", ImGuiSliderFlags.Logarithmic)
s.f32_v = ImGui.SliderScalar("slider float high", ImGuiDataType.Float, s.f32_v, f32_lo_a, f32_hi_a, "%e") s.f32_v = ImGui.SliderScalar("slider float high", ImGuiDataType.Float, s.f32_v, f32_lo_a, f32_hi_a, "%e")
@@ -1614,7 +1620,8 @@ function DemoWindowWidgetsDataTypes()
s.u8_v = ImGui.SliderScalar("slider u8 reverse", ImGuiDataType.U8, s.u8_v, u8_max, u8_min, "%u") s.u8_v = ImGui.SliderScalar("slider u8 reverse", ImGuiDataType.U8, s.u8_v, u8_max, u8_min, "%u")
s.s32_v = ImGui.SliderScalar("slider s32 reverse", ImGuiDataType.S32, s.s32_v, s32_fifty, s32_zero, "%d") s.s32_v = ImGui.SliderScalar("slider s32 reverse", ImGuiDataType.S32, s.s32_v, s32_fifty, s32_zero, "%d")
s.u32_v = ImGui.SliderScalar("slider u32 reverse", ImGuiDataType.U32, s.u32_v, u32_fifty, u32_zero, "%u") s.u32_v = ImGui.SliderScalar("slider u32 reverse", ImGuiDataType.U32, s.u32_v, u32_fifty, u32_zero, "%u")
-- [Port] "slider s64 reverse" / "slider u64 reverse": 64-bit types not supported s.s64_v = ImGui.SliderScalar("slider s64 reverse", ImGuiDataType.S64, s.s64_v, s64_fifty, s64_zero, "%lld")
s.u64_v = ImGui.SliderScalar("slider u64 reverse", ImGuiDataType.U64, s.u64_v, u64_fifty, u64_zero, "%llu ms")
IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs") IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs")
ImGui.SeparatorText("Inputs") ImGui.SeparatorText("Inputs")
@@ -1631,8 +1638,8 @@ function DemoWindowWidgetsDataTypes()
s.s32_v = ImGui.InputScalar("input s32 hex", ImGuiDataType.S32, s.s32_v, inputs_step and s32_one or nil, nil, "%04X", flags) s.s32_v = ImGui.InputScalar("input s32 hex", ImGuiDataType.S32, s.s32_v, inputs_step and s32_one or nil, nil, "%04X", flags)
s.u32_v = ImGui.InputScalar("input u32", ImGuiDataType.U32, s.u32_v, inputs_step and u32_one or nil, nil, "%u", flags) s.u32_v = ImGui.InputScalar("input u32", ImGuiDataType.U32, s.u32_v, inputs_step and u32_one or nil, nil, "%u", flags)
s.u32_v = ImGui.InputScalar("input u32 hex", ImGuiDataType.U32, s.u32_v, inputs_step and u32_one or nil, nil, "%08X", flags) s.u32_v = ImGui.InputScalar("input u32 hex", ImGuiDataType.U32, s.u32_v, inputs_step and u32_one or nil, nil, "%08X", flags)
-- [Port] ImGui.InputScalar("input s64", ImGuiDataType.S64, ...) -- 64-bit types not supported s.s64_v = ImGui.InputScalar("input s64", ImGuiDataType.S64, s.s64_v, inputs_step and s64_one or nil, nil, nil, flags)
-- [Port] ImGui.InputScalar("input u64", ImGuiDataType.U64, ...) -- 64-bit types not supported s.u64_v = ImGui.InputScalar("input u64", ImGuiDataType.U64, s.u64_v, inputs_step and u64_one or nil, nil, nil, flags)
s.f32_v = ImGui.InputScalar("input float", ImGuiDataType.Float, s.f32_v, inputs_step and f32_one or nil, nil, nil, flags) s.f32_v = ImGui.InputScalar("input float", ImGuiDataType.Float, s.f32_v, inputs_step and f32_one or nil, nil, nil, flags)
s.f64_v = ImGui.InputScalar("input double", ImGuiDataType.Double, s.f64_v, inputs_step and f64_one or nil, nil, nil, flags) s.f64_v = ImGui.InputScalar("input double", ImGuiDataType.Double, s.f64_v, inputs_step and f64_one or nil, nil, nil, flags)
@@ -8188,10 +8195,10 @@ function DemoWindowInputs()
end end
ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y) ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y)
ImGui.Text("Mouse down:") ImGui.Text("Mouse down:")
for i = 0, 2 do if ImGui.IsMouseDown(i) then ImGui.SameLine(); ImGui.Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]) end end -- IM_COUNTOF(io.MouseDown) == 3, 0-based for i = 0, ImGuiMouseButton.COUNT - 1 do if ImGui.IsMouseDown(i) then ImGui.SameLine(); ImGui.Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]) end end -- IM_COUNTOF(io.MouseDown), 0-based
ImGui.Text("Mouse wheel: %.1f", io.MouseWheel) ImGui.Text("Mouse wheel: %.1f", io.MouseWheel)
ImGui.Text("Mouse clicked count:") ImGui.Text("Mouse clicked count:")
for i = 0, 2 do if io.MouseClickedCount[i] > 0 then ImGui.SameLine(); ImGui.Text("b%d: %d", i, io.MouseClickedCount[i]) end end for i = 0, ImGuiMouseButton.COUNT - 1 do if io.MouseClickedCount[i] > 0 then ImGui.SameLine(); ImGui.Text("b%d: %d", i, io.MouseClickedCount[i]) end end
-- We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows -- We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows
-- displaying the data for old/new backends. -- displaying the data for old/new backends.
+28 -6
View File
@@ -4144,6 +4144,16 @@ function ImGui.AddDrawListToDrawDataEx(draw_data, out_list, draw_list)
IM_ASSERT(draw_list._VtxCurrentIdx == draw_list.VtxBuffer.Size + 1) IM_ASSERT(draw_list._VtxCurrentIdx == draw_list.VtxBuffer.Size + 1)
end end
-- Resolve callback data pointers
local cb_buf = draw_list._CallbacksDataBuf
if cb_buf.Size > 0 then
for _, cmd in draw_list.CmdBuffer:iter() do
if cmd.UserCallback ~= nil and cmd.UserCallbackDataOffset ~= -1 and cmd.UserCallbackDataSize > 0 then
cmd.UserCallbackData = cb_buf.Data[cmd.UserCallbackDataOffset + 1]
end
end
end
-- Add to output list + records state in ImDrawData -- Add to output list + records state in ImDrawData
out_list:push_back(draw_list) out_list:push_back(draw_list)
draw_data.TotalVtxCount = draw_data.TotalVtxCount + draw_list.VtxBuffer.Size draw_data.TotalVtxCount = draw_data.TotalVtxCount + draw_list.VtxBuffer.Size
@@ -4250,7 +4260,6 @@ end
-- Initialize before use in a new frame. We always have a command ready in the buffer. -- Initialize before use in a new frame. We always have a command ready in the buffer.
-- In the majority of cases, you would want to call PushClipRect() and PushTexture() after this. -- In the majority of cases, you would want to call PushClipRect() and PushTexture() after this.
-- TODO:
function MT.ImDrawList:_ResetForNewFrame() function MT.ImDrawList:_ResetForNewFrame()
self._ContentClipX0 = nil -- set again by Begin() (Roblox backend scroll reuse) self._ContentClipX0 = nil -- set again by Begin() (Roblox backend scroll reuse)
if self._Splitter._Count > 1 then if self._Splitter._Count > 1 then
@@ -4272,6 +4281,7 @@ function MT.ImDrawList:_ResetForNewFrame()
self._IdxWritePtr = 1 self._IdxWritePtr = 1
self._ClipRectStack:resize(0) self._ClipRectStack:resize(0)
self._TextureStack:resize(0) self._TextureStack:resize(0)
self._CallbacksDataBuf:resize(0)
self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_) self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_)
self._Path:resize(0) self._Path:resize(0)
@@ -4292,7 +4302,7 @@ function MT.ImDrawList:_ClearFreeMemory()
self._ClipRectStack:clear() self._ClipRectStack:clear()
self._TextureStack:clear() self._TextureStack:clear()
-- self._CallbacksDataBuf:clear() self._CallbacksDataBuf:clear()
self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_) self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_)
self._Path:clear() self._Path:clear()
self._Splitter:ClearFreeMemory() self._Splitter:ClearFreeMemory()
@@ -4365,15 +4375,27 @@ function MT.ImDrawList:AddCallback(callback, userdata, userdata_size)
curr_cmd = self.CmdBuffer.Data[self.CmdBuffer.Size] curr_cmd = self.CmdBuffer.Data[self.CmdBuffer.Size]
end end
curr_cmd.UserCallback = callback curr_cmd.UserCallback = callback
-- TODO: _CallbacksDataBuf?
if userdata_size == 0 then if userdata_size == 0 then
-- Store user data directly in command (no indirection) -- Store user data directly in command (no indirection)
curr_cmd.UserCallbackData = userdata curr_cmd.UserCallbackData = userdata
curr_cmd.UserCallbackDataSize = 0
curr_cmd.UserCallbackDataOffset = -1
else else
-- Copy and store user data in a buffer
-- [Lua] No raw bytes: the "copy" is a shallow copy of a table userdata (other values are immutable and stored as is),
-- so later changes to the caller's table don't affect this command. userdata_size is only recorded.
IM_ASSERT(userdata ~= nil) IM_ASSERT(userdata ~= nil)
IM_ASSERT(userdata_size < bit32.lshift(1, 31)) IM_ASSERT(userdata_size < 2147483648) -- (1u << 31)
curr_cmd.UserCallbackData = nil -- Will be resolved during Render()
curr_cmd.UserCallbackDataSize = userdata_size
curr_cmd.UserCallbackDataOffset = self._CallbacksDataBuf.Size -- 0-based
local copy = userdata
if type(userdata) == "table" then
copy = {}
for k, v in pairs(userdata) do copy[k] = v end
setmetatable(copy, getmetatable(userdata))
end
self._CallbacksDataBuf:push_back(copy) -- memcpy()
end end
self:AddDrawCmd() -- Force a new command after us (see comment below) self:AddDrawCmd() -- Force a new command after us (see comment below)
+44 -23
View File
@@ -75,6 +75,14 @@ function ImU32(val) return bitAnd(val, 0xFFFFFFFF) end
--- @return ImS32 --- @return ImS32
function ImS32(val) return bitAnd(val, 0xFFFFFFFF) end function ImS32(val) return bitAnd(val, 0xFFFFFFFF) end
-- [Luau] 64-bit integers are stored in doubles (exact only within +-2^53): the cast just truncates toward zero like a C double->int64 cast.
--- @param val number
--- @return ImS64
function ImS64(val) if val >= 0 then return math.floor(val) end return -math.floor(-val) end
--- @param val number
--- @return ImU64
function ImU64(val) if val >= 0 then return math.floor(val) end return -math.floor(-val) end
--- @alias float number --- @alias float number
--- @class double : number --- @class double : number
@@ -155,15 +163,17 @@ ImGuiDataType =
U16 = 3, -- unsigned short U16 = 3, -- unsigned short
S32 = 4, -- int S32 = 4, -- int
U32 = 5, -- unsigned int U32 = 5, -- unsigned int
Float = 6, -- float S64 = 6, -- long long / __int64 -- [Luau] stored in a double: exact only within +-2^53
Double = 7, -- double U64 = 7, -- unsigned long long / unsigned __int64 -- [Luau] stored in a double: exact only within 0..2^53
Bool = 8, -- bool (provided for user convenience, not supported by scalar widgets) Float = 8, -- float
String = 9, -- string (provided for user convenience, not supported by scalar widgets) Double = 9, -- double
COUNT = 10 Bool = 10, -- bool (provided for user convenience, not supported by scalar widgets)
String = 11, -- string (provided for user convenience, not supported by scalar widgets)
COUNT = 12
} }
-- Extend ImGuiDataType_ -- Extend ImGuiDataType_
ImGuiDataType.Pointer = 11 -- [internal] ImGuiDataType.Pointer = ImGuiDataType.COUNT -- [internal]
ImGuiDataType.ID = 12 -- [internal] ImGuiDataType.ID = ImGuiDataType.COUNT + 1 -- [internal]
ImTextureID_Invalid = -1 ImTextureID_Invalid = -1
@@ -673,7 +683,7 @@ function ImDrawList(data)
_Splitter = ImDrawListSplitter(), -- [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) _Splitter = ImDrawListSplitter(), -- [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
_ClipRectStack = ImVector(), -- [Internal] _ClipRectStack = ImVector(), -- [Internal]
_TextureStack = ImVector(), -- [Internal] _TextureStack = ImVector(), -- [Internal]
_CallbacksDataBuf = nil, -- [Internal] _CallbacksDataBuf = ImVector(), -- [Internal] [Lua] copies of AddCallback() userdata (userdata_size > 0)
_DrawFlagsStack = ImVector(), -- [Internal] ImSmallStack_<ImDrawFlags,3>: capacity checked by PushDrawFlag() _DrawFlagsStack = ImVector(), -- [Internal] ImSmallStack_<ImDrawFlags,3>: capacity checked by PushDrawFlag()
_FringeScale = 1.0, -- [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content -- [Luau] 1.0 instead of memset 0 so a list used before _SetPixelDensity() still works _FringeScale = 1.0, -- [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content -- [Luau] 1.0 instead of memset 0 so a list used before _SetPixelDensity() still works
_InvFringeScale = 1.0, -- [internal] 1.0 / _FringeScale // FIXME: Consider renaming to _PixelDensity. _InvFringeScale = 1.0, -- [internal] 1.0 / _FringeScale // FIXME: Consider renaming to _PixelDensity.
@@ -1258,7 +1268,7 @@ function ImGuiIO()
MouseDelta = ImVec2(), -- Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. MouseDelta = ImVec2(), -- Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
MouseDown = {[0] = false, [1] = false, [2] = false}, -- Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton.COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. MouseDown = {[0] = false, [1] = false, [2] = false, [3] = false, [4] = false}, -- Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton.COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
MouseWheel = 0, -- Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold Shift to turn vertical scroll into horizontal scroll. MouseWheel = 0, -- Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold Shift to turn vertical scroll into horizontal scroll.
MouseWheelH = 0, -- Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends. MouseWheelH = 0, -- Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
@@ -1360,23 +1370,23 @@ function ImGuiIO()
-- (you can visualize and interact with all options in 'Demo->Configuration') -- (you can visualize and interact with all options in 'Demo->Configuration')
MouseDrawCursor = false, -- = false -- Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. MouseDrawCursor = false, -- = false -- Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
MouseClicked = {[0] = false, [1] = false, [2] = false}, -- Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0) MouseClicked = {[0] = false, [1] = false, [2] = false, [3] = false, [4] = false}, -- Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0)
MouseReleased = {[0] = false, [1] = false, [2] = false}, -- Mouse button went from Down to !Down MouseReleased = {[0] = false, [1] = false, [2] = false, [3] = false, [4] = false}, -- Mouse button went from Down to !Down
MouseClickedCount = {[0] = 0, [1] = 0, [2] = 0}, -- == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down MouseClickedCount = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0}, -- == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down
MouseClickedLastCount = {[0] = 0, [1] = 0, [2] = 0}, -- Count successive number of clicks. Stays valid after mouse release. Reset after another click is done. MouseClickedLastCount = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0}, -- Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
MouseDownDuration = {[0] = -1, [1] = -1, [2] = -1}, -- Duration the mouse button has been down (0.0f == just clicked) MouseDownDuration = {[0] = -1, [1] = -1, [2] = -1, [3] = -1, [4] = -1}, -- Duration the mouse button has been down (0.0f == just clicked)
MouseDownDurationPrev = {[0] = -1, [1] = -1, [2] = -1}, -- Previous time the mouse button has been down MouseDownDurationPrev = {[0] = -1, [1] = -1, [2] = -1, [3] = -1, [4] = -1}, -- Previous time the mouse button has been down
MouseDragMaxDistanceAbs = {[0] = ImVec2(), [1] = ImVec2(), [2] = ImVec2()}, -- Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point MouseDragMaxDistanceAbs = {[0] = ImVec2(), [1] = ImVec2(), [2] = ImVec2(), [3] = ImVec2(), [4] = ImVec2()}, -- Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
MouseDragMaxDistanceSqr = {[0] = 0, [1] = 0, [2] = 0}, -- Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds) MouseDragMaxDistanceSqr = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0}, -- Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
MouseDownOwned = {[0] = nil, [1] = nil, [2] = nil}, -- Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. MouseDownOwned = {[0] = nil, [1] = nil, [2] = nil, [3] = nil, [4] = nil}, -- Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
MouseDownOwnedUnlessPopupClose = {[0] = nil, [1] = nil, [2] = nil}, -- Track if button was clicked inside a dear imgui window. MouseDownOwnedUnlessPopupClose = {[0] = nil, [1] = nil, [2] = nil, [3] = nil, [4] = nil}, -- Track if button was clicked inside a dear imgui window.
MouseClickedTime = {[0] = 0, [1] = 0, [2] = 0}, -- Time of last click (used to figure out double-click) MouseClickedTime = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0}, -- Time of last click (used to figure out double-click)
MouseReleasedTime = {[0] = 0, [1] = 0, [2] = 0}, -- Time of last released (rarely used! but useful to handle delayed single-click when trying to disambiguate them from double-click). MouseReleasedTime = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0}, -- Time of last released (rarely used! but useful to handle delayed single-click when trying to disambiguate them from double-click).
MouseClickedPos = {[0] = ImVec2(), [1] = ImVec2(), [2] = ImVec2()}, -- Position at time of clicking MouseClickedPos = {[0] = ImVec2(), [1] = ImVec2(), [2] = ImVec2(), [3] = ImVec2(), [4] = ImVec2()}, -- Position at time of clicking
MouseDoubleClicked = {[0] = false, [1] = false, [2] = false}, -- Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2) MouseDoubleClicked = {[0] = false, [1] = false, [2] = false, [3] = false, [4] = false}, -- Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2)
-- Inputs Behaviors -- Inputs Behaviors
-- (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle) -- (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
@@ -2777,6 +2787,17 @@ ImGuiTableBgTarget = { None = 0, RowBg0 = 1, RowBg1 = 2, CellBg = 3 }
--- @enum ImGuiSortDirection --- @enum ImGuiSortDirection
ImGuiSortDirection = { None = 0, Ascending = 1, Descending = 2 } ImGuiSortDirection = { None = 0, Ascending = 1, Descending = 2 }
-- Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin().
-- NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough.
--- @class ImGuiSizeCallbackData
--- @field UserData any Read-only. What user passed to SetNextWindowSizeConstraints(). Generally store an integer or float in here.
--- @field Pos ImVec2 Read-only. Window position, for reference.
--- @field CurrentSize ImVec2 Read-only. Current window size.
--- @field DesiredSize ImVec2 Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
--- @return ImGuiSizeCallbackData
function ImGuiSizeCallbackData()
return { UserData = nil, Pos = ImVec2(), CurrentSize = ImVec2(), DesiredSize = ImVec2() }
end
-- Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload() -- Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload()
+140 -48
View File
@@ -54,6 +54,11 @@ local IM_S32_MIN = INT_MIN -- (-2147483647 - 1), (0x80000000);
local IM_S32_MAX = INT_MAX -- (2147483647), (0x7FFFFFFF) local IM_S32_MAX = INT_MAX -- (2147483647), (0x7FFFFFFF)
local IM_U32_MIN = 0 local IM_U32_MIN = 0
local IM_U32_MAX = UINT_MAX -- (0xFFFFFFFF) local IM_U32_MAX = UINT_MAX -- (0xFFFFFFFF)
-- [Luau] 64-bit limits as doubles: IM_S64_MAX/IM_U64_MAX round up to 2^63/2^64 (values are exact only within +-2^53)
local IM_S64_MIN = -9223372036854775808 -- (-9223372036854775807ll - 1ll)
local IM_S64_MAX = 9223372036854775807 -- (9223372036854775807ll)
local IM_U64_MIN = 0
local IM_U64_MAX = 18446744073709551615 -- (0xFFFFFFFFFFFFFFFFull)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- [SECTION] Widgets: Text, etc. -- [SECTION] Widgets: Text, etc.
@@ -786,8 +791,9 @@ function ImGui.ButtonEx(label, size_arg, flags)
ImGui.RenderNavCursor(bb, id) ImGui.RenderNavCursor(bb, id)
ImGui.RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding) ImGui.RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding)
-- if (g.LogEnabled) if g.LogEnabled then
-- LogSetNextTextDecoration("[", "]"); ImGui.LogSetNextTextDecoration("[", "]")
end
local text_min, text_max = ButtonEx_text_min, ButtonEx_text_max -- [Luau] scratch: RenderTextClipped() only reads them local text_min, text_max = ButtonEx_text_min, ButtonEx_text_max -- [Luau] scratch: RenderTextClipped() only reads them
text_min.x = bb.Min.x + frame_padding.x; text_min.y = bb.Min.y + frame_padding.y text_min.x = bb.Min.x + frame_padding.x; text_min.y = bb.Min.y + frame_padding.y
text_max.x = bb.Max.x - frame_padding.x; text_max.y = bb.Max.y - frame_padding.y text_max.x = bb.Max.x - frame_padding.x; text_max.y = bb.Max.y - frame_padding.y
@@ -1369,7 +1375,7 @@ function ImGui.Checkbox(label, v)
end end
if g.LogEnabled then if g.LogEnabled then
-- ImGui.LogRenderedText(label_pos, mixed_value and "[~]" or (v and "[x]" or "[ ]")) ImGui.LogRenderedText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), mixed_value and "[~]" or (v and "[x]" or "[ ]")) -- label_pos
end end
if is_visible and label_size.x > 0.0 then if is_visible and label_size.x > 0.0 then
@@ -1466,7 +1472,7 @@ function ImGui.RadioButtonEx(label, active)
end end
local label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y) local label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y)
if g.LogEnabled then if g.LogEnabled then
-- ImGui.LogRenderedText(label_pos, active and "(x)" or "( )") ImGui.LogRenderedText(label_pos, active and "(x)" or "( )")
end end
if label_size.x > 0.0 then if label_size.x > 0.0 then
ImGui.RenderText(label_pos, label, 1, label_end, false) ImGui.RenderText(label_pos, label, 1, label_end, false)
@@ -1788,7 +1794,7 @@ function ImGui.SeparatorEx(flags, thickness)
-- Draw -- Draw
window.DrawList:AddRectFilled(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.Separator)) window.DrawList:AddRectFilled(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.Separator))
if g.LogEnabled then if g.LogEnabled then
ImGui.LogRenderedText(bb.Min, "--------------------------------") ImGui.LogRenderedText(bb.Min, "--------------------------------\n")
end end
end end
@@ -2347,6 +2353,8 @@ local GDataTypeInfo = {
ImGuiDataTypeInfo(2, "U16", "%u", "%u"), ImGuiDataTypeInfo(2, "U16", "%u", "%u"),
ImGuiDataTypeInfo(4, "S32", "%d", "%d"), -- ImGuiDataType.S32 ImGuiDataTypeInfo(4, "S32", "%d", "%d"), -- ImGuiDataType.S32
ImGuiDataTypeInfo(4, "U32", "%u", "%u"), ImGuiDataTypeInfo(4, "U32", "%u", "%u"),
ImGuiDataTypeInfo(8, "S64", "%lld", "%lld"), -- ImGuiDataType.S64
ImGuiDataTypeInfo(8, "U64", "%llu", "%llu"),
ImGuiDataTypeInfo(4, "float", "%.3f", "%f"), -- ImGuiDataType.Float ImGuiDataTypeInfo(4, "float", "%.3f", "%f"), -- ImGuiDataType.Float
ImGuiDataTypeInfo(8, "double", "%f", "%lf"), -- ImGuiDataType.Double ImGuiDataTypeInfo(8, "double", "%f", "%lf"), -- ImGuiDataType.Double
ImGuiDataTypeInfo(1, "bool", "%d", "%d"), -- ImGuiDataType.Bool ImGuiDataTypeInfo(1, "bool", "%d", "%d"), -- ImGuiDataType.Bool
@@ -2359,33 +2367,64 @@ function ImGui.DataTypeGetInfo(data_type)
return GDataTypeInfo[data_type + 1] return GDataTypeInfo[data_type + 1]
end end
-- [Luau] string.format() has no length modifiers (%lld, %I64d...) and formats negative numbers as 64-bit for %u/%x/%X/%o:
-- strip modifiers and re-apply C's integer promotion/two's complement for signed types.
local DataTypeFormatStringCached do
local fmt_info_memo = {} -- format -> { stripped format, is unsigned conversion }
local function GetFormatInfo(format)
local info = fmt_info_memo[format]
if info == nil then
local stripped = string.gsub(string.gsub(format, "(%%[-+ #0']*%d*%.?%d*)[hlLqjzt]+", "%1"), "(%%[-+ #0']*%d*%.?%d*)I64", "%1")
local conv = string.match(stripped, "%%[-+ #0']*%d*%.?%d*([diouxXc])")
info = { stripped, conv == "u" or conv == "x" or conv == "X" or conv == "o" }
fmt_info_memo[format] = info
end
return info
end
--- Lua-string version of DataTypeFormatString() (memoized), used for display.
--- @param data_type ImGuiDataType
--- @param data number
--- @param format string
--- @return string
function DataTypeFormatStringCached(data_type, data, format)
if data_type == ImGuiDataType.Float or data_type == ImGuiDataType.Double then
return FormatCached(format, data)
end
local info = GetFormatInfo(format)
if data_type == ImGuiDataType.S8 then data = (ImS8)(data)
elseif data_type == ImGuiDataType.U8 then data = (ImU8)(data)
elseif data_type == ImGuiDataType.S16 then data = (ImS16)(data)
elseif data_type == ImGuiDataType.U16 then data = (ImU16)(data)
elseif data_type == ImGuiDataType.S32 then -- (signed values are already stored signed)
elseif data_type == ImGuiDataType.U32 then data = (ImU32)(data)
elseif data_type == ImGuiDataType.S64 or data_type == ImGuiDataType.U64 then
-- (string.format() already prints negative numbers as 64-bit two's complement for %u/%x/%X/%o)
if info[2] then
if data >= 18446744073709551616 then data = -1 end -- (ImU64)-1 rounds to 2^64 in a double: print ULLONG_MAX
elseif data >= 9223372036854775808 then
data = 9223372036854774784 -- largest double below 2^63 (LLONG_MAX isn't representable)
end
return FormatCached(info[1], data)
else
IM_ASSERT(false)
end
if data < 0 and info[2] then data = data + 4294967296 end -- Signedness doesn't matter when pushing integer arguments
return FormatCached(info[1], data)
end
end
--- @param buf char[] --- @param buf char[]
--- @param buf_size int --- @param buf_size int
--- @param data_type ImGuiDataType --- @param data_type ImGuiDataType
--- @param data number --- @param data number
--- @param format string --- @param format string
--- @return int
function ImGui.DataTypeFormatString(buf, buf_size, data_type, data, format) function ImGui.DataTypeFormatString(buf, buf_size, data_type, data, format)
local str local str = DataTypeFormatStringCached(data_type, data, format)
if data_type == ImGuiDataType.S32 then local len = ImMin(#str, buf_size - 1) -- ImFormatString(): truncate and return the written length
str = ImFormatString(format, (ImS32)(data)) ImStd.ImStrncpy(buf, 1, { string.byte(str, 1, len) }, 1, len + 1)
elseif data_type == ImGuiDataType.U32 then return len
str = ImFormatString(format, (ImU32)(data))
elseif data_type == ImGuiDataType.Float then
str = ImFormatString(format, data)
elseif data_type == ImGuiDataType.Double then
str = ImFormatString(format, data)
elseif data_type == ImGuiDataType.S8 then
str = ImFormatString(format, (ImS8)(data))
elseif data_type == ImGuiDataType.U8 then
str = ImFormatString(format, (ImU8)(data))
elseif data_type == ImGuiDataType.S16 then
str = ImFormatString(format, (ImS16)(data))
elseif data_type == ImGuiDataType.U16 then
str = ImFormatString(format, (ImU16)(data))
else
IM_ASSERT(false)
end
ImStd.ImStrncpy(buf, 1, { string.byte(str, 1, #str) }, 1, ImMin(#str + 1, buf_size)) -- TODO: update this when new ImFormatString is implemented
end end
--- @param data_type ImGuiDataType --- @param data_type ImGuiDataType
@@ -2431,6 +2470,18 @@ function ImGui.DataTypeApplyOp(data_type, op, arg1, arg2)
elseif op == 45 then elseif op == 45 then
return ImSubClampOverflow(arg1, arg2, IM_U32_MIN, IM_U32_MAX) return ImSubClampOverflow(arg1, arg2, IM_U32_MIN, IM_U32_MAX)
end end
elseif data_type == ImGuiDataType.S64 then
if op == 43 then
return ImAddClampOverflow(arg1, arg2, IM_S64_MIN, IM_S64_MAX)
elseif op == 45 then
return ImSubClampOverflow(arg1, arg2, IM_S64_MIN, IM_S64_MAX)
end
elseif data_type == ImGuiDataType.U64 then
if op == 43 then
return ImAddClampOverflow(arg1, arg2, IM_U64_MIN, IM_U64_MAX)
elseif op == 45 then
return ImSubClampOverflow(arg1, arg2, IM_U64_MIN, IM_U64_MAX)
end
elseif data_type == ImGuiDataType.Float then elseif data_type == ImGuiDataType.Float then
if op == 43 then if op == 43 then
return arg1 + arg2 return arg1 + arg2
@@ -2534,6 +2585,8 @@ function ImGui.DataTypeCompare(data_type, arg1, arg2)
elseif data_type == ImGuiDataType.U16 then return DataTypeCompareT((ImU16)(arg1), (ImU16)(arg2)) elseif data_type == ImGuiDataType.U16 then return DataTypeCompareT((ImU16)(arg1), (ImU16)(arg2))
elseif data_type == ImGuiDataType.S32 then return DataTypeCompareT((ImS32)(arg1), (ImS32)(arg2)) elseif data_type == ImGuiDataType.S32 then return DataTypeCompareT((ImS32)(arg1), (ImS32)(arg2))
elseif data_type == ImGuiDataType.U32 then return DataTypeCompareT((ImU32)(arg1), (ImU32)(arg2)) elseif data_type == ImGuiDataType.U32 then return DataTypeCompareT((ImU32)(arg1), (ImU32)(arg2))
elseif data_type == ImGuiDataType.S64 then return DataTypeCompareT((ImS64)(arg1), (ImS64)(arg2))
elseif data_type == ImGuiDataType.U64 then return DataTypeCompareT((ImU64)(arg1), (ImU64)(arg2))
elseif data_type == ImGuiDataType.Float then return DataTypeCompareT(arg1, arg2) elseif data_type == ImGuiDataType.Float then return DataTypeCompareT(arg1, arg2)
elseif data_type == ImGuiDataType.Double then return DataTypeCompareT(arg1, arg2) elseif data_type == ImGuiDataType.Double then return DataTypeCompareT(arg1, arg2)
end end
@@ -2564,6 +2617,8 @@ function ImGui.DataTypeClamp(data_type, data, min, max)
elseif data_type == ImGuiDataType.U16 then return DataTypeClampT((ImU16)(data), min and (ImU16)(min), max and (ImU16)(max)) elseif data_type == ImGuiDataType.U16 then return DataTypeClampT((ImU16)(data), min and (ImU16)(min), max and (ImU16)(max))
elseif data_type == ImGuiDataType.S32 then return DataTypeClampT((ImS32)(data), min and (ImS32)(min), max and (ImS32)(max)) elseif data_type == ImGuiDataType.S32 then return DataTypeClampT((ImS32)(data), min and (ImS32)(min), max and (ImS32)(max))
elseif data_type == ImGuiDataType.U32 then return DataTypeClampT((ImU32)(data), min and (ImU32)(min), max and (ImU32)(max)) elseif data_type == ImGuiDataType.U32 then return DataTypeClampT((ImU32)(data), min and (ImU32)(min), max and (ImU32)(max))
elseif data_type == ImGuiDataType.S64 then return DataTypeClampT((ImS64)(data), min and (ImS64)(min), max and (ImS64)(max))
elseif data_type == ImGuiDataType.U64 then return DataTypeClampT((ImU64)(data), min and (ImU64)(min), max and (ImU64)(max))
elseif data_type == ImGuiDataType.Float then return DataTypeClampT(data, min, max) elseif data_type == ImGuiDataType.Float then return DataTypeClampT(data, min, max)
elseif data_type == ImGuiDataType.Double then return DataTypeClampT(data, min, max) elseif data_type == ImGuiDataType.Double then return DataTypeClampT(data, min, max)
end end
@@ -2947,7 +3002,7 @@ function ImGui.InputScalar(label, data_type, data, step, step_fast, format, flag
local data_default = (bit32.band(g.NextItemData.HasFlags, ImGuiNextItemDataFlags.HasRefVal) ~= 0) and g.NextItemData.RefVal or g.DataTypeZeroValue local data_default = (bit32.band(g.NextItemData.HasFlags, ImGuiNextItemDataFlags.HasRefVal) ~= 0) and g.NextItemData.RefVal or g.DataTypeZeroValue
local buf, buf_size = {}, 64 -- TODO: IM_COUNTOF() local buf, buf_size = {}, 64 -- char buf[64]; IM_COUNTOF(buf)
if bit32.band(flags, ImGuiInputTextFlags.DisplayEmptyRefVal) ~= 0 and ImGui.DataTypeCompare(data_type, data, data_default) == 0 then if bit32.band(flags, ImGuiInputTextFlags.DisplayEmptyRefVal) ~= 0 and ImGui.DataTypeCompare(data_type, data, data_default) == 0 then
buf[1] = 0 buf[1] = 0
else else
@@ -3401,6 +3456,10 @@ function ImGui.DragBehavior(id, data_type, v, v_speed, min, max, format, flags)
return ImGui.DragBehaviorT(ImS32, ImS32, data_type, v, v_speed, min and min or IM_S32_MIN, max and max or IM_S32_MAX, format, flags) return ImGui.DragBehaviorT(ImS32, ImS32, data_type, v, v_speed, min and min or IM_S32_MIN, max and max or IM_S32_MAX, format, flags)
elseif data_type == ImGuiDataType.U32 then elseif data_type == ImGuiDataType.U32 then
return ImGui.DragBehaviorT(ImU32, ImS32, data_type, v, v_speed, min and min or IM_U32_MIN, max and max or IM_U32_MAX, format, flags) return ImGui.DragBehaviorT(ImU32, ImS32, data_type, v, v_speed, min and min or IM_U32_MIN, max and max or IM_U32_MAX, format, flags)
elseif data_type == ImGuiDataType.S64 then
return ImGui.DragBehaviorT(ImS64, ImS64, data_type, v, v_speed, min and min or IM_S64_MIN, max and max or IM_S64_MAX, format, flags)
elseif data_type == ImGuiDataType.U64 then
return ImGui.DragBehaviorT(ImU64, ImS64, data_type, v, v_speed, min and min or IM_U64_MIN, max and max or IM_U64_MAX, format, flags)
elseif data_type == ImGuiDataType.Float then elseif data_type == ImGuiDataType.Float then
return ImGui.DragBehaviorT(float, float, data_type, v, v_speed, min and min or -FLT_MAX, max and max or FLT_MAX, format, flags) return ImGui.DragBehaviorT(float, float, data_type, v, v_speed, min and min or -FLT_MAX, max and max or FLT_MAX, format, flags)
elseif data_type == ImGuiDataType.Double then elseif data_type == ImGuiDataType.Double then
@@ -3553,10 +3612,19 @@ function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, fla
ImGui.MarkItemEdited(id) ImGui.MarkItemEdited(id)
end end
-- TODO: ImGui.DataTypeFormatString() should be used here instead of ImFormatString()
-- Display value using user-provided display format so user can add prefix/suffix/decorations to the value. -- Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN) local is_mixed = bit32.band(g.LastItemData.ItemFlags, ImGuiItemFlags.MixedValue) ~= 0
local value_buf = DataTypeFormatStringCached(data_type, data, (is_mixed and g.MixedValueLabel ~= nil) and g.MixedValueLabel or format)
if g.LogEnabled then
ImGui.LogSetNextTextDecoration("{", "}")
end
if is_mixed then
ImGui.PushStyleColor(ImGuiCol.Text, g.Style.Colors[ImGuiCol.TextDisabled]) -- ImGuiCol_TextMixedValue
end
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, nil, nil, DRAG_TEXT_ALIGN)
if is_mixed then
ImGui.PopStyleColor()
end
if label_size.x > 0.0 then if label_size.x > 0.0 then
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false) ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
@@ -4127,6 +4195,12 @@ function ImGui.SliderBehavior(bb, id, data_type, v, min, max, format, flags, out
elseif data_type == ImGuiDataType.U32 then elseif data_type == ImGuiDataType.U32 then
IM_ASSERT(max <= math.floor(IM_U32_MAX / 2)) IM_ASSERT(max <= math.floor(IM_U32_MAX / 2))
return ImGui.SliderBehaviorT(ImU32, ImS32, bb, id, data_type, v, min, max, format, flags, out_grab_bb) return ImGui.SliderBehaviorT(ImU32, ImS32, bb, id, data_type, v, min, max, format, flags, out_grab_bb)
elseif data_type == ImGuiDataType.S64 then
IM_ASSERT(min >= IM_S64_MIN / 2 and max <= IM_S64_MAX / 2)
return ImGui.SliderBehaviorT(ImS64, ImS64, bb, id, data_type, v, min, max, format, flags, out_grab_bb)
elseif data_type == ImGuiDataType.U64 then
IM_ASSERT(max <= IM_U64_MAX / 2)
return ImGui.SliderBehaviorT(ImU64, ImS64, bb, id, data_type, v, min, max, format, flags, out_grab_bb)
elseif data_type == ImGuiDataType.Float then elseif data_type == ImGuiDataType.Float then
IM_ASSERT(min >= -FLT_MAX / 2.0 and max <= FLT_MAX / 2.0) IM_ASSERT(min >= -FLT_MAX / 2.0 and max <= FLT_MAX / 2.0)
return ImGui.SliderBehaviorT(float, float, bb, id, data_type, v, min, max, format, flags, out_grab_bb) return ImGui.SliderBehaviorT(float, float, bb, id, data_type, v, min, max, format, flags, out_grab_bb)
@@ -4239,13 +4313,19 @@ function ImGui.SliderScalar(label, data_type, data, min, max, format, flags)
window.DrawList:AddRectFilled(grab_bb.Min, grab_bb.Max, ImGui.GetColorU32((g.ActiveId == id) and ImGuiCol.SliderGrabActive or ImGuiCol.SliderGrab), style.GrabRounding) window.DrawList:AddRectFilled(grab_bb.Min, grab_bb.Max, ImGui.GetColorU32((g.ActiveId == id) and ImGuiCol.SliderGrabActive or ImGuiCol.SliderGrab), style.GrabRounding)
end end
-- TODO: ImGui.DataTypeFormatString() should be used here instead of ImFormatString()
-- Display value using user-provided display format so user can add prefix/suffix/decorations to the value. -- Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
-- if g.LogEnabled then local is_mixed = bit32.band(g.LastItemData.ItemFlags, ImGuiItemFlags.MixedValue) ~= 0
-- ImGui.LogSetNextTextDecoration("{", "}") local value_buf = DataTypeFormatStringCached(data_type, data, (is_mixed and g.MixedValueLabel ~= nil) and g.MixedValueLabel or format)
-- end if g.LogEnabled then
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, FormatCached(format, data), nil, nil, DRAG_TEXT_ALIGN) ImGui.LogSetNextTextDecoration("{", "}")
end
if is_mixed then
ImGui.PushStyleColor(ImGuiCol.Text, g.Style.Colors[ImGuiCol.TextDisabled]) -- ImGuiCol_TextMixedValue
end
ImGui.RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, nil, nil, DRAG_TEXT_ALIGN)
if is_mixed then
ImGui.PopStyleColor()
end
if label_size.x > 0.0 then if label_size.x > 0.0 then
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false) ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
@@ -4461,9 +4541,15 @@ function ImGui.VSliderScalar(label, size, data_type, data, min, max, format, fla
-- Display value using user-provided display format so user can add prefix/suffix/decorations to the value. -- Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
-- For the vertical slider we allow centered text to overlap the frame padding -- For the vertical slider we allow centered text to overlap the frame padding
-- local value_buf, value_buf_size = {}, 64 local is_mixed = bit32.band(g.LastItemData.ItemFlags, ImGuiItemFlags.MixedValue) ~= 0
-- TODO: ImGui.DataTypeFormatString() local value_buf = DataTypeFormatStringCached(data_type, data, (is_mixed and g.MixedValueLabel ~= nil) and g.MixedValueLabel or format)
ImGui.RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, ImFormatString(format, data), nil, nil, ImVec2(0.5, 0.0)) if is_mixed then
ImGui.PushStyleColor(ImGuiCol.Text, g.Style.Colors[ImGuiCol.TextDisabled]) -- ImGuiCol_TextMixedValue
end
ImGui.RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, nil, nil, ImVec2(0.5, 0.0))
if is_mixed then
ImGui.PopStyleColor()
end
if label_size.x > 0.0 then if label_size.x > 0.0 then
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false) ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
end end
@@ -6350,6 +6436,12 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback
state.TextSrc = nil state.TextSrc = nil
end end
-- Log as text
if g.LogEnabled and (not is_password or is_displaying_hint) then
ImGui.LogSetNextTextDecoration("{", "}")
ImGui.LogRenderedText(draw_pos, ImGui._ByteArrayToString(buf_display, 1, buf_display_end))
end
if label_size.x > 0.0 then if label_size.x > 0.0 then
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false) ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
end end
@@ -7968,9 +8060,9 @@ function ImGui.TreeNodeBehavior(id, flags, label, label_end)
if bit32.band(flags, ImGuiTreeNodeFlags.ClipLabelForTrailingButton) ~= 0 then if bit32.band(flags, ImGuiTreeNodeFlags.ClipLabelForTrailingButton) ~= 0 then
frame_bb.Max.x = frame_bb.Max.x - (g.FontSize + style.FramePadding.x) frame_bb.Max.x = frame_bb.Max.x - (g.FontSize + style.FramePadding.x)
end end
-- if g.LogEnabled then if g.LogEnabled then
-- ImGui.LogSetNextTextDecoration("###", "###") ImGui.LogSetNextTextDecoration("###", "###")
-- end end
else else
-- Unframed typed for tree nodes -- Unframed typed for tree nodes
if hovered or selected then if hovered or selected then
@@ -7986,9 +8078,9 @@ function ImGui.TreeNodeBehavior(id, flags, label, label_end)
elseif not is_leaf then elseif not is_leaf then
ImGui.RenderArrow(window.DrawList, ImVec2(text_pos.x - text_offset_x + padding_x, text_pos.y + g.FontSize * 0.15), text_col, is_open and ((bit32.band(flags, ImGuiTreeNodeFlags.UpsideDownArrow) ~= 0) and ImGuiDir.Up or ImGuiDir.Down) or ImGuiDir.Right, 0.70) ImGui.RenderArrow(window.DrawList, ImVec2(text_pos.x - text_offset_x + padding_x, text_pos.y + g.FontSize * 0.15), text_col, is_open and ((bit32.band(flags, ImGuiTreeNodeFlags.UpsideDownArrow) ~= 0) and ImGuiDir.Up or ImGuiDir.Down) or ImGuiDir.Right, 0.70)
end end
-- if g.LogEnabled then if g.LogEnabled then
-- ImGui.LogSetNextTextDecoration(">", nil) ImGui.LogSetNextTextDecoration(">", nil)
-- end end
end end
if draw_tree_lines then if draw_tree_lines then
@@ -10447,7 +10539,7 @@ function ImGui.BeginMenuEx(label, icon, enabled)
ImGui.PushStyleVarX(ImGuiStyleVar.ItemSpacing, style.ItemSpacing.x * 2.0) ImGui.PushStyleVarX(ImGuiStyleVar.ItemSpacing, style.ItemSpacing.x * 2.0)
local text_pos = ImVec2(window.DC.CursorPos.x + offsets.OffsetLabel, pos.y + window.DC.CurrLineTextBaseOffset) local text_pos = ImVec2(window.DC.CursorPos.x + offsets.OffsetLabel, pos.y + window.DC.CurrLineTextBaseOffset)
pressed = ImGui.Selectable("", menu_is_open, selectable_flags, label_size) pressed = ImGui.Selectable("", menu_is_open, selectable_flags, label_size)
-- TODO: ImGui.LogSetNextTextDecoration("[", "]") ImGui.LogSetNextTextDecoration("[", "]")
ImGui.RenderText(text_pos, label, 1, label_end, false) ImGui.RenderText(text_pos, label, 1, label_end, false)
ImGui.PopStyleVar() ImGui.PopStyleVar()
window.DC.CursorPos.x = window.DC.CursorPos.x + IM_TRUNC(style.ItemSpacing.x * (-1.0 + 0.5)) -- -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window.DC.CursorPos.x = window.DC.CursorPos.x + IM_TRUNC(style.ItemSpacing.x * (-1.0 + 0.5)) -- -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@@ -10463,7 +10555,7 @@ function ImGui.BeginMenuEx(label, icon, enabled)
local extra_w = ImMax(0.0, ImGui.GetContentRegionAvail().x - min_w) local extra_w = ImMax(0.0, ImGui.GetContentRegionAvail().x - min_w)
local text_pos = ImVec2(window.DC.CursorPos.x, pos.y + window.DC.CurrLineTextBaseOffset) local text_pos = ImVec2(window.DC.CursorPos.x, pos.y + window.DC.CurrLineTextBaseOffset)
pressed = ImGui.Selectable("", menu_is_open, bit32.bor(selectable_flags, ImGuiSelectableFlags.SpanAvailWidth), ImVec2(min_w, label_size.y)) pressed = ImGui.Selectable("", menu_is_open, bit32.bor(selectable_flags, ImGuiSelectableFlags.SpanAvailWidth), ImVec2(min_w, label_size.y))
-- ImGui.LogSetNextTextDecoration("", ">") ImGui.LogSetNextTextDecoration("", ">")
ImGui.RenderText(ImVec2(text_pos.x + offsets.OffsetLabel, text_pos.y), label, 1, label_end, false) ImGui.RenderText(ImVec2(text_pos.x + offsets.OffsetLabel, text_pos.y), label, 1, label_end, false)
if icon_w > 0.0 then if icon_w > 0.0 then
--- @cast icon string --- @cast icon string
@@ -10713,7 +10805,7 @@ function ImGui.MenuItemEx(label, icon, shortcut, selected, enabled)
end end
if shortcut_w > 0.0 then if shortcut_w > 0.0 then
ImGui.PushStyleColor(ImGuiCol.Text, style.Colors[ImGuiCol.TextDisabled]) ImGui.PushStyleColor(ImGuiCol.Text, style.Colors[ImGuiCol.TextDisabled])
-- ImGui.LogSetNextTextDecoration("(", ")") ImGui.LogSetNextTextDecoration("(", ")")
--- @cast shortcut string --- @cast shortcut string
ImGui.RenderText(text_pos + ImVec2(offsets.OffsetShortcut + stretch_w, 0.0), shortcut, nil, nil, false) ImGui.RenderText(text_pos + ImVec2(offsets.OffsetShortcut + stretch_w, 0.0), shortcut, nil, nil, false)
ImGui.PopStyleColor() ImGui.PopStyleColor()
+31 -14
View File
@@ -3,7 +3,8 @@
-- Supports: -- Supports:
-- - %x, %X, %nx, %nX (where n is a number) -- - %x, %X, %nx, %nX (where n is a number)
-- - %d, %nd (where n is a number) -- - %d, %nd, %u, %nu (where n is a number)
-- - length modifiers h, hh, l, ll, I64 on integers: ll/I64 = 64-bit range (doubles: exact only within +-2^53)
-- - %f, %lf (very limited) -- - %f, %lf (very limited)
-- --
-- Returns items_matched instead of EOF on error -- Returns items_matched instead of EOF on error
@@ -17,6 +18,9 @@ local CHAR_0, CHAR_9 = _byte'0', _byte'9'
local CHAR_a, CHAR_A = _byte'a', _byte'A' local CHAR_a, CHAR_A = _byte'a', _byte'A'
local CHAR_d = _byte'd' local CHAR_d = _byte'd'
local CHAR_l = _byte'l' local CHAR_l = _byte'l'
local CHAR_h = _byte'h'
local CHAR_u = _byte'u'
local CHAR_I = _byte'I'
local CHAR_f, CHAR_F = _byte'f', _byte'F' local CHAR_f, CHAR_F = _byte'f', _byte'F'
local CHAR_x, CHAR_X = _byte'x', _byte'X' local CHAR_x, CHAR_X = _byte'x', _byte'X'
@@ -37,10 +41,15 @@ local function hex_digit_to_int(c)
end end
-- we force this behavior by default -- we force this behavior by default
local function clamp_if_overflow(spec, val) local function clamp_if_overflow(spec, val, is_64)
if spec == CHAR_d or spec == CHAR_x or spec == CHAR_X then if spec == CHAR_d or spec == CHAR_x or spec == CHAR_X then
if val > INT_MAX then return INT_MAX end local max = is_64 and 9223372036854775807 or INT_MAX
if val < INT_MIN then return INT_MIN end local min = is_64 and -9223372036854775808 or INT_MIN
if val > max then return max end
if val < min then return min end
elseif spec == CHAR_u then
local max = is_64 and 18446744073709551615 or UINT_MAX
if val > max then return max end
end end
return val return val
@@ -104,22 +113,27 @@ local function sscanf(buffer, buffer_begin, format, result)
width = math.huge width = math.huge
end end
-- length modifiers
local n_l = 0
while _byte(format, f, f) == CHAR_l or _byte(format, f, f) == CHAR_h do
if _byte(format, f, f) == CHAR_l then n_l = n_l + 1 end
f = f + 1
end
if _byte(format, f, f) == CHAR_I and string.sub(format, f, f + 2) == "I64" then
n_l = 2
f = f + 3
end
local is_64 = n_l >= 2
local spec = _byte(format, f, f) local spec = _byte(format, f, f)
local base local base
local is_float = false local is_float = false
if spec == CHAR_x or spec == CHAR_X then if spec == CHAR_x or spec == CHAR_X then
base = 16 base = 16
elseif spec == CHAR_d then elseif spec == CHAR_d or spec == CHAR_u then
base = 10 base = 10
elseif spec == CHAR_f or spec == CHAR_F then elseif spec == CHAR_f or spec == CHAR_F then
is_float = true is_float = true -- TODO: distinguish %lf from %f?
elseif spec == CHAR_l then
f = f + 1
if _byte(format, f, f) == CHAR_f then
is_float = true -- TODO: distinguish from float?
else
return items_matched
end
else else
return items_matched return items_matched
end end
@@ -197,11 +211,14 @@ local function sscanf(buffer, buffer_begin, format, result)
val = val * base + sign * hex_digit_to_int(c) val = val * base + sign * hex_digit_to_int(c)
local old_val = val local old_val = val
val = clamp_if_overflow(spec, val) val = clamp_if_overflow(spec, val, is_64)
if old_val ~= val then if old_val ~= val then
break break
end end
end end
if spec == CHAR_u and val < 0 then
val = val + (is_64 and 18446744073709551616 or 4294967296) -- unsigned wrap-around like strtoul()
end
end end
result[assigned + 1] = val result[assigned + 1] = val
+1 -1
View File
@@ -14,7 +14,7 @@ CHECKS=(
"cached|CACHED OK|$R --main tools/test/scripts/t_cached_window.luau --frames 130" "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" "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" "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" "helpers|HELPERS OK|$R --main tools/test/scripts/t_helpers.luau --frames 45"
"multiselect|MULTISELECT OK|$R --main tools/test/scripts/t_multiselect.luau --frames 380" "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" "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" "widgets|OK|$R --main tools/test/scripts/t_widgets.luau --frames 80"
+1 -1
View File
@@ -4,4 +4,4 @@ set -e
cd "$(dirname "$0")/../../.." cd "$(dirname "$0")/../../.."
python3 tools/bundle.py --target love >/dev/null python3 tools/bundle.py --target love >/dev/null
nix-shell -p luajit --run "luajit tools/test/love/t_drawhash.lua 150 Widgets,Basic && luajit tools/test/love/t_drawhash.lua 150 all && luajit tools/test/love/t_examples.lua" nix-shell -p luajit --run "luajit tools/test/love/t_drawhash.lua 150 Widgets,Basic && luajit tools/test/love/t_drawhash.lua 150 all && luajit tools/test/love/t_examples.lua"
echo "expected (Luau, tools/test/scripts/t_drawhash.luau): 154977593 / 338324359" echo "expected (Luau, tools/test/scripts/t_drawhash.luau): 154977593 / 263656315"
+78 -2
View File
@@ -1,5 +1,6 @@
-- Small upstream helpers: ImGuiInputTextState selection API + ReloadUserBuf*, ImGuiInputTextCallbackData:SetSelection, ImDrawList AddImageQuad/PrimQuadUV/ -- Small upstream helpers: ImGuiInputTextState selection API + ReloadUserBuf*, ImGuiInputTextCallbackData:SetSelection, ImDrawList AddImageQuad/PrimQuadUV/
-- CloneOutput, ImDrawData DeIndexAllBuffers/ScaleClipRects, ImBitVector/ImBitArray*, ImGuiPackedDate, ImParseFormatSanitizeForPrinting, drag cancel (ShortcutsForCancel) -- CloneOutput, ImDrawData DeIndexAllBuffers/ScaleClipRects, ImBitVector/ImBitArray*, ImGuiPackedDate, ImParseFormatSanitizeForPrinting, drag cancel (ShortcutsForCancel),
-- log decorations, ImGuiDataType.S64/U64, BringWindowToDisplayBehind, ImGuiSizeCallbackData
local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui")) local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui"))
local ImGui, ImVec2 = G.ImGui, G.ImVec2 local ImGui, ImVec2 = G.ImGui, G.ImVec2
ImGui.CreateContext(); G.ImGui_ImplRoblox.Init() ImGui.CreateContext(); G.ImGui_ImplRoblox.Init()
@@ -40,6 +41,7 @@ local function cb(data)
return 0 return 0
end end
local df, rect_df = 10.0, nil local df, rect_df = 10.0, nil
local s64_v = 2 ^ 40
local f = 0 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 center(r) return (r[1].x + r[2].x) / 2, (r[1].y + r[2].y) / 2 end
@@ -218,8 +220,82 @@ game:GetService("RunService").Stepped:Connect(function()
check(not string.find(ImGui.SaveIniSettingsToMemory(), "LastUsed", 1, true), "ConfigIniSettingsSaveLastUsedDate = false") check(not string.find(ImGui.SaveIniSettingsToMemory(), "LastUsed", 1, true), "ConfigIniSettingsSaveLastUsedDate = false")
io.ConfigIniSettingsSaveLastUsedDate = true io.ConfigIniSettingsSaveLastUsedDate = true
pio.Platform_SessionDate = 0 pio.Platform_SessionDate = 0
-- Log decorations: Selectable/Button/Checkbox/MenuItem shortcut
ImGui.LogToBuffer()
ImGui.Selectable("sel item")
ImGui.Button("btn")
ImGui.Checkbox("chk", true)
ImGui.MenuItem("mi", "Ctrl+M")
local log = g.LogBuffer:c_str()
ImGui.LogFinish()
check(string.find(log, "[sel item]", 1, true) == nil and string.find(log, "sel item", 1, true) ~= nil, "Selectable logs plain label: " .. log)
check(string.find(log, "[ btn ]", 1, true) ~= nil and string.find(log, "[x]", 1, true) ~= nil and string.find(log, "mi ( Ctrl+M )", 1, true) ~= nil, "LogSetNextTextDecoration [ ]: " .. log)
-- DragScalar S64/U64 (doubles) + DataTypeFormatString
local v64, ch = ImGui.DragScalar("##s64", G.ImGuiDataType.S64, 2 ^ 40, 1.0)
check(v64 == 2 ^ 40 and ch == false, "DragScalar S64 idle")
local b64 = {}
local n = ImGui.DataTypeFormatString(b64, 64, G.ImGuiDataType.S64, -(2 ^ 40), "%lld")
check(G.ImGui._ByteArrayToString(b64, 1, n + 1) == "-1099511627776", "DataTypeFormatString S64")
n = ImGui.DataTypeFormatString(b64, 64, G.ImGuiDataType.U64, 18446744073709551615, "%llu")
check(G.ImGui._ByteArrayToString(b64, 1, n + 1) == "18446744073709551615", "DataTypeFormatString U64 max")
n = ImGui.DataTypeFormatString(b64, 64, G.ImGuiDataType.S32, -5, "%X")
check(G.ImGui._ByteArrayToString(b64, 1, n + 1) == "FFFFFFFB", "DataTypeFormatString S32 hex")
local tb = ImGui.NewTextBuffer("-123456789012", 64)
local r64, c64 = ImGui.DataTypeApplyFromText(tb, G.ImGuiDataType.S64, 0, "%lld")
check(r64 == -123456789012 and c64, "DataTypeApplyFromText S64 " .. tostring(r64))
check(ImGui.DataTypeApplyOp(G.ImGuiDataType.S64, 43, 2 ^ 62, 2 ^ 62) == 9223372036854775807, "DataTypeApplyOp S64 clamp")
check(G.ImGuiDataType.Float == 8 and G.ImGuiDataType.COUNT == 12 and ImGui.DataTypeGetInfo(G.ImGuiDataType.Float).Name == "float", "ImGuiDataType layout")
end end
-- DragScalar S64: drag with the mouse
local s64_rect
s64_v = ImGui.DragScalar("##drag_s64", G.ImGuiDataType.S64, s64_v, 1.0)
do local a, b = ImGui.GetItemRectMin(), ImGui.GetItemRectMax(); s64_rect = { ImVec2(a.x, a.y), ImVec2(b.x, b.y) } end
if f == 33 then io:AddMousePosEvent(center(s64_rect)) end
if f == 34 then io:AddMouseButtonEvent(0, true) end
if f == 35 then local x, y = center(s64_rect); io:AddMousePosEvent(x + 30, y) end
if f == 37 then io:AddMouseButtonEvent(0, false); check(s64_v > 2 ^ 40 and s64_v == math.floor(s64_v), "DragScalar S64 drag " .. s64_v) end
ImGui.End() ImGui.End()
-- BringWindowToDisplayBehind
if f == 38 then
local g = ImGui.GetCurrentContext()
local wa, wb, wc = ImGui.FindWindowByName("WA"), ImGui.FindWindowByName("WB"), ImGui.FindWindowByName("WC")
local function idx(w) return ImGui.FindWindowDisplayIndex(w) end
ImGui.BringWindowToDisplayFront(wa); ImGui.BringWindowToDisplayFront(wb); ImGui.BringWindowToDisplayFront(wc)
local n0 = g.Windows.Size
ImGui.BringWindowToDisplayBehind(wc, wa) -- move forward-placed window behind: WC WA WB
check(idx(wc) + 1 == idx(wa) and idx(wa) + 1 == idx(wb) and g.Windows.Size == n0, ("BringWindowToDisplayBehind back %d %d %d"):format(idx(wa), idx(wb), idx(wc)))
ImGui.BringWindowToDisplayBehind(wa, wb) -- already directly behind: unchanged
check(idx(wc) + 1 == idx(wa) and idx(wa) + 1 == idx(wb), "BringWindowToDisplayBehind no-op")
ImGui.BringWindowToDisplayBehind(wc, wb) -- WA WC WB
check(idx(wa) + 1 == idx(wc) and idx(wc) + 1 == idx(wb) and g.Windows.Size == n0, ("BringWindowToDisplayBehind fwd %d %d %d"):format(idx(wa), idx(wb), idx(wc)))
end
for _, name in { "WA", "WB", "WC" } do
ImGui.SetNextWindowPos(ImVec2(820, 10)); ImGui.SetNextWindowSize(ImVec2(80, 60))
ImGui.Begin(name); ImGui.End()
end
-- Size callback (Step + AspectRatio)
ImGui.SetNextWindowPos(ImVec2(10, 420))
if f <= 3 then ImGui.SetNextWindowSize(ImVec2(237, 160)) end
ImGui.SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(G.FLT_MAX, G.FLT_MAX), function(data)
local step = data.UserData
check(data.Pos ~= nil and data.CurrentSize ~= nil and not rawequal(data.DesiredSize, data.CurrentSize), "ImGuiSizeCallbackData fields")
data.DesiredSize = ImVec2(math.floor(data.DesiredSize.x / step + 0.5) * step, math.floor(data.DesiredSize.y / step + 0.5) * step)
end, 100.0)
ImGui.Begin("Step"); local step_size = ImGui.GetWindowSize(); ImGui.End()
ImGui.SetNextWindowPos(ImVec2(300, 420))
if f <= 3 then ImGui.SetNextWindowSize(ImVec2(320, 100)) end
ImGui.SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(G.FLT_MAX, G.FLT_MAX), function(data)
data.DesiredSize.y = math.floor(data.DesiredSize.x / data.UserData)
end, 16 / 9)
ImGui.Begin("Aspect"); local asp_size = ImGui.GetWindowSize(); ImGui.End()
if f == 5 then
check(step_size.x == 200 and step_size.y == 200, ("size callback Step %gx%g"):format(step_size.x, step_size.y))
check(asp_size.x == 320 and asp_size.y == 180, ("size callback AspectRatio %gx%g"):format(asp_size.x, asp_size.y))
end
ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData()) ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
if f == 32 and #failed == 0 then print("HELPERS OK") end if f == 40 and #failed == 0 then print("HELPERS OK") end
end) end)