Draw list 1.93: baked round corners in the font atlas (ImFontAtlasBuildUpdateTexDataCorners, fill radii 1..16 + 3 stroke thicknesses) used by AddRect/AddRectFilled when pixel-aligned (_AddRectBaked/_AddRectFilledBaked)

This commit is contained in:
4DBug
2026-10-15 06:55:57 -05:00
parent af2026113a
commit 9872d43fd6
7 changed files with 1357 additions and 232 deletions
+384 -8
View File
@@ -1,7 +1,7 @@
--!optimize 2
-- GENERATED by tools/bundle.py from *.lua, backends/, fonts/ - do not edit
local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImGuiDataType, ImStb, IM_TRUNC, ImGuiKey, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, IM_ASSERT_USER_ERROR_RET, ImHashStr, ImS32, ImGuiColorEditFlags, ImIsPowerOfTwo, ImAbs, ImVec4_Copy, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, ImGui_ImplRoblox_GetBackendData, stbte, ImColor, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiLocKey, ImU32, ExampleTreeFuncs, IM_ASSERT_PARANOID, ImCos, ImGuiListClipper, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImGuiTabBarFlags, ImSin, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImGuiCol, ImGuiSelectionBasicStorage, ImLengthSqr, ImS8, ImU8, ExampleAppPropertyEditorMT, ImFabs, ImGuiChildFlags, ImGuiLastItemData_Copy, ImGuiScrollFlags, ImLog, ImMemchr, ImStrByte, ExampleSelectionWithDeletionMT, IMGUI_DEBUG_LOG_VIEWPORT, ImGuiInputEvent, ImGuiTextBuffer, ImPow, ImTrunc64, CustomConstraints, ExampleAppLogMT, IMGUI_DEBUG_LOG_FONT, IMGUI_DEBUG_LOG_SELECTION, ImAddClampOverflow, ImFontAtlasBuildInit, ImFontCalcWordWrapPositionEx, ImGuiComboFlags, ImGuiLastItemData, ImGuiPayload_IsDataType, ImGuiPopupFlags, ImGuiSliderFlags, ImGuiTextFilter, ImRotate, ImSqrt, ImSubClampOverflow, ImTextClassifierSetCharClass, MyDocument, ShowExampleMenuFile, CalcNextScrollFromScrollTargetAndClamp, IMGUI_PAYLOAD_TYPE_WINDOW, IMGUI_VERSION, ImCharIsBlankW, ImCharIsSeparatorW, ImFmod, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImGuiInputTextFlags, ImGuiNavMoveFlags, ImGuiStyle_Copy, ImHashData, ImVec1_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, ExampleTree_CreateNode, IMGUI_PAYLOAD_TYPE_COLOR_4F, IM_F32_TO_INT8_UNBOUND, IM_PI, ImCharIsBlankA, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroyOutput, ImFontAtlasFontDiscardBakes, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImFontAtlasRectId_GetIndex, ImFontAtlasTextureAdd, ImFontAtlasTextureBlockQueueUpload, ImFontAtlasTextureGrow, ImFontBaked_BuildGrowIndex, ImFontConfig, ImFontGlyph, ImGuiTableColumn, ImGuiWindowClass, ImGui_ImplRoblox_RenderDrawData, ImParseFormatFindStart, ImRect_CopyFromV4, ImTextureRect, ImTextureRef, MyItem_s_current_sort_specs, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, DockSettingsHandler_ClearAll, EditTableSizingFlags, ExampleSelectionWithDeletion, IMGUI_DEBUG_LOG_TABLE, IMGUI_PAYLOAD_TYPE_COLOR_3F, IM_FREE, ImDrawListSplitter, ImFontAtlasBakedDiscard, ImFontAtlasBuildDestroy, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildSetTexture, ImFontAtlasBuildSetupFontBakedFallback, ImFontAtlasFontDestroySourceData, ImFontAtlasPackInit, ImFontAtlasTextureBlockCopy, ImFontAtlasTextureGetSizeEstimate, ImFontAtlasUpdateDrawListsSharedData
local ImGui, ImVec2, ImVec4, ImRect, HelpMarker, ImVec2_Copy, IMGUI_DEMO_MARKER, ImGuiTableFlags, ImStd, ImVector, ImDrawFlags, ImGuiInputFlags, ImRect_Copy, ImGuiDataType, ImStb, IM_TRUNC, ImGuiKey, ImVec2_CopyV, ImGuiStyleVarInfo, IM_ASSERT_USER_ERROR, ImGuiHoveredFlags, ImFormatString, IM_ASSERT_USER_ERROR_RET, ImHashStr, ImS32, ImGuiColorEditFlags, ImIsPowerOfTwo, ImAbs, ImVec4_Copy, ExampleAppConsoleMT, IM_ROUND, ImGuiTableColumnFlags, ImGuiTreeNodeFlags, PopStyleCompact, PushStyleCompact, IM_ASSERT_PARANOID, ImU16, ExampleNames, ImGuiWindowFlags, ImGuiItemFlags, ImGui_ImplRoblox_GetBackendData, stbte, ImColor, ImCos, ImGuiButtonFlags, ImGuiDebugLogFlags, ImGuiLocKey, ImU32, ExampleTreeFuncs, ImGuiListClipper, ImS16, _PathArcToFastExXY, ImGuiMultiSelectFlags, ImSin, ImGuiTabBarFlags, ImUpperPowerOfTwo, IM_F32_TO_INT8_SAT, ImFontAtlasPackGetRect, DockSettingsRenameNodeReferences, ExampleDualListBoxMT, IM_DRAWLIST_TEX_LINES_WIDTH_MAX, ImCeil, ImGuiCol, ImGuiSelectionBasicStorage, ImLengthSqr, ImS8, ImU8, ExampleAppPropertyEditorMT, ImFabs, ImGuiChildFlags, ImGuiLastItemData_Copy, ImGuiScrollFlags, ImLog, ImMemchr, ImStrByte, ExampleSelectionWithDeletionMT, IMGUI_DEBUG_LOG_VIEWPORT, ImGuiInputEvent, ImGuiTextBuffer, ImPow, ImTrunc64, CustomConstraints, ExampleAppLogMT, IMGUI_DEBUG_LOG_FONT, IMGUI_DEBUG_LOG_SELECTION, ImAddClampOverflow, ImFontAtlasBuildInit, ImFontCalcWordWrapPositionEx, ImGuiComboFlags, ImGuiLastItemData, ImGuiPayload_IsDataType, ImGuiPopupFlags, ImGuiSliderFlags, ImGuiTextFilter, ImRotate, ImSqrt, ImSubClampOverflow, ImTextClassifierSetCharClass, MyDocument, ShowExampleMenuFile, CalcCornerArcStepAndCount, CalcNextScrollFromScrollTargetAndClamp, IMGUI_PAYLOAD_TYPE_WINDOW, IMGUI_VERSION, ImCharIsBlankW, ImCharIsSeparatorW, ImFmod, ImFontAtlasBakedAddFontGlyph, ImFontAtlasPackAddRect, ImFontBaked_BuildLoadGlyph, ImGuiInputTextFlags, ImGuiNavMoveFlags, ImGuiStyle_Copy, ImHashData, ImVec1_Copy, ExampleAsset_s_current_sort_specs, ExampleMemberInfo, ExampleTree_CreateNode, IMGUI_PAYLOAD_TYPE_COLOR_4F, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC, IM_F32_TO_INT8_UNBOUND, IM_PI, ImCharIsBlankA, ImFontAtlasBuildRenderBitmapFromString, ImFontAtlasFontDestroyOutput, ImFontAtlasFontDiscardBakes, ImFontAtlasFontSourceAddToFont, ImFontAtlasFontSourceInit, ImFontAtlasRectId_GetIndex, ImFontAtlasTextureAdd, ImFontAtlasTextureBlockQueueUpload, ImFontAtlasTextureGrow, ImFontBaked_BuildGrowIndex, ImFontConfig, ImFontGlyph, ImGuiTableColumn, ImGuiWindowClass, ImGui_ImplRoblox_RenderDrawData, ImParseFormatFindStart, ImRect_CopyFromV4, ImTextureRect, ImTextureRef, MyItem_s_current_sort_specs, stb_textedit_key, stbtt_GetGlyphBitmapBoxSubpixel, DockSettingsHandler_ClearAll, EditTableSizingFlags, ExampleSelectionWithDeletion, IMGUI_DEBUG_LOG_TABLE, IMGUI_PAYLOAD_TYPE_COLOR_3F, IM_FREE, ImDrawListSplitter, ImFontAtlasBakedDiscard, ImFontAtlasBuildDestroy, ImFontAtlasBuildNotifySetFont, ImFontAtlasBuildSetTexture, ImFontAtlasBuildSetupFontBakedFallback, ImFontAtlasFontDestroySourceData, ImFontAtlasPackInit, ImFontAtlasRect
local type, mathMin, mathMax, mathFloor, mathCeil, bitOr, bitLShift = type, math.min, math.max, math.floor, math.ceil, bit32.bor, bit32.lshift
local function IM_COL32(R, G, B, A) return (bitOr(bitLShift(A, 24 --[[IM_COL32_A_SHIFT]]), bitLShift(B, 16 --[[IM_COL32_B_SHIFT]]), bitLShift(G, 8 --[[IM_COL32_G_SHIFT]]), bitLShift(R, 0 --[[IM_COL32_R_SHIFT]]))) end
@native
@@ -33758,7 +33758,10 @@ local ImFontAtlasBakedGetClosestMatch
local ImFontAtlasBuildInit
local ImFontAtlasBuildSetTexture
local ImFontAtlasBuildUpdateTexDataLines
local ImFontAtlasBuildUpdateTexDataCorners
local ImFontAtlasBuildUpdateTexDataBasic
local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC -- [Luau] forward declared, defined in [SECTION] ImDrawList
local CalcCornerArcStepAndCount -- [Luau] forward declared, defined in [SECTION] ImDrawList
local ImFontAtlasBuildSetupFontLoader
local ImFontAtlasBuildSetupFontSpecialGlyphs
local ImFontAtlasBuildSetupFontBakedBlanks
@@ -35264,7 +35267,7 @@ end
function ImFontAtlasBuildUpdateTexData(atlas)
ImFontAtlasBuildUpdateTexDataBasic(atlas)
ImFontAtlasBuildUpdateTexDataLines(atlas)
-- [Port] TODO baked round corners: ImFontAtlasBuildUpdateTexDataCorners(atlas)
ImFontAtlasBuildUpdateTexDataCorners(atlas)
end
-- Create a new texture, discard previous one
@@ -35388,6 +35391,176 @@ function ImFontAtlasPackInit(atlas)
end
--- @param atlas ImFontAtlas
-- #define IM_DRAWLIST_CORNER_POINTS_MAX (IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4 + 3) // Max number of points in corner profiles
-- [Luau] ImVec2 line_normals[] / float line_distances[] / ImVec2 points[] are flat 1-based scratch arrays (x, y, distance).
local corner_points_x, corner_points_y = {}, {}
local corner_normals_x, corner_normals_y, corner_distances = {}, {}, {}
-- [Luau] line_normals is passed as two arrays (line_normals_x, line_normals_y), 1-based.
local function InitCornerGeometry(cx, cy, rounding, circle_segment_max_error, line_normals_x, line_normals_y, line_distances)
-- This tries to quite faithfully replicate how we render the corners using tessellation.
-- Older code sampled a circle SDF directly, but it had clearly visible discrepancy between the baked corners
-- and tessellated corners due to circle_segment_max_error.
local auto_seg_count = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(rounding, circle_segment_max_error)
local arc_step, arc_step_count = CalcCornerArcStepAndCount(auto_seg_count)
local arc_point_count = arc_step_count + 1
-- Build arc of points, with straight segments at each end.
-- . [n-2]..[n-1]
-- .`
-- .
-- [1] x (cx,cy)
-- :
-- [0]
local points_x, points_y = corner_points_x, corner_points_y
local num_points = 0
num_points = num_points + 1; points_x[num_points] = cx - rounding; points_y[num_points] = cy + 1.0
local da = (arc_step / 48 --[[IM_DRAWLIST_ARCFAST_TABLE_SIZE]]) * 3.141592653589793 --[[IM_PI]] * 2.0
local a = 3.141592653589793 --[[IM_PI]]
for _ = 0, arc_point_count - 1 do
local dx = ImCos(a)
local dy = ImSin(a)
num_points = num_points + 1; points_x[num_points] = cx + dx * rounding; points_y[num_points] = cy + dy * rounding
a = a + da
end
num_points = num_points + 1; points_x[num_points] = cx + 1.0; points_y[num_points] = cy - rounding
-- Turn segments to half spaces.
for i = 1, num_points - 1 do
local diff_x = points_x[i + 1] - points_x[i]
local diff_y = points_y[i + 1] - points_y[i]
local d2 = diff_x * diff_x + diff_y * diff_y
local inv_d = ImRsqrtPrecise(d2)
line_normals_x[i] = diff_y * inv_d -- Normal points outwards
line_normals_y[i] = -diff_x * inv_d
line_distances[i] = -(points_x[i] * line_normals_x[i] + points_y[i] * line_normals_y[i]) -- -ImDot()
end
return num_points - 1
end
-- Returns distance to convex shape limited by lines.
local function SampleConvex(x, y, line_normals_x, line_normals_y, line_distances, num_lines)
local result = -3.4028234663853e+38 --[[FLT_MAX]]
for i = 1, num_lines do
local d = line_normals_x[i] * x + line_normals_y[i] * y + line_distances[i]
if d > result then
result = d
end
end
return result
end
local function SampleCornerFillOrStroke(x, y, thickness, line_normals_x, line_normals_y, line_distances, num_lines)
local d = SampleConvex(x, y, line_normals_x, line_normals_y, line_distances, num_lines)
local aa_width = 1.0
if thickness == 0.0 then
-- Fill
return math.floor(ImClamp(1.0 - (d + aa_width * 0.5) / aa_width, 0.0, 1.0) * 255.0) -- (ImU8)
else
-- Stroke
local outer = 1.0 - (d + aa_width * 0.5) / aa_width
local inner = (d + thickness + aa_width * 0.5) / aa_width
return math.floor(ImClamp(ImMin(inner, outer), 0.0, 1.0) * 255.0) -- (ImU8)
end
end
-- [Port] #if 0 DEBUG_TEX_CORNER_U8/DEBUG_TEX_CORNER_U32 coverage visualization not ported (always 0xFF/0xFFFFFFFF).
function ImFontAtlasBuildUpdateTexDataCorners(atlas)
if bit32.band(atlas.Flags, 8 --[[ImFontAtlasFlags.NoBakedRoundCorners]]) ~= 0 then
return
end
-- Pack and store identifier so we can refresh UV coordinates on texture resize.
local tex = atlas.TexData
local builder = atlas.Builder
-- FIXME-TEXCORNERS: Ideally we should pick up the max error from the styles, but it does not seem be to set by the time we build the data the first time.
local circle_segment_max_error = 0.30 -- Default matching ImGuiStyle::CircleTessellationMaxError.
-- if (atlas->OwnerContext)
-- circle_segment_max_error = atlas->OwnerContext->DrawListSharedData.CircleSegmentMaxError;
-- Calculate size and pack
local r = ImFontAtlasRect()
local add_and_draw = (atlas:GetCustomRect(builder.PackIdCornersTexData, r) == false)
if add_and_draw then
-- (thickness 0 for filled, thickness >0 for strokes)
local pack_size_x, pack_size_y = 0, 0 -- ImVec2i
for thickness = 0, 4 --[[IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]] - 1 do
local is_filled = (thickness == 0)
local row_width = 0
local row_height = 0
for n = 0, 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]] - 1 do
local rounding = n + 1
local size = is_filled and (rounding + 1) or ImMax(rounding, thickness)
row_width = row_width + size + 2
row_height = ImMax(row_height, size + 2)
end
pack_size_x = ImMax(pack_size_x, row_width)
pack_size_y = pack_size_y + row_height
end
builder.PackIdCornersTexData = atlas:AddCustomRect(pack_size_x, pack_size_y, r)
assert(builder.PackIdCornersTexData ~= (-1) --[[ImFontAtlasRectId_Invalid]])
end
-- Render
local y = r.y
local line_normals_x, line_normals_y, line_distances = corner_normals_x, corner_normals_y, corner_distances
for thickness = 0, 4 --[[IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]] - 1 do
local is_filled = (thickness == 0)
local x = r.x
local row_height = 0
for n = 0, 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]] - 1 do
-- Filled: Always add 1px to the fill side of the rounded corner to prevent the corner AA to bleed into the rectangle edges.
local rounding = n + 1
local size = is_filled and (rounding + 1) or ImMax(rounding, thickness)
local w = size + 2
local h = size + 2
-- Corner circle
local cx = 1.0 + (n + 1)
local cy = 1.0 + (n + 1)
assert((x + w) <= (r.x + r.w) and (y + h) <= (r.y + r.h)) -- Make sure we're inside the texture bounds
local num_lines = InitCornerGeometry(cx, cy, rounding, circle_segment_max_error, line_normals_x, line_normals_y, line_distances)
-- Write each slice
if add_and_draw and tex.Format == 1 --[[ImTextureFormat.Alpha8]] then
local write_ptr, write_ptr_base = tex:GetPixelsAt(x, y)
local pitch = tex.Width
for ly = 0, h - 1 do
for lx = 0, w - 1 do
write_ptr[write_ptr_base + lx] = SampleCornerFillOrStroke(lx + 0.5, ly + 0.5, thickness, line_normals_x, line_normals_y, line_distances, num_lines)
end
write_ptr_base = write_ptr_base + pitch
end
elseif add_and_draw and tex.Format == 0 --[[ImTextureFormat.RGBA32]] then
local write_ptr, write_ptr_base = tex:GetPixelsAt(x, y)
local pitch = tex.Width * 4
for ly = 0, h - 1 do
for lx = 0, w - 1 do
write_u32(write_ptr, write_ptr_base + lx * 4, IM_COL32(255, 255, 255, SampleCornerFillOrStroke(lx + 0.5, ly + 0.5, thickness, line_normals_x, line_normals_y, line_distances, num_lines)))
end
write_ptr_base = write_ptr_base + pitch
end
end
-- Refresh UV coordinates
local uv0_x, uv0_y = (x + 1) * atlas.TexUvScale.x, (y + 1) * atlas.TexUvScale.y
local uv1_x, uv1_y = (x + 1 + size) * atlas.TexUvScale.x, (y + 1 + size) * atlas.TexUvScale.y
builder.TexUvCorners[n + thickness * 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]]] = ImVec4(uv0_x, uv0_y, uv1_x, uv1_y)
x = x + w
row_height = ImMax(row_height, h)
end
y = y + row_height
end
end
function ImFontAtlasBuildUpdateTexDataLines(atlas)
if bit32.band(atlas.Flags, 4 --[[ImFontAtlasFlags.NoBakedLines]]) ~= 0 then
return
@@ -35595,6 +35768,7 @@ function ImFontAtlasUpdateDrawListsSharedData(atlas)
if (shared_data.FontAtlas == atlas) then
shared_data.TexUvWhitePixel = atlas.TexUvWhitePixel
shared_data.TexUvLines = atlas.Builder.TexUvLines
shared_data.TexUvCorners = atlas.Builder.TexUvCorners
end
end
end
@@ -37026,13 +37200,13 @@ end
local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN = 4
local IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX = 512
local function IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD, _MAXERROR) return ImClamp(IM_ROUNDUP_TO_EVEN(ImCeil(3.141592653589793 --[[IM_PI]] / ImAcos(1 - ImMin(_MAXERROR, _RAD) / _RAD))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) end
function IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD, _MAXERROR) return ImClamp(IM_ROUNDUP_TO_EVEN(ImCeil(3.141592653589793 --[[IM_PI]] / ImAcos(1 - ImMin(_MAXERROR, _RAD) / _RAD))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) end
local function IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(_N, _MAXERROR) return (_MAXERROR / (1 - ImCos(3.141592653589793 --[[IM_PI]] / ImMax(_N, 3.141592653589793 --[[IM_PI]])))) end
local function IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_ERROR(_N, _RAD) return ((1 - ImCos(3.141592653589793 --[[IM_PI]] / ImMax(_N, 3.141592653589793 --[[IM_PI]]))) / _RAD) end
-- Calculates arc step and step count for 90 degree arc. The calculated arc step will complete a 90 degree arc when stepped arc_step_count times.
-- [Luau] returns arc_step, arc_step_count (C++ out-references)
local function CalcCornerArcStepAndCount(segment_count)
function CalcCornerArcStepAndCount(segment_count)
local quarter = 48 --[[IM_DRAWLIST_ARCFAST_TABLE_SIZE]] / 4
local arc_step = ImClamp(math.floor(48 --[[IM_DRAWLIST_ARCFAST_SAMPLE_MAX]] / segment_count), 1, quarter)
local arc_step_count = math.floor(quarter / arc_step)
@@ -38641,7 +38815,122 @@ function MT.ImDrawList:AddLineV(x, min_y, max_y, col, thickness, flags)
end
end
-- [Port] TODO baked round corners: _AddRectBaked() (UseTexForRoundCorners) not ported yet, AddRect() falls back to the geometry path.
-- [Luau] IM_APPEND_VTX() x4 + IM_APPEND_TRI(idx + 0, idx + 1, idx + 2) + IM_APPEND_TRI(idx + 0, idx + 2, idx + 3)
local function AppendQuadUV(self, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, col)
local vb = self.VtxBuffer.Buf
local ib = self.IdxBuffer.Data
local vw = self._VtxWritePtr
local iw = self._IdxWritePtr
local idx = self._VtxCurrentIdx
WV(vb, vw + 0, x0, y0, u0, v0, col)
WV(vb, vw + 1, x1, y1, u1, v1, col)
WV(vb, vw + 2, x2, y2, u2, v2, col)
WV(vb, vw + 3, x3, y3, u3, v3, col)
ib[iw + 0] = idx + 0; ib[iw + 1] = idx + 1; ib[iw + 2] = idx + 2
ib[iw + 3] = idx + 0; ib[iw + 4] = idx + 2; ib[iw + 5] = idx + 3
self._VtxWritePtr = vw + 4
self._IdxWritePtr = iw + 6
self._VtxCurrentIdx = idx + 4
end
-- [Luau] _AddRectBaked() taking p_min/p_max as scalars
@native
local function _AddRectBakedXY(self, p_min_x, p_min_y, p_max_x, p_max_y, col, r, t, tex_uvs, flags)
local uv_l, uv_t, uv_r, uv_b = tex_uvs.x, tex_uvs.y, tex_uvs.z, tex_uvs.w -- uv_tl = (l,t), uv_tr = (r,t), uv_br = (r,b), uv_bl = (l,b)
local idx_allocated = 8 * 2 * 3
local vtx_allocated = 8 * 4
PrimReserve(self, idx_allocated, vtx_allocated)
local start_vtx_ptr = self._VtxWritePtr
local start_idx_ptr = self._IdxWritePtr
local round_tl = bit32.band(flags, 16 --[[ImDrawFlags.RoundTopLeft]]) ~= 0
local round_tr = bit32.band(flags, 32 --[[ImDrawFlags.RoundTopRight]]) ~= 0
local round_br = bit32.band(flags, 128 --[[ImDrawFlags.RoundBottomRight]]) ~= 0
local round_bl = bit32.band(flags, 64 --[[ImDrawFlags.RoundBottomLeft]]) ~= 0
if round_tl then
AppendQuadUV(self,
p_min_x, p_min_y, uv_l, uv_t,
p_min_x + r, p_min_y, uv_r, uv_t,
p_min_x + r, p_min_y + r, uv_r, uv_b,
p_min_x, p_min_y + r, uv_l, uv_b, col)
end
if round_tr then
AppendQuadUV(self,
p_max_x - r, p_min_y, uv_r, uv_t,
p_max_x, p_min_y, uv_l, uv_t,
p_max_x, p_min_y + r, uv_l, uv_b,
p_max_x - r, p_min_y + r, uv_r, uv_b, col)
end
if round_br then
AppendQuadUV(self,
p_max_x - r, p_max_y - r, uv_r, uv_b,
p_max_x, p_max_y - r, uv_l, uv_b,
p_max_x, p_max_y, uv_l, uv_t,
p_max_x - r, p_max_y, uv_r, uv_t, col)
end
if round_bl then
AppendQuadUV(self,
p_min_x, p_max_y - r, uv_l, uv_b,
p_min_x + r, p_max_y - r, uv_r, uv_b,
p_min_x + r, p_max_y, uv_r, uv_t,
p_min_x, p_max_y, uv_l, uv_t, col)
end
local r_tl = round_tl and r or 0
local r_tr = round_tr and r or 0
local r_br = round_br and r or 0
local r_bl = round_bl and r or 0
local opaque_uv = self._Data.TexUvWhitePixel
local ou, ov = opaque_uv.x, opaque_uv.y
do
-- Top
local x0 = p_min_x + r_tl
local x1 = p_max_x - r_tr
AppendQuadUV(self, x0, p_min_y, ou, ov, x1, p_min_y, ou, ov, x1, p_min_y + t, ou, ov, x0, p_min_y + t, ou, ov, col)
end
do
-- Left
local y0 = p_min_y + ImMax(r_tl, t)
local y1 = p_max_y - ImMax(r_bl, t)
AppendQuadUV(self, p_min_x, y0, ou, ov, p_min_x + t, y0, ou, ov, p_min_x + t, y1, ou, ov, p_min_x, y1, ou, ov, col)
end
do
-- Right
local y0 = p_min_y + ImMax(r_tr, t)
local y1 = p_max_y - ImMax(r_br, t)
AppendQuadUV(self, p_max_x - t, y0, ou, ov, p_max_x, y0, ou, ov, p_max_x, y1, ou, ov, p_max_x - t, y1, ou, ov, col)
end
do
-- Bottom
local x0 = p_min_x + r_bl
local x1 = p_max_x - r_br
AppendQuadUV(self, x0, p_max_y - t, ou, ov, x1, p_max_y - t, ou, ov, x1, p_max_y, ou, ov, x0, p_max_y, ou, ov, col)
end
local idx_used = self._IdxWritePtr - start_idx_ptr
local vtx_used = self._VtxWritePtr - start_vtx_ptr
IM_ASSERT_PARANOID(idx_used <= idx_allocated and vtx_used <= vtx_allocated)
if idx_used < idx_allocated or vtx_used < vtx_allocated then
self:PrimUnreserve(idx_allocated - idx_used, vtx_allocated - vtx_used)
end
end
--- @param p_min ImVec2
--- @param p_max ImVec2
--- @param col ImU32
--- @param r float
--- @param t float
--- @param tex_uvs ImVec4
--- @param flags ImDrawFlags
function MT.ImDrawList:_AddRectBaked(p_min, p_max, col, r, t, tex_uvs, flags)
_AddRectBakedXY(self, p_min.x, p_min.y, p_max.x, p_max.y, col, r, t, tex_uvs, flags)
end
local corner_offset_x = { 1, -1, -1, 1 } -- static const ImVec2 corner_offset[4] = { {1,1}, {-1,1}, {-1,-1}, {1,-1} };
local corner_offset_y = { 1, 1, -1, -1 }
@@ -38897,7 +39186,18 @@ function MT.ImDrawList:AddRect(p_min, p_max, col, rounding, thickness, flags)
return
end
-- Textured corners are baked with AA, do not use them if no-AA is requested.
-- [Port] TODO baked round corners: allow_tex_corners -> _AddRectBaked(), falls back to the geometry path below.
local allow_tex_corners_mask = bit32.bor(8192 --[[ImDrawFlags.AALines]], 2097152 --[[ImDrawFlags.UseTexForRoundCorners]], 8388608 --[[ImDrawFlags.AllowTexForRoundCorners_]])
local allow_tex_corners = bit32.band(flags, allow_tex_corners_mask) == allow_tex_corners_mask
if allow_tex_corners and s_thickness < 4 --[[IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]] and s_rounding <= 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]] then
-- Pixel aligned rect with round corners rendered using baked textures.
IM_ASSERT_PARANOID(s_thickness > 0 and s_rounding > 0)
local size = ImMax(s_rounding, s_thickness) -- This is matching the baking calculations.
local idx = (s_thickness * 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]]) + s_rounding - 1
-- IM_ASSERT_PARANOID((_Data->Font->OwnerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners) == 0) -- [Luau] not evaluated (arguments are not compiled out)
IM_ASSERT_PARANOID(idx >= 0 and idx < 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]] * 4 --[[IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]])
_AddRectBakedXY(self, outer_min_x, outer_min_y, outer_max_x, outer_max_y, col, size * fringe_scale, thickness, self._Data.TexUvCorners[idx], flags)
return
end
end
if not has_rounding or bit32.band(flags, 496 --[[ImDrawFlags.RoundMask_]]) == 256 --[[ImDrawFlags.RoundNone]] then
@@ -38931,7 +39231,67 @@ function MT.ImDrawList:AddRect(p_min, p_max, col, rounding, thickness, flags)
end
end
-- [Port] TODO baked round corners: _AddRectFilledBaked() (UseTexForRoundCorners) not ported yet, AddRectFilled() falls back to the geometry path.
-- [Luau] _AddRectFilledBaked() taking p_min/p_max as scalars
@native
local function _AddRectFilledBakedXY(self, p_min_x, p_min_y, p_max_x, p_max_y, col, r, tex_uvs, flags)
-- 9-slice with corner mirroring
local uv_l, uv_t, uv_r, uv_b = tex_uvs.x, tex_uvs.y, tex_uvs.z, tex_uvs.w -- uv_tl = (l,t), uv_tr = (r,t), uv_br = (r,b), uv_bl = (l,b)
PrimReserve(self, 9 * 2 * 3, 4 * 4)
local r_tl = (bit32.band(flags, 16 --[[ImDrawFlags.RoundTopLeft]]) ~= 0) and r or 0.0
local r_tr = (bit32.band(flags, 32 --[[ImDrawFlags.RoundTopRight]]) ~= 0) and r or 0.0
local r_br = (bit32.band(flags, 128 --[[ImDrawFlags.RoundBottomRight]]) ~= 0) and r or 0.0
local r_bl = (bit32.band(flags, 64 --[[ImDrawFlags.RoundBottomLeft]]) ~= 0) and r or 0.0
local vb = self.VtxBuffer.Buf
local ib = self.IdxBuffer.Data
local vw = self._VtxWritePtr
local iw = self._IdxWritePtr
local idx = self._VtxCurrentIdx
WV(vb, vw + 0, p_min_x, p_min_y, uv_l, uv_t, col)
WV(vb, vw + 1, p_min_x + r_tl, p_min_y, uv_r, uv_t, col)
WV(vb, vw + 2, p_max_x - r_tr, p_min_y, uv_r, uv_t, col)
WV(vb, vw + 3, p_max_x, p_min_y, uv_l, uv_t, col)
WV(vb, vw + 4, p_min_x, p_min_y + r_tl, uv_l, uv_b, col)
WV(vb, vw + 5, p_min_x + r_tl, p_min_y + r_tl, uv_r, uv_b, col)
WV(vb, vw + 6, p_max_x - r_tr, p_min_y + r_tr, uv_r, uv_b, col)
WV(vb, vw + 7, p_max_x, p_min_y + r_tr, uv_l, uv_b, col)
WV(vb, vw + 8, p_min_x, p_max_y - r_bl, uv_l, uv_b, col)
WV(vb, vw + 9, p_min_x + r_bl, p_max_y - r_bl, uv_r, uv_b, col)
WV(vb, vw + 10, p_max_x - r_br, p_max_y - r_br, uv_r, uv_b, col)
WV(vb, vw + 11, p_max_x, p_max_y - r_br, uv_l, uv_b, col)
WV(vb, vw + 12, p_min_x, p_max_y, uv_l, uv_t, col)
WV(vb, vw + 13, p_min_x + r_bl, p_max_y, uv_r, uv_t, col)
WV(vb, vw + 14, p_max_x - r_br, p_max_y, uv_r, uv_t, col)
WV(vb, vw + 15, p_max_x, p_max_y, uv_l, uv_t, col)
for _ = 0, 2 do
for _ = 0, 2 do
ib[iw + 0] = idx + 4; ib[iw + 1] = idx + 0; ib[iw + 2] = idx + 1
ib[iw + 3] = idx + 4; ib[iw + 4] = idx + 1; ib[iw + 5] = idx + 5
iw = iw + 6
idx = idx + 1
end
idx = idx + 1
end
self._VtxWritePtr = vw + 16
self._IdxWritePtr = iw
self._VtxCurrentIdx = self._VtxCurrentIdx + 16
end
--- @param p_min ImVec2
--- @param p_max ImVec2
--- @param col ImU32
--- @param r float
--- @param tex_uvs ImVec4
--- @param flags ImDrawFlags
function MT.ImDrawList:_AddRectFilledBaked(p_min, p_max, col, r, tex_uvs, flags)
_AddRectFilledBakedXY(self, p_min.x, p_min.y, p_max.x, p_max.y, col, r, tex_uvs, flags)
end
--- @param p_min ImVec2
--- @param p_max ImVec2
@@ -39008,7 +39368,20 @@ function MT.ImDrawList:AddRectFilled(p_min, p_max, col, rounding, flags)
return
end
-- Textured corners are baked with AA, do not use them if no-AA is requested.
-- [Port] TODO baked round corners: allow_tex_corners -> _AddRectFilledBaked(), falls back to the geometry path below.
local allow_tex_corners_mask = bit32.bor(4096 --[[ImDrawFlags.AAFill]], 2097152 --[[ImDrawFlags.UseTexForRoundCorners]], 8388608 --[[ImDrawFlags.AllowTexForRoundCorners_]])
local allow_tex_corners = bit32.band(flags, allow_tex_corners_mask) == allow_tex_corners_mask
if allow_tex_corners and s_rounding <= 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]] then
-- IM_ASSERT_PARANOID((_Data->Font->OwnerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners) == 0) -- [Luau] not evaluated (arguments are not compiled out)
-- This is matching the baking calculations. The rounding clamping above makes sure that there's enough space for the extra pixel.
local corner_size = s_rounding + 1
-- Check that the baked corners do not overlap (this could be made more accurate if tested for x and y separately).
if corner_size * 2.0 * fringe_scale < min_dim then
local idx = (s_rounding - 1)
IM_ASSERT_PARANOID(idx >= 0 and idx < 16 --[[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX]])
_AddRectFilledBakedXY(self, ax, ay, bx, by, col, corner_size * fringe_scale, self._Data.TexUvCorners[idx], flags)
return
end
end
end
if not has_rounding then
@@ -77390,6 +77763,7 @@ IM_INCLUDE('imgui_demo.lua')
return {
BuildLoadGlyphGetAdvanceOrFallback = BuildLoadGlyphGetAdvanceOrFallback,
CalcCornerArcStepAndCount = CalcCornerArcStepAndCount,
CalcNextScrollFromScrollTargetAndClamp = CalcNextScrollFromScrollTargetAndClamp,
CustomConstraints = CustomConstraints,
DBL_MAX = DBL_MAX,
@@ -77521,6 +77895,7 @@ return {
IM_DELETE = IM_DELETE,
IM_DRAWLIST_ARCFAST_SAMPLE_MAX = IM_DRAWLIST_ARCFAST_SAMPLE_MAX,
IM_DRAWLIST_ARCFAST_TABLE_SIZE = IM_DRAWLIST_ARCFAST_TABLE_SIZE,
IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC,
IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX = IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX,
IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX = IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX,
IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH = IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH,
@@ -77604,6 +77979,7 @@ return {
ImFontAtlasBuildSetupFontSpecialGlyphs = ImFontAtlasBuildSetupFontSpecialGlyphs,
ImFontAtlasBuildUpdateTexData = ImFontAtlasBuildUpdateTexData,
ImFontAtlasBuildUpdateTexDataBasic = ImFontAtlasBuildUpdateTexDataBasic,
ImFontAtlasBuildUpdateTexDataCorners = ImFontAtlasBuildUpdateTexDataCorners,
ImFontAtlasBuildUpdateTexDataLines = ImFontAtlasBuildUpdateTexDataLines,
ImFontAtlasBuilder = ImFontAtlasBuilder,
ImFontAtlasFlags = ImFontAtlasFlags,