Skip to content

Commit 76cc17c

Browse files
authored
Configurable atlas textures packing (#2328)
make #-prefixed parameters in .atlas files
1 parent b590958 commit 76cc17c

File tree

4 files changed

+177
-18
lines changed

4 files changed

+177
-18
lines changed

buildSrc/src/main/kotlin/korlibs/korge/gradle/processor/KorgeTexturePacker.kt

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import kotlin.system.*
77

88
open class KorgeTexturePacker : KorgeResourceProcessor {
99
override fun processFolder(context: KorgeResourceProcessorContext) {
10+
context.resourceFolders
1011
for (folder in context.resourceFolders) {
1112
val files = folder.listFiles()?.toList() ?: emptyList()
1213
for (file in files) {
@@ -18,17 +19,32 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
1819
generate(context.logger, atlasJsonFile, arrayOf(file))
1920
}
2021
file.isFile -> {
21-
val sources = file.readLines().filter { it.isNotBlank() }.map { File(folder, it) }.toTypedArray()
22+
val settings = parseAtlasSettingsFile(file)
23+
val sources = settings.files.map { File(folder, it) }.toTypedArray()
2224
context.skipFiles(file, *sources)
23-
generate(context.logger, atlasJsonFile, sources)
25+
generate(
26+
context.logger,
27+
atlasJsonFile,
28+
sources,
29+
enableRotation = settings.enableRotation,
30+
enableTrimming = settings.enableTrimming,
31+
padding = settings.padding,
32+
)
2433
}
2534
}
2635
}
2736
}
2837
}
2938
}
3039

