-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfixedSize.lua
108 lines (96 loc) · 4.21 KB
/
fixedSize.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
-- Copyright (c) 2021 EngineerSmith
-- Under the MIT license, see license suppiled with this file
local path = select(1, ...):match("(.-)[^%.]+$")
local baseAtlas = require(path .. "baseAtlas")
local util = require(path .. "util")
local fixedSizeTA = setmetatable({}, baseAtlas)
fixedSizeTA.__index = fixedSizeTA
local lg = love.graphics
local newImageData = love.image.newImageData
local ceil, floor, sqrt = math.ceil, math.sqrt, math.floor
fixedSizeTA.new = function(width, height, padding, extrude, spacing)
local self = setmetatable(baseAtlas.new(padding, extrude, spacing), fixedSizeTA)
self.width = width or error("Width required")
self.height = height or width
return self
end
fixedSizeTA.add = function(self, image, id, bake)
local width, height = util.getImageDimensions(image)
if width ~= self.width or height ~= self.height then
error("Given image cannot fit into a fixed sized texture atlas\n Gave: W:".. tostring(width) .. " H:" ..tostring(height) .. ", Expected: W:"..self.width.." H:"..self.height)
end
return baseAtlas.add(self, image, id, bake)
end
fixedSizeTA.bake = function(self)
if self._dirty and not self._hardBake then
local columns = ceil(sqrt(self.imagesSize))
local width, height = self.width, self.height
local widthPadded = width + self.spacing + self.extrude * 2 + self.padding * 2
local heightPadded = height + self.spacing + self.extrude * 2 + self.padding * 2
local maxIndex = self.imagesSize
local data
local widthCanvas = columns * widthPadded
if widthCanvas > (self.maxWidth or self._maxCanvasSize) then
error("Required width for atlas cannot be created due to reaching limits. Required: "..widthCanvas..", width limit: "..(self.maxWidth or self._maxCanvasSize))
end
local rows = ceil(self.imagesSize / columns)
local heightCanvas = rows * heightPadded
if heightPadded > (self.maxHeight or self._maxCanvasSize) then
error("Required height for atlas cannot be created due to reaching limits. Required: "..heightCanvas..", height limit: "..(self.maxHeight or self._maxCanvasSize))
end
widthCanvas, heightCanvas = widthCanvas - self.spacing, heightCanvas - self.spacing
if self.bakeAsPow2 then
widthCanvas = math.pow(2, math.ceil(math.log(widthCanvas)/math.log(2)))
heightCanvas = math.pow(2, math.ceil(math.log(heightCanvas)/math.log(2)))
end
if self._pureImageMode then
data = newImageData(widthCanvas, heightCanvas, "rgba8")
for x=0, columns-1 do
for y=0, rows-1 do
local index = (x*rows+y)+1
if index > maxIndex then
break
end
local x, y = x * widthPadded + self.padding + self.extrude, y * heightPadded + self.padding + self.extrude
local image = self.images[index]
data:paste(image.image, x, y, 0, 0, image.image:getDimensions())
if self.extrude > 0 then
util.extrudeWithFill(data, image.image, self.extrude, x, y)
end
self.quads[image.id] = {x+self.extrude, y+self.extrude, width, height}
end
end
else
local extrudeQuad = lg.newQuad(-self.extrude, -self.extrude, width+self.extrude*2, height+self.extrude*2, self.width, self.height)
local canvas = lg.newCanvas(widthCanvas, heightCanvas, self._canvasSettings)
lg.push("all")
lg.setBlendMode("replace")
lg.setCanvas(canvas)
for x=0, columns-1 do
for y=0, rows-1 do
local index = (x*rows+y)+1
if index > maxIndex then
break
end
local x, y = x * widthPadded + self.padding, y * heightPadded + self.padding
local image = self.images[index]
lg.draw(image.image, extrudeQuad, x, y)
self.quads[image.id] = lg.newQuad(x+self.extrude, y+self.extrude, width, height, widthCanvas, heightCanvas)
end
end
lg.pop()
local major = love.getVersion()
if major == 12 and lg.readbackTexture then
data = lg.readbackTexture(canvas)
else
data = canvas:newImageData()
end
self.image = lg.newImage(data)
self.image:setFilter(self.filterMin, self.filterMag)
end
self._dirty = false
return self, data
end
return self
end
return fixedSizeTA