demo: port all Widgets sections, ShowStyleEditor/ShowStyleSelector, menus; fix crashes found by click fuzzer (color/scalar default args, InputTextWithHint string hint, AddText overload, splitter reset, CollapsingHeader close button, callback data methods, SetKeyboardFocusHere & misc getters)
This commit is contained in:
@@ -12930,6 +12930,86 @@ function ImGui.BeginTooltipHidden()
|
||||
return ret
|
||||
end
|
||||
|
||||
-- [SECTION] MISC GETTERS/SETTERS, FOCUS
|
||||
|
||||
function ImGui.NavMoveRequestResolveWithLastItem(result)
|
||||
local g = GImGui
|
||||
g.NavMoveScoringItems = false -- Ensure request doesn't need more processing
|
||||
ImGui.NavApplyItemToResult(result)
|
||||
ImGui.NavUpdateAnyRequestFlag()
|
||||
end
|
||||
|
||||
function ImGui.SetKeyboardFocusHere(offset)
|
||||
if offset == nil then offset = 0 end
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
IM_ASSERT(offset >= -1) -- -1 is allowed but not below
|
||||
|
||||
if g.DragDropActive or g.MovingWindow ~= nil then
|
||||
return
|
||||
end
|
||||
|
||||
ImGui.SetNavWindow(window)
|
||||
|
||||
local move_flags = bit32.bor(ImGuiNavMoveFlags.IsTabbing, ImGuiNavMoveFlags.Activate, ImGuiNavMoveFlags.FocusApi, ImGuiNavMoveFlags.NoSetNavCursorVisible)
|
||||
local scroll_flags = window.Appearing and bit32.bor(ImGuiScrollFlags.KeepVisibleEdgeX, ImGuiScrollFlags.AlwaysCenterY) or bit32.bor(ImGuiScrollFlags.KeepVisibleEdgeX, ImGuiScrollFlags.KeepVisibleEdgeY)
|
||||
ImGui.NavMoveRequestSubmit(ImGuiDir.None, (offset < 0) and ImGuiDir.Up or ImGuiDir.Down, move_flags, scroll_flags)
|
||||
if offset == -1 then
|
||||
ImGui.NavMoveRequestResolveWithLastItem(g.NavMoveResultLocal)
|
||||
else
|
||||
g.NavTabbingDir = 1
|
||||
g.NavTabbingCounter = offset + 1
|
||||
end
|
||||
end
|
||||
|
||||
function ImGui.FocusItem()
|
||||
local g = GImGui
|
||||
local window = g.CurrentWindow
|
||||
if g.DragDropActive or g.MovingWindow ~= nil then
|
||||
return
|
||||
end
|
||||
local move_flags = bit32.bor(ImGuiNavMoveFlags.IsTabbing, ImGuiNavMoveFlags.FocusApi, ImGuiNavMoveFlags.NoSetNavCursorVisible, ImGuiNavMoveFlags.NoSelect)
|
||||
local scroll_flags = window.Appearing and bit32.bor(ImGuiScrollFlags.KeepVisibleEdgeX, ImGuiScrollFlags.AlwaysCenterY) or bit32.bor(ImGuiScrollFlags.KeepVisibleEdgeX, ImGuiScrollFlags.KeepVisibleEdgeY)
|
||||
ImGui.SetNavWindow(window)
|
||||
ImGui.NavMoveRequestSubmit(ImGuiDir.None, ImGuiDir.Up, move_flags, scroll_flags)
|
||||
ImGui.NavMoveRequestResolveWithLastItem(g.NavMoveResultLocal)
|
||||
end
|
||||
|
||||
function ImGui.ActivateItemByID(id)
|
||||
local g = GImGui
|
||||
g.NavNextActivateId = id
|
||||
g.NavNextActivateFlags = ImGuiActivateFlags.None
|
||||
end
|
||||
|
||||
function ImGui.SetNavCursorVisible(visible)
|
||||
local g = GImGui
|
||||
if g.NavWindow and bit32.band(g.NavWindow.Flags, ImGuiWindowFlags.NoNavInputs) ~= 0 then
|
||||
visible = false
|
||||
elseif g.IO.ConfigNavCursorVisibleAlways then
|
||||
visible = true
|
||||
end
|
||||
g.NavCursorVisible = visible
|
||||
end
|
||||
|
||||
function ImGui.GetFrameCount() return GImGui.FrameCount end
|
||||
function ImGui.GetStateStorage() return GImGui.CurrentWindow.DC.StateStorage end
|
||||
function ImGui.SetStateStorage(tree)
|
||||
local window = GImGui.CurrentWindow
|
||||
window.DC.StateStorage = tree or window.StateStorage
|
||||
end
|
||||
function ImGui.SetNextFrameWantCaptureKeyboard(want) GImGui.WantCaptureKeyboardNextFrame = want and 1 or 0 end
|
||||
function ImGui.SetNextFrameWantCaptureMouse(want) GImGui.WantCaptureMouseNextFrame = want and 1 or 0 end
|
||||
function ImGui.GetVersion() return IMGUI_VERSION end
|
||||
|
||||
local StyleColorNames = nil
|
||||
function ImGui.GetStyleColorName(idx)
|
||||
if StyleColorNames == nil then
|
||||
StyleColorNames = {}
|
||||
for k, v in pairs(ImGuiCol) do if k ~= "COUNT" then StyleColorNames[v] = k end end
|
||||
end
|
||||
return StyleColorNames[idx] or "Unknown"
|
||||
end
|
||||
|
||||
-- [SECTION] NAV END FRAME
|
||||
|
||||
local NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15
|
||||
|
||||
@@ -119,11 +119,7 @@ end
|
||||
|
||||
--- Closable header: CollapsingHeader(label, &p_open). Returns visible, open.
|
||||
function DemoCollapsingHeaderClosable(label, open)
|
||||
if not open then return false, open end
|
||||
local visible = ImGui.CollapsingHeader(label, open)
|
||||
-- ponytail: until CollapsingHeader(label, p_open) lands, a boolean 2nd arg is treated as flags=None by the library
|
||||
if type(visible) == "table" then visible = visible[1] end
|
||||
return visible, open
|
||||
return ImGui.CollapsingHeader(label, open)
|
||||
end
|
||||
|
||||
--- ImColor::HSV() as ImVec4
|
||||
|
||||
@@ -838,7 +838,7 @@ local function DemoWindowLayout_TextClipping()
|
||||
else
|
||||
local clip_rect = ImVec4(p0.x, p0.y, p1.x, p1.y)
|
||||
draw_list:AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255))
|
||||
draw_list:AddText(ImGui.GetFont(), ImGui.GetFontSize(), text_pos, IM_COL32_WHITE, text_str, nil, 0.0, clip_rect)
|
||||
draw_list:AddText(ImGui.GetFont(), ImGui.GetFontSize(), text_pos, IM_COL32_WHITE, text_str, 1, #text_str + 1, 0.0, clip_rect)
|
||||
end
|
||||
until true end
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3129,6 +3129,12 @@ end
|
||||
|
||||
-- TODO:
|
||||
function MT.ImDrawList:_ResetForNewFrame()
|
||||
if self._Splitter._Count > 1 then
|
||||
self._Splitter:Merge(self)
|
||||
end
|
||||
self._Splitter._Current = 0 -- [Lua] recover from an error thrown mid-split
|
||||
self._Splitter._Count = 1
|
||||
|
||||
self.CmdBuffer:resize(0)
|
||||
self.IdxBuffer:resize(0)
|
||||
self.VtxBuffer:resize(0)
|
||||
@@ -4205,6 +4211,11 @@ end
|
||||
--- @param wrap_width float
|
||||
--- @param cpu_fine_clip_rect? ImVec4
|
||||
function MT.ImDrawList:AddText(font, font_size, pos, col, text, text_begin, text_end, wrap_width, cpu_fine_clip_rect)
|
||||
-- Overload: AddText(pos, col, text, text_end?)
|
||||
if type(font) == "table" and type(font[1]) == "number" then
|
||||
font, font_size, pos, col, text, text_begin, text_end, wrap_width, cpu_fine_clip_rect = nil, 0.0, font, font_size, pos, 1, col, 0.0, nil
|
||||
if text_end == nil then text_end = #text + 1 end
|
||||
end
|
||||
if text_begin == nil then text_begin = 1 end
|
||||
|
||||
if bit32.band(col, IM_COL32_A_MASK) == 0 then return end
|
||||
|
||||
+57
-1
@@ -67,6 +67,9 @@ function ImS32(val) return bitAnd(val, 0xFFFFFFFF) end
|
||||
|
||||
--- @alias ImDrawIdx unsigned_int
|
||||
|
||||
IMGUI_VERSION = "1.93.0 WIP"
|
||||
IMGUI_VERSION_NUM = 19298
|
||||
|
||||
IM_UNICODE_CODEPOINT_INVALID = 0xFFFD
|
||||
IM_UNICODE_CODEPOINT_MAX = 0xFFFF
|
||||
|
||||
@@ -1980,10 +1983,63 @@ ImGuiInputTextFlags = {
|
||||
--- @class ImGuiInputTextCallbackData
|
||||
|
||||
--- @return ImGuiInputTextCallbackData
|
||||
-- Buf is a 1-based zero-terminated byte table; positions (CursorPos, pos...) are 0-based byte offsets like upstream.
|
||||
MT.ImGuiInputTextCallbackData = {}
|
||||
MT.ImGuiInputTextCallbackData.__index = MT.ImGuiInputTextCallbackData
|
||||
function ImGuiInputTextCallbackData()
|
||||
return {}
|
||||
return setmetatable({}, MT.ImGuiInputTextCallbackData)
|
||||
end
|
||||
|
||||
function MT.ImGuiInputTextCallbackData:DeleteChars(pos, bytes_count)
|
||||
IM_ASSERT(pos + bytes_count <= self.BufTextLen)
|
||||
local buf = self.Buf
|
||||
local n = self.BufTextLen - bytes_count - pos + 1 -- includes zero terminator
|
||||
for i = 1, n do buf[pos + i] = buf[pos + bytes_count + i] end
|
||||
|
||||
if self.CursorPos >= pos + bytes_count then
|
||||
self.CursorPos = self.CursorPos - bytes_count
|
||||
elseif self.CursorPos >= pos then
|
||||
self.CursorPos = pos
|
||||
end
|
||||
self.SelectionStart = self.CursorPos; self.SelectionEnd = self.CursorPos
|
||||
self.BufDirty = true
|
||||
self.BufTextLen = self.BufTextLen - bytes_count
|
||||
end
|
||||
|
||||
--- @param new_text string
|
||||
function MT.ImGuiInputTextCallbackData:InsertChars(pos, new_text)
|
||||
local new_text_len = #new_text
|
||||
if new_text_len == 0 then return end
|
||||
local is_resizable = bit32.band(self.Flags, ImGuiInputTextFlags.CallbackResize) ~= 0
|
||||
-- We support partial insertion
|
||||
local avail = self.BufSize - 1 - self.BufTextLen
|
||||
if not is_resizable and new_text_len > avail then
|
||||
new_text_len = avail -- ponytail: truncates by bytes, not to the closest UTF-8 codepoint
|
||||
end
|
||||
if new_text_len <= 0 then return end
|
||||
-- ponytail: CallbackResize buffer growth not supported, text is truncated at BufSize instead
|
||||
if self.BufTextLen + new_text_len + 1 > self.BufSize then
|
||||
new_text_len = self.BufSize - 1 - self.BufTextLen
|
||||
if new_text_len <= 0 then return end
|
||||
end
|
||||
|
||||
local buf = self.Buf
|
||||
for i = self.BufTextLen, pos + 1, -1 do buf[i + new_text_len] = buf[i] end
|
||||
for i = 1, new_text_len do buf[pos + i] = string.byte(new_text, i) end
|
||||
buf[self.BufTextLen + new_text_len + 1] = 0
|
||||
|
||||
self.BufDirty = true
|
||||
self.BufTextLen = self.BufTextLen + new_text_len
|
||||
if self.CursorPos >= pos then
|
||||
self.CursorPos = self.CursorPos + new_text_len
|
||||
end
|
||||
self.SelectionStart = self.CursorPos; self.SelectionEnd = self.CursorPos
|
||||
end
|
||||
|
||||
function MT.ImGuiInputTextCallbackData:SelectAll() self.SelectionStart = 0; self.SelectionEnd = self.BufTextLen end
|
||||
function MT.ImGuiInputTextCallbackData:ClearSelection() self.SelectionStart = self.BufTextLen; self.SelectionEnd = self.BufTextLen end
|
||||
function MT.ImGuiInputTextCallbackData:HasSelection() return self.SelectionStart ~= self.SelectionEnd end
|
||||
|
||||
--- @alias ImGuiInputTextCallback fun(data: ImGuiInputTextCallbackData)
|
||||
|
||||
--- @alias ImGuiMemAllocFunc fun(T: function, start_idx: int, end_idx: int, userdata: any): table
|
||||
|
||||
+53
-4
@@ -2704,6 +2704,7 @@ end
|
||||
--- @param format? string
|
||||
--- @param flags? ImGuiInputTextFlags
|
||||
function ImGui.InputScalarN(label, data_type, data, components, step, step_fast, format, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return false
|
||||
@@ -3052,6 +3053,8 @@ end
|
||||
--- @param format string
|
||||
--- @param flags ImGuiSliderFlags
|
||||
function ImGui.DragScalar(label, data_type, data, v_speed, min, max, format, flags)
|
||||
if v_speed == nil then v_speed = 1.0 end
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return data, false
|
||||
@@ -3922,6 +3925,7 @@ end
|
||||
--- @param format? string
|
||||
--- @param flags? ImGuiSliderFlags
|
||||
function ImGui.VSliderScalar(label, size, data_type, data, min, max, format, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return data, false
|
||||
@@ -4776,7 +4780,20 @@ end
|
||||
--- @param flags ImGuiInputTextFlags
|
||||
--- @param callback? ImGuiInputTextCallback
|
||||
--- @param callback_user_data any
|
||||
local HintBufCache = setmetatable({}, { __mode = "k" })
|
||||
local function HintToBuf(hint)
|
||||
local t = HintBufCache[hint]
|
||||
if t == nil then
|
||||
t = {}
|
||||
for i = 1, #hint do t[i] = string.byte(hint, i) end
|
||||
t[#hint + 1] = 0
|
||||
HintBufCache[hint] = t
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function ImGui.InputTextEx(label, hint, buf, buf_size, size_arg, flags, callback, callback_user_data)
|
||||
if type(hint) == "string" then hint = HintToBuf(hint) end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return false
|
||||
@@ -5823,6 +5840,7 @@ local fmt_table_float = {
|
||||
--- @param col float[]
|
||||
--- @param flags ImGuiColorEditFlags
|
||||
function ImGui.ColorEdit4(label, col, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return false
|
||||
@@ -6074,12 +6092,14 @@ end
|
||||
--- @param flags? ImGuiColorEditFlags
|
||||
function ImGui.ColorEdit3(label, col, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
if flags == nil then flags = 0 end
|
||||
|
||||
return ImGui.ColorEdit4(label, col, bit32.bor(flags, ImGuiColorEditFlags.NoAlpha))
|
||||
end
|
||||
|
||||
-- `col` mutated in place, returns value_changed
|
||||
function ImGui.ColorPicker3(label, col, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local col4 = { col[1], col[2], col[3], 1.0 }
|
||||
if not ImGui.ColorPicker4(label, col4, bit32.bor(flags or 0, ImGuiColorEditFlags.NoAlpha)) then
|
||||
return false
|
||||
@@ -6122,6 +6142,7 @@ local backup_initial_col = {0, 0, 0, 0}
|
||||
--- @param flags ImGuiColorEditFlags
|
||||
--- @param ref_col? float[]
|
||||
function ImGui.ColorPicker4(label, col, flags, ref_col)
|
||||
if flags == nil then flags = 0 end
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return false
|
||||
@@ -7356,17 +7377,45 @@ function ImGui.SetNextItemStorageID(storage_id)
|
||||
g.NextItemData.StorageId = storage_id
|
||||
end
|
||||
|
||||
-- Overloads: CollapsingHeader(label, flags?) -> is_open
|
||||
-- CollapsingHeader(label, p_visible: bool, flags?) -> is_open, p_visible
|
||||
--- @param label string
|
||||
--- @param flags? ImGuiTreeNodeFlags
|
||||
function ImGui.CollapsingHeader(label, flags)
|
||||
function ImGui.CollapsingHeader(label, a, b)
|
||||
local p_visible, flags
|
||||
if type(a) == "boolean" then p_visible, flags = a, b else flags = a end
|
||||
if flags == nil then flags = 0 end
|
||||
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return false
|
||||
return false, p_visible
|
||||
end
|
||||
|
||||
if p_visible == false then
|
||||
return false, p_visible
|
||||
end
|
||||
|
||||
local id = window:GetID(label)
|
||||
return ImGui.TreeNodeBehavior(id, bit32.bor(flags, ImGuiTreeNodeFlags.CollapsingHeader), label)
|
||||
flags = bit32.bor(flags, ImGuiTreeNodeFlags.CollapsingHeader)
|
||||
if p_visible ~= nil then
|
||||
flags = bit32.bor(flags, ImGuiTreeNodeFlags.AllowOverlap, ImGuiTreeNodeFlags.ClipLabelForTrailingButton)
|
||||
end
|
||||
local is_open = ImGui.TreeNodeBehavior(id, flags, label)
|
||||
if p_visible ~= nil then
|
||||
-- Create a small overlapping close button
|
||||
local g = GImGui
|
||||
local last_item_backup = ImGuiLastItemData()
|
||||
ImGuiLastItemData_Copy(last_item_backup, g.LastItemData)
|
||||
local button_size = g.FontSize
|
||||
local button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x - button_size)
|
||||
local button_y = g.LastItemData.Rect.Min.y + g.Style.FramePadding.y
|
||||
local close_button_id = ImGui.GetIDWithSeed("#CLOSE", nil, id)
|
||||
if ImGui.CloseButton(close_button_id, ImVec2(button_x, button_y)) then
|
||||
p_visible = false
|
||||
end
|
||||
ImGuiLastItemData_Copy(g.LastItemData, last_item_backup)
|
||||
end
|
||||
|
||||
return is_open, p_visible
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user