From 8161da26deeaeb47810e722b256553fb9c5ac456 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Wed, 22 Sep 2021 21:11:39 +0200 Subject: [PATCH] Texture pack/load for mods also distributes by Images.*X* (#5296) --- core/src/com/unciv/ui/utils/ImageGetter.kt | 51 ++++++++++--------- .../src/com/unciv/app/desktop/ImagePacker.kt | 34 ++++++++----- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/core/src/com/unciv/ui/utils/ImageGetter.kt b/core/src/com/unciv/ui/utils/ImageGetter.kt index 8c7678073b..aa52881016 100644 --- a/core/src/com/unciv/ui/utils/ImageGetter.kt +++ b/core/src/com/unciv/ui/utils/ImageGetter.kt @@ -1,6 +1,7 @@ package com.unciv.ui.utils import com.badlogic.gdx.Gdx +import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture.TextureFilter @@ -62,38 +63,40 @@ object ImageGetter { textureRegionDrawables[region.name] = drawable } - // See #4993 - you can't .list() on a jar file, so the ImagePacker leaves us the list of actual atlases. - val fileNames = GameSaver.json().fromJson(Array::class.java, Gdx.files.internal("Atlases.json")) - for (fileName in fileNames) { - val file = Gdx.files.internal("$fileName.atlas") - val extraAtlas = file.nameWithoutExtension() - val tempAtlas = atlases[extraAtlas] // fetch if cached - ?: TextureAtlas(file.name()).apply { // load if not - atlases[extraAtlas] = this // cache the freshly loaded - } - for (region in tempAtlas.regions) { - val drawable = TextureRegionDrawable(region) - textureRegionDrawables[region.name] = drawable - } - } + // Load base (except game.atlas which is already loaded) + loadModAtlases("", Gdx.files.internal(".")) // These are from the mods for (mod in UncivGame.Current.settings.visualMods + ruleset.mods) { - val modAtlasFile = Gdx.files.local("mods/$mod/game.atlas") - if (!modAtlasFile.exists()) continue - - if (!atlases.containsKey(mod)) atlases[mod] = TextureAtlas(modAtlasFile) - val modAtlas = atlases[mod]!! - - for (region in modAtlas.regions) { - val drawable = TextureRegionDrawable(region) - textureRegionDrawables[region.name] = drawable - } + loadModAtlases(mod, Gdx.files.local("mods/$mod")) } TileSetCache.assembleTileSetConfigs(ruleset.mods) } + /** Loads all atlas/texture files from a folder, as controlled by an Atlases.json */ + fun loadModAtlases(mod: String, folder: FileHandle) { + // See #4993 - you can't .list() on a jar file, so the ImagePacker leaves us the list of actual atlases. + val controlFile = folder.child("Atlases.json") + val fileNames = (if (controlFile.exists()) GameSaver.json().fromJson(Array::class.java, controlFile) + else emptyArray()).toMutableList() + if (mod.isNotEmpty()) fileNames += "game" + for (fileName in fileNames) { + val file = folder.child("$fileName.atlas") + if (!file.exists()) continue + val extraAtlas = if (mod.isEmpty()) fileName else if (fileName == "game") mod else "$mod/$fileName" + var tempAtlas = atlases[extraAtlas] // fetch if cached + if (tempAtlas == null) { + println("Loading $extraAtlas = ${file.path()}") + tempAtlas = TextureAtlas(file) // load if not + atlases[extraAtlas] = tempAtlas // cache the freshly loaded + } + for (region in tempAtlas.regions) { + val drawable = TextureRegionDrawable(region) + textureRegionDrawables[region.name] = drawable + } + } + } /** * Colors a multilayer image and returns it as a list of layers (Image). diff --git a/desktop/src/com/unciv/app/desktop/ImagePacker.kt b/desktop/src/com/unciv/app/desktop/ImagePacker.kt index e2dc625b86..35f0726184 100644 --- a/desktop/src/com/unciv/app/desktop/ImagePacker.kt +++ b/desktop/src/com/unciv/app/desktop/ImagePacker.kt @@ -58,23 +58,15 @@ internal object ImagePacker { val defaultSettings = getDefaultSettings() // Scan for Image folders and build one atlas each - if (File("../Images").exists()) { // So we don't run this from within a fat JAR - val atlasList = mutableListOf() - for ((file, packFileName) in imageFolders()) { - atlasList += packFileName - packImagesIfOutdated(defaultSettings, file, ".", packFileName) - } - atlasList.remove("game") - File("Atlases.json").writeText(atlasList.sorted().joinToString(",","[","]")) - } + packImagesPerMod("..", ".", defaultSettings) // pack for mods as well val modDirectory = File("mods") if (modDirectory.exists()) { for (mod in modDirectory.listFiles()!!) { - if (!mod.isHidden && File(mod.path + "/Images").exists()) { + if (!mod.isHidden) { try { - packImagesIfOutdated(defaultSettings, mod.path + "/Images", mod.path, "game") + packImagesPerMod(mod.path, mod.path, defaultSettings) } catch (ex: Throwable) { println("Exception in ImagePacker: ${ex.message}") } @@ -86,6 +78,20 @@ internal object ImagePacker { println("Packing textures - " + texturePackingTime + "ms") } + // Scan multiple image folders and generate an atlas for each - if outdated + private fun packImagesPerMod(input: String, output: String, defaultSettings: TexturePacker.Settings) { + if (!File("$input${File.separator}Images").exists()) return // So we don't run this from within a fat JAR + val atlasList = mutableListOf() + for ((file, packFileName) in imageFolders(input)) { + atlasList += packFileName + packImagesIfOutdated(defaultSettings, file, output, packFileName) + } + atlasList.remove("game") + val listFile = File("$output${File.separator}Atlases.json") + if (atlasList.isEmpty()) listFile.delete() + else listFile.writeText(atlasList.sorted().joinToString(",","[","]")) + } + // Process one Image folder, checking for atlas older than contained images first private fun packImagesIfOutdated(defaultSettings: TexturePacker.Settings, input: String, output: String, packFileName: String) { fun File.listTree(): Sequence = when { @@ -112,13 +118,13 @@ internal object ImagePacker { // Iterator providing all Image folders to process with the destination atlas name private data class ImageFolderResult(val folder: String, val atlasName: String) - private fun imageFolders() = sequence { - val parent = File("..") + private fun imageFolders(path: String) = sequence { + val parent = File(path) for (folder in parent.listFiles()!!) { if (!folder.isDirectory) continue if (folder.nameWithoutExtension != "Images") continue val atlasName = if (folder.name == "Images") "game" else folder.extension - yield(ImageFolderResult("..${File.separator}${folder.name}", atlasName)) + yield(ImageFolderResult(folder.path, atlasName)) } } }