-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport_layers.lua
More file actions
266 lines (246 loc) · 8.15 KB
/
export_layers.lua
File metadata and controls
266 lines (246 loc) · 8.15 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
--[[
Description:
A script to save all different layers in different files.
Made by Gaspi.
- Itch.io: https://gaspi.itch.io/
- Twitter: @_Gaspi
Further Contributors:
- Levy E ("StoneLabs")
- David Höchtl ("DavidHoechtl")
- Demonkiller8973
--]]
-- Import main.
local err = dofile("main.lua")
if err ~= 0 then return err end
-- Variable to keep track of the number of layers exported.
local n_layers = 0
-- Function to calculate the bounding box of the non-transparent pixels in a layer
local function calculateBoundingBox(layer)
local minX, minY, maxX, maxY = nil, nil, nil, nil
for _, cel in ipairs(layer.cels) do
local image = cel.image
local position = cel.position
for y = 0, image.height - 1 do
for x = 0, image.width - 1 do
if image:getPixel(x, y) ~= 0 then -- Non-transparent pixel
local pixelX = position.x + x
local pixelY = position.y + y
if not minX or pixelX < minX then minX = pixelX end
if not minY or pixelY < minY then minY = pixelY end
if not maxX or pixelX > maxX then maxX = pixelX end
if not maxY or pixelY > maxY then maxY = pixelY end
end
end
end
end
return Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1)
end
-- Exports every layer individually.
local function exportLayers(sprite, root_layer, filename, group_sep, data)
for _, layer in ipairs(root_layer.layers) do
local filename = filename
if layer.isGroup then
-- Recursive for groups.
local previousVisibility = layer.isVisible
layer.isVisible = true
filename = filename:gsub("{layergroups}",
layer.name .. group_sep .. "{layergroups}")
exportLayers(sprite, layer, filename, group_sep, data)
layer.isVisible = previousVisibility
else
-- Individual layer. Export it.
layer.isVisible = true
filename = filename:gsub("{layergroups}", "")
filename = filename:gsub("{layername}", layer.name)
os.execute("mkdir \"" .. Dirname(filename) .. "\"")
if data.spritesheet then
local sheettype=SpriteSheetType.HORIZONTAL
if (data.tagsplit == "To Rows") then
sheettype=SpriteSheetType.ROWS
elseif (data.tagsplit == "To Columns") then
sheettype=SpriteSheetType.COLUMNS
end
app.command.ExportSpriteSheet{
ui=false,
askOverwrite=false,
type=sheettype,
columns=0,
rows=0,
width=0,
height=0,
bestFit=false,
textureFilename=filename,
dataFilename="",
dataFormat=SpriteSheetDataFormat.JSON_HASH,
borderPadding=0,
shapePadding=0,
innerPadding=0,
trimSprite=data.trimSprite,
trim=data.trimCells,
trimByGrid=data.trimByGrid,
mergeDuplicates=data.mergeDuplicates,
extrude=false,
openGenerated=false,
layer="",
tag="",
splitLayers=false,
splitTags=(data.tagsplit ~= "No"),
listLayers=layer,
listTags=true,
listSlices=true,
}
elseif data.trim then -- Trim the layer
local boundingRect = calculateBoundingBox(layer)
-- make a selection on the active layer
app.activeLayer = layer;
sprite.selection = Selection(boundingRect);
-- create a new sprite from that selection
app.command.NewSpriteFromSelection()
-- save it as png
app.command.SaveFile {
ui=false,
filename=filename
}
app.command.CloseFile()
app.activeSprite = layer.sprite -- Set the active sprite to the current layer's sprite
sprite.selection = Selection();
else
sprite:saveCopyAs(filename)
end
layer.isVisible = false
n_layers = n_layers + 1
end
end
end
-- Open main dialog.
local dlg = Dialog("Export layers")
dlg:file{
id = "directory",
label = "Output directory:",
filename = Sprite.filename,
open = false
}
dlg:entry{
id = "filename",
label = "File name format:",
text = "{layergroups}{layername}"
}
dlg:combobox{
id = 'format',
label = 'Export Format:',
option = 'png',
options = {'png', 'gif', 'jpg'}
}
dlg:combobox{
id = 'group_sep',
label = 'Group separator:',
option = Sep,
options = {Sep, '-', '_'}
}
dlg:slider{id = 'scale', label = 'Export Scale:', min = 1, max = 10, value = 1}
dlg:check{
id = "spritesheet",
label = "Export as spritesheet:",
selected = false,
onclick = function()
-- Hide these options when spritesheet is checked.
dlg:modify{
id = "trim",
visible = not dlg.data.spritesheet
}
-- Show these options when spritesheet is checked.
dlg:modify{
id = "trimSprite",
visible = dlg.data.spritesheet
}
dlg:modify{
id = "trimCells",
visible = dlg.data.spritesheet
}
dlg:modify{
id = "mergeDuplicates",
visible = dlg.data.spritesheet
}
dlg:modify{
id = "tagsplit",
visible = dlg.data.spritesheet
}
end
}
dlg:check{
id = "trim",
label = "Trim:",
selected = false
}
dlg:check{
id = "trimSprite",
label = " Trim Sprite:",
selected = false,
visible = false,
onclick = function()
dlg:modify{
id = "trimByGrid",
visible = dlg.data.trimSprite or dlg.data.trimCells,
}
end
}
dlg:check{
id = "trimCells",
label = " Trim Cells:",
selected = false,
visible = false,
onclick = function()
dlg:modify{
id = "trimByGrid",
visible = dlg.data.trimSprite or dlg.data.trimCells,
}
end
}
dlg:check{
id = "trimByGrid",
label = " Trim Grid:",
selected = false,
visible = false
}
dlg:combobox{ -- Spritesheet export only option
id = "tagsplit",
label = " Split Tags:",
visible = false,
option = 'No',
options = {'No', 'To Rows', 'To Columns'}
}
dlg:check{ -- Spritesheet export only option
id = "mergeDuplicates",
label = " Merge duplicates:",
selected = false,
visible = false
}
dlg:check{id = "save", label = "Save sprite:", selected = false}
dlg:button{id = "ok", text = "Export"}
dlg:button{id = "cancel", text = "Cancel"}
dlg:show()
if not dlg.data.ok then return 0 end
-- Get path and filename
local output_path = Dirname(dlg.data.directory)
local filename = dlg.data.filename .. "." .. dlg.data.format
if output_path == nil then
local dlg = MsgDialog("Error", "No output directory was specified.")
dlg:show()
return 1
end
local group_sep = dlg.data.group_sep
filename = filename:gsub("{spritename}",
RemoveExtension(Basename(Sprite.filename)))
filename = filename:gsub("{groupseparator}", group_sep)
-- Finally, perform everything.
Sprite:resize(Sprite.width * dlg.data.scale, Sprite.height * dlg.data.scale)
local layers_visibility_data = HideLayers(Sprite)
exportLayers(Sprite, Sprite, output_path .. filename, group_sep, dlg.data)
RestoreLayersVisibility(Sprite, layers_visibility_data)
Sprite:resize(Sprite.width / dlg.data.scale, Sprite.height / dlg.data.scale)
-- Save the original file if specified
if dlg.data.save then Sprite:saveAs(dlg.data.directory) end
-- Success dialog.
local dlg = MsgDialog("Success!", "Exported " .. n_layers .. " layers.")
dlg:show()
return 0