diff --git a/lib/simple_ui/9slice.lua b/lib/simple_ui/9slice.lua new file mode 100644 index 0000000..d71633b --- /dev/null +++ b/lib/simple_ui/9slice.lua @@ -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