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:
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because it is too large
Load Diff
+1033
-1033
File diff suppressed because it is too large
Load Diff
+13
-25
@@ -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.)
|
||||
|
||||
|
||||
FEATURES NOT PORTED
|
||||
-------------------
|
||||
- Multi-select / box-select: BeginMultiSelect, EndMultiSelect, MultiSelectItemHeader/Footer, MultiSelectAddSetAll,
|
||||
MultiSelectAddSetRange, SetNextItemSelectionUserData, BeginBoxSelect/EndBoxSelect, DebugNodeMultiSelectState.
|
||||
(Selectable/TreeNode call sites are stubbed with TODOs; the demo "Selection State & Multi-Select" section is not ported.)
|
||||
- Typing-select (type to jump in lists): GetTypingSelectRequest, TypingSelectFind*, DebugNodeTypingSelectState.
|
||||
- Examples > Assets Browser (needs multi-select + box-select).
|
||||
- Metrics > Tools > Item Picker (UpdateDebugToolItemPicker).
|
||||
- DebugFlashStyleColor / UpdateDebugToolFlashStyleColor (Style Editor "?" flash button).
|
||||
- DebugNodeInputTextState (Metrics > Internal state > InputText).
|
||||
- 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).
|
||||
FEATURES NOT PORTED / PARTIAL
|
||||
-----------------------------
|
||||
- ImFont::AddRemapCodepointToGlyphIndex / FontSrcGetGlyphIndexFromCodepoint (needs the 1.93 font loader split).
|
||||
- Default compressed font data (GetDefaultCompressedFontDataTTF / ProggyClean/ProggyForever embedded data):
|
||||
AddFontFromMemoryCompressedTTF works, but the default font comes from fonts/ instead.
|
||||
- DebugLogSkippedErrors / DebugDrawIdConflicts* (Metrics error-recovery and ID-conflict debug tools).
|
||||
- ImGuiDataType.S64/U64: supported, but values are Luau doubles: exact only within +-2^53 (LLONG_MAX/ULLONG_MAX
|
||||
round up to 2^63/2^64; U64 max prints as 18446744073709551615 via a special case).
|
||||
- ImDrawList::AddCallback(userdata_size > 0): "copy" = shallow copy of a table userdata (no raw bytes in Lua).
|
||||
- stb_truetype: cmap format 2 (high-byte mapping) asserts -- same as upstream stb_truetype ("@TODO").
|
||||
- GetAllocatorFunctions (n/a in Luau).
|
||||
|
||||
WON'T DO (platform)
|
||||
@@ -41,11 +31,9 @@ NOT VERIFIED LINE BY LINE AGAINST UPSTREAM
|
||||
KNOWN ISSUES
|
||||
------------
|
||||
- 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).
|
||||
|
||||
PERFORMANCE IDEAS (not done)
|
||||
----------------------------
|
||||
- Cheaper visible ColorEdit4 rows; cheaper Begin() for child windows.
|
||||
- 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
|
||||
overlapping-triangle fallback).
|
||||
|
||||
PLANNED EXTENSIONS
|
||||
------------------
|
||||
|
||||
@@ -6489,7 +6489,7 @@ function ImGui.IsMouseDragPastThreshold(button, lock_threshold)
|
||||
if lock_threshold == nil then lock_threshold = -1.0 end
|
||||
|
||||
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
|
||||
lock_threshold = g.IO.MouseDragThreshold
|
||||
end
|
||||
@@ -6502,7 +6502,7 @@ function ImGui.IsMouseDragging(button, lock_threshold)
|
||||
if lock_threshold == nil then lock_threshold = -1.0 end
|
||||
|
||||
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
|
||||
return false
|
||||
end
|
||||
@@ -7048,7 +7048,7 @@ function ImGui.EndGroup()
|
||||
IM_ASSERT(group_data.WindowID == window.ID) -- EndGroup() in wrong window?
|
||||
|
||||
if (window.DC.IsSetPos) then
|
||||
-- TODO: ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
|
||||
ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
|
||||
end
|
||||
|
||||
-- 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
|
||||
window = 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
|
||||
|
||||
--- @param under_this_window? ImGuiWindow
|
||||
@@ -8298,7 +8307,7 @@ function MT.ImGuiIO:ClearInputMouse()
|
||||
|
||||
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.MouseDownDuration[n] = -1.0
|
||||
self.MouseDownDurationPrev[n] = -1.0
|
||||
@@ -8841,7 +8850,6 @@ function ImGui.IsKeyPressedEx(key, flags, owner_id)
|
||||
return true
|
||||
end
|
||||
|
||||
-- TODO:
|
||||
-- Return untranslated names: on macOS, Cmd key will show as Ctrl, Ctrl key will show as super.
|
||||
function ImGui.GetKeyChordName(key_chord)
|
||||
local key = bit32.band(key_chord, bit32.bnot(ImGuiMod_Mask_))
|
||||
@@ -9290,7 +9298,7 @@ end
|
||||
--- @return bool
|
||||
function ImGui.IsAnyMouseDown()
|
||||
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
|
||||
return true
|
||||
end
|
||||
@@ -9304,7 +9312,7 @@ function ImGui.IsMouseDown(button, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
|
||||
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.
|
||||
end
|
||||
|
||||
@@ -9324,7 +9332,7 @@ function ImGui.IsMouseClickedEx(button, flags, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
|
||||
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)
|
||||
return false
|
||||
@@ -9355,7 +9363,7 @@ function ImGui.IsMouseReleased(button, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
@@ -9368,7 +9376,7 @@ end
|
||||
function ImGui.IsMouseReleasedWithDelay(button, delay)
|
||||
if delay == nil then delay = -1.0 end
|
||||
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
|
||||
return false
|
||||
end
|
||||
@@ -9384,14 +9392,14 @@ end
|
||||
function ImGui.IsMouseDoubleClicked(button, owner_id)
|
||||
if owner_id == nil then owner_id = ImGuiKeyOwner_Any end
|
||||
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)
|
||||
end
|
||||
|
||||
--- @param button ImGuiMouseButton
|
||||
function ImGui.GetMouseClickedCount(button)
|
||||
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]
|
||||
end
|
||||
|
||||
@@ -9482,7 +9490,7 @@ function ImGui.GetMouseDragDelta(button, lock_threshold)
|
||||
if button == nil then button = 0 end
|
||||
if lock_threshold == nil then lock_threshold = -1.0 end
|
||||
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
|
||||
lock_threshold = g.IO.MouseDragThreshold
|
||||
end
|
||||
@@ -9500,7 +9508,7 @@ end
|
||||
function ImGui.ResetMouseDragDelta(button)
|
||||
if button == nil then button = 0 end
|
||||
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
|
||||
ImVec2_Copy(g.IO.MouseClickedPos[button], g.IO.MousePos)
|
||||
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.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
|
||||
local data = {} -- TODO: ImGuiSizeCallbackData
|
||||
local data = ImGuiSizeCallbackData()
|
||||
data.UserData = g.NextWindowData.SizeCallbackUserData
|
||||
data.Pos = ImVec2(window.Pos.x, window.Pos.y)
|
||||
data.CurrentSize = ImVec2(window.SizeFull.x, window.SizeFull.y)
|
||||
data.DesiredSize = ImVec2(new_size.x, new_size.y)
|
||||
ImVec2_Copy(data.Pos, window.Pos)
|
||||
ImVec2_Copy(data.CurrentSize, window.SizeFull)
|
||||
ImVec2_Copy(data.DesiredSize, new_size)
|
||||
g.NextWindowData.SizeCallback(data)
|
||||
new_size.x = data.DesiredSize.x
|
||||
new_size.y = data.DesiredSize.y
|
||||
ImVec2_Copy(new_size, data.DesiredSize)
|
||||
end
|
||||
new_size.x = IM_TRUNC(new_size.x)
|
||||
new_size.y = IM_TRUNC(new_size.y)
|
||||
@@ -11161,6 +11168,7 @@ local function SetCurrentWindow(window)
|
||||
local g = GImGui
|
||||
--- @diagnostic disable-next-line
|
||||
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
|
||||
|
||||
if window then
|
||||
@@ -11177,7 +11185,6 @@ local function SetCurrentWindow(window)
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO:
|
||||
function ImGui.GcCompactTransientMiscBuffers()
|
||||
local g = GImGui
|
||||
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
|
||||
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)
|
||||
function ImGui.UpdateHoveredWindowAndCaptureFlags(mouse_pos)
|
||||
local g = GImGui
|
||||
@@ -13436,7 +13442,7 @@ function ImGui.UpdateHoveredWindowAndCaptureFlags(mouse_pos)
|
||||
local mouse_earliest_down = -1
|
||||
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
|
||||
io.MouseDownOwned[i] = (g.HoveredWindow ~= nil) or has_open_popup
|
||||
io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow ~= nil) or has_open_modal
|
||||
@@ -13525,7 +13531,7 @@ function ImGui.UpdateKeyboardInputs()
|
||||
end
|
||||
|
||||
-- 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)
|
||||
end
|
||||
ImGui.UpdateAliasKey(ImGuiKey.MouseWheelX, io.MouseWheelH ~= 0.0, io.MouseWheelH)
|
||||
@@ -13633,7 +13639,7 @@ function ImGui.UpdateMouseInputs()
|
||||
g.NavHighlightItemUnderNav = false
|
||||
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.MouseClickedCount[i] = 0 -- Will be filled below
|
||||
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)
|
||||
end
|
||||
|
||||
-- TODO:
|
||||
-- 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:
|
||||
-- it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend)
|
||||
@@ -16452,7 +16457,7 @@ end
|
||||
|
||||
function ImGui.PopFocusScope()
|
||||
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()
|
||||
if g.FocusScopeStack.Size > 0 then
|
||||
g.CurrentFocusScopeId = g.FocusScopeStack:back().ID
|
||||
@@ -19467,9 +19472,10 @@ function ImGui.ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
|
||||
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.SkipItems then return end
|
||||
-- Upstream asserts (user error): "Code uses SetCursorPos()/SetCursorScreenPos() to extend 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)
|
||||
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.")
|
||||
|
||||
-- For reference, the old behavior was essentially:
|
||||
--window.DC.CursorMaxPos = ImMax(window.DC.CursorMaxPos, window.DC.CursorPos)
|
||||
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
|
||||
ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y)
|
||||
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:")
|
||||
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:")
|
||||
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("MouseStationaryTimer: %.2f", g.MouseStationaryTimer)
|
||||
ImGui.Text("Mouse source: %s", GetMouseSourceName(io.MouseSource))
|
||||
|
||||
+19
-12
@@ -1520,7 +1520,8 @@ S.DemoWindowWidgetsDataTypes = {
|
||||
u16_v = 65535,
|
||||
s32_v = -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,
|
||||
f64_v = 90000.01234567890123456789,
|
||||
drag_clamp = false,
|
||||
@@ -1551,14 +1552,15 @@ function DemoWindowWidgetsDataTypes()
|
||||
|
||||
-- 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.
|
||||
-- [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 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 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 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 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 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")
|
||||
-- [Port] ImGui.DragScalar("drag s64", ImGuiDataType.S64, s64_v, ...) -- 64-bit types not supported
|
||||
-- [Port] ImGui.DragScalar("drag u64", ImGuiDataType.U64, u64_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)
|
||||
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 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")
|
||||
@@ -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 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")
|
||||
-- [Port] "slider s64 low" / "slider s64 high" / "slider s64 full" (ImGuiDataType.S64): 64-bit types not supported
|
||||
-- [Port] "slider u64 low" / "slider u64 high" / "slider u64 full" (ImGuiDataType.U64): 64-bit types not supported
|
||||
s.s64_v = ImGui.SliderScalar("slider s64 low", ImGuiDataType.S64, s.s64_v, s64_zero, s64_fifty,"%lld") -- "%" PRId64
|
||||
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 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")
|
||||
@@ -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.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")
|
||||
-- [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.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.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)
|
||||
-- [Port] ImGui.InputScalar("input s64", ImGuiDataType.S64, ...) -- 64-bit types not supported
|
||||
-- [Port] ImGui.InputScalar("input u64", ImGuiDataType.U64, ...) -- 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)
|
||||
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.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
|
||||
ImGui.Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y)
|
||||
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 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
|
||||
-- displaying the data for old/new backends.
|
||||
|
||||
+28
-6
@@ -4144,6 +4144,16 @@ function ImGui.AddDrawListToDrawDataEx(draw_data, out_list, draw_list)
|
||||
IM_ASSERT(draw_list._VtxCurrentIdx == draw_list.VtxBuffer.Size + 1)
|
||||
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
|
||||
out_list:push_back(draw_list)
|
||||
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.
|
||||
-- In the majority of cases, you would want to call PushClipRect() and PushTexture() after this.
|
||||
-- TODO:
|
||||
function MT.ImDrawList:_ResetForNewFrame()
|
||||
self._ContentClipX0 = nil -- set again by Begin() (Roblox backend scroll reuse)
|
||||
if self._Splitter._Count > 1 then
|
||||
@@ -4272,6 +4281,7 @@ function MT.ImDrawList:_ResetForNewFrame()
|
||||
self._IdxWritePtr = 1
|
||||
self._ClipRectStack:resize(0)
|
||||
self._TextureStack:resize(0)
|
||||
self._CallbacksDataBuf:resize(0)
|
||||
self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_)
|
||||
self._Path:resize(0)
|
||||
|
||||
@@ -4292,7 +4302,7 @@ function MT.ImDrawList:_ClearFreeMemory()
|
||||
|
||||
self._ClipRectStack:clear()
|
||||
self._TextureStack:clear()
|
||||
-- self._CallbacksDataBuf:clear()
|
||||
self._CallbacksDataBuf:clear()
|
||||
self._DrawFlagsStack.Size = 0 -- _DrawFlagsStack.clear() (ImSmallStack_)
|
||||
self._Path:clear()
|
||||
self._Splitter:ClearFreeMemory()
|
||||
@@ -4365,15 +4375,27 @@ function MT.ImDrawList:AddCallback(callback, userdata, userdata_size)
|
||||
curr_cmd = self.CmdBuffer.Data[self.CmdBuffer.Size]
|
||||
end
|
||||
curr_cmd.UserCallback = callback
|
||||
-- TODO: _CallbacksDataBuf?
|
||||
if userdata_size == 0 then
|
||||
-- Store user data directly in command (no indirection)
|
||||
curr_cmd.UserCallbackData = userdata
|
||||
|
||||
curr_cmd.UserCallbackDataSize = 0
|
||||
curr_cmd.UserCallbackDataOffset = -1
|
||||
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_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
|
||||
|
||||
self:AddDrawCmd() -- Force a new command after us (see comment below)
|
||||
|
||||
+44
-23
@@ -75,6 +75,14 @@ function ImU32(val) return bitAnd(val, 0xFFFFFFFF) end
|
||||
--- @return ImS32
|
||||
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
|
||||
--- @class double : number
|
||||
|
||||
@@ -155,15 +163,17 @@ ImGuiDataType =
|
||||
U16 = 3, -- unsigned short
|
||||
S32 = 4, -- int
|
||||
U32 = 5, -- unsigned int
|
||||
Float = 6, -- float
|
||||
Double = 7, -- double
|
||||
Bool = 8, -- bool (provided for user convenience, not supported by scalar widgets)
|
||||
String = 9, -- string (provided for user convenience, not supported by scalar widgets)
|
||||
COUNT = 10
|
||||
S64 = 6, -- long long / __int64 -- [Luau] stored in a double: exact only within +-2^53
|
||||
U64 = 7, -- unsigned long long / unsigned __int64 -- [Luau] stored in a double: exact only within 0..2^53
|
||||
Float = 8, -- float
|
||||
Double = 9, -- double
|
||||
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_
|
||||
ImGuiDataType.Pointer = 11 -- [internal]
|
||||
ImGuiDataType.ID = 12 -- [internal]
|
||||
ImGuiDataType.Pointer = ImGuiDataType.COUNT -- [internal]
|
||||
ImGuiDataType.ID = ImGuiDataType.COUNT + 1 -- [internal]
|
||||
|
||||
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!)
|
||||
_ClipRectStack = 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()
|
||||
_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.
|
||||
@@ -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.
|
||||
|
||||
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.
|
||||
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')
|
||||
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)
|
||||
MouseReleased = {[0] = false, [1] = false, [2] = 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
|
||||
MouseClickedLastCount = {[0] = 0, [1] = 0, [2] = 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)
|
||||
MouseDownDurationPrev = {[0] = -1, [1] = -1, [2] = -1}, -- Previous time the mouse button has been down
|
||||
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, [3] = false, [4] = false}, -- Mouse button went 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, [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, [3] = -1, [4] = -1}, -- Duration the mouse button has been down (0.0f == just clicked)
|
||||
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
|
||||
MouseDragMaxDistanceSqr = {[0] = 0, [1] = 0, [2] = 0}, -- Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
|
||||
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, [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.
|
||||
MouseDownOwnedUnlessPopupClose = {[0] = nil, [1] = nil, [2] = 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)
|
||||
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).
|
||||
MouseClickedPos = {[0] = ImVec2(), [1] = ImVec2(), [2] = ImVec2()}, -- Position at time of clicking
|
||||
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, [3] = nil, [4] = nil}, -- Track if button was clicked inside a dear imgui window.
|
||||
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, [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(), [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
|
||||
-- (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
|
||||
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()
|
||||
|
||||
+140
-48
@@ -54,6 +54,11 @@ local IM_S32_MIN = INT_MIN -- (-2147483647 - 1), (0x80000000);
|
||||
local IM_S32_MAX = INT_MAX -- (2147483647), (0x7FFFFFFF)
|
||||
local IM_U32_MIN = 0
|
||||
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.
|
||||
@@ -786,8 +791,9 @@ function ImGui.ButtonEx(label, size_arg, flags)
|
||||
ImGui.RenderNavCursor(bb, id)
|
||||
ImGui.RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding)
|
||||
|
||||
-- if (g.LogEnabled)
|
||||
-- LogSetNextTextDecoration("[", "]");
|
||||
if g.LogEnabled then
|
||||
ImGui.LogSetNextTextDecoration("[", "]")
|
||||
end
|
||||
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_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
|
||||
|
||||
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
|
||||
|
||||
if is_visible and label_size.x > 0.0 then
|
||||
@@ -1466,7 +1472,7 @@ function ImGui.RadioButtonEx(label, active)
|
||||
end
|
||||
local label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y)
|
||||
if g.LogEnabled then
|
||||
-- ImGui.LogRenderedText(label_pos, active and "(x)" or "( )")
|
||||
ImGui.LogRenderedText(label_pos, active and "(x)" or "( )")
|
||||
end
|
||||
if label_size.x > 0.0 then
|
||||
ImGui.RenderText(label_pos, label, 1, label_end, false)
|
||||
@@ -1788,7 +1794,7 @@ function ImGui.SeparatorEx(flags, thickness)
|
||||
-- Draw
|
||||
window.DrawList:AddRectFilled(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.Separator))
|
||||
if g.LogEnabled then
|
||||
ImGui.LogRenderedText(bb.Min, "--------------------------------")
|
||||
ImGui.LogRenderedText(bb.Min, "--------------------------------\n")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2347,6 +2353,8 @@ local GDataTypeInfo = {
|
||||
ImGuiDataTypeInfo(2, "U16", "%u", "%u"),
|
||||
ImGuiDataTypeInfo(4, "S32", "%d", "%d"), -- ImGuiDataType.S32
|
||||
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(8, "double", "%f", "%lf"), -- ImGuiDataType.Double
|
||||
ImGuiDataTypeInfo(1, "bool", "%d", "%d"), -- ImGuiDataType.Bool
|
||||
@@ -2359,33 +2367,64 @@ function ImGui.DataTypeGetInfo(data_type)
|
||||
return GDataTypeInfo[data_type + 1]
|
||||
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_size int
|
||||
--- @param data_type ImGuiDataType
|
||||
--- @param data number
|
||||
--- @param format string
|
||||
--- @return int
|
||||
function ImGui.DataTypeFormatString(buf, buf_size, data_type, data, format)
|
||||
local str
|
||||
if data_type == ImGuiDataType.S32 then
|
||||
str = ImFormatString(format, (ImS32)(data))
|
||||
elseif data_type == ImGuiDataType.U32 then
|
||||
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
|
||||
local str = DataTypeFormatStringCached(data_type, data, format)
|
||||
local len = ImMin(#str, buf_size - 1) -- ImFormatString(): truncate and return the written length
|
||||
ImStd.ImStrncpy(buf, 1, { string.byte(str, 1, len) }, 1, len + 1)
|
||||
return len
|
||||
end
|
||||
|
||||
--- @param data_type ImGuiDataType
|
||||
@@ -2431,6 +2470,18 @@ function ImGui.DataTypeApplyOp(data_type, op, arg1, arg2)
|
||||
elseif op == 45 then
|
||||
return ImSubClampOverflow(arg1, arg2, IM_U32_MIN, IM_U32_MAX)
|
||||
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
|
||||
if op == 43 then
|
||||
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.S32 then return DataTypeCompareT((ImS32)(arg1), (ImS32)(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.Double then return DataTypeCompareT(arg1, arg2)
|
||||
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.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.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.Double then return DataTypeClampT(data, min, max)
|
||||
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 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
|
||||
buf[1] = 0
|
||||
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)
|
||||
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)
|
||||
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
|
||||
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
|
||||
@@ -3553,10 +3612,19 @@ function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, fla
|
||||
ImGui.MarkItemEdited(id)
|
||||
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.
|
||||
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
|
||||
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
|
||||
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)
|
||||
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
|
||||
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)
|
||||
@@ -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)
|
||||
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.
|
||||
-- if g.LogEnabled then
|
||||
-- ImGui.LogSetNextTextDecoration("{", "}")
|
||||
-- end
|
||||
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
|
||||
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.
|
||||
-- For the vertical slider we allow centered text to overlap the frame padding
|
||||
-- local value_buf, value_buf_size = {}, 64
|
||||
-- TODO: ImGui.DataTypeFormatString()
|
||||
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))
|
||||
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 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
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
end
|
||||
@@ -6350,6 +6436,12 @@ function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback
|
||||
state.TextSrc = nil
|
||||
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
|
||||
ImGui.RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, 1, label_end, false)
|
||||
end
|
||||
@@ -7968,9 +8060,9 @@ function ImGui.TreeNodeBehavior(id, flags, label, label_end)
|
||||
if bit32.band(flags, ImGuiTreeNodeFlags.ClipLabelForTrailingButton) ~= 0 then
|
||||
frame_bb.Max.x = frame_bb.Max.x - (g.FontSize + style.FramePadding.x)
|
||||
end
|
||||
-- if g.LogEnabled then
|
||||
-- ImGui.LogSetNextTextDecoration("###", "###")
|
||||
-- end
|
||||
if g.LogEnabled then
|
||||
ImGui.LogSetNextTextDecoration("###", "###")
|
||||
end
|
||||
else
|
||||
-- Unframed typed for tree nodes
|
||||
if hovered or selected then
|
||||
@@ -7986,9 +8078,9 @@ function ImGui.TreeNodeBehavior(id, flags, label, label_end)
|
||||
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)
|
||||
end
|
||||
-- if g.LogEnabled then
|
||||
-- ImGui.LogSetNextTextDecoration(">", nil)
|
||||
-- end
|
||||
if g.LogEnabled then
|
||||
ImGui.LogSetNextTextDecoration(">", nil)
|
||||
end
|
||||
end
|
||||
|
||||
if draw_tree_lines then
|
||||
@@ -10447,7 +10539,7 @@ function ImGui.BeginMenuEx(label, icon, enabled)
|
||||
ImGui.PushStyleVarX(ImGuiStyleVar.ItemSpacing, style.ItemSpacing.x * 2.0)
|
||||
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)
|
||||
-- TODO: ImGui.LogSetNextTextDecoration("[", "]")
|
||||
ImGui.LogSetNextTextDecoration("[", "]")
|
||||
ImGui.RenderText(text_pos, label, 1, label_end, false)
|
||||
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().
|
||||
@@ -10463,7 +10555,7 @@ function ImGui.BeginMenuEx(label, icon, enabled)
|
||||
local extra_w = ImMax(0.0, ImGui.GetContentRegionAvail().x - min_w)
|
||||
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))
|
||||
-- ImGui.LogSetNextTextDecoration("", ">")
|
||||
ImGui.LogSetNextTextDecoration("", ">")
|
||||
ImGui.RenderText(ImVec2(text_pos.x + offsets.OffsetLabel, text_pos.y), label, 1, label_end, false)
|
||||
if icon_w > 0.0 then
|
||||
--- @cast icon string
|
||||
@@ -10713,7 +10805,7 @@ function ImGui.MenuItemEx(label, icon, shortcut, selected, enabled)
|
||||
end
|
||||
if shortcut_w > 0.0 then
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, style.Colors[ImGuiCol.TextDisabled])
|
||||
-- ImGui.LogSetNextTextDecoration("(", ")")
|
||||
ImGui.LogSetNextTextDecoration("(", ")")
|
||||
--- @cast shortcut string
|
||||
ImGui.RenderText(text_pos + ImVec2(offsets.OffsetShortcut + stretch_w, 0.0), shortcut, nil, nil, false)
|
||||
ImGui.PopStyleColor()
|
||||
|
||||
+31
-14
@@ -3,7 +3,8 @@
|
||||
|
||||
-- Supports:
|
||||
-- - %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)
|
||||
--
|
||||
-- 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_d = _byte'd'
|
||||
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_x, CHAR_X = _byte'x', _byte'X'
|
||||
|
||||
@@ -37,10 +41,15 @@ local function hex_digit_to_int(c)
|
||||
end
|
||||
|
||||
-- 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 val > INT_MAX then return INT_MAX end
|
||||
if val < INT_MIN then return INT_MIN end
|
||||
local max = is_64 and 9223372036854775807 or INT_MAX
|
||||
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
|
||||
|
||||
return val
|
||||
@@ -104,22 +113,27 @@ local function sscanf(buffer, buffer_begin, format, result)
|
||||
width = math.huge
|
||||
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 base
|
||||
local is_float = false
|
||||
if spec == CHAR_x or spec == CHAR_X then
|
||||
base = 16
|
||||
elseif spec == CHAR_d then
|
||||
elseif spec == CHAR_d or spec == CHAR_u then
|
||||
base = 10
|
||||
elseif spec == CHAR_f or spec == CHAR_F then
|
||||
is_float = true
|
||||
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
|
||||
is_float = true -- TODO: distinguish %lf from %f?
|
||||
else
|
||||
return items_matched
|
||||
end
|
||||
@@ -197,11 +211,14 @@ local function sscanf(buffer, buffer_begin, format, result)
|
||||
val = val * base + sign * hex_digit_to_int(c)
|
||||
|
||||
local old_val = val
|
||||
val = clamp_if_overflow(spec, val)
|
||||
val = clamp_if_overflow(spec, val, is_64)
|
||||
if old_val ~= val then
|
||||
break
|
||||
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
|
||||
|
||||
result[assigned + 1] = val
|
||||
|
||||
@@ -14,7 +14,7 @@ CHECKS=(
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
|
||||
@@ -4,4 +4,4 @@ set -e
|
||||
cd "$(dirname "$0")/../../.."
|
||||
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"
|
||||
echo "expected (Luau, tools/test/scripts/t_drawhash.luau): 154977593 / 338324359"
|
||||
echo "expected (Luau, tools/test/scripts/t_drawhash.luau): 154977593 / 263656315"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
-- 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 ImGui, ImVec2 = G.ImGui, G.ImVec2
|
||||
ImGui.CreateContext(); G.ImGui_ImplRoblox.Init()
|
||||
@@ -40,6 +41,7 @@ local function cb(data)
|
||||
return 0
|
||||
end
|
||||
local df, rect_df = 10.0, nil
|
||||
local s64_v = 2 ^ 40
|
||||
local f = 0
|
||||
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")
|
||||
io.ConfigIniSettingsSaveLastUsedDate = true
|
||||
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
|
||||
-- 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()
|
||||
|
||||
-- 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())
|
||||
if f == 32 and #failed == 0 then print("HELPERS OK") end
|
||||
if f == 40 and #failed == 0 then print("HELPERS OK") end
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user