WIP: tabs, docking, dragdrop, settings, logging, harness
This commit is contained in:
+1728
-53
File diff suppressed because it is too large
Load Diff
+753
-836
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,289 @@
|
||||
--- ImGui Sincerely
|
||||
-- Drag and drop: 1:1 port of imgui.cpp [SECTION] DRAG AND DROP (docking branch)
|
||||
-- Payload `Data` is any Lua value (no copy is made). `data_size` is optional and only kept for API parity.
|
||||
|
||||
function ImGui.IsDragDropActive()
|
||||
return ImGui.GetCurrentContext().DragDropActive
|
||||
end
|
||||
|
||||
function ImGui.ClearDragDrop()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
g.DragDropActive = false
|
||||
ImGuiPayload_Clear(g.DragDropPayload)
|
||||
g.DragDropAcceptFlagsCurr = ImGuiDragDropFlags.None
|
||||
g.DragDropAcceptIdCurr = 0
|
||||
g.DragDropAcceptIdPrev = 0
|
||||
g.DragDropAcceptIdCurrRectSurface = FLT_MAX
|
||||
g.DragDropAcceptFrameCount = -1
|
||||
end
|
||||
|
||||
function ImGui.BeginDragDropSource(flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local g = ImGui.GetCurrentContext()
|
||||
local window = g.CurrentWindow
|
||||
|
||||
local mouse_button = ImGuiMouseButton.Left
|
||||
|
||||
local source_drag_active = false
|
||||
local source_id = 0
|
||||
local source_parent_id = 0
|
||||
if bit32.band(flags, ImGuiDragDropFlags.SourceExtern) == 0 then
|
||||
source_id = g.LastItemData.ID
|
||||
if source_id ~= 0 then
|
||||
if g.ActiveId ~= source_id then return false end
|
||||
if g.ActiveIdMouseButton ~= -1 then mouse_button = g.ActiveIdMouseButton end
|
||||
if g.IO.MouseDown[mouse_button] == false or window.SkipItems then return false end
|
||||
g.ActiveIdAllowOverlap = false
|
||||
else
|
||||
if g.IO.MouseDown[mouse_button] == false or window.SkipItems then return false end
|
||||
if bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HoveredRect) == 0 and (g.ActiveId == 0 or g.ActiveIdWindow ~= window) then
|
||||
return false
|
||||
end
|
||||
if bit32.band(flags, ImGuiDragDropFlags.SourceAllowNullID) == 0 then
|
||||
IM_ASSERT(false, "Use ImGuiDragDropFlags.SourceAllowNullID for items without an ID")
|
||||
return false
|
||||
end
|
||||
source_id = window:GetIDFromRectangle(g.LastItemData.Rect)
|
||||
g.LastItemData.ID = source_id
|
||||
ImGui.KeepAliveID(source_id)
|
||||
local is_hovered = ImGui.ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags)
|
||||
if is_hovered and g.IO.MouseClicked[mouse_button] then
|
||||
ImGui.SetActiveID(source_id, window)
|
||||
ImGui.FocusWindow(window)
|
||||
end
|
||||
if g.ActiveId == source_id then g.ActiveIdAllowOverlap = is_hovered end
|
||||
end
|
||||
if g.ActiveId ~= source_id then return false end
|
||||
source_parent_id = window.IDStack.Data[window.IDStack.Size]
|
||||
source_drag_active = ImGui.IsMouseDragging(mouse_button)
|
||||
|
||||
ImGui.SetActiveIdUsingAllKeyboardKeys()
|
||||
else
|
||||
window = nil
|
||||
source_id = ImHashStr("#SourceExtern")
|
||||
source_drag_active = true
|
||||
mouse_button = g.IO.MouseDown[0] and 0 or -1
|
||||
ImGui.KeepAliveID(source_id)
|
||||
ImGui.SetActiveID(source_id, nil)
|
||||
end
|
||||
|
||||
IM_ASSERT(g.DragDropWithinTarget == false)
|
||||
if not source_drag_active then return false end
|
||||
|
||||
if not g.DragDropActive then
|
||||
IM_ASSERT(source_id ~= 0)
|
||||
ImGui.ClearDragDrop()
|
||||
local payload = g.DragDropPayload
|
||||
payload.SourceId = source_id
|
||||
payload.SourceParentId = source_parent_id
|
||||
g.DragDropActive = true
|
||||
g.DragDropSourceFlags = flags
|
||||
g.DragDropMouseButton = mouse_button
|
||||
if payload.SourceId == g.ActiveId then g.ActiveIdNoClearOnFocusLoss = true end
|
||||
end
|
||||
g.DragDropSourceFrameCount = g.FrameCount
|
||||
g.DragDropWithinSource = true
|
||||
|
||||
if bit32.band(flags, ImGuiDragDropFlags.SourceNoPreviewTooltip) == 0 then
|
||||
local ret
|
||||
if g.DragDropAcceptIdPrev ~= 0 and bit32.band(g.DragDropAcceptFlagsPrev, ImGuiDragDropFlags.AcceptNoPreviewTooltip) ~= 0 then
|
||||
ret = ImGui.BeginTooltipHidden()
|
||||
else
|
||||
ret = ImGui.BeginTooltip()
|
||||
end
|
||||
IM_ASSERT(ret)
|
||||
end
|
||||
|
||||
if bit32.band(flags, ImGuiDragDropFlags.SourceNoDisableHover) == 0 and bit32.band(flags, ImGuiDragDropFlags.SourceExtern) == 0 then
|
||||
g.LastItemData.StatusFlags = bit32.band(g.LastItemData.StatusFlags, bit32.bnot(ImGuiItemStatusFlags.HoveredRect))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function ImGui.EndDragDropSource()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
IM_ASSERT(g.DragDropActive)
|
||||
IM_ASSERT(g.DragDropWithinSource, "Not after a BeginDragDropSource()?")
|
||||
|
||||
if bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.SourceNoPreviewTooltip) == 0 then
|
||||
ImGui.EndTooltip()
|
||||
end
|
||||
|
||||
if g.DragDropPayload.DataFrameCount == -1 then ImGui.ClearDragDrop() end
|
||||
g.DragDropWithinSource = false
|
||||
end
|
||||
|
||||
--- @param data any # any Lua value
|
||||
--- @return bool accepted
|
||||
function ImGui.SetDragDropPayload(type, data, data_size, cond)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
local payload = g.DragDropPayload
|
||||
if cond == nil or cond == 0 then cond = ImGuiCond.Always end
|
||||
|
||||
IM_ASSERT(type ~= nil)
|
||||
IM_ASSERT(#type < 32, "Payload type can be at most 32 characters long")
|
||||
IM_ASSERT(cond == ImGuiCond.Always or cond == ImGuiCond.Once)
|
||||
IM_ASSERT(payload.SourceId ~= 0)
|
||||
|
||||
if cond == ImGuiCond.Always or payload.DataFrameCount == -1 then
|
||||
payload.DataType = type
|
||||
payload.Data = data
|
||||
payload.DataSize = data_size or ((data ~= nil) and 1 or 0)
|
||||
end
|
||||
payload.DataFrameCount = g.FrameCount
|
||||
|
||||
return (g.DragDropAcceptFrameCount == g.FrameCount) or (g.DragDropAcceptFrameCount == g.FrameCount - 1)
|
||||
end
|
||||
|
||||
function ImGui.BeginDragDropTargetCustom(bb, id)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
if not g.DragDropActive then return false end
|
||||
|
||||
local window = g.CurrentWindow
|
||||
local hovered_window = g.HoveredWindowUnderMovingWindow
|
||||
if hovered_window == nil or window.RootWindowDockTree ~= hovered_window.RootWindowDockTree then return false end
|
||||
IM_ASSERT(id ~= 0)
|
||||
if not ImGui.IsMouseHoveringRect(bb.Min, bb.Max) or (id == g.DragDropPayload.SourceId) then return false end
|
||||
if window.SkipItems then return false end
|
||||
|
||||
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
|
||||
g.DragDropTargetRect = ImRect(bb.Min, bb.Max)
|
||||
g.DragDropTargetClipRect = ImRect(window.ClipRect.Min, window.ClipRect.Max)
|
||||
g.DragDropTargetId = id
|
||||
g.DragDropTargetFullViewport = 0
|
||||
g.DragDropWithinTarget = true
|
||||
return true
|
||||
end
|
||||
|
||||
function ImGui.BeginDragDropTargetViewport(viewport, p_bb)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
if not g.DragDropActive then return false end
|
||||
|
||||
local bb = p_bb or viewport:GetWorkRect()
|
||||
local id = viewport.ID
|
||||
if g.MouseViewport ~= viewport or not ImGui.IsMouseHoveringRect(bb.Min, bb.Max, false) or (id == g.DragDropPayload.SourceId) then
|
||||
return false
|
||||
end
|
||||
|
||||
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
|
||||
g.DragDropTargetRect = ImRect(bb.Min, bb.Max)
|
||||
g.DragDropTargetClipRect = ImRect(bb.Min, bb.Max)
|
||||
g.DragDropTargetId = id
|
||||
g.DragDropTargetFullViewport = id
|
||||
g.DragDropWithinTarget = true
|
||||
return true
|
||||
end
|
||||
|
||||
function ImGui.BeginDragDropTarget()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
if not g.DragDropActive then return false end
|
||||
|
||||
local window = g.CurrentWindow
|
||||
if bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HoveredRect) == 0 then return false end
|
||||
local hovered_window = g.HoveredWindowUnderMovingWindow
|
||||
if hovered_window == nil or window.RootWindowDockTree ~= hovered_window.RootWindowDockTree or window.SkipItems then return false end
|
||||
|
||||
local display_rect = (bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HasDisplayRect) ~= 0) and g.LastItemData.DisplayRect or g.LastItemData.Rect
|
||||
local id = g.LastItemData.ID
|
||||
if id == 0 then
|
||||
id = window:GetIDFromRectangle(display_rect)
|
||||
ImGui.KeepAliveID(id)
|
||||
end
|
||||
if g.DragDropPayload.SourceId == id then return false end
|
||||
|
||||
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
|
||||
g.DragDropTargetRect = ImRect(display_rect.Min, display_rect.Max)
|
||||
local clip = (bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HasClipRect) ~= 0) and g.LastItemData.ClipRect or window.ClipRect
|
||||
g.DragDropTargetClipRect = ImRect(clip.Min, clip.Max)
|
||||
g.DragDropTargetId = id
|
||||
g.DragDropWithinTarget = true
|
||||
return true
|
||||
end
|
||||
|
||||
function ImGui.IsDragDropPayloadBeingAccepted()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
return g.DragDropActive and g.DragDropAcceptIdPrev ~= 0
|
||||
end
|
||||
|
||||
--- @return ImGuiPayload?
|
||||
function ImGui.AcceptDragDropPayload(type, flags)
|
||||
if flags == nil then flags = 0 end
|
||||
local g = ImGui.GetCurrentContext()
|
||||
local payload = g.DragDropPayload
|
||||
IM_ASSERT(g.DragDropActive)
|
||||
IM_ASSERT(payload.DataFrameCount ~= -1)
|
||||
if type ~= nil and not ImGuiPayload_IsDataType(payload, type) then return nil end
|
||||
|
||||
local was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId)
|
||||
local r = g.DragDropTargetRect
|
||||
local r_surface = r:GetWidth() * r:GetHeight()
|
||||
if r_surface > g.DragDropAcceptIdCurrRectSurface then return nil end
|
||||
|
||||
g.DragDropAcceptFlagsCurr = flags
|
||||
g.DragDropAcceptIdCurr = g.DragDropTargetId
|
||||
g.DragDropAcceptIdCurrRectSurface = r_surface
|
||||
|
||||
payload.Preview = was_accepted_previously
|
||||
flags = bit32.bor(flags, bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.AcceptNoDrawDefaultRect))
|
||||
local draw_target_rect = payload.Preview and bit32.band(flags, ImGuiDragDropFlags.AcceptNoDrawDefaultRect) == 0
|
||||
if draw_target_rect and g.DragDropTargetFullViewport ~= 0 then
|
||||
ImGui.RenderDragDropTargetRectForViewport(g.DragDropTargetFullViewport, g.DragDropTargetRect)
|
||||
elseif draw_target_rect then
|
||||
ImGui.RenderDragDropTargetRectForItem(r)
|
||||
end
|
||||
|
||||
g.DragDropAcceptFrameCount = g.FrameCount
|
||||
if bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.SourceExtern) ~= 0 and g.DragDropMouseButton == -1 then
|
||||
payload.Delivery = was_accepted_previously and (g.DragDropSourceFrameCount < g.FrameCount)
|
||||
else
|
||||
payload.Delivery = was_accepted_previously and not ImGui.IsMouseDown(g.DragDropMouseButton)
|
||||
end
|
||||
if not payload.Delivery and bit32.band(flags, ImGuiDragDropFlags.AcceptBeforeDelivery) == 0 then return nil end
|
||||
return payload
|
||||
end
|
||||
|
||||
function ImGui.RenderDragDropTargetRectForItem(bb)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
local window = g.CurrentWindow
|
||||
local bb_display = ImRect(bb.Min, bb.Max)
|
||||
bb_display:ClipWith(g.DragDropTargetClipRect)
|
||||
bb_display:Expand(g.Style.DragDropTargetPadding)
|
||||
local push_clip_rect = not window.ClipRect:Contains(bb_display)
|
||||
if push_clip_rect then window.DrawList:PushClipRectFullScreen() end
|
||||
ImGui.RenderDragDropTargetRectEx(window.DrawList, bb_display, g.Style.DragDropTargetRounding)
|
||||
if push_clip_rect then window.DrawList:PopClipRect() end
|
||||
end
|
||||
|
||||
function ImGui.RenderDragDropTargetRectForViewport(viewport_id, bb)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
local viewport = ImGui.FindViewportByID(viewport_id)
|
||||
IM_ASSERT(viewport ~= nil)
|
||||
local bb_padded = ImRect(bb.Min, bb.Max)
|
||||
bb_padded:Expand(-g.Style.DragDropTargetPadding)
|
||||
ImGui.RenderDragDropTargetRectEx(ImGui.GetForegroundDrawList(viewport), bb_padded, g.Style.DragDropTargetRounding)
|
||||
end
|
||||
|
||||
function ImGui.RenderDragDropTargetRectEx(draw_list, bb, rounding)
|
||||
local g = ImGui.GetCurrentContext()
|
||||
draw_list:AddRectFilled(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.DragDropTargetBg), rounding, 0)
|
||||
draw_list:AddRect(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.DragDropTarget), rounding, 0, g.Style.DragDropTargetBorderSize)
|
||||
end
|
||||
|
||||
--- @return ImGuiPayload?
|
||||
function ImGui.GetDragDropPayload()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
return (g.DragDropActive and g.DragDropPayload.DataFrameCount ~= -1) and g.DragDropPayload or nil
|
||||
end
|
||||
|
||||
function ImGui.EndDragDropTarget()
|
||||
local g = ImGui.GetCurrentContext()
|
||||
IM_ASSERT(g.DragDropActive)
|
||||
IM_ASSERT(g.DragDropWithinTarget)
|
||||
g.DragDropWithinTarget = false
|
||||
if g.DragDropPayload.Delivery then ImGui.ClearDragDrop() end
|
||||
end
|
||||
|
||||
-- Payload methods (C++ ImGuiPayload members): payload:IsDataType(t) etc. also work through these globals
|
||||
function ImGui.PayloadIsDataType(payload, t) return ImGuiPayload_IsDataType(payload, t) end
|
||||
|
||||
return true
|
||||
+218
-1
@@ -137,6 +137,8 @@ function ImGui.StyleColorsDark(dst)
|
||||
colors[ImGuiCol.TabDimmed] = ImLerpV4V4F(colors[ImGuiCol.Tab], colors[ImGuiCol.TitleBg], 0.80)
|
||||
colors[ImGuiCol.TabDimmedSelected] = ImLerpV4V4F(colors[ImGuiCol.TabSelected], colors[ImGuiCol.TitleBg], 0.40)
|
||||
colors[ImGuiCol.TabDimmedSelectedOverline] = ImVec4(0.50, 0.50, 0.50, 0.00)
|
||||
colors[ImGuiCol.DockingPreview] = ImVec4(colors[ImGuiCol.HeaderActive].x, colors[ImGuiCol.HeaderActive].y, colors[ImGuiCol.HeaderActive].z, colors[ImGuiCol.HeaderActive].w * 0.7)
|
||||
colors[ImGuiCol.DockingEmptyBg] = ImVec4(0.20, 0.20, 0.20, 1.00)
|
||||
colors[ImGuiCol.PlotLines] = ImVec4(0.61, 0.61, 0.61, 1.00)
|
||||
colors[ImGuiCol.PlotLinesHovered] = ImVec4(1.00, 0.43, 0.35, 1.00)
|
||||
colors[ImGuiCol.PlotHistogram] = ImVec4(0.90, 0.70, 0.00, 1.00)
|
||||
@@ -205,6 +207,8 @@ function ImGui.StyleColorsClassic(dst)
|
||||
colors[ImGuiCol.TabDimmed] = ImLerpV4V4F(colors[ImGuiCol.Tab], colors[ImGuiCol.TitleBg], 0.80)
|
||||
colors[ImGuiCol.TabDimmedSelected] = ImLerpV4V4F(colors[ImGuiCol.TabSelected], colors[ImGuiCol.TitleBg], 0.40)
|
||||
colors[ImGuiCol.TabDimmedSelectedOverline] = ImVec4(0.53, 0.53, 0.87, 0.00)
|
||||
colors[ImGuiCol.DockingPreview] = ImVec4(colors[ImGuiCol.Header].x, colors[ImGuiCol.Header].y, colors[ImGuiCol.Header].z, colors[ImGuiCol.Header].w * 0.7)
|
||||
colors[ImGuiCol.DockingEmptyBg] = ImVec4(0.20, 0.20, 0.20, 1.00)
|
||||
colors[ImGuiCol.PlotLines] = ImVec4(1.00, 1.00, 1.00, 1.00)
|
||||
colors[ImGuiCol.PlotLinesHovered] = ImVec4(0.90, 0.70, 0.00, 1.00)
|
||||
colors[ImGuiCol.PlotHistogram] = ImVec4(0.90, 0.70, 0.00, 1.00)
|
||||
@@ -274,6 +278,8 @@ function ImGui.StyleColorsLight(dst)
|
||||
colors[ImGuiCol.TabDimmed] = ImLerpV4V4F(colors[ImGuiCol.Tab], colors[ImGuiCol.TitleBg], 0.80)
|
||||
colors[ImGuiCol.TabDimmedSelected] = ImLerpV4V4F(colors[ImGuiCol.TabSelected], colors[ImGuiCol.TitleBg], 0.40)
|
||||
colors[ImGuiCol.TabDimmedSelectedOverline] = ImVec4(0.26, 0.59, 1.00, 0.00)
|
||||
colors[ImGuiCol.DockingPreview] = ImVec4(colors[ImGuiCol.Header].x, colors[ImGuiCol.Header].y, colors[ImGuiCol.Header].z, colors[ImGuiCol.Header].w * 0.7)
|
||||
colors[ImGuiCol.DockingEmptyBg] = ImVec4(0.68, 0.69, 0.73, 1.00)
|
||||
colors[ImGuiCol.PlotLines] = ImVec4(0.39, 0.39, 0.39, 1.00)
|
||||
colors[ImGuiCol.PlotLinesHovered] = ImVec4(1.00, 0.43, 0.35, 1.00)
|
||||
colors[ImGuiCol.PlotHistogram] = ImVec4(0.90, 0.70, 0.00, 1.00)
|
||||
@@ -328,6 +334,18 @@ function ImGui.ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx,
|
||||
end
|
||||
end
|
||||
|
||||
-- Rotate and translate vertices [vert_start_idx, vert_end_idx) (1-based, like _VtxCurrentIdx)
|
||||
function ImGui.ShadeVertsTransformPos(draw_list, vert_start_idx, vert_end_idx, pivot_in, cos_a, sin_a, pivot_out)
|
||||
local data = draw_list.VtxBuffer.Data
|
||||
local pix, piy, pox, poy = pivot_in.x, pivot_in.y, pivot_out.x, pivot_out.y
|
||||
for i = vert_start_idx, vert_end_idx - 1 do
|
||||
local pos = data[i][1]
|
||||
local x, y = pos[1] - pix, pos[2] - piy
|
||||
pos[1] = x * cos_a - y * sin_a + pox
|
||||
pos[2] = x * sin_a + y * cos_a + poy
|
||||
end
|
||||
end
|
||||
|
||||
-- Distribute UV over (a, b) rectangle
|
||||
--- @param draw_list ImDrawList
|
||||
--- @param vert_start_idx int
|
||||
@@ -3145,7 +3163,7 @@ function MT.ImDrawList:_ClearFreeMemory()
|
||||
self._TextureStack:clear()
|
||||
-- self._CallbacksDataBuf:clear()
|
||||
self._Path:clear()
|
||||
-- self._Splitter.ClearFreeMemory()
|
||||
self._Splitter:ClearFreeMemory()
|
||||
end
|
||||
|
||||
function MT.ImDrawList:AddDrawCmd()
|
||||
@@ -3312,6 +3330,184 @@ function MT.ImDrawList:_OnChangedVtxOffset()
|
||||
curr_cmd.VtxOffset = self._CmdHeader.VtxOffset
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- [SECTION] ImDrawListSplitter
|
||||
----------------------------------------------------------------
|
||||
-- Lua: channels swap ImVector objects with the draw list (C++ memcpy of the vector headers).
|
||||
-- Channel 0 holds nothing while it is the current channel (its buffers live in the draw list).
|
||||
|
||||
-- Copy ClipRect, TexRef, VtxOffset (TexRef is assigned by reference, never mutated)
|
||||
local function ImDrawCmd_HeaderCopyRef(dst, src)
|
||||
ImVec4_Copy(dst.ClipRect, src.ClipRect)
|
||||
dst.TexRef = src.TexRef
|
||||
dst.VtxOffset = src.VtxOffset
|
||||
end
|
||||
|
||||
function MT.ImDrawListSplitter:Clear()
|
||||
self._Current = 0
|
||||
self._Count = 1
|
||||
end
|
||||
|
||||
function MT.ImDrawListSplitter:ClearFreeMemory()
|
||||
for i = 1, self._Channels.Size do
|
||||
local ch = self._Channels.Data[i]
|
||||
if i - 1 == self._Current then
|
||||
-- Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again
|
||||
self._Channels.Data[i] = ImDrawChannel()
|
||||
else
|
||||
ch._CmdBuffer:clear()
|
||||
ch._IdxBuffer:clear()
|
||||
end
|
||||
end
|
||||
self._Current = 0
|
||||
self._Count = 1
|
||||
self._Channels:clear()
|
||||
end
|
||||
|
||||
--- @param draw_list ImDrawList
|
||||
--- @param channels_count int
|
||||
function MT.ImDrawListSplitter:Split(draw_list, channels_count)
|
||||
IM_ASSERT(self._Current == 0 and self._Count <= 1, "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter.")
|
||||
local old_channels_count = self._Channels.Size
|
||||
if old_channels_count < channels_count then
|
||||
self._Channels:reserve(channels_count)
|
||||
self._Channels:resize(channels_count)
|
||||
end
|
||||
self._Count = channels_count
|
||||
|
||||
-- Channel 0 is the draw list itself (memset to 0 in C++)
|
||||
local channels = self._Channels.Data
|
||||
channels[1] = { _CmdBuffer = nil, _IdxBuffer = nil }
|
||||
for i = 2, channels_count do
|
||||
if i > old_channels_count or channels[i] == nil then
|
||||
channels[i] = ImDrawChannel()
|
||||
else
|
||||
channels[i]._CmdBuffer:resize(0)
|
||||
channels[i]._IdxBuffer:resize(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param draw_list ImDrawList
|
||||
function MT.ImDrawListSplitter:Merge(draw_list)
|
||||
-- Note that we never use or rely on _Channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
|
||||
if self._Count <= 1 then
|
||||
return
|
||||
end
|
||||
|
||||
self:SetCurrentChannel(draw_list, 0)
|
||||
draw_list:_PopUnusedDrawCmd()
|
||||
|
||||
-- Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command.
|
||||
local new_cmd_buffer_count = 0
|
||||
local new_idx_buffer_count = 0
|
||||
local last_cmd = (self._Count > 0 and draw_list.CmdBuffer.Size > 0) and draw_list.CmdBuffer.Data[draw_list.CmdBuffer.Size] or nil
|
||||
local idx_offset = last_cmd and (last_cmd.IdxOffset + last_cmd.ElemCount) or 0
|
||||
local channels = self._Channels.Data
|
||||
for i = 2, self._Count do
|
||||
local ch = channels[i]
|
||||
local cmds = ch._CmdBuffer
|
||||
if cmds.Size > 0 and cmds.Data[cmds.Size].ElemCount == 0 and cmds.Data[cmds.Size].UserCallback == nil then -- Equivalent of PopUnusedDrawCmd()
|
||||
cmds:pop_back()
|
||||
end
|
||||
|
||||
if cmds.Size > 0 and last_cmd ~= nil then
|
||||
-- Do not include ImDrawCmd_AreSequentialIdxOffset() in the compare as we rebuild IdxOffset values ourselves.
|
||||
-- Manipulating IdxOffset (e.g. by reordering draw commands like done by RenderDimmedBackgroundBehindWindow()) is not supported within a splitter.
|
||||
local next_cmd = cmds.Data[1]
|
||||
if ImDrawCmd_HeaderCompare(last_cmd, next_cmd) and last_cmd.UserCallback == nil and next_cmd.UserCallback == nil then
|
||||
-- Merge previous channel last draw command with current channel first draw command if matching.
|
||||
last_cmd.ElemCount = last_cmd.ElemCount + next_cmd.ElemCount
|
||||
idx_offset = idx_offset + next_cmd.ElemCount
|
||||
cmds:erase(1) -- FIXME-OPT: Improve for multiple merges.
|
||||
end
|
||||
end
|
||||
if cmds.Size > 0 then
|
||||
last_cmd = cmds.Data[cmds.Size]
|
||||
end
|
||||
new_cmd_buffer_count = new_cmd_buffer_count + cmds.Size
|
||||
new_idx_buffer_count = new_idx_buffer_count + ch._IdxBuffer.Size
|
||||
for cmd_n = 1, cmds.Size do
|
||||
cmds.Data[cmd_n].IdxOffset = idx_offset
|
||||
idx_offset = idx_offset + cmds.Data[cmd_n].ElemCount
|
||||
end
|
||||
end
|
||||
local cmd_write = draw_list.CmdBuffer.Size + 1
|
||||
local idx_write = draw_list.IdxBuffer.Size + 1
|
||||
draw_list.CmdBuffer:resize(draw_list.CmdBuffer.Size + new_cmd_buffer_count)
|
||||
draw_list.IdxBuffer:resize(draw_list.IdxBuffer.Size + new_idx_buffer_count)
|
||||
|
||||
-- Write commands and indices in order (they are fairly small structures, we don't copy vertices only indices)
|
||||
local dst_cmds = draw_list.CmdBuffer.Data
|
||||
local dst_idx = draw_list.IdxBuffer.Data
|
||||
for i = 2, self._Count do
|
||||
local ch = channels[i]
|
||||
local src_cmds = ch._CmdBuffer.Data
|
||||
for n = 1, ch._CmdBuffer.Size do
|
||||
dst_cmds[cmd_write] = src_cmds[n]
|
||||
src_cmds[n] = nil -- ownership moved to the draw list
|
||||
cmd_write = cmd_write + 1
|
||||
end
|
||||
local src_idx = ch._IdxBuffer.Data
|
||||
for n = 1, ch._IdxBuffer.Size do
|
||||
dst_idx[idx_write] = src_idx[n]
|
||||
idx_write = idx_write + 1
|
||||
end
|
||||
end
|
||||
draw_list._IdxWritePtr = idx_write
|
||||
|
||||
-- Ensure there's always a non-callback draw command trailing the command-buffer
|
||||
if draw_list.CmdBuffer.Size == 0 or draw_list.CmdBuffer.Data[draw_list.CmdBuffer.Size].UserCallback ~= nil then
|
||||
draw_list:AddDrawCmd()
|
||||
end
|
||||
|
||||
-- If current command is used with different settings we need to add a new command
|
||||
local curr_cmd = draw_list.CmdBuffer.Data[draw_list.CmdBuffer.Size]
|
||||
if curr_cmd.ElemCount == 0 then
|
||||
ImDrawCmd_HeaderCopyRef(curr_cmd, draw_list._CmdHeader) -- Copy ClipRect, TexRef, VtxOffset
|
||||
elseif not ImDrawCmd_HeaderCompare(curr_cmd, draw_list._CmdHeader) then
|
||||
draw_list:AddDrawCmd()
|
||||
end
|
||||
|
||||
self._Count = 1
|
||||
end
|
||||
|
||||
--- @param draw_list ImDrawList
|
||||
--- @param idx int # 0-based channel index
|
||||
function MT.ImDrawListSplitter:SetCurrentChannel(draw_list, idx)
|
||||
IM_ASSERT(idx >= 0 and idx < self._Count)
|
||||
if self._Current == idx then
|
||||
return
|
||||
end
|
||||
|
||||
-- Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
|
||||
local channels = self._Channels.Data
|
||||
local cur = channels[self._Current + 1]
|
||||
cur._CmdBuffer = draw_list.CmdBuffer
|
||||
cur._IdxBuffer = draw_list.IdxBuffer
|
||||
self._Current = idx
|
||||
local ch = channels[idx + 1]
|
||||
draw_list.CmdBuffer = ch._CmdBuffer
|
||||
draw_list.IdxBuffer = ch._IdxBuffer
|
||||
draw_list._IdxWritePtr = draw_list.IdxBuffer.Size + 1
|
||||
|
||||
-- If current command is used with different settings we need to add a new command
|
||||
local curr_cmd = (draw_list.CmdBuffer.Size == 0) and nil or draw_list.CmdBuffer.Data[draw_list.CmdBuffer.Size]
|
||||
if curr_cmd == nil then
|
||||
draw_list:AddDrawCmd()
|
||||
elseif curr_cmd.ElemCount == 0 then
|
||||
ImDrawCmd_HeaderCopyRef(curr_cmd, draw_list._CmdHeader) -- Copy ClipRect, TexRef, VtxOffset
|
||||
elseif not ImDrawCmd_HeaderCompare(curr_cmd, draw_list._CmdHeader) then
|
||||
draw_list:AddDrawCmd()
|
||||
end
|
||||
end
|
||||
|
||||
--- @param count int
|
||||
function MT.ImDrawList:ChannelsSplit(count) self._Splitter:Split(self, count) end
|
||||
function MT.ImDrawList:ChannelsMerge() self._Splitter:Merge(self) end
|
||||
--- @param n int # 0-based
|
||||
function MT.ImDrawList:ChannelsSetCurrent(n) self._Splitter:SetCurrentChannel(self, n) end
|
||||
|
||||
--- @param points ImVec2[]
|
||||
--- @param points_count int
|
||||
--- @param col ImU32
|
||||
@@ -3912,6 +4108,27 @@ function MT.ImDrawList:AddTriangle(p1, p2, p3, col, thickness)
|
||||
self:PathStroke(col, thickness, ImDrawFlags.Closed)
|
||||
end
|
||||
|
||||
function MT.ImDrawList:AddQuad(p1, p2, p3, p4, col, thickness)
|
||||
if thickness == nil then thickness = 1.0 end
|
||||
if bit32.band(col, IM_COL32_A_MASK) == 0 then return end
|
||||
|
||||
self:PathLineTo(p1)
|
||||
self:PathLineTo(p2)
|
||||
self:PathLineTo(p3)
|
||||
self:PathLineTo(p4)
|
||||
self:PathStroke(col, thickness, ImDrawFlags.Closed)
|
||||
end
|
||||
|
||||
function MT.ImDrawList:AddQuadFilled(p1, p2, p3, p4, col)
|
||||
if bit32.band(col, IM_COL32_A_MASK) == 0 then return end
|
||||
|
||||
self:PathLineTo(p1)
|
||||
self:PathLineTo(p2)
|
||||
self:PathLineTo(p3)
|
||||
self:PathLineTo(p4)
|
||||
self:PathFillConvex(col)
|
||||
end
|
||||
|
||||
function MT.ImDrawList:AddTriangleFilled(p1, p2, p3, col)
|
||||
if bit32.band(col, IM_COL32_A_MASK) == 0 then return end
|
||||
|
||||
|
||||
+175
-23
@@ -513,7 +513,9 @@ function ImDrawChannel() return { _CmdBuffer = ImVector(), _IdxBuffer = ImVector
|
||||
|
||||
--- @return ImDrawListSplitter
|
||||
--- @nodiscard
|
||||
function ImDrawListSplitter() return { _Current = 0, _Count = 0, _Channels = ImVector() } end
|
||||
MT.ImDrawListSplitter = {} -- methods in imgui_draw.lua
|
||||
MT.ImDrawListSplitter.__index = MT.ImDrawListSplitter
|
||||
function ImDrawListSplitter() return setmetatable({ _Current = 0, _Count = 0, _Channels = ImVector() }, MT.ImDrawListSplitter) end
|
||||
|
||||
--- @class ImDrawList
|
||||
--- @field CmdBuffer ImVector<ImDrawCmd>
|
||||
@@ -1000,6 +1002,7 @@ ImGuiConfigFlags = {
|
||||
NoMouse = bitLShift(1, 4),
|
||||
NoMouseCursorChange = bitLShift(1, 5),
|
||||
NoKeyboard = bitLShift(1, 6),
|
||||
DockingEnable = bitLShift(1, 7),
|
||||
ViewportsEnable = bitLShift(1, 10),
|
||||
IsSRGB = bitLShift(1, 20),
|
||||
IsTouchScreen = bitLShift(1, 21)
|
||||
@@ -1054,7 +1057,25 @@ function ImGuiIO()
|
||||
ConfigWindowsResizeFromEdges = true,
|
||||
|
||||
ConfigDebugIniSettings = false,
|
||||
ConfigWindowsCopyContentsWithCtrlC = false,
|
||||
ConfigWindowsMoveFromTitleBarOnly = false,
|
||||
ConfigErrorRecovery = true,
|
||||
ConfigErrorRecoveryEnableAssert = true,
|
||||
ConfigErrorRecoveryEnableDebugLog = true,
|
||||
ConfigErrorRecoveryEnableTooltip = true,
|
||||
ConfigDebugHighlightIdConflicts = false,
|
||||
ConfigDebugHighlightIdConflictsShowItemPicker = true,
|
||||
|
||||
IniFilename = "imgui.ini", -- Roblox: no disk access, only used as a flag (nil disables .ini handling)
|
||||
IniSavingRate = 5.0,
|
||||
LogFilename = "imgui_log.txt",
|
||||
WantSaveIniSettings = false,
|
||||
|
||||
ConfigDockingNoSplit = false,
|
||||
ConfigDockingNoDockingOver = false,
|
||||
ConfigDockingWithShift = false,
|
||||
ConfigDockingAlwaysTabBar = false,
|
||||
ConfigDockingTransparentPayload = false,
|
||||
ConfigViewportsNoAutoMerge = false,
|
||||
ConfigViewportsNoTaskBarIcon = false,
|
||||
ConfigViewportsNoDecoration = true,
|
||||
@@ -1084,6 +1105,7 @@ function ImGuiIO()
|
||||
MouseDoubleClicked = {[0] = false, [1] = false, [2] = false},
|
||||
|
||||
MouseDoubleClickTime = 0.30,
|
||||
MouseSingleClickDelay = 0.50,
|
||||
MouseDoubleClickMaxDist = 6.0,
|
||||
MouseDragThreshold = 6.0,
|
||||
KeyRepeatDelay = 0.275,
|
||||
@@ -1546,6 +1568,7 @@ ImGuiHoveredFlags = {
|
||||
RootWindow = bitLShift(1, 1),
|
||||
AnyWindow = bitLShift(1, 2),
|
||||
NoPopupHierarchy = bitLShift(1, 3),
|
||||
DockHierarchy = bitLShift(1, 4),
|
||||
AllowWhenBlockedByPopup = bitLShift(1, 5),
|
||||
AllowWhenBlockedByActiveItem = bitLShift(1, 7),
|
||||
AllowWhenOverlappedByItem = bitLShift(1, 8),
|
||||
@@ -1560,11 +1583,22 @@ ImGuiHoveredFlags = {
|
||||
NoSharedDelay = bitLShift(1, 17)
|
||||
}
|
||||
|
||||
--- @enum ImGuiFocusedFlags
|
||||
ImGuiFocusedFlags = {
|
||||
None = 0,
|
||||
ChildWindows = bitLShift(1, 0), -- Return true if any children of the window is focused
|
||||
RootWindow = bitLShift(1, 1), -- Test from root window (top most parent of the current hierarchy)
|
||||
AnyWindow = bitLShift(1, 2), -- Return true if any window is focused
|
||||
NoPopupHierarchy = bitLShift(1, 3), -- Do not consider popup hierarchy
|
||||
DockHierarchy = bitLShift(1, 4), -- Consider docking hierarchy
|
||||
}
|
||||
ImGuiFocusedFlags.RootAndChildWindows = bitOr(ImGuiFocusedFlags.RootWindow, ImGuiFocusedFlags.ChildWindows)
|
||||
|
||||
ImGuiHoveredFlags.AllowWhenOverlapped = bitOr(ImGuiHoveredFlags.AllowWhenOverlappedByItem, ImGuiHoveredFlags.AllowWhenOverlappedByWindow)
|
||||
ImGuiHoveredFlags.RectOnly = bitOr(ImGuiHoveredFlags.AllowWhenBlockedByPopup, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.AllowWhenOverlapped)
|
||||
ImGuiHoveredFlags.RootAndChildWindows = bitOr(ImGuiHoveredFlags.RootWindow, ImGuiHoveredFlags.ChildWindows)
|
||||
ImGuiHoveredFlags.DelayMask_ = bitOr(ImGuiHoveredFlags.DelayNone, ImGuiHoveredFlags.DelayShort, ImGuiHoveredFlags.DelayNormal, ImGuiHoveredFlags.NoSharedDelay)
|
||||
ImGuiHoveredFlags.AllowedMaskForIsWindowHovered = bitOr(ImGuiHoveredFlags.ChildWindows, ImGuiHoveredFlags.RootWindow, ImGuiHoveredFlags.AnyWindow, ImGuiHoveredFlags.NoPopupHierarchy, ImGuiHoveredFlags.AllowWhenBlockedByPopup, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.ForTooltip, ImGuiHoveredFlags.Stationary)
|
||||
ImGuiHoveredFlags.AllowedMaskForIsWindowHovered = bitOr(ImGuiHoveredFlags.ChildWindows, ImGuiHoveredFlags.RootWindow, ImGuiHoveredFlags.AnyWindow, ImGuiHoveredFlags.NoPopupHierarchy, ImGuiHoveredFlags.DockHierarchy, ImGuiHoveredFlags.AllowWhenBlockedByPopup, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.ForTooltip, ImGuiHoveredFlags.Stationary)
|
||||
ImGuiHoveredFlags.AllowedMaskForIsItemHovered = bitOr(ImGuiHoveredFlags.AllowWhenBlockedByPopup, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.AllowWhenOverlapped, ImGuiHoveredFlags.AllowWhenDisabled, ImGuiHoveredFlags.NoNavOverride, ImGuiHoveredFlags.ForTooltip, ImGuiHoveredFlags.Stationary, ImGuiHoveredFlags.DelayMask_)
|
||||
|
||||
--- @enum ImGuiKey
|
||||
@@ -1683,26 +1717,28 @@ ImGuiCol = {
|
||||
TabDimmed = 39,
|
||||
TabDimmedSelected = 40,
|
||||
TabDimmedSelectedOverline = 41,
|
||||
PlotLines = 42,
|
||||
PlotLinesHovered = 43,
|
||||
PlotHistogram = 44,
|
||||
PlotHistogramHovered = 45,
|
||||
TableHeaderBg = 46,
|
||||
TableBorderStrong = 47,
|
||||
TableBorderLight = 48,
|
||||
TableRowBg = 49,
|
||||
TableRowBgAlt = 50,
|
||||
TextLink = 51,
|
||||
TextSelectedBg = 52,
|
||||
TreeLines = 53,
|
||||
DragDropTarget = 54,
|
||||
DragDropTargetBg = 55,
|
||||
UnsavedMarker = 56,
|
||||
NavCursor = 57,
|
||||
NavWindowingHighlight = 58,
|
||||
NavWindowingDimBg = 59,
|
||||
ModalWindowDimBg = 60,
|
||||
COUNT = 61
|
||||
DockingPreview = 42,
|
||||
DockingEmptyBg = 43,
|
||||
PlotLines = 44,
|
||||
PlotLinesHovered = 45,
|
||||
PlotHistogram = 46,
|
||||
PlotHistogramHovered = 47,
|
||||
TableHeaderBg = 48,
|
||||
TableBorderStrong = 49,
|
||||
TableBorderLight = 50,
|
||||
TableRowBg = 51,
|
||||
TableRowBgAlt = 52,
|
||||
TextLink = 53,
|
||||
TextSelectedBg = 54,
|
||||
TreeLines = 55,
|
||||
DragDropTarget = 56,
|
||||
DragDropTargetBg = 57,
|
||||
UnsavedMarker = 58,
|
||||
NavCursor = 59,
|
||||
NavWindowingHighlight = 60,
|
||||
NavWindowingDimBg = 61,
|
||||
ModalWindowDimBg = 62,
|
||||
COUNT = 63
|
||||
}
|
||||
|
||||
--- @enum ImGuiBackendFlags
|
||||
@@ -1992,8 +2028,124 @@ ImGuiTreeNodeFlags.DrawLinesMask_ = bitOr(ImGuiTreeNodeFlags.DrawLinesNone, ImGu
|
||||
--- @enum ImGuiTableFlags
|
||||
ImGuiTableFlags =
|
||||
{
|
||||
None = 0,
|
||||
None = 0,
|
||||
Resizable = bitLShift(1, 0),
|
||||
Reorderable = bitLShift(1, 1),
|
||||
Hideable = bitLShift(1, 2),
|
||||
Sortable = bitLShift(1, 3),
|
||||
NoSavedSettings = bitLShift(1, 4),
|
||||
ContextMenuInBody = bitLShift(1, 5),
|
||||
RowBg = bitLShift(1, 6),
|
||||
BordersInnerH = bitLShift(1, 7),
|
||||
BordersOuterH = bitLShift(1, 8),
|
||||
BordersInnerV = bitLShift(1, 9),
|
||||
BordersOuterV = bitLShift(1, 10),
|
||||
NoBordersInBody = bitLShift(1, 11),
|
||||
NoBordersInBodyUntilResize = bitLShift(1, 12),
|
||||
SizingFixedFit = bitLShift(1, 13),
|
||||
SizingFixedSame = bitLShift(2, 13),
|
||||
SizingStretchProp = bitLShift(3, 13),
|
||||
SizingStretchSame = bitLShift(4, 13),
|
||||
NoHostExtendX = bitLShift(1, 16),
|
||||
NoHostExtendY = bitLShift(1, 17),
|
||||
NoKeepColumnsVisible = bitLShift(1, 18),
|
||||
PreciseWidths = bitLShift(1, 19),
|
||||
NoClip = bitLShift(1, 20),
|
||||
PadOuterX = bitLShift(1, 21),
|
||||
NoPadOuterX = bitLShift(1, 22),
|
||||
NoPadInnerX = bitLShift(1, 23),
|
||||
ScrollX = bitLShift(1, 24),
|
||||
ScrollY = bitLShift(1, 25),
|
||||
SortMulti = bitLShift(1, 26),
|
||||
SortTristate = bitLShift(1, 27),
|
||||
HighlightHoveredColumn = bitLShift(1, 28),
|
||||
}
|
||||
ImGuiTableFlags.BordersH = bitOr(ImGuiTableFlags.BordersInnerH, ImGuiTableFlags.BordersOuterH)
|
||||
ImGuiTableFlags.BordersV = bitOr(ImGuiTableFlags.BordersInnerV, ImGuiTableFlags.BordersOuterV)
|
||||
ImGuiTableFlags.BordersInner = bitOr(ImGuiTableFlags.BordersInnerV, ImGuiTableFlags.BordersInnerH)
|
||||
ImGuiTableFlags.BordersOuter = bitOr(ImGuiTableFlags.BordersOuterV, ImGuiTableFlags.BordersOuterH)
|
||||
ImGuiTableFlags.Borders = bitOr(ImGuiTableFlags.BordersInner, ImGuiTableFlags.BordersOuter)
|
||||
ImGuiTableFlags.SizingMask_ = bitOr(ImGuiTableFlags.SizingFixedFit, ImGuiTableFlags.SizingFixedSame, ImGuiTableFlags.SizingStretchProp, ImGuiTableFlags.SizingStretchSame)
|
||||
|
||||
--- @enum ImGuiTableColumnFlags
|
||||
ImGuiTableColumnFlags =
|
||||
{
|
||||
None = 0,
|
||||
Disabled = bitLShift(1, 0),
|
||||
DefaultHide = bitLShift(1, 1),
|
||||
DefaultSort = bitLShift(1, 2),
|
||||
WidthStretch = bitLShift(1, 3),
|
||||
WidthFixed = bitLShift(1, 4),
|
||||
NoResize = bitLShift(1, 5),
|
||||
NoReorder = bitLShift(1, 6),
|
||||
NoHide = bitLShift(1, 7),
|
||||
NoClip = bitLShift(1, 8),
|
||||
NoSort = bitLShift(1, 9),
|
||||
NoSortAscending = bitLShift(1, 10),
|
||||
NoSortDescending = bitLShift(1, 11),
|
||||
NoHeaderLabel = bitLShift(1, 12),
|
||||
NoHeaderWidth = bitLShift(1, 13),
|
||||
PreferSortAscending = bitLShift(1, 14),
|
||||
PreferSortDescending = bitLShift(1, 15),
|
||||
IndentEnable = bitLShift(1, 16),
|
||||
IndentDisable = bitLShift(1, 17),
|
||||
AngledHeader = bitLShift(1, 18),
|
||||
|
||||
IsEnabled = bitLShift(1, 24),
|
||||
IsVisible = bitLShift(1, 25),
|
||||
IsSorted = bitLShift(1, 26),
|
||||
IsHovered = bitLShift(1, 27),
|
||||
|
||||
NoDirectResize_ = bitLShift(1, 30),
|
||||
}
|
||||
ImGuiTableColumnFlags.WidthMask_ = bitOr(ImGuiTableColumnFlags.WidthStretch, ImGuiTableColumnFlags.WidthFixed)
|
||||
ImGuiTableColumnFlags.IndentMask_ = bitOr(ImGuiTableColumnFlags.IndentEnable, ImGuiTableColumnFlags.IndentDisable)
|
||||
ImGuiTableColumnFlags.StatusMask_ = bitOr(ImGuiTableColumnFlags.IsEnabled, ImGuiTableColumnFlags.IsVisible, ImGuiTableColumnFlags.IsSorted, ImGuiTableColumnFlags.IsHovered)
|
||||
|
||||
--- @enum ImGuiTableRowFlags
|
||||
ImGuiTableRowFlags = { None = 0, Headers = bitLShift(1, 0) }
|
||||
|
||||
--- @enum ImGuiTableBgTarget
|
||||
ImGuiTableBgTarget = { None = 0, RowBg0 = 1, RowBg1 = 2, CellBg = 3 }
|
||||
|
||||
--- @enum ImGuiSortDirection
|
||||
ImGuiSortDirection = { None = 0, Ascending = 1, Descending = 2 }
|
||||
|
||||
|
||||
|
||||
--- @class ImGuiPayload
|
||||
--- Drag and drop payload. `Data` is any Lua value (C++ stores raw bytes); `DataSize` kept for API parity.
|
||||
local IM_PAYLOAD = {}
|
||||
IM_PAYLOAD.__index = IM_PAYLOAD
|
||||
function IM_PAYLOAD:Clear() ImGuiPayload_Clear(self) end
|
||||
function IM_PAYLOAD:IsDataType(t) return ImGuiPayload_IsDataType(self, t) end
|
||||
function IM_PAYLOAD:IsPreview() return self.Preview end
|
||||
function IM_PAYLOAD:IsDelivery() return self.Delivery end
|
||||
function ImGuiPayload()
|
||||
return setmetatable({ Data = nil, DataSize = 0, SourceId = 0, SourceParentId = 0, DataFrameCount = -1, DataType = "", Preview = false, Delivery = false }, IM_PAYLOAD)
|
||||
end
|
||||
function ImGuiPayload_Clear(p) p.SourceId = 0; p.SourceParentId = 0; p.Data = nil; p.DataSize = 0; p.DataType = ""; p.DataFrameCount = -1; p.Preview = false; p.Delivery = false end
|
||||
function ImGuiPayload_IsDataType(p, t) return p.DataFrameCount ~= -1 and p.DataType == t end
|
||||
function ImGuiPayload_IsPreview(p) return p.Preview end
|
||||
function ImGuiPayload_IsDelivery(p) return p.Delivery end
|
||||
|
||||
--- @class ImGuiTextBuffer # string builder: Buf is a list of string chunks
|
||||
local ImGuiTextBufferMT = {}
|
||||
ImGuiTextBufferMT.__index = ImGuiTextBufferMT
|
||||
function ImGuiTextBuffer() return setmetatable({ Buf = {} }, ImGuiTextBufferMT) end
|
||||
function ImGuiTextBufferMT:clear() self.Buf = {} end
|
||||
function ImGuiTextBufferMT:empty() return #self.Buf == 0 end
|
||||
function ImGuiTextBufferMT:append(str) self.Buf[#self.Buf + 1] = str end
|
||||
function ImGuiTextBufferMT:appendf(fmt, ...) self.Buf[#self.Buf + 1] = string.format(fmt, ...) end
|
||||
function ImGuiTextBufferMT:c_str() return table.concat(self.Buf) end
|
||||
function ImGuiTextBufferMT:size() return #self:c_str() end
|
||||
|
||||
--- @class ImGuiSettingsHandler
|
||||
--- Fns take (ctx, handler, ...) like upstream. ReadOpenFn(ctx, handler, name) returns entry; ReadLineFn(ctx, handler, entry, line);
|
||||
--- WriteAllFn(ctx, handler, buf: ImGuiTextBuffer)
|
||||
function ImGuiSettingsHandler()
|
||||
return { TypeName = nil, TypeHash = 0, ClearAllFn = nil, ReadInitFn = nil, ReadOpenFn = nil, ReadLineFn = nil,
|
||||
ApplyAllFn = nil, WriteAllFn = nil, CleanupFn = nil, UserData = nil }
|
||||
end
|
||||
|
||||
return true -- [Roblox] ModuleScripts must return exactly one value
|
||||
|
||||
@@ -33,6 +33,44 @@ function ImGui._ByteArrayToString(buf, buf_begin, buf_end)
|
||||
return table.concat(str)
|
||||
end
|
||||
|
||||
|
||||
--- ImPool<T>: pool of objects keyed by ID. Public indices are 0-based like upstream (Buf is stored 1-based).
|
||||
--- `ctor` creates a new element. Removed slots are recycled via FreeIdx (-1 = none; free slots chain through `_NextFree`).
|
||||
local IM_POOL = {}
|
||||
IM_POOL.__index = IM_POOL
|
||||
function ImPool(ctor) return setmetatable({ Buf = {}, Map = {}, FreeIdx = 0, AliveCount = 0, BufSize = 0, _Ctor = ctor }, IM_POOL) end
|
||||
function IM_POOL:GetByKey(key) local i = self.Map[key]; return i and self.Buf[i + 1] or nil end
|
||||
function IM_POOL:GetByIndex(n) return self.Buf[n + 1] end
|
||||
function IM_POOL:GetIndex(p) return p._PoolIdx end
|
||||
function IM_POOL:Contains(p) return p ~= nil and self.Buf[(p._PoolIdx or -1) + 1] == p end
|
||||
function IM_POOL:GetMapSize() return self.BufSize end
|
||||
function IM_POOL:Clear() self.Buf = {}; self.Map = {}; self.FreeIdx = 0; self.AliveCount = 0; self.BufSize = 0 end
|
||||
function IM_POOL:Add()
|
||||
local idx
|
||||
if self._Free and #self._Free > 0 then idx = table.remove(self._Free) else idx = self.BufSize; self.BufSize = self.BufSize + 1 end
|
||||
local p = self._Ctor and self._Ctor() or {}
|
||||
p._PoolIdx = idx
|
||||
self.Buf[idx + 1] = p
|
||||
self.AliveCount = self.AliveCount + 1
|
||||
return p
|
||||
end
|
||||
function IM_POOL:GetOrAddByKey(key)
|
||||
local i = self.Map[key]
|
||||
if i then return self.Buf[i + 1] end
|
||||
local p = self:Add(); self.Map[key] = p._PoolIdx; return p
|
||||
end
|
||||
function IM_POOL:Remove(key, p)
|
||||
if type(key) == "table" then p = key; key = nil end
|
||||
if key == nil then for k, i in pairs(self.Map) do if i == p._PoolIdx then key = k break end end end
|
||||
if key ~= nil then self.Map[key] = nil end
|
||||
self.Buf[p._PoolIdx + 1] = false
|
||||
self._Free = self._Free or {}
|
||||
table.insert(self._Free, p._PoolIdx)
|
||||
self.AliveCount = self.AliveCount - 1
|
||||
end
|
||||
function IM_POOL:Reserve(n) end
|
||||
-- NOTE: removed slots hold `false`; iterate with `for i = 0, pool:GetMapSize() - 1 do local t = pool:GetByIndex(i) if t then ... end end`
|
||||
|
||||
--- @type ImGuiContext?
|
||||
local GImGui
|
||||
|
||||
@@ -1162,6 +1200,15 @@ function ImGuiNextWindowData()
|
||||
ScrollVal = ImVec2(),
|
||||
WindowFlags = nil,
|
||||
ChildFlags = nil,
|
||||
WindowFlagsSet = 0,
|
||||
WindowFlagsClear = 0,
|
||||
ChildFlagsSet = 0,
|
||||
ChildFlagsClear = 0,
|
||||
ViewportId = 0,
|
||||
DockId = 0,
|
||||
DockCond = 0,
|
||||
PosUndock = false,
|
||||
WindowClass = nil,
|
||||
CollapsedVal = nil,
|
||||
SizeConstraintRect = nil,
|
||||
SizeCallback = nil,
|
||||
@@ -1293,6 +1340,7 @@ function ImGuiStyle()
|
||||
PopupBorderSize = 1.0,
|
||||
|
||||
DockingSeparatorSize = 2.0,
|
||||
DockingNodeHasCloseButton = true,
|
||||
MouseCursorScale = 1.0,
|
||||
|
||||
ItemSpacing = ImVec2(8, 4),
|
||||
@@ -1655,6 +1703,91 @@ end
|
||||
--- @field DebugAllocInfo ImGuiDebugAllocInfo
|
||||
--- @field TempBuffer ImVector<char>
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- [SECTION] Tab bar, Tab item support (public flags from imgui.h + private extensions)
|
||||
----------------------------------------------------------------
|
||||
|
||||
--- @enum ImGuiTabBarFlags
|
||||
ImGuiTabBarFlags = {
|
||||
None = 0,
|
||||
Reorderable = bitLShift(1, 0),
|
||||
AutoSelectNewTabs = bitLShift(1, 1),
|
||||
TabListPopupButton = bitLShift(1, 2),
|
||||
NoCloseWithMiddleMouseButton = bitLShift(1, 3),
|
||||
NoTabListScrollingButtons = bitLShift(1, 4),
|
||||
NoTooltip = bitLShift(1, 5),
|
||||
DrawSelectedOverline = bitLShift(1, 6),
|
||||
FittingPolicyMixed = bitLShift(1, 7),
|
||||
FittingPolicyShrink = bitLShift(1, 8),
|
||||
FittingPolicyScroll = bitLShift(1, 9),
|
||||
-- Private
|
||||
DockNode = bitLShift(1, 20),
|
||||
IsFocused = bitLShift(1, 21),
|
||||
SaveSettings = bitLShift(1, 22),
|
||||
}
|
||||
ImGuiTabBarFlags.FittingPolicyMask_ = bitOr(ImGuiTabBarFlags.FittingPolicyMixed, ImGuiTabBarFlags.FittingPolicyShrink, ImGuiTabBarFlags.FittingPolicyScroll)
|
||||
ImGuiTabBarFlags.FittingPolicyDefault_ = ImGuiTabBarFlags.FittingPolicyMixed
|
||||
ImGuiTabBarFlags.FittingPolicyResizeDown = ImGuiTabBarFlags.FittingPolicyShrink
|
||||
|
||||
--- @enum ImGuiTabItemFlags
|
||||
ImGuiTabItemFlags = {
|
||||
None = 0,
|
||||
UnsavedDocument = bitLShift(1, 0),
|
||||
SetSelected = bitLShift(1, 1),
|
||||
NoCloseWithMiddleMouseButton = bitLShift(1, 2),
|
||||
NoPushId = bitLShift(1, 3),
|
||||
NoTooltip = bitLShift(1, 4),
|
||||
NoReorder = bitLShift(1, 5),
|
||||
Leading = bitLShift(1, 6),
|
||||
Trailing = bitLShift(1, 7),
|
||||
NoAssumedClosure = bitLShift(1, 8),
|
||||
-- Private
|
||||
NoCloseButton = bitLShift(1, 20),
|
||||
Button = bitLShift(1, 21),
|
||||
Invisible = bitLShift(1, 22),
|
||||
Unsorted = bitLShift(1, 23),
|
||||
}
|
||||
ImGuiTabItemFlags.SectionMask_ = bitOr(ImGuiTabItemFlags.Leading, ImGuiTabItemFlags.Trailing)
|
||||
|
||||
-- Storage for one active tab item. In this port the label is stored in `Name` (C++ uses NameOffset into TabBar.TabsNames)
|
||||
--- @class ImGuiTabItem
|
||||
--- @return ImGuiTabItem
|
||||
function ImGuiTabItem()
|
||||
return {
|
||||
ID = 0, Flags = 0, Window = nil,
|
||||
LastFrameVisible = -1, LastFrameSelected = -1,
|
||||
Offset = 0.0, Width = 0.0, ContentWidth = 0.0, RequestedWidth = -1.0,
|
||||
NameOffset = -1, Name = nil,
|
||||
BeginOrder = -1, -- 0-based
|
||||
IndexDuringLayout = -1, -- 0-based
|
||||
WantClose = false,
|
||||
}
|
||||
end
|
||||
|
||||
-- Storage for a tab bar. Tabs: ImVector of ImGuiTabItem tables (references; "pointers" stay valid across reorders)
|
||||
--- @class ImGuiTabBar
|
||||
--- @return ImGuiTabBar
|
||||
function ImGuiTabBar()
|
||||
return {
|
||||
Window = nil, Tabs = ImVector(), Flags = 0, ID = 0,
|
||||
SelectedTabId = 0, NextSelectedTabId = 0, NextScrollToTabId = 0, VisibleTabId = 0,
|
||||
CurrFrameVisible = -1, PrevFrameVisible = -1,
|
||||
BarRect = ImRect(), BarRectPrevWidth = 0.0,
|
||||
CurrTabsContentsHeight = 0.0, PrevTabsContentsHeight = 0.0,
|
||||
WidthAllTabs = 0.0, WidthAllTabsIdeal = 0.0,
|
||||
ScrollingAnim = 0.0, ScrollingTarget = 0.0, ScrollingTargetDistToVisibility = 0.0, ScrollingSpeed = 0.0,
|
||||
ScrollingRectMinX = 0.0, ScrollingRectMaxX = 0.0, SeparatorMinX = 0.0, SeparatorMaxX = 0.0,
|
||||
ReorderRequestTabId = 0, ReorderRequestOffset = 0, BeginCount = 0,
|
||||
WantLayout = false, VisibleTabWasSubmitted = false, TabsAddedNew = false, ScrollButtonEnabled = false,
|
||||
TabsActiveCount = 0,
|
||||
LastTabItemIdx = -1, -- 0-based
|
||||
ItemSpacingY = 0.0, FramePadding = ImVec2(), BackupCursorPos = ImVec2(),
|
||||
}
|
||||
end
|
||||
|
||||
--- @class ImGuiShrinkWidthItem
|
||||
function ImGuiShrinkWidthItem() return { Index = 0, Width = 0.0, InitialWidth = 0.0 } end
|
||||
|
||||
--- @param shared_font_atlas? ImFontAtlas
|
||||
--- @return ImGuiContext
|
||||
--- @nodiscard
|
||||
@@ -1881,6 +2014,15 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct
|
||||
|
||||
ComboPreviewData = ImGuiComboPreviewData(),
|
||||
|
||||
CurrentTabBar = nil,
|
||||
TabBars = ImPool(ImGuiTabBar), -- ImPool<ImGuiTabBar>
|
||||
-- Docking
|
||||
DockContext = ImGuiDockContext(),
|
||||
DockNodeWindowMenuHandler = nil,
|
||||
DebugHoveredDockNode = nil,
|
||||
CurrentTabBarStack = ImVector(), -- holds ImGuiTabBar references directly (no ImGuiPtrOrIndex needed in Lua)
|
||||
ShrinkWidthBuffer = ImVector(), -- ImGuiShrinkWidthItem
|
||||
|
||||
WindowResizeBorderExpectedRect = ImRect(),
|
||||
WindowResizeRelativeMode = false,
|
||||
|
||||
@@ -1914,16 +2056,61 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct
|
||||
UserTextures = ImVector(),
|
||||
|
||||
-- Settings
|
||||
SettingsLoaded = false,
|
||||
SettingsDirtyTimer = 0.0,
|
||||
SettingsIniData = "", -- In memory .ini settings (string)
|
||||
SettingsHandlers = ImVector(), -- List of .ini settings handlers
|
||||
SettingsWindows = ImVector(),
|
||||
SettingsTables = ImVector(),
|
||||
|
||||
-- Hooks
|
||||
Hooks = ImVector(),
|
||||
HookIdNext = 0,
|
||||
|
||||
-- Drag and Drop
|
||||
DragDropActive = false,
|
||||
DragDropWithinSource = false,
|
||||
DragDropWithinTarget = false,
|
||||
DragDropSourceFlags = 0,
|
||||
DragDropSourceFrameCount = -1,
|
||||
DragDropMouseButton = -1,
|
||||
DragDropPayload = ImGuiPayload(),
|
||||
DragDropTargetRect = ImRect(),
|
||||
DragDropTargetClipRect = ImRect(),
|
||||
DragDropTargetId = 0,
|
||||
DragDropTargetFullViewport = 0,
|
||||
DragDropAcceptFlagsCurr = 0, DragDropAcceptFlagsPrev = 0,
|
||||
DragDropAcceptIdCurrRectSurface = 0.0,
|
||||
DragDropAcceptFrameCount = -1,
|
||||
DragDropHoldJustPressedId = 0,
|
||||
|
||||
DragDropAcceptIdPrev = 0, DragDropAcceptIdCurr = 0,
|
||||
|
||||
-- Clipper
|
||||
ClipperTempDataStacked = 0,
|
||||
ClipperTempData = ImVector(),
|
||||
|
||||
-- Logging
|
||||
LogEnabled = false,
|
||||
LogLineFirstItem = false,
|
||||
LogFlags = 0,
|
||||
LogWindow = nil,
|
||||
LogFile = nil,
|
||||
LogBuffer = ImGuiTextBuffer(),
|
||||
LogNextPrefix = nil, LogNextSuffix = nil,
|
||||
LogLinePosY = FLT_MAX,
|
||||
LogDepthRef = 0,
|
||||
LogDepthToExpand = 2, LogDepthToExpandDefault = 2,
|
||||
|
||||
-- Error handling
|
||||
ErrorCallback = nil, ErrorCallbackUserData = nil,
|
||||
ErrorTooltipLockedPos = ImVec2(),
|
||||
ErrorFirst = true,
|
||||
ErrorCountCurrentFrame = 0,
|
||||
StackSizesInNewFrame = nil,
|
||||
ContextName = "",
|
||||
DebugBreakInWindow = 0,
|
||||
|
||||
LocalizationTable = {},
|
||||
|
||||
DebugLogFlags = bitOr(ImGuiDebugLogFlags.EventError, ImGuiDebugLogFlags.OutputToTTY),
|
||||
@@ -1942,6 +2129,16 @@ function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this struct
|
||||
WantCaptureKeyboardNextFrame = -1,
|
||||
WantTextInputNextFrame = -1,
|
||||
TempBuffer = ImVector(),
|
||||
|
||||
-- Tables (imgui_tables.lua)
|
||||
CurrentTable = nil,
|
||||
DebugBreakInTable = 0,
|
||||
TablesTempDataStacked = 0,
|
||||
TablesTempData = ImVector(),
|
||||
Tables = ImPool(), -- ImPool<ImGuiTable>, 0-based indices (imgui_tables.lua)
|
||||
TablesLastTimeActive = ImVector(), -- [table_idx + 1] = float
|
||||
DrawChannelsTempMergeBuffer = ImVector(),
|
||||
SettingsTables = ImVector(), -- ImChunkStream<ImGuiTableSettings>: plain vector, SettingsOffset = 1-based index
|
||||
}
|
||||
|
||||
for i = 0, 59 do this.FramerateSecPerFrame[i] = 0 end
|
||||
@@ -1989,6 +2186,12 @@ function ImGuiWindowSettings()
|
||||
WantApply = false,
|
||||
WantDelete = false,
|
||||
Name = "",
|
||||
ViewportId = 0,
|
||||
ViewportPos = ImVec2(0, 0),
|
||||
DockId = 0,
|
||||
DockOrder = -1,
|
||||
ClassId = 0,
|
||||
LastUsedDate = 0,
|
||||
}, IMGUI_WINDOW_SETTINGS)
|
||||
end
|
||||
|
||||
@@ -2049,6 +2252,8 @@ end
|
||||
--- @nodiscard
|
||||
local function ImGuiWindowTempData()
|
||||
return {
|
||||
DockTabItemStatusFlags = 0,
|
||||
DockTabItemRect = ImRect(),
|
||||
CursorPos = ImVec2(),
|
||||
CursorPosPrevLine = ImVec2(),
|
||||
CursorStartPos = ImVec2(),
|
||||
@@ -2082,6 +2287,8 @@ local function ImGuiWindowTempData()
|
||||
TreeRecordsClippedNodesY2Mask = nil,
|
||||
|
||||
ChildWindows = ImVector(),
|
||||
CurrentTableIdx = -1, -- 0-based index into g.Tables, -1 if none
|
||||
CurrentColumns = nil, -- ImGuiOldColumns (legacy Columns API)
|
||||
StateStorage = nil,
|
||||
|
||||
LayoutType = nil
|
||||
@@ -2274,6 +2481,7 @@ function ImGuiWindow(ctx, name)
|
||||
LastTimeActive = -1.0,
|
||||
|
||||
StateStorage = {},
|
||||
ColumnsStorage = ImVector(), -- ImVector<ImGuiOldColumns>
|
||||
|
||||
WriteAccessed = false,
|
||||
|
||||
@@ -2297,6 +2505,21 @@ function ImGuiWindow(ctx, name)
|
||||
this.ID = ImHashStr(name)
|
||||
this.IDStack:push_back(this.ID)
|
||||
this.MoveId = this:GetID("#MOVE")
|
||||
this.TabId = this:GetID("#TAB")
|
||||
-- Docking
|
||||
this.ChildId = this.ChildId or 0
|
||||
this.SetWindowDockAllowFlags = 0
|
||||
this.ParentWindowForFocusRoute = nil
|
||||
this.DockIsActive = false
|
||||
this.DockNodeIsVisible = false
|
||||
this.DockTabIsVisible = false
|
||||
this.DockTabWantClose = false
|
||||
this.DockOrder = -1
|
||||
this.DockStyle = { Colors = {} }
|
||||
for i = 0, 8 do this.DockStyle.Colors[i] = 0 end
|
||||
this.DockNode = nil
|
||||
this.DockNodeAsHost = nil
|
||||
this.DockId = 0
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -301,6 +301,28 @@ function ImGui.BulletText(fmt, ...)
|
||||
ImGui.RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0), text, 1, text_end, false)
|
||||
end
|
||||
|
||||
-- va_list variants: identical to the varargs versions in Lua
|
||||
ImGui.TextColoredV = ImGui.TextColored
|
||||
ImGui.TextDisabledV = ImGui.TextDisabled
|
||||
ImGui.TextWrappedV = ImGui.TextWrapped
|
||||
ImGui.TextAlignedV = ImGui.TextAligned
|
||||
ImGui.LabelTextV = ImGui.LabelText
|
||||
ImGui.BulletTextV = ImGui.BulletText
|
||||
|
||||
-- Value(prefix, b) / Value(prefix, int) / Value(prefix, float, float_format)
|
||||
-- Lua can't tell int from float: integers without float_format print as %d, otherwise %.3f
|
||||
function ImGui.Value(prefix, v, float_format)
|
||||
if type(v) == "boolean" then
|
||||
ImGui.Text("%s: %s", prefix, v and "true" or "false")
|
||||
elseif float_format then
|
||||
ImGui.Text("%s: " .. float_format, prefix, v)
|
||||
elseif math.floor(v) == v then
|
||||
ImGui.Text("%s: %d", prefix, v)
|
||||
else
|
||||
ImGui.Text("%s: %.3f", prefix, v)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- [SECTION] MAIN: BUTTONS, SCROLLBARS, ...
|
||||
----------------------------------------------------------------
|
||||
@@ -1198,6 +1220,7 @@ function ImGui.CheckboxFlags(label, flags, flags_value)
|
||||
|
||||
return pressed, flags
|
||||
end
|
||||
ImGui.CheckboxFlagsT = ImGui.CheckboxFlags
|
||||
|
||||
--- @param label string
|
||||
--- @param active bool
|
||||
@@ -2625,6 +2648,26 @@ function ImGui.InputFloat3(label, v, format, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.Float, v, 3, nil, nil, format, flags)
|
||||
end
|
||||
|
||||
function ImGui.InputFloat2(label, v, format, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.Float, v, 2, nil, nil, format or "%.3f", flags)
|
||||
end
|
||||
|
||||
function ImGui.InputFloat4(label, v, format, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.Float, v, 4, nil, nil, format or "%.3f", flags)
|
||||
end
|
||||
|
||||
function ImGui.InputInt2(label, v, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.S32, v, 2, nil, nil, "%d", flags)
|
||||
end
|
||||
|
||||
function ImGui.InputInt3(label, v, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.S32, v, 3, nil, nil, "%d", flags)
|
||||
end
|
||||
|
||||
function ImGui.InputInt4(label, v, flags)
|
||||
return ImGui.InputScalarN(label, ImGuiDataType.S32, v, 4, nil, nil, "%d", flags)
|
||||
end
|
||||
|
||||
--- @param label string
|
||||
--- @param v int
|
||||
--- @param step? int
|
||||
@@ -3041,6 +3084,112 @@ function ImGui.DragInt(label, v, v_speed, v_min, v_max, format, flags)
|
||||
return ImGui.DragScalar(label, ImGuiDataType.S32, v, v_speed, v_min, v_max, format, flags)
|
||||
end
|
||||
|
||||
-- `v` is mutated in place (1-based), returns value_changed
|
||||
function ImGui.DragScalarN(label, data_type, v, components, v_speed, v_min, v_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 false
|
||||
end
|
||||
|
||||
local g = GImGui
|
||||
local value_changed = false
|
||||
ImGui.BeginGroup()
|
||||
ImGui.PushID(label)
|
||||
ImGui.PushMultiItemsWidths(components, ImGui.CalcItemWidth())
|
||||
for i = 1, components do
|
||||
ImGui.PushID(i - 1)
|
||||
if i > 1 then
|
||||
ImGui.SameLine(0, g.Style.ItemInnerSpacing.x)
|
||||
end
|
||||
if bit32.band(flags, ImGuiSliderFlags.ColorMarkers) ~= 0 then
|
||||
ImGui.SetNextItemColorMarker(GDefaultRgbaColorMarkers[i])
|
||||
end
|
||||
local changed
|
||||
v[i], changed = ImGui.DragScalar("", data_type, v[i], v_speed, v_min, v_max, format, flags)
|
||||
value_changed = value_changed or changed
|
||||
ImGui.PopID()
|
||||
ImGui.PopItemWidth()
|
||||
end
|
||||
ImGui.PopID()
|
||||
|
||||
local label_end = ImGui.FindRenderedTextEnd(label)
|
||||
if label_end > 1 then
|
||||
ImGui.SameLine(0, g.Style.ItemInnerSpacing.x)
|
||||
ImGui.TextEx(label, label_end)
|
||||
end
|
||||
|
||||
ImGui.EndGroup()
|
||||
return value_changed
|
||||
end
|
||||
|
||||
local function DragFloatN(n)
|
||||
return function(label, v, v_speed, v_min, v_max, format, flags)
|
||||
return ImGui.DragScalarN(label, ImGuiDataType.Float, v, n, v_speed or 1.0, v_min or 0.0, v_max or 0.0, format or "%.3f", flags or 0)
|
||||
end
|
||||
end
|
||||
local function DragIntN(n)
|
||||
return function(label, v, v_speed, v_min, v_max, format, flags)
|
||||
return ImGui.DragScalarN(label, ImGuiDataType.S32, v, n, v_speed or 1.0, v_min or 0, v_max or 0, format or "%d", flags or 0)
|
||||
end
|
||||
end
|
||||
ImGui.DragFloat2 = DragFloatN(2)
|
||||
ImGui.DragFloat3 = DragFloatN(3)
|
||||
ImGui.DragFloat4 = DragFloatN(4)
|
||||
ImGui.DragInt2 = DragIntN(2)
|
||||
ImGui.DragInt3 = DragIntN(3)
|
||||
ImGui.DragInt4 = DragIntN(4)
|
||||
|
||||
-- NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this.
|
||||
--- @return float v_current_min
|
||||
--- @return float v_current_max
|
||||
--- @return bool value_changed
|
||||
local function DragRange2(data_type, label, v_current_min, v_current_max, v_speed, v_min, v_max, format, format_max, flags)
|
||||
local window = ImGui.GetCurrentWindow()
|
||||
if window.SkipItems then
|
||||
return v_current_min, v_current_max, false
|
||||
end
|
||||
|
||||
local g = GImGui
|
||||
local lo = (data_type == ImGuiDataType.Float) and -FLT_MAX or INT_MIN
|
||||
local hi = (data_type == ImGuiDataType.Float) and FLT_MAX or INT_MAX
|
||||
ImGui.PushID(label)
|
||||
ImGui.BeginGroup()
|
||||
ImGui.PushMultiItemsWidths(2, ImGui.CalcItemWidth())
|
||||
|
||||
local min_min = (v_min >= v_max) and lo or v_min
|
||||
local min_max = (v_min >= v_max) and v_current_max or ImMin(v_max, v_current_max)
|
||||
local min_flags = bit32.bor(flags, (min_min == min_max) and ImGuiSliderFlags.ReadOnly or 0)
|
||||
local value_changed, changed
|
||||
v_current_min, value_changed = ImGui.DragScalar("##min", data_type, v_current_min, v_speed, min_min, min_max, format, min_flags)
|
||||
ImGui.PopItemWidth()
|
||||
ImGui.SameLine(0, g.Style.ItemInnerSpacing.x)
|
||||
|
||||
local max_min = (v_min >= v_max) and v_current_min or ImMax(v_min, v_current_min)
|
||||
local max_max = (v_min >= v_max) and hi or v_max
|
||||
local max_flags = bit32.bor(flags, (max_min == max_max) and ImGuiSliderFlags.ReadOnly or 0)
|
||||
v_current_max, changed = ImGui.DragScalar("##max", data_type, v_current_max, v_speed, max_min, max_max, format_max or format, max_flags)
|
||||
value_changed = value_changed or changed
|
||||
ImGui.PopItemWidth()
|
||||
ImGui.SameLine(0, g.Style.ItemInnerSpacing.x)
|
||||
|
||||
ImGui.TextEx(label, ImGui.FindRenderedTextEnd(label))
|
||||
ImGui.EndGroup()
|
||||
ImGui.PopID()
|
||||
|
||||
return v_current_min, v_current_max, value_changed
|
||||
end
|
||||
|
||||
function ImGui.DragFloatRange2(label, v_current_min, v_current_max, v_speed, v_min, v_max, format, format_max, flags)
|
||||
return DragRange2(ImGuiDataType.Float, label, v_current_min, v_current_max, v_speed or 1.0, v_min or 0.0, v_max or 0.0, format or "%.3f", format_max, flags or 0)
|
||||
end
|
||||
|
||||
function ImGui.DragIntRange2(label, v_current_min, v_current_max, v_speed, v_min, v_max, format, format_max, flags)
|
||||
return DragRange2(ImGuiDataType.S32, label, v_current_min, v_current_max, v_speed or 1.0, v_min or 0, v_max or 0, format or "%d", format_max, flags or 0)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- [SECTION] SLIDERXXX
|
||||
----------------------------------------------------------------
|
||||
@@ -3651,6 +3800,18 @@ function ImGui.SliderInt(label, v, v_min, v_max, format, flags)
|
||||
return ImGui.SliderScalar(label, ImGuiDataType.S32, v, v_min, v_max, format, flags)
|
||||
end
|
||||
|
||||
function ImGui.SliderInt2(label, v, v_min, v_max, format, flags)
|
||||
return ImGui.SliderScalarN(label, ImGuiDataType.S32, v, 2, v_min, v_max, format or "%d", flags)
|
||||
end
|
||||
|
||||
function ImGui.SliderInt3(label, v, v_min, v_max, format, flags)
|
||||
return ImGui.SliderScalarN(label, ImGuiDataType.S32, v, 3, v_min, v_max, format or "%d", flags)
|
||||
end
|
||||
|
||||
function ImGui.SliderInt4(label, v, v_min, v_max, format, flags)
|
||||
return ImGui.SliderScalarN(label, ImGuiDataType.S32, v, 4, v_min, v_max, format or "%d", flags)
|
||||
end
|
||||
|
||||
--- @param label string
|
||||
--- @param size ImVec2
|
||||
--- @param data_type ImGuiDataType
|
||||
@@ -3764,6 +3925,11 @@ function ImGui.InputText(label, buf, buf_size, flags, callback, user_data)
|
||||
return ImGui.InputTextEx(label, nil, buf, buf_size, ImVec2(0, 0), flags, callback, user_data)
|
||||
end
|
||||
|
||||
--- @param size? ImVec2
|
||||
function ImGui.InputTextMultiline(label, buf, buf_size, size, flags, callback, user_data)
|
||||
return ImGui.InputTextEx(label, nil, buf, buf_size, size or ImVec2(0, 0), bit32.bor(flags or 0, ImGuiInputTextFlags.Multiline), callback, user_data)
|
||||
end
|
||||
|
||||
ImStb = {}
|
||||
|
||||
--- @module "imstb_textedit"
|
||||
@@ -5811,6 +5977,27 @@ function ImGui.ColorEdit3(label, col, flags)
|
||||
return ImGui.ColorEdit4(label, col, bit32.bor(flags, ImGuiColorEditFlags.NoAlpha))
|
||||
end
|
||||
|
||||
-- `col` mutated in place, returns value_changed
|
||||
function ImGui.ColorPicker3(label, col, flags)
|
||||
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
|
||||
end
|
||||
col[1] = col4[1]; col[2] = col4[2]; col[3] = col4[3]
|
||||
return true
|
||||
end
|
||||
|
||||
function ImGui.SetColorEditOptions(flags)
|
||||
local g = GImGui
|
||||
local def = ImGuiColorEditFlags.DefaultOptions_
|
||||
for _, mask in ipairs({ ImGuiColorEditFlags.DisplayMask_, ImGuiColorEditFlags.DataTypeMask_, ImGuiColorEditFlags.PickerMask_, ImGuiColorEditFlags.InputMask_ }) do
|
||||
if bit32.band(flags, mask) == 0 then
|
||||
flags = bit32.bor(flags, bit32.band(def, mask))
|
||||
end
|
||||
end
|
||||
g.IO.ConfigColorEditFlags = flags
|
||||
end
|
||||
|
||||
-- Helper for ColorPicker4()
|
||||
--- @param draw_list ImDrawList
|
||||
--- @param pos ImVec2
|
||||
|
||||
Reference in New Issue
Block a user