-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsgdk_tile_priority.lua
More file actions
310 lines (247 loc) · 8.94 KB
/
Copy pathsgdk_tile_priority.lua
File metadata and controls
310 lines (247 loc) · 8.94 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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
-- When using a 8bpp indexed image as input you can use the extra bits of palette to provide extra information for the TILEMAP data but you have to
-- ensure that all pixels from a same tile (block of 8x8 pixels) use the same value otherwise rescomp will generate an error.
-- bit 4-5: palette index (0-3) so it allows to use the 4 available palettes to draw the tilemap / MAP.
-- bit 6: not used (ignored)
-- bit 7: priority information (0=LOW 1=HIGH)
--TODO: get an image and a mask layer. every non 0 tile on the layer (8x8 grid) sets high priority on the til by pushing all pixel to +128 color index, otherwise mask the 7bit to push to low priority
--make sure to also 0 6th bit for safety
if not app.activeSprite then
return app.alert("No active sprite.")
end
local sprite = app.activeSprite
if sprite.colorMode ~= ColorMode.INDEXED then
return app.alert("Sprite must be in indexed color mode.")
end
-- Collect layer names
local targetlayerNames = {}
local masklayerNames = {}
for _, layer in ipairs(sprite.layers) do
if (layer.isTilemap) then
table.insert(masklayerNames, layer.name)
else
table.insert(targetlayerNames, layer.name)
end
end
table.insert(masklayerNames, "Auto")
if #targetlayerNames == 0 then
return app.alert("You need at least 1 image layer")
end
local function findLayerByName(name)
for _, layer in ipairs(sprite.layers) do
if layer.name == name then
return layer
end
end
return nil
end
local function getBoundsText(layer, frame)
if not layer then return "Layer not found" end
local cel = layer:cel(frame)
if not cel or not cel.image then return "No Cel in current frame" end
local pos = cel.position
local img = cel.image
return string.format("Cel Pos: (%d,%d) Size: %dx%d", pos.x, pos.y, img.width, img.height)
end
local palette = sprite.palettes[1]
local function CreateDialog()
local dlg = Dialog("SGDK Tile Priority Modifier")
dlg:combobox{
id = "source",
label = "Priority Layer:",
options = masklayerNames,
option = masklayerNames[1],
onchange = function()
dlg:modify{id = "sourceBounds",text = getBoundsText(findLayerByName(dlg.data.source), frame) }
end
}
dlg:label{ id = "sourceBounds", text = getBoundsText(findLayerByName(dlg.data.source), frame) }
dlg:newrow{always = false}
dlg:combobox{
id = "target",
label = "Target Layer:",
options = targetlayerNames,
option = targetlayerNames[1],
onchange = function()
dlg:modify{id = "targetBounds", text = getBoundsText(findLayerByName(dlg.data.target), frame) }
end
}
dlg:label{ id = "targetBounds", text = getBoundsText(findLayerByName(dlg.data.target), frame) }
dlg:newrow{always = false}
dlg:separator()
dlg:newrow{always = false}
dlg:button{ id = "confirm", text = "&OK", focus = true }
:button{ id = "cancel", text = "&Cancel", onclick = function() dlg:close() end }
dlg:label{ id = "warn", label=#palette.." colors will be expanded to 192", text = "Pay attention to layers/cels origins!"
}
dlg:show()
return dlg
end
local dlg = CreateDialog()
local data = dlg.data
if data.cancel or not data.confirm then
return
end
app.transaction("Adjust Priority", function()
-- Find selected layers
local sourceLayer, targetLayer
for _, layer in ipairs(sprite.layers) do
if layer.name == data.source then
sourceLayer = layer
elseif layer.name == data.target then
targetLayer = layer
end
end
if not targetLayer then
return app.alert("Selected image layer not found.")
end
if not targetLayer.isImage then
return app.alert("Target layer must be an image layer.")
end
if data.source ~= "Auto" then
--local palette = sprite.palettes[1]
--make sure we have at least 64 slots
if #palette < 192 then
app.command.PaletteSize {
ui=false,
size=192
}
end
--local palette = sprite.palettes[1]
for i=64 , 127 do
palette:setColor(i, Color{ r=255, g=0, b=255, a=255 })
end
app.refresh() -- Refresh the view
for i=128, 128+63 do
palette:setColor(i, palette:getColor(i-128))
end
local color = palette:getColor(index)
--Returns the color in the given entry index (the index goes from 0 to #palette-1).
if not sourceLayer then
return app.alert("Selected image layer not found.")
end
if not sourceLayer.isTilemap then
return app.alert("Source layer must be a tilemap layer.")
end
-- Duplicate the target layer
local originalTarget = targetLayer
app.activeLayer = originalTarget
app.command.DuplicateLayer()
targetLayer = app.layer
targetLayer.name = originalTarget.name .. " (processed)"
local frame = app.activeFrame
local sourceCel = sourceLayer:cel(frame)
if not sourceCel then
return app.alert("No cel in source layer at current frame.")
end
local targetCel = targetLayer:cel(frame)
if not targetCel then
return app.alert("No cel in target layer at current frame.")
end
local tileset = sourceLayer.tileset
if not tileset then
return app.alert("No tileset in tilemap layer.")
end
local grid = tileset.grid
local tileSize = grid.tileSize
local tileW = tileSize.w
local tileH = tileSize.h
-- Iterate over tilemap cells
local targetImg = targetCel.image
local mapImg = sourceCel.image
local modifiedCount = 0
local sourceOrigin = sourceCel.bounds
local targetOrigin = targetCel.bounds
for mapY = 0, mapImg.height - 1 do
local targetYoff = sourceOrigin.y + mapY * tileH - targetOrigin.y
for mapX = 0, mapImg.width - 1 do
local tileColor = mapImg:getPixel(mapX, mapY)
local tileIndex = app.pixelColor.tileI(tileColor)
local targetXoff = sourceOrigin.x + mapX * tileW - targetOrigin.x
if tileIndex > 0 then
--print("cel "..mapX.." "..mapY.." "..targetXoff.." "..targetYoff)
--For this tile position, process pixels in target layer
for dy = 0, tileH - 1 do
for dx = 0, tileW - 1 do
local targetX = targetXoff + dx
local targetY = targetYoff + dy
if targetX < targetImg.width and targetY < targetImg.height then
local col = targetImg:getPixel(targetX, targetY)
if col ~= 0 then -- Skip transparent pixels
-- Modify color index: set bit 7 (128) to 1, bit 6 (64) to 0
local newCol = col | 128
newCol = newCol & ~64
targetImg:putPixel(targetX, targetY, newCol)
modifiedCount = modifiedCount + 1
end
end
end
end
else
for dy = 0, tileH - 1 do
for dx = 0, tileW - 1 do
local targetX = targetXoff + dx
local targetY = targetYoff + dy
if targetX < targetImg.width and targetY < targetImg.height then
local col = targetImg:getPixel(targetX, targetY)
if col ~= 0 then -- Skip transparent pixels
-- Modify color index: set bit 7 (128) to 1, bit 6 (64) to 0
local newCol = col & ~128
newCol = newCol & ~64
targetImg:putPixel(targetX, targetY, newCol)
modifiedCount = modifiedCount + 1
end
end
end
end
end
end
end
else
if targetLayer.isTilemap then
return app.alert("Target layer must be an image layer.")
end
-- Duplicate the mask layer
sourceLayer = sprite:newLayer()
sourceLayer.name = targetLayer.name .. " (mask)"
local frame = app.activeFrame
local targetCel = targetLayer:cel(frame)
if not targetCel then
return app.alert("No cel in target layer at current frame.")
end
local tileW = 8
local tileH = 8
local sourceCel = sprite:newCel(sourceLayer, frame)
-- Iterate over tilemap cells
local targetImg = targetCel.image
local mapImg = sourceCel.image
local modifiedCount = 0
local sourceOrigin = sourceCel.bounds
local targetOrigin = targetCel.bounds
for mapY = 0, targetImg.height - 1 do
for mapX = 0, targetImg.width - 1 do
local PixelColor = targetImg:getPixel(mapX, mapY)
if (PixelColor>127) then
local tileX = (mapX//tileW)*tileW
local tileY = (mapY//tileH)*tileH
if (mapImg:getPixel(mapX, mapY)==0) then
for pY = tileY, tileY+7 do
for pX = tileX, tileX+7 do
mapImg:drawPixel(pX, pY, 1)
end
end
mapX=tileX+tileW-1
modifiedCount = modifiedCount+1
end
end
end
end
app.command.ConvertLayer({
ui = false, -- Shows the tileset properties dialog
to = "tilemap"
})
end
end)
app.refresh() -- Refresh the view
if (modifiedCount == 0) then
app.alert(string.format("WARNING: No Pixels were modified!"))
end