-
Notifications
You must be signed in to change notification settings - Fork 139
Add korge-fleks extension to gradle plugin #2352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jobe-m
merged 44 commits into
main
from
feature/Add-korge-fleks-extension-to-gradle-plugin
Feb 2, 2026
Merged
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
bd660c9
Add KorgeFleksExtension
a836323
Start to add CommonAssetConfig
jobe-m da3d0b7
Cleanup KorgeFleksExtension, move out AssetConfig into own file
jobe-m b3ed1f9
Add unit test for AseLayer in ASEInfo
jobe-m 163b8a8
Implement addImageAse for all layer and tag combinations
jobe-m 14f015f
Add build atlas and nine-patch functions
jobe-m fd17d81
Refactor packImages and add packTilesets function
jobe-m 18c57d2
Update AssetConfig to test packTilesets function
jobe-m 63c6903
Fix error in AssetConfig whem export dir does not exist
jobe-m 1ae9fbf
[NewTexturePacker] Add TODO comment
jobe-m aeb3bc4
Cleanup NewTexturePacker
jobe-m 91cdcfc
Start to add AssetInfo data class
jobe-m 32817e4
Image tiles added to AssetInfo
jobe-m 72e75a9
Write yaml assetInfo file
jobe-m cd6794a
Update putting images into textureAtlas
jobe-m 4854180
Save for each frame index of tileset where it is located
jobe-m 031d47c
Write texture index for frame into yaml atlas info
jobe-m f414125
Remove deprecated gradle properties
jobe-m a4bd0b9
Add frame duration into asssetInfo and related unit test
jobe-m 74b4686
Get frame duration actually written into yaml asset config
jobe-m 5be3b2c
Change asset info format to JSON
jobe-m 4f5b3b2
Add nine-patch image loading into asset into and texture atlas
jobe-m dd13780
Add pixel fonts into texture atlas
jobe-m d6810a7
Add frame info for pixel fonts into asset config
jobe-m 57089f7
Start adding parallax info config to korge-gradle-plugin
jobe-m 6bdea52
Add parallax config into asset json info
jobe-m 42e3a9c
Minimize serial names for image info in asset config
jobe-m 4bc1915
Add parallax plane line textures to asset info
jobe-m 986c885
Update export of parallax related images and slices
jobe-m 420bebe
Finish parallax layer config saving into Asset JSON info
jobe-m f764b17
Cleanup ImageAseExporter
jobe-m 75482f8
Add worldLevelChunkAssets type and make sure resource folder exists
jobe-m 87cc1ac
Start to add building tilesets into atlas JSON info
jobe-m 4144fdf
Add saving tileset into into asset atlas JSON info
jobe-m e01fdf4
Update asset tileset info
jobe-m de2448d
Identify empty tiles in tilesets
jobe-m d94f7ec
Start to work on LevelMap LDtk importer
jobe-m 0cc0cd0
Fix bug with image size in Korge-gradle-plugin when loading parallax …
jobe-m d7a23d4
Start to add tile map LDtk loader
jobe-m 8f746a0
Refactor asset pipeline and simplify it
jobe-m 098f8f0
Add new Gradle task for loading LDtk levels - WIP
jobe-m 84ebdf6
Fix unit tests
jobe-m ccc2a64
Merge branch 'main' into feature/Add-korge-fleks-extension-to-gradle-…
jobe-m e6c36b4
Fix review findings
jobe-m File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
298 changes: 298 additions & 0 deletions
298
korge-gradle-plugin/src/main/kotlin/korlibs/korge/gradle/korgefleks/AssetConfig.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,298 @@ | ||
| package korlibs.korge.gradle.korgefleks | ||
|
|
||
| import com.android.build.gradle.internal.cxx.json.jsonStringOf | ||
| import kotlinx.kover.util.json.readJsonArray | ||
| import java.io.File | ||
|
|
||
|
|
||
| /** | ||
| * Configuration for managing assets in a KorgeFleks project. | ||
| * | ||
| * This class is a convenience wrapper around AssetImageLoader. | ||
| * | ||
| * @param asepriteExe The path to the Aseprite executable. | ||
| * @param projectDir The root directory of the project. | ||
| * @param assetPath The relative path to the directory containing asset files. | ||
| * @param resourcePath The relative path to the directory for game resources. | ||
| */ | ||
| open class AssetConfig( | ||
| private val asepriteExe: String, | ||
| projectDir: File, | ||
| assetPath: String, | ||
| resourcePath: String | ||
| ) { | ||
| var textureAtlasName: String = "texture" | ||
| var tilesetAtlasName: String = "tileset" | ||
| var simplifyJson: Boolean = true | ||
|
|
||
| var tileWidth: Int = 16 | ||
| var tileHeight: Int = 16 | ||
| var atlasWidth: Int = 2048 | ||
| var atlasHeight: Int = 2048 | ||
| var atlasPadding: Int = 1 | ||
|
|
||
| companion object { | ||
| internal const val VERSION = "version" | ||
| internal const val TEXTURES = "textures" | ||
| internal const val TILESETS = "tilesets" | ||
| internal const val IMAGES = "images" | ||
| internal const val NINE_PATCHES = "ninePatches" | ||
| internal const val PIXEL_FONTS = "pixelFonts" | ||
| internal const val PARALLAX_LAYERS = "parallaxLayers" | ||
| internal const val TILES = "tiles" | ||
| } | ||
|
|
||
| // Directory where Aseprite files are located | ||
| protected val assetDir = projectDir.resolve(assetPath) | ||
| // Directory where exported tiles and tilesets will be stored | ||
| protected val exportTilesDir = projectDir.resolve("build/assets/imageAtlasInput") | ||
| // Directory where game resources are located | ||
| protected val gameResourcesDir = projectDir.resolve("src/commonMain/resources/${resourcePath}") | ||
|
|
||
| protected val assetInfo = linkedMapOf<String, Any>() | ||
|
|
||
| init { | ||
| // Make sure the export directories exist and that they are empty | ||
| if (exportTilesDir.exists()) exportTilesDir.deleteRecursively() | ||
| exportTilesDir.mkdirs() | ||
|
|
||
| // Set version info | ||
| val major = 1 | ||
| val minor = 0 | ||
| val build = 1 | ||
| assetInfo[VERSION] = arrayOf(major, minor, build) | ||
|
|
||
| // Initialize maps and lists in asset info | ||
| assetInfo[TEXTURES] = arrayListOf<String>() | ||
| assetInfo[TILESETS] = arrayListOf<String>() | ||
| assetInfo[IMAGES] = linkedMapOf<String, Any>() | ||
| assetInfo[NINE_PATCHES] = linkedMapOf<String, Any>() | ||
| assetInfo[PIXEL_FONTS] = linkedMapOf<String, Any>() | ||
| assetInfo[PARALLAX_LAYERS] = linkedMapOf<String, Any>() | ||
| assetInfo[TILES] = linkedMapOf<String, Any>() | ||
| } | ||
|
|
||
| protected val assetImageAseExporter = AssetImageAseExporter(asepriteExe, assetDir, exportTilesDir, assetInfo) | ||
| protected val assetFileInstaller = AssetFileInstaller(assetDir, exportTilesDir, gameResourcesDir, assetInfo) | ||
| protected val assetImageAtlasBuilder = AssetImageAtlasBuilder(exportTilesDir, gameResourcesDir, assetInfo) | ||
| protected val assetLevelMapExporter = AssetLevelMapExporter(assetDir, gameResourcesDir, assetInfo) | ||
|
|
||
| /** | ||
| * Export specific layers and tags from Aseprite file as independent png images. | ||
| * Adds exported images to internal asset info list. | ||
| */ | ||
| fun addImageAse(filename: String, layers: List<String>, tags: List<String>, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, layers, tags, output) | ||
| } | ||
|
|
||
| /** Export full image from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, emptyList(), emptyList(), output ) | ||
| } | ||
|
|
||
| /** Export specific layer from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, layer: String, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, listOf(layer), emptyList(), output) | ||
| } | ||
|
|
||
| /** Export specific layer and tag from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, layer: String, tag: String, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, listOf(layer), listOf(tag), output) | ||
| } | ||
|
|
||
| /** Export specific layer and tags from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, layer: String, tags: List<String>, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, listOf(layer), tags, output) | ||
| } | ||
|
|
||
| /** Export specific layers from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, layers: List<String>, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, layers, emptyList(), output) | ||
| } | ||
|
|
||
| /** Export specific layers and tag from Aseprite file | ||
| */ | ||
| fun addImageAse(filename: String, layers: List<String>, tag: String, output: String) { | ||
| assetImageAseExporter.addImageAse(filename, layers, listOf(tag), output) | ||
| } | ||
|
|
||
| /** | ||
| * Export nine-patch image from Aseprite file. | ||
| * Adds exported nine-patch image to internal asset info list. | ||
| */ | ||
| fun addNinePatchImageAse(filename: String, output: String) { | ||
| assetImageAseExporter.addNinePatchImageAse(filename, emptyList(), emptyList(), output) | ||
| } | ||
|
|
||
| /** | ||
| * Export pixel font file and associated pixel font image. | ||
| * It copies font file to game resources and exports font image to assets folder for atlas packing. | ||
| */ | ||
| fun addPixelFont(filename: String) { | ||
| assetFileInstaller.addPixelFont(filename) | ||
| } | ||
|
|
||
| /** | ||
| * Export parallax layer images from Aseprite file. | ||
| * Adds exported parallax images to internal asset info list. | ||
| */ | ||
| fun addParallaxImageAse(filename: String, parallaxInfo: ParallaxInfo) { | ||
| assetImageAseExporter.addParallaxImageAse(filename, parallaxInfo) | ||
| } | ||
|
|
||
| /** | ||
| * Add a generic file to the asset configuration. | ||
| * Copies the file to the game resources' directory. | ||
| */ | ||
| fun addFile(filename: String) { | ||
| assetFileInstaller.addFile(filename) | ||
| } | ||
|
|
||
| /** | ||
| * Build texture and tileset atlases from exported images. | ||
| * Uses atlas names and sizes from the AssetConfig properties. | ||
| * | ||
| * This will always be called as last step after all assets have been added. | ||
| */ | ||
| internal open fun buildAssetStore() { | ||
| // First build the image and tileset atlases | ||
| assetImageAtlasBuilder.buildAtlases( | ||
| textureAtlasName, | ||
| atlasWidth, | ||
| atlasHeight, | ||
| atlasPadding | ||
| ) | ||
| // Finally, write out the asset info as JSON file | ||
| writeAssetInfoJson() | ||
| } | ||
|
|
||
| protected fun writeAssetInfoJson() { | ||
| val assetInfoJsonFile = gameResourcesDir.resolve("${textureAtlasName}.atlas.json") | ||
| assetInfoJsonFile.parentFile?.let { parent -> | ||
| if (!parent.exists() && !parent.mkdirs()) error("Failed to create directory: ${parent.path}") | ||
| val jsonString = jsonStringOf(assetInfo) | ||
| // Simplify JSON string by removing unnecessary spaces and line breaks | ||
| val simplifiedJsonString = if (simplifyJson) jsonString.replace(Regex("\\s+"), "") | ||
| else jsonString | ||
| assetInfoJsonFile.writeText(simplifiedJsonString) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class WorldClusterAssetConfig( | ||
| asepriteExe: String, | ||
| projectDir: File, | ||
| assetPath: String, | ||
| resourcePath: String | ||
| ) : AssetConfig(asepriteExe, projectDir, assetPath, resourcePath) { | ||
|
|
||
| private val tileSetFiles: MutableList<File> = mutableListOf() | ||
| private val exportTilesetDir = projectDir.resolve("build/assets/tilesetAtlasInput") | ||
|
|
||
| // Directory with cluster asset info files (e.g. world.json, intro.json, etc.) | ||
| private val clusterAssetInfoDir = projectDir.resolve("gradle/worldClusterAssetInfo") | ||
|
|
||
| private val assetTilesetExporter = AssetTilesetExporter(assetDir, exportTilesetDir, tileSetFiles) | ||
| private val assetTilesetAtlasBuilder = AssetTilesetAtlasBuilder(exportTilesetDir, gameResourcesDir, assetInfo, tileSetFiles, clusterAssetInfoDir) | ||
|
|
||
| init { | ||
| // Make sure the export directories exist and that they are empty | ||
| if (exportTilesDir.exists()) exportTilesDir.deleteRecursively() | ||
| if (exportTilesetDir.exists()) exportTilesetDir.deleteRecursively() | ||
| exportTilesDir.mkdirs() | ||
| exportTilesetDir.mkdirs() | ||
| } | ||
|
|
||
| /** | ||
| * Export single tiles from a png tileset file and stores them in a tileset atlas. | ||
| * Adds exported tiles and tileset images to internal asset info list. | ||
| */ | ||
| fun addTilesetImagePng(filename: String) { | ||
| assetTilesetExporter.addTilesetImagePng(filename) | ||
| } | ||
|
|
||
| /** | ||
| * Export single level from LDtk file as an TileMap object. | ||
| * Adds exported level map to internal asset info list. | ||
| * | ||
| * @param filename The LDtk file containing the level data. | ||
| * @param levelName The name of the level to export. | ||
| */ | ||
| fun addTileMapLDtkFile(filename: String, levelName: String) { | ||
| // TODO Get data for all clusters and extract used tilesets | ||
| val tileSetsPerClusterMap = mapOf<String, List<String>>() | ||
|
|
||
| assetLevelMapExporter.exportTileMapLDtk(filename, levelName, tileSetsPerClusterMap) | ||
| } | ||
|
|
||
| /** | ||
| * Build texture and tileset atlases from exported images. | ||
| * Uses atlas names and sizes from the AssetConfig properties. | ||
| * | ||
| * This will always be called as last step after all assets have been added. | ||
| * | ||
| * @param assetResourcePath The relative path to the directory for game resources. The name of the last folder is the cluster name. | ||
| */ | ||
| fun buildAssetStore(assetResourcePath: String) { | ||
| // First build the image and tileset atlases | ||
| assetImageAtlasBuilder.buildAtlases( | ||
| textureAtlasName, | ||
| atlasWidth, | ||
| atlasHeight, | ||
| atlasPadding | ||
| ) | ||
| assetTilesetAtlasBuilder.buildTilesetAtlas( | ||
| assetResourcePath, | ||
| tilesetAtlasName, | ||
| tileWidth, | ||
| tileHeight, | ||
| atlasWidth, | ||
| atlasHeight, | ||
| atlasPadding | ||
| ) | ||
| // Finally, write out the asset info as JSON file | ||
| writeAssetInfoJson() | ||
| } | ||
| } | ||
|
|
||
| class WorldLDtkLevelMapAssetConfig( | ||
| projectDir: File, | ||
| world: Int, | ||
| private val levelMapFilePath: String, | ||
| resourcePath: String | ||
| ) { | ||
| // Directory with cluster asset info files (e.g. world.json, intro.json, etc.) | ||
| private val clusterAssetInfoDir = projectDir.resolve("gradle/worldClusterAssetInfo/world_${world}") | ||
| // Directory where game resources are located | ||
| private val gameResourcesDir = projectDir.resolve("src/commonMain/resources/${resourcePath}") | ||
| private val assetLevelMapExporter = AssetLevelMapExporter(projectDir, gameResourcesDir, linkedMapOf()) | ||
|
|
||
| /** | ||
| * Export level map from LDtk file as chunked level map. | ||
| * Adds exported level map to internal asset info list. | ||
| */ | ||
| fun buildAssetStore() { | ||
| // Get the info which tileset are available in each processed asset cluster | ||
| if (clusterAssetInfoDir.listFiles() != null && clusterAssetInfoDir.listFiles().isNotEmpty()) { | ||
| val clusterAssetInfoFiles = clusterAssetInfoDir.listFiles()!!.filter { it.extension == "json" } | ||
|
|
||
| val tileSetsPerClusterMap: Map<String, List<String>> = clusterAssetInfoFiles.associate { file -> | ||
| val clusterName = file.nameWithoutExtension | ||
| val tileSetsList: List<String> = file.readJsonArray().let { jsonArray -> | ||
| jsonArray.map { it as String } | ||
| } | ||
| clusterName to tileSetsList | ||
| } | ||
|
|
||
| println("Tilesets per cluster: $tileSetsPerClusterMap") | ||
|
|
||
| // TODO change to support world chunks | ||
| assetLevelMapExporter.exportLevelMapLDtk(levelMapFilePath, tileSetsPerClusterMap) | ||
| } else error("ERROR: No cluster asset info files found. Please run first all world cluster asset tasks before running level map asset task.") | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.