mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-18 19:59:47 +07:00
Tilesets: Added edge tile images!
This commit is contained in:
@ -691,6 +691,8 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
else probability
|
||||
}
|
||||
|
||||
fun isTilemapInitialized() = ::tileMap.isInitialized
|
||||
|
||||
//endregion
|
||||
//region state-changing functions
|
||||
|
||||
@ -712,7 +714,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
isOcean = baseTerrain == Constants.ocean
|
||||
|
||||
// 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
|
||||
setTileResource(tileResource, majorDeposit = false)
|
||||
}
|
||||
@ -812,7 +814,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
// 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.tilesets.TileSetCache
|
||||
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.ImageGetter
|
||||
|
||||
@ -67,6 +69,26 @@ class TileSetStrings(
|
||||
val bottomRiver by lazy { orFallback { tilesLocation + "River-Bottom"} }
|
||||
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 bordersLocation = tileSetLocation + "Borders/"
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.ui.components.tilegroups.layers
|
||||
|
||||
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.ui.Image
|
||||
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?) {
|
||||
val tileBaseImageLocations = getTileBaseImageLocations(viewingCiv)
|
||||
val tileBaseImageLocations = getTileBaseImageLocations(viewingCiv) +
|
||||
getEdgeTileLocations()
|
||||
|
||||
if (tileBaseImageLocations.size == tileImageIdentifiers.size) {
|
||||
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!!) }
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fun getAllImageNames() = textureRegionDrawables.keys
|
||||
|
||||
fun getAvailableSkins() = ninePatchDrawables.keys.asSequence().map { it.split("/")[1] }.distinct()
|
||||
|
||||
/** 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>`.
|
||||
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