31-
fun generate(logger: org.slf4j.Logger, outputFile: File, imageFolders: Array<File>) {
40+
private fun generate(
41+
logger: org.slf4j.Logger,
42+
outputFile: File,
43+
imageFolders: Array<File>,
44+
enableRotation: Boolean = true,
45+
enableTrimming: Boolean = true,
46+
padding: Int = 2,
47+
) {
3248
val involvedFiles = NewTexturePacker.getAllFiles(*imageFolders)
3349
//val maxLastModifiedTime = involvedFiles.maxOfOrNull { it.file.lastModified() } ?: System.currentTimeMillis()
3450
val involvedString = involvedFiles.map { it.relative.name + ":" + it.file.length() + ":" + it.file.lastModified() }.sorted().joinToString("\n")
@@ -37,7 +53,12 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
3753
//if (!outputFile.exists() || involvedFile.takeIfExists()?.readText() != involvedString) {
3854
if (involvedFile.takeIfExists()?.readText() != involvedString) {
3955
val time = measureTimeMillis {
40-
val results = NewTexturePacker.packImages(*imageFolders, enableRotation = true, enableTrimming = true)
56+
val results = NewTexturePacker.packImages(
57+
*imageFolders,
58+
enableRotation = enableRotation,
59+
enableTrimming = enableTrimming,
60+
padding = padding
61+
)
4162
for (result in results) {
4263
val imageOut = result.write(outputFile)
4364
}
@@ -50,4 +71,63 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
5071
logger.info("KorgeTexturePacker.CACHED: $involvedFile")
5172
}
5273
}
74+
75+
private fun parseAtlasSettingsFile(atlasFile: File): AtlasGenerationSettings {
76+
var enableRotation = true
77+
var enableTrimming = true
78+
var padding = 2
79+
val files = mutableListOf<String>()
80+
81+
atlasFile.forEachLine { line ->
82+
val trimmedLine = line.trim()
83+
if (trimmedLine.isBlank()) return@forEachLine
84+
85+
val enableRotationSetting = tryExtractSetting(trimmedLine, "#enable-rotation") { it.toBoolean() }
86+
if (enableRotationSetting != null) {
87+
enableRotation = enableRotationSetting
88+
return@forEachLine
89+
}
90+
91+
val enableTrimmingSetting = tryExtractSetting(trimmedLine, "#enable-trimming") { it.toBoolean() }
92+
if (enableTrimmingSetting != null) {
93+
enableTrimming = enableTrimmingSetting
94+
return@forEachLine
95+
}
96+
97+
val paddingSetting = tryExtractSetting(trimmedLine, "#padding") { it.toInt() }
98+
if (paddingSetting != null) {
99+
padding = paddingSetting
100+
return@forEachLine
101+
}
102+
103+
files.add(trimmedLine)
104+
}
105+
106+
return AtlasGenerationSettings(
107+
files = files,
108+
enableRotation = enableRotation,
109+
enableTrimming = enableTrimming,
110+
padding = padding,
111+
)
112+
}
113+
114+
private inline fun <T> tryExtractSetting(line: String, key: String, valueParser: (String) -> T): T? {
115+
return if (line.startsWith(key)) {
116+
try {
117+
val value = line.substringAfter("=").trim()
118+
valueParser(value)
119+
} catch (e: Exception) {
120+
null
121+
}
122+
} else {
123+
null
124+
}
125+
}
53126
}
127+
128+
private data class AtlasGenerationSettings(
129+
val files: List<String>,
130+
val enableRotation: Boolean,
131+
val enableTrimming: Boolean,
132+
val padding: Int,
133+
)

buildSrc/src/main/kotlin/korlibs/korge/gradle/texpacker/NewTexturePacker.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ object NewTexturePacker {
4444
vararg folders: File,
4545
enableRotation: Boolean = true,
4646
enableTrimming: Boolean = true,
47+
padding: Int = 2,
4748
): List<AtlasInfo> {
4849
val images: List<Pair<File, SimpleBitmap>> = getAllFiles(*folders).mapNotNull {
4950
try {
@@ -54,16 +55,14 @@ object NewTexturePacker {
5455
}
5556
}
5657

57-
val PADDING = 2
58-
59-
val packer = NewBinPacker.MaxRectsPacker(4096, 4096, PADDING * 2, NewBinPacker.IOption(
58+
val packer = NewBinPacker.MaxRectsPacker(4096, 4096, padding * 2, NewBinPacker.IOption(
6059
smart = true,
6160
pot = true,
6261
square = false,
6362
allowRotation = enableRotation,
6463
//allowRotation = false,
6564
tag = false,
66-
border = PADDING
65+
border = padding
6766
))
6867

6968
packer.addArray(images.map { (file, image) ->
@@ -94,7 +93,7 @@ object NewTexturePacker {
9493
//println("$rect :: info=$info")
9594

9695
val chunk = if (rect.rot) info.trimmedImage.flipY().rotate90() else info.trimmedImage
97-
out.put(rect.x - PADDING, rect.y - PADDING, chunk.extrude(PADDING))
96+
out.put(rect.x - padding, rect.y - padding, chunk.extrude(padding))
9897
//out.put(rect.x, rect.y, chunk)
9998

10099
val obj = LinkedHashMap<String, Any?>()
@@ -139,3 +138,4 @@ object NewTexturePacker {
139138
return outAtlases
140139
}
141140
}
141+

korge-gradle-plugin/src/main/kotlin/korlibs/korge/gradle/processor/KorgeTexturePacker.kt

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import kotlin.system.*
77

88
open class KorgeTexturePacker : KorgeResourceProcessor {
99
override fun processFolder(context: KorgeResourceProcessorContext) {
10+
context.resourceFolders
1011
for (folder in context.resourceFolders) {
1112
val files = folder.listFiles()?.toList() ?: emptyList()
1213
for (file in files) {
@@ -18,17 +19,32 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
1819
generate(context.logger, atlasJsonFile, arrayOf(file))
1920
}
2021
file.isFile -> {
21-
val sources = file.readLines().filter { it.isNotBlank() }.map { File(folder, it) }.toTypedArray()
22+
val settings = parseAtlasSettingsFile(file)
23+
val sources = settings.files.map { File(folder, it) }.toTypedArray()
2224
context.skipFiles(file, *sources)
23-
generate(context.logger, atlasJsonFile, sources)
25+
generate(
26+
context.logger,
27+
atlasJsonFile,
28+
sources,
29+
enableRotation = settings.enableRotation,
30+
enableTrimming = settings.enableTrimming,
31+
padding = settings.padding,
32+
)
2433
}
2534
}
2635
}
2736
}
2837
}
2938
}
3039

31-
fun generate(logger: org.slf4j.Logger, outputFile: File, imageFolders: Array<File>) {
40+
private fun generate(
41+
logger: org.slf4j.Logger,
42+
outputFile: File,
43+
imageFolders: Array<File>,
44+
enableRotation: Boolean = true,
45+
enableTrimming: Boolean = true,
46+
padding: Int = 2,
47+
) {
3248
val involvedFiles = NewTexturePacker.getAllFiles(*imageFolders)
3349
//val maxLastModifiedTime = involvedFiles.maxOfOrNull { it.file.lastModified() } ?: System.currentTimeMillis()
3450
val involvedString = involvedFiles.map { it.relative.name + ":" + it.file.length() + ":" + it.file.lastModified() }.sorted().joinToString("\n")
@@ -37,7 +53,12 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
3753
//if (!outputFile.exists() || involvedFile.takeIfExists()?.readText() != involvedString) {
3854
if (involvedFile.takeIfExists()?.readText() != involvedString) {
3955
val time = measureTimeMillis {
40-
val results = NewTexturePacker.packImages(*imageFolders, enableRotation = true, enableTrimming = true)
56+
val results = NewTexturePacker.packImages(
57+
*imageFolders,
58+
enableRotation = enableRotation,
59+
enableTrimming = enableTrimming,
60+
padding = padding
61+
)
4162
for (result in results) {
4263
val imageOut = result.write(outputFile)
4364
}
@@ -50,4 +71,63 @@ open class KorgeTexturePacker : KorgeResourceProcessor {
5071
logger.info("KorgeTexturePacker.CACHED: $involvedFile")
5172
}
5273
}
74+
75+
private fun parseAtlasSettingsFile(atlasFile: File): AtlasGenerationSettings {
76+
var enableRotation = true
77+
var enableTrimming = true
78+
var padding = 2
79+
val files = mutableListOf<String>()
80+
81+
atlasFile.forEachLine { line ->
82+
val trimmedLine = line.trim()
83+
if (trimmedLine.isBlank()) return@forEachLine
84+
85+
val enableRotationSetting = tryExtractSetting(trimmedLine, "#enable-rotation") { it.toBoolean() }
86+
if (enableRotationSetting != null) {
87+
enableRotation = enableRotationSetting
88+
return@forEachLine
89+
}
90+
91+
val enableTrimmingSetting = tryExtractSetting(trimmedLine, "#enable-trimming") { it.toBoolean() }
92+
if (enableTrimmingSetting != null) {
93+
enableTrimming = enableTrimmingSetting
94+
return@forEachLine
95+
}
96+
97+
val paddingSetting = tryExtractSetting(trimmedLine, "#padding") { it.toInt() }
98+
if (paddingSetting != null) {
99+
padding = paddingSetting
100+
return@forEachLine
101+
}
102+
103+
files.add(trimmedLine)
104+
}
105+
106+
return AtlasGenerationSettings(
107+
files = files,
108+
enableRotation = enableRotation,
109+
enableTrimming = enableTrimming,
110+
padding = padding,
111+
)
112+
}
113+
114+
private inline fun <T> tryExtractSetting(line: String, key: String, valueParser: (String) -> T): T? {
115+
return if (line.startsWith(key)) {
116+
try {
117+
val value = line.substringAfter("=").trim()
118+
valueParser(value)
119+
} catch (e: Exception) {
120+
null
121+
}
122+
} else {
123+
null
124+
}
125+
}
53126
}
127+
128+
private data class AtlasGenerationSettings(
129+
val files: List<String>,
130+
val enableRotation: Boolean,
131+
val enableTrimming: Boolean,
132+
val padding: Int,
133+
)

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ object NewTexturePacker {
4444
vararg folders: File,
4545
enableRotation: Boolean = true,
4646
enableTrimming: Boolean = true,
47+
padding: Int = 2,
4748
): List<AtlasInfo> {
4849
val images: List<Pair<File, SimpleBitmap>> = getAllFiles(*folders).mapNotNull {
4950
try {
@@ -54,16 +55,14 @@ object NewTexturePacker {
5455
}
5556
}
5657

57-
val PADDING = 2
58-
59-
val packer = NewBinPacker.MaxRectsPacker(4096, 4096, PADDING * 2, NewBinPacker.IOption(
58+
val packer = NewBinPacker.MaxRectsPacker(4096, 4096, padding * 2, NewBinPacker.IOption(
6059
smart = true,
6160
pot = true,
6261
square = false,
6362
allowRotation = enableRotation,
6463
//allowRotation = false,
6564
tag = false,
66-
border = PADDING
65+
border = padding
6766
))
6867

6968
packer.addArray(images.map { (file, image) ->
@@ -94,7 +93,7 @@ object NewTexturePacker {
9493
//println("$rect :: info=$info")
9594

9695
val chunk = if (rect.rot) info.trimmedImage.flipY().rotate90() else info.trimmedImage
97-
out.put(rect.x - PADDING, rect.y - PADDING, chunk.extrude(PADDING))
96+
out.put(rect.x - padding, rect.y - padding, chunk.extrude(padding))
9897
//out.put(rect.x, rect.y, chunk)
9998

10099
val obj = LinkedHashMap<String, Any?>()

0 commit comments

Comments
 (0)