mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-21 05:09:25 +07:00
Tilesets: Added edge tile images!
This commit is contained in:
@ -691,6 +691,8 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
|||||||
else probability
|
else probability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isTilemapInitialized() = ::tileMap.isInitialized
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region state-changing functions
|
//region state-changing functions
|
||||||
|
|
||||||
@ -712,7 +714,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
|||||||
isOcean = baseTerrain == Constants.ocean
|
isOcean = baseTerrain == Constants.ocean
|
||||||
|
|
||||||
// Resource amounts missing - Old save or bad mapgen?
|
// Resource amounts missing - Old save or bad mapgen?
|
||||||
if (::tileMap.isInitialized && resource != null && tileResource.resourceType == ResourceType.Strategic && resourceAmount == 0) {
|
if (isTilemapInitialized() && resource != null && tileResource.resourceType == ResourceType.Strategic && resourceAmount == 0) {
|
||||||
// Let's assume it's a small deposit
|
// Let's assume it's a small deposit
|
||||||
setTileResource(tileResource, majorDeposit = false)
|
setTileResource(tileResource, majorDeposit = false)
|
||||||
}
|
}
|
||||||
@ -812,7 +814,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUniqueMap() {
|
private fun updateUniqueMap() {
|
||||||
if (!::tileMap.isInitialized) return // This tile is a fake tile, for visual display only (e.g. map editor, civilopedia)
|
if (!isTilemapInitialized()) return // This tile is a fake tile, for visual display only (e.g. map editor, civilopedia)
|
||||||
val terrainNameList = allTerrains.map { it.name }.toList()
|
val terrainNameList = allTerrains.map { it.name }.toList()
|
||||||
|
|
||||||
// List hash is function of all its items, so the same items in the same order will always give the same hash
|
// List hash is function of all its items, so the same items in the same order will always give the same hash
|
||||||
|
@ -8,6 +8,8 @@ import com.unciv.models.metadata.GameSettings
|
|||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.tilesets.TileSetCache
|
import com.unciv.models.tilesets.TileSetCache
|
||||||
import com.unciv.models.tilesets.TileSetConfig
|
import com.unciv.models.tilesets.TileSetConfig
|
||||||
|
import com.unciv.ui.components.tilegroups.layers.EdgeTileImage
|
||||||
|
import com.unciv.ui.components.tilegroups.layers.NeighborDirection
|
||||||
import com.unciv.ui.images.ImageAttempter
|
import com.unciv.ui.images.ImageAttempter
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
|
|
||||||
@ -67,6 +69,26 @@ class TileSetStrings(
|
|||||||
val bottomRiver by lazy { orFallback { tilesLocation + "River-Bottom"} }
|
val bottomRiver by lazy { orFallback { tilesLocation + "River-Bottom"} }
|
||||||
val bottomLeftRiver by lazy { orFallback { tilesLocation + "River-BottomLeft"} }
|
val bottomLeftRiver by lazy { orFallback { tilesLocation + "River-BottomLeft"} }
|
||||||
|
|
||||||
|
val edgeImagesByPosition = ImageGetter.getAllImageNames()
|
||||||
|
.filter { it.startsWith(tileSetLocation +"Edges/") }
|
||||||
|
.mapNotNull {
|
||||||
|
val split = it.split('/').last() // without folder
|
||||||
|
.split("-")
|
||||||
|
// Comprised of 3 parts: origin tilefilter, destination tilefilter,
|
||||||
|
// and edge type: Bottom, BottomLeft or BottomRight
|
||||||
|
if (split.size != 4) return@mapNotNull null
|
||||||
|
|
||||||
|
// split[0] is name and is unused
|
||||||
|
val originTileFilter = split[1]
|
||||||
|
val destinationTileFilter = split[2]
|
||||||
|
val neighborDirection = split[3]
|
||||||
|
val neighborDirectionEnumValue = NeighborDirection.entries
|
||||||
|
.firstOrNull { it.name == neighborDirection } ?: return@mapNotNull null
|
||||||
|
|
||||||
|
EdgeTileImage(it, originTileFilter, destinationTileFilter, neighborDirectionEnumValue)
|
||||||
|
}
|
||||||
|
.groupBy { it.edgeType }
|
||||||
|
|
||||||
val unitsLocation = unitSetLocation + "Units/"
|
val unitsLocation = unitSetLocation + "Units/"
|
||||||
|
|
||||||
val bordersLocation = tileSetLocation + "Borders/"
|
val bordersLocation = tileSetLocation + "Borders/"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.unciv.ui.components.tilegroups.layers
|
package com.unciv.ui.components.tilegroups.layers
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
@ -86,8 +87,30 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getEdgeTileLocations(): Sequence<String> {
|
||||||
|
val tile = tile()
|
||||||
|
if (!tile.isTilemapInitialized()) // fake tile
|
||||||
|
return emptySequence()
|
||||||
|
return tile.neighbors
|
||||||
|
.filter { it.position.x < tile.position.x || it.position.y < tile.position.y }
|
||||||
|
.flatMap { getMatchingEdges(tile, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMatchingEdges(originTile: Tile, neighborTile: Tile): List<String>{
|
||||||
|
val vectorToNeighbor = neighborTile.position.cpy().sub(originTile.position)
|
||||||
|
val direction = NeighborDirection.fromVector(vectorToNeighbor) ?: return emptyList()
|
||||||
|
val possibleEdgeFiles = strings().edgeImagesByPosition[direction] ?: return emptyList()
|
||||||
|
|
||||||
|
return possibleEdgeFiles.filter {
|
||||||
|
if (!originTile.matchesFilter(it.originTileFilter)) return@filter false
|
||||||
|
if (!neighborTile.matchesFilter(it.destinationTileFilter)) return@filter false
|
||||||
|
return@filter true
|
||||||
|
}.map { it.fileName }
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateTileImage(viewingCiv: Civilization?) {
|
private fun updateTileImage(viewingCiv: Civilization?) {
|
||||||
val tileBaseImageLocations = getTileBaseImageLocations(viewingCiv)
|
val tileBaseImageLocations = getTileBaseImageLocations(viewingCiv) +
|
||||||
|
getEdgeTileLocations()
|
||||||
|
|
||||||
if (tileBaseImageLocations.size == tileImageIdentifiers.size) {
|
if (tileBaseImageLocations.size == tileImageIdentifiers.size) {
|
||||||
if (tileBaseImageLocations.withIndex().all { (i, imageLocation) -> tileImageIdentifiers[i] == imageLocation })
|
if (tileBaseImageLocations.withIndex().all { (i, imageLocation) -> tileImageIdentifiers[i] == imageLocation })
|
||||||
@ -211,3 +234,21 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
|
|||||||
else baseHexagon + strings().orFallback{ getTile(tileGroup.tile.naturalWonder!!) }
|
else baseHexagon + strings().orFallback{ getTile(tileGroup.tile.naturalWonder!!) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class NeighborDirection {
|
||||||
|
Top, TopRight, TopLeft, Bottom, BottomLeft, BottomRight;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromVector(vector2: Vector2): NeighborDirection? = when {
|
||||||
|
vector2.x == 1f && vector2.y == 1f -> Top
|
||||||
|
vector2.x == 0f && vector2.y == 1f -> TopRight
|
||||||
|
vector2.x == 1f && vector2.y == 0f -> TopLeft
|
||||||
|
vector2.x == -1f && vector2.y == -1f -> Bottom
|
||||||
|
vector2.x == 0f && vector2.y == -1f -> BottomLeft
|
||||||
|
vector2.x == -1f && vector2.y == 0f -> BottomRight
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class EdgeTileImage(val fileName:String, val originTileFilter: String, val destinationTileFilter: String, val edgeType: NeighborDirection)
|
@ -468,6 +468,8 @@ object ImageGetter {
|
|||||||
return specialist
|
return specialist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAllImageNames() = textureRegionDrawables.keys
|
||||||
|
|
||||||
fun getAvailableSkins() = ninePatchDrawables.keys.asSequence().map { it.split("/")[1] }.distinct()
|
fun getAvailableSkins() = ninePatchDrawables.keys.asSequence().map { it.split("/")[1] }.distinct()
|
||||||
|
|
||||||
/** Determines available TileSets from the currently loaded Texture paths.
|
/** Determines available TileSets from the currently loaded Texture paths.
|
||||||
|
@ -146,3 +146,22 @@ They can be for unit types (Archery, Seige, Cavalry) or for specific unit names
|
|||||||
|
|
||||||
The files should be in the format of `<unit type/unit name>-attack-<frame number>`.
|
The files should be in the format of `<unit type/unit name>-attack-<frame number>`.
|
||||||
For example, a 3 frame animation for Sword units would have the files `Sword-attack-1.png`, `Sword-attack-3.png`, `Sword-attack-3.png`
|
For example, a 3 frame animation for Sword units would have the files `Sword-attack-1.png`, `Sword-attack-3.png`, `Sword-attack-3.png`
|
||||||
|
|
||||||
|
## Edge images
|
||||||
|
|
||||||
|
You can add additional images that will be drawn only when a tile is adjacent to another tile in a specific direction.
|
||||||
|
|
||||||
|
The images should be placed in the `Images/Tilesets/<tileset name>/Edges` folder, rather than in `/Tiles`.
|
||||||
|
|
||||||
|
The name of the tile should be `<tile name>-<origin tile filter>-<destination tile filter>-<neighbor direction>.png`, where direction of one of:
|
||||||
|
|
||||||
|
- Bottom
|
||||||
|
- BottomLeft
|
||||||
|
- BottomRight
|
||||||
|
- Top
|
||||||
|
- TopLeft
|
||||||
|
- TopRight
|
||||||
|
|
||||||
|
For example: `Cliff-Hills-Coast-Top.png`
|
||||||
|
|
||||||
|
The initial name has no bearing on the image used, it is just a way to group images together.
|
||||||
|
Reference in New Issue
Block a user