/
Unique 8x8 Tiles Tilemap.lua
119 lines (106 loc) · 3.57 KB
/
Unique 8x8 Tiles Tilemap.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
109
110
111
112
113
114
115
116
117
118
119
-- Unique 8x8 tile counter for Aseprite tilemaps
-- Copyright 2022, NovaSquirel
--
-- Copying and distribution of this file, with or without modification, are permitted in any medium without royalty, provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.
-- This script looks at all of the tilemap layers in the current frame of an Aseprite sprite,
-- then calculates how many unique 8x8 tiles there are on each layer, taking flips into account.
local pc = app.pixelColor
local sprite = app.activeSprite
if not sprite then return app.alert("There is no active sprite") end
local frameNumber = app.activeFrame.frameNumber
-- Does this table contain a value?
local function contains(t, element)
for _, value in pairs(t) do
if value == element then
return true
end
end
return false
end
-- Flip an 8x8 image's bytes only horizontally
local function horizFlipImageBytes(b, stride)
local pixelSize = #b / 64
local out = ''
for y=0,7 do
local line = string.sub(b, y*stride+1, (y+1)*stride-1+1)
for x=7,0,-1 do
out = out .. string.sub(line, x*pixelSize+1, (x+1)*pixelSize-1+1)
end
end
return out
end
-- Flip an 8x8 image's bytes only vertically
local function vertFlipImageBytes(b, stride)
local out = ''
for y=7,0,-1 do
out = out .. string.sub(b, y*stride+1, (y+1)*stride-1+1)
end
return out
end
-- Flip an 8x8 image's bytes horizontally and vertically
local function bothFlipImageBytes(b, stride)
local pixelSize = #b / 64
local out = ''
for y=7,0,-1 do
local line = string.sub(b, y*stride+1, (y+1)*stride-1+1)
for x=7,0,-1 do
out = out .. string.sub(line, x*pixelSize+1, (x+1)*pixelSize-1+1)
end
end
return out
end
-- Check one tilemap and look at all of the used tiles
local function checkTilemap(layer)
local cel = layer:cel(frameNumber)
if cel == nil then return end
-- Set up variables first
local tileset = layer.tileset
local tileWidth = tileset.grid.tileSize.width
local tileHeight = tileset.grid.tileSize.height
local used8x8Set = {}
-- Find all of the used tileset entries
usedTilesetEntries = {}
for pixel in cel.image:pixels() do
usedTilesetEntries[pc.tileI(pixel())] = true
end
-- Figure out how many unique 8x8 tiles there are in the used tileset entries
local reused = 0
local reusedFlips = 0
local total = 0
for key,value in pairs(usedTilesetEntries) do
total = total + 1
local fullImage = tileset:getTile(key)
for x=1,tileWidth/8 do
for y=1,tileHeight/8 do
local tileImage = Image(8, 8, fullImage.colorMode)
tileImage:clear()
tileImage:drawImage(fullImage, Point(-(x-1)*8, -(y-1)*8))
-- Check if the 8x8 tile already exists in the set of used ones, otherwise add it
local b = tileImage.bytes
if contains(used8x8Set, b) then
reused = reused + 1
elseif contains(used8x8Set, horizFlipImageBytes(b, tileImage.rowStride)) then
reusedFlips = reusedFlips + 1
elseif contains(used8x8Set, vertFlipImageBytes(b, tileImage.rowStride)) then
reusedFlips = reusedFlips + 1
elseif contains(used8x8Set, bothFlipImageBytes(b, tileImage.rowStride)) then
reusedFlips = reusedFlips + 1
else
table.insert(used8x8Set, b)
end
end
end
end
app.alert{title=layer.name, text={"Unique: " .. #used8x8Set, "Reused (all): " .. reused+reusedFlips, "Reused (flips): " .. reusedFlips, "Metatiles: " .. total}}
end
-- Recursively find all of the layers
local function findLayers(layers)
for i,layer in ipairs(layers) do
if layer.isTilemap then
checkTilemap(layer)
elseif layer.isGroup then
findLayers(layer.layers)
end
end
end
findLayers(sprite.layers)