Compare commits

...

1 Commits

Author SHA1 Message Date
b2e4f28327 implement 9slice-based ui borders 2026-05-01 02:04:50 +03:00

66
lib/simple_ui/9slice.lua Normal file
View File

@ -0,0 +1,66 @@
local NineSlice = {}
local function tileRegion(batch, atlasW, atlasH, sliceInfo, startX, startY, targetW, targetH)
-- Если область нулевая или отрицательная (окно слишком маленькое), ничего не делаем
if targetW <= 0 or targetH <= 0 then return end
local sx, sy, sw, sh = sliceInfo[1], sliceInfo[2], sliceInfo[3], sliceInfo[4]
for y = 0, targetH - 1, sh do
-- Вычисляем высоту текущего куска (целый или обрезанный остаток)
local drawH = math.min(sh, targetH - y)
for x = 0, targetW - 1, sw do
local drawW = math.min(sw, targetW - x)
-- Создаем Quad именно для этого кусочка и добавляем в батч
local quad = love.graphics.newQuad(sx, sy, drawW, drawH, atlasW, atlasH)
batch:add(quad, startX + x, startY + y)
end
end
end
--- Создает SpriteBatch для заполнения произвольного прямоугольника по принципу 9-slice
---
--- Углы фиксированные, стороны тайлятся
function NineSlice.create(atlas, slices, width, height)
local batch = love.graphics.newSpriteBatch(atlas)
local aw, ah = atlas:getDimensions()
local tl = slices.topLeft
local t = slices.top
local tr = slices.topRight
local l = slices.left
local c = slices.center
local r = slices.right
local bl = slices.bottomLeft
local b = slices.bottom
local br = slices.bottomRight
-- Размеры углов диктуют отступы
local leftW, rightW = tl[3], tr[3]
local topH, bottomH = tl[4], bl[4]
-- Высчитываем пространство для центра и сторон
local innerW = width - leftW - rightW
local innerH = height - topH - bottomH
-- 1. Рисуем углы (они не тайлятся, просто рисуются 1 раз)
tileRegion(batch, aw, ah, tl, 0, 0, leftW, topH)
tileRegion(batch, aw, ah, tr, leftW + innerW, 0, rightW, topH)
tileRegion(batch, aw, ah, bl, 0, topH + innerH, leftW, bottomH)
tileRegion(batch, aw, ah, br, leftW + innerW, topH + innerH, rightW, bottomH)
-- 2. Рисуем стороны (тайлим по одной оси)
tileRegion(batch, aw, ah, t, leftW, 0, innerW, topH)
tileRegion(batch, aw, ah, b, leftW, topH + innerH, innerW, bottomH)
tileRegion(batch, aw, ah, l, 0, topH, leftW, innerH)
tileRegion(batch, aw, ah, r, leftW + innerW, topH, rightW, innerH)
-- 3. Рисуем центр (тайлим по обеим осям)
tileRegion(batch, aw, ah, c, leftW, topH, innerW, innerH)
return batch
end
return NineSlice