Skip to content

Commit adcebcc

Browse files
committed
Implement remove duplicate tiles in TexturePacker
- Write unit tests for packTilesets in NewTexturePacker
1 parent 0c9bc80 commit adcebcc

File tree

5 files changed

+86
-29
lines changed

5 files changed

+86
-29
lines changed

korge-gradle-plugin/src/main/kotlin/korlibs/korge/gradle/texpacker/NewTexturePacker.kt

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ object NewTexturePacker {
7676
// println("Tileset: ${file}, images: $images")
7777
}
7878

79-
packImages(images, enableRotation = false, enableTrimming = false, padding = padding, trimFileName = true, removeDuplicates = true)
80-
81-
return listOf()
79+
return packImages(images, enableRotation = false, enableTrimming = false, padding = padding, trimFileName = true, removeDuplicates = true)
8280
}
8381

8482
/**
@@ -133,7 +131,8 @@ object NewTexturePacker {
133131
val mappedImages = if (removeDuplicates) { // mappedImages will contain only unique images if removeDuplicates is true
134132
// Remove duplicate images
135133
val uniqueMap = linkedMapOf<Int, Pair<File, SimpleBitmap>>()
136-
for ((file, image) in images) {
134+
for ((fileName, image) in images) {
135+
val file = if (trimFileName) File(fileName.nameWithoutExtension) else fileName
137136
val hash = image.hashCode()
138137
val existing = uniqueMap[hash]
139138
if (existing == null) {
@@ -144,7 +143,8 @@ object NewTexturePacker {
144143
uniqueMap.values.toList()
145144
} else {
146145
// No duplicate removal, use all images
147-
for ((file, _) in images) {
146+
for ((fileName, _) in images) {
147+
val file = if (trimFileName) File(fileName.nameWithoutExtension) else fileName
148148
tileMapping[file] = file
149149
}
150150
images
@@ -164,7 +164,7 @@ object NewTexturePacker {
164164
))
165165
})
166166

167-
// Building info which includes mapping duplicates
167+
// Building info which includes mapping duplicates
168168
val outAtlases = arrayListOf<AtlasInfo>()
169169
// TODO for loop needs to go over tileMapping to map possible duplicate files to the same image area in the atlas
170170
for (bin in packer.bins) {
@@ -173,31 +173,37 @@ object NewTexturePacker {
173173

174174
for (rect in bin.rects) {
175175
val info = rect.raw as Info
176-
val fileName = info.file.name
177-
//println("$rect :: info=$info")
176+
// val fileName = info.file.name
177+
// Check if this rect (image) is used by any duplicate files
178+
val files = tileMapping.filterValues { it == info.file }.keys
179+
for (file in files) {
178180

179-
val chunk = if (rect.rot) info.trimmedImage.flipY().rotate90() else info.trimmedImage
180-
out.put(rect.x - padding, rect.y - padding, chunk.extrude(padding))
181-
//out.put(rect.x, rect.y, chunk)
181+
val fileName = file.name
182182

183-
val obj = LinkedHashMap<String, Any?>()
183+
val chunk = if (rect.rot) info.trimmedImage.flipY().rotate90() else info.trimmedImage
184+
out.put(rect.x - padding, rect.y - padding, chunk.extrude(padding))
185+
//out.put(rect.x, rect.y, chunk)
184186

185-
fun Dimension.toObj(rot: Boolean): Map<String, Any?> {
186-
val w = if (!rot) width else height
187-
val h = if (!rot) height else width
188-
return mapOf("w" to w, "h" to h)
189-
}
190-
fun Rectangle.toObj(rot: Boolean): Map<String, Any?> {
191-
return mapOf("x" to x, "y" to y) + this.size.toObj(rot)
192-
}
187+
val obj = LinkedHashMap<String, Any?>()
193188

194-
obj["frame"] = Rectangle(rect.x, rect.y, rect.width, rect.height).toObj(rect.rot)
195-
obj["rotated"] = rect.rot
196-
obj["trimmed"] = info.trimArea != info.fullArea
197-
obj["spriteSourceSize"] = info.trimArea.toObj(false)
198-
obj["sourceSize"] = info.fullArea.size.toObj(false)
189+
fun Dimension.toObj(rot: Boolean): Map<String, Any?> {
190+
val w = if (!rot) width else height
191+
val h = if (!rot) height else width
192+
return mapOf("w" to w, "h" to h)
193+
}
199194

200-
frames[fileName] = obj
195+
fun Rectangle.toObj(rot: Boolean): Map<String, Any?> {
196+
return mapOf("x" to x, "y" to y) + this.size.toObj(rot)
197+
}
198+
199+
obj["frame"] = Rectangle(rect.x, rect.y, rect.width, rect.height).toObj(rect.rot)
200+
obj["rotated"] = rect.rot
201+
obj["trimmed"] = info.trimArea != info.fullArea
202+
obj["spriteSourceSize"] = info.trimArea.toObj(false)
203+
obj["sourceSize"] = info.fullArea.size.toObj(false)
204+
205+
frames[fileName] = obj
206+
}
201207
}
202208

203209

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package korlibs.korge.gradle.texpacker
2+
3+
import korlibs.korge.gradle.typedresources.getResourceURL
4+
import org.junit.Assert
5+
import org.junit.Test
6+
import java.io.File
7+
8+
9+
class NewTexturePackerTest {
10+
@Test
11+
fun testPackTilesets() {
12+
val atlasInfos = NewTexturePacker.packTilesets(File(getResourceURL("tilesets").file))
13+
14+
// Check if duplicate tiles were detected and merged into one tile rect area in the tileset atlas
15+
val atlasInfo = atlasInfos.first()
16+
val frames = atlasInfo.info["frames"] as Map<String, Any>
17+
18+
val tile_1 = frames["test_tileset_1"] as Map<String, Any>
19+
val tile_2 = frames["test_tileset_4"] as Map<String, Any>
20+
val tile_3 = frames["test_tileset_2_0"] as Map<String, Any> // This tile is in the second tileset but is a duplicate of test_tileset_1
21+
22+
// Check that all three tiles point to the same frame data (i.e., they are duplicates)
23+
val tileFrame_1 = tile_1["frame"] as Map<String, Int>
24+
val tileFrame_2 = tile_2["frame"] as Map<String, Int>
25+
val tileFrame_3 = tile_3["frame"] as Map<String, Int>
26+
Assert.assertEquals(tileFrame_1["x"], tileFrame_2["x"])
27+
Assert.assertEquals(tileFrame_1["y"], tileFrame_2["y"])
28+
Assert.assertEquals(tileFrame_1["w"], tileFrame_2["w"])
29+
Assert.assertEquals(tileFrame_1["h"], tileFrame_2["h"])
30+
Assert.assertEquals(tileFrame_1["x"], tileFrame_3["x"])
31+
Assert.assertEquals(tileFrame_1["y"], tileFrame_3["y"])
32+
Assert.assertEquals(tileFrame_1["w"], tileFrame_3["w"])
33+
Assert.assertEquals(tileFrame_1["h"], tileFrame_3["h"])
34+
35+
// Check that tiles are not rotated or trimmed
36+
val rotated_1 = tile_1["rotated"] as Boolean
37+
val rotated_2 = tile_2["rotated"] as Boolean
38+
val rotated_3 = tile_3["rotated"] as Boolean
39+
Assert.assertFalse(rotated_1)
40+
Assert.assertFalse(rotated_2)
41+
Assert.assertFalse(rotated_3)
42+
val trimmed_1 = tile_1["trimmed"] as Boolean
43+
val trimmed_2 = tile_2["trimmed"] as Boolean
44+
val trimmed_3 = tile_3["trimmed"] as Boolean
45+
Assert.assertFalse(trimmed_1)
46+
Assert.assertFalse(trimmed_2)
47+
Assert.assertFalse(trimmed_3)
48+
49+
//println("Atlas Info: $atlasInfos")
50+
}
51+
}

korge-gradle-plugin/src/test/kotlin/korlibs/korge/gradle/typedresources/AseSpriteTest.kt renamed to korge-gradle-plugin/src/test/kotlin/korlibs/korge/gradle/util/AseInfoTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
package korlibs.korge.gradle.typedresources
1+
package korlibs.korge.gradle.util
22

3-
import korlibs.korge.gradle.util.*
3+
import korlibs.korge.gradle.typedresources.getResourceBytes
44
import org.junit.Assert
55
import org.junit.Test
66

7-
class AseSpriteTest {
7+
class AseInfoTest {
88
@Test
99
fun test() {
1010
val info = ASEInfo.Companion.getAseInfo(getResourceBytes("sprites.ase"))
222 Bytes
Loading
224 Bytes
Loading

0 commit comments

Comments
 (0)