perf: save tile ref on each tile layer

This commit is contained in:
yairm210 2024-12-15 19:39:24 +02:00
parent c3c397aade
commit 7bc5047ace
9 changed files with 65 additions and 65 deletions

View File

@ -19,8 +19,9 @@ abstract class TileLayer(val tileGroup: TileGroup, size: Float) : Group() {
setSize(size, size)
}
fun tile(): Tile = tileGroup.tile
fun strings(): TileSetStrings = tileGroup.tileSetStrings
// these should not change
val tile: Tile = tileGroup.tile
val strings: TileSetStrings = tileGroup.tileSetStrings
fun Image.setHexagonSize(scale: Float? = null): Image {
this.setSize(tileGroup.hexagonImageWidth, this.height*tileGroup.hexagonImageWidth/this.width)

View File

@ -128,7 +128,7 @@ class TileLayerBorders(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
val angle = sign * (atan(sign * relativeWorldPosition.y / relativeWorldPosition.x) * 180 / PI - 90.0).toFloat()
val innerBorderImage = ImageGetter.getImage(
strings().orFallback { getBorder(borderShapeString,"Inner") }
strings.orFallback { getBorder(borderShapeString,"Inner") }
).setHexagonSize()
addActor(innerBorderImage)
@ -137,7 +137,7 @@ class TileLayerBorders(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
innerBorderImage.color = civOuterColor
val outerBorderImage = ImageGetter.getImage(
strings().orFallback { getBorder(borderShapeString, "Outer") }
strings.orFallback { getBorder(borderShapeString, "Outer") }
).setHexagonSize()
addActor(outerBorderImage)

View File

@ -47,7 +47,7 @@ class TileLayerCityButton(tileGroup: TileGroup, size: Float) : TileLayer(tileGro
override fun doUpdate(viewingCiv: Civilization?, localUniqueCache: LocalUniqueCache) {
if (tileGroup !is WorldTileGroup) return
val city = tile().getCity()
val city = tile.getCity()
// There used to be a city here but it was razed
if (city == null && cityButton != null) {

View File

@ -51,7 +51,7 @@ class TileLayerFeatures(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup
}
if (roadStatus == RoadStatus.None) continue // no road image
val image = ImageGetter.getImage(strings().orFallback { roadsMap[roadStatus]!! })
val image = ImageGetter.getImage(strings.orFallback { roadsMap[roadStatus]!! })
roadImage.image = image
val relativeWorldPosition = tile.tileMap.getNeighborTilePositionAsWorldCoords(tile, neighbor)

View File

@ -50,7 +50,7 @@ private class MapArrow(val targetTile: Tile, val arrowType: MapArrowType, val st
class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, size) {
// For different unit views, we want to effectively "ignore" the terrain and color it by special view
private var terrainOverlay: Image? = ImageGetter.getImage(strings().hexagon).setHexagonSize()
private var terrainOverlay: Image? = ImageGetter.getImage(strings.hexagon).setHexagonSize()
override fun act(delta: Float) {}
override fun hit(x: Float, y: Float, touchable: Boolean): Actor? {
@ -108,11 +108,11 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
for (arrowToAdd in arrowsToDraw) {
val targetTile = arrowToAdd.targetTile
var targetPos = Vector2(targetTile.position)
if (tile().tileMap.mapParameters.worldWrap)
if (tile.tileMap.mapParameters.worldWrap)
targetPos = HexMath.getUnwrappedNearestTo(targetPos,
tile().position, tile().tileMap.maxLongitude)
tile.position, tile.tileMap.maxLongitude)
val targetRelative = HexMath.hex2WorldCoords(targetPos)
.sub(HexMath.hex2WorldCoords(tile().position))
.sub(HexMath.hex2WorldCoords(tile.position))
val targetDistance = sqrt(targetRelative.x.pow(2) + targetRelative.y.pow(2))
val targetAngle = atan2(targetRelative.y, targetRelative.x)
@ -139,9 +139,9 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
private fun updateImprovementIcon(viewingCiv: Civilization?, show: Boolean) {
// If improvement has changed, force new icon next time it is needed
val improvementToShow = tile().getShownImprovement(viewingCiv)
val improvementToShow = tile.getShownImprovement(viewingCiv)
val newImprovementPlusPillagedID = if (improvementToShow==null) null
else if (tile().improvementIsPillaged) "$improvementToShow-Pillaged"
else if (tile.improvementIsPillaged) "$improvementToShow-Pillaged"
else improvementToShow
if (improvementPlusPillagedID != newImprovementPlusPillagedID) {
@ -152,7 +152,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
// Get new icon when needed
if (improvementPlusPillagedID != null && show && improvementIcon == null) {
val icon = ImageGetter.getImprovementPortrait(improvementToShow!!, dim = false, isPillaged = tile().improvementIsPillaged)
val icon = ImageGetter.getImprovementPortrait(improvementToShow!!, dim = false, isPillaged = tile.improvementIsPillaged)
icon.center(tileGroup)
icon.x -= 22 // left
icon.y -= 12 // bottom
@ -168,14 +168,14 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
val effectiveVisible = when {
tileGroup.isForceVisible -> show
show && viewingCiv == null -> true
show && tile().hasViewableResource(viewingCiv!!) -> true
show && tile.hasViewableResource(viewingCiv!!) -> true
else -> false
}
// If resource has changed (e.g. tech researched) - force new icon next time it's needed
if (resourceName != tile().resource || resourceAmount != tile().resourceAmount) {
resourceName = tile().resource
resourceAmount = tile().resourceAmount
if (resourceName != tile.resource || resourceAmount != tile.resourceAmount) {
resourceName = tile.resource
resourceAmount = tile.resourceAmount
resourceIcon?.remove()
resourceIcon = null
}
@ -213,7 +213,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
return
if (DebugUtils.SHOW_TILE_COORDS) {
val label = this.tile().position.toPrettyString()
val label = this.tile.position.toPrettyString()
startingLocationIcons.add(label.toLabel(ImageGetter.CHARCOAL.cpy().apply { a = 0.7f }, 14).apply {
tileGroup.layerMisc.addActor(this)
setOrigin(Align.center)
@ -228,7 +228,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
})
}
val tilemap = tile().tileMap
val tilemap = tile.tileMap
if (tilemap.startingLocationsByNation.isEmpty())
return
@ -237,7 +237,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
// Sorted so major get precedence and to make the display deterministic, otherwise you could get
// different stacking order of the same nations in the same editing session
val nations = tilemap.startingLocationsByNation.asSequence()
.filter { tile() in it.value }
.filter { tile in it.value }
.filter { it.key in tilemap.ruleset!!.nations } // Ignore missing nations
.map { it.key to tilemap.ruleset!!.nations[it.key]!! }
.sortedWith(compareBy({ it.second.isCityState }, { it.first }))
@ -295,9 +295,9 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
if (effectiveVisible) yields.run {
// Update YieldGroup Icon
if (tileGroup is CityTileGroup)
setStats(tile().stats.getTileStats(tileGroup.city, viewingCiv, localUniqueCache))
setStats(tile.stats.getTileStats(tileGroup.city, viewingCiv, localUniqueCache))
else
setStats(tile().stats.getTileStats(viewingCiv, localUniqueCache))
setStats(tile.stats.getTileStats(viewingCiv, localUniqueCache))
toFront()
centerX(tileGroup)
isVisible = true
@ -339,7 +339,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
private fun overlayTerrainInner(color: Color) {
if (terrainOverlay == null){
terrainOverlay = ImageGetter.getImage(strings().hexagon).setHexagonSize()
terrainOverlay = ImageGetter.getImage(strings.hexagon).setHexagonSize()
addActor(terrainOverlay)
}
terrainOverlay?.color = color
@ -354,8 +354,8 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
fun addArrow(targetTile: Tile, type: MapArrowType) {
if (targetTile.position != tile().position)
arrowsToDraw.add(MapArrow(targetTile, type, strings()))
if (targetTile.position != tile.position)
arrowsToDraw.add(MapArrow(targetTile, type, strings))
}
fun resetArrows() {

View File

@ -22,13 +22,13 @@ class TileLayerOverlay(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
private var fog: Image? = null
private var unexplored: Image? = null
private fun getHighlight() = ImageGetter.getImage(strings().highlight).setHexagonSize() // for blue and red circles/emphasis on the tile
private fun getCrosshair() = ImageGetter.getImage(strings().crosshair).setHexagonSize() // for when a unit is targeted
private fun getHighlight() = ImageGetter.getImage(strings.highlight).setHexagonSize() // for blue and red circles/emphasis on the tile
private fun getCrosshair() = ImageGetter.getImage(strings.crosshair).setHexagonSize() // for when a unit is targeted
private fun getGoodCityLocationIndicator() = ImageGetter.getImage("OtherIcons/Cities").setHexagonSize(0.25f)
private fun getFog() = ImageGetter.getImage(strings().crosshatchHexagon ).setHexagonSize().apply {
private fun getFog() = ImageGetter.getImage(strings.crosshatchHexagon ).setHexagonSize().apply {
color = Color.WHITE.cpy().apply { a = 0.2f }
}
private fun getUnexplored() = ImageGetter.getImage(strings().unexploredTile ).setHexagonSize()
private fun getUnexplored() = ImageGetter.getImage(strings.unexploredTile ).setHexagonSize()
fun orderToFront() {
unexplored?.toFront()
@ -100,19 +100,19 @@ class TileLayerOverlay(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
setUnexplored(viewingCiv)
if (tile().getShownImprovement(viewingCiv) == Constants.barbarianEncampment
&& tile().isExplored(viewingCiv))
if (tile.getShownImprovement(viewingCiv) == Constants.barbarianEncampment
&& tile.isExplored(viewingCiv))
showHighlight(Color.RED)
}
private fun setUnexplored(viewingCiv: Civilization) {
val unexploredShouldBeVisible = !viewingCiv.hasExplored(tile())
val unexploredShouldBeVisible = !viewingCiv.hasExplored(tile)
val unexploredIsVisible = unexplored != null
if (unexploredIsVisible && !unexploredShouldBeVisible) {
unexplored?.remove()
determineVisibility()
} else if (!unexploredIsVisible && unexploredShouldBeVisible
&& ImageGetter.imageExists(strings().unexploredTile)) {
&& ImageGetter.imageExists(strings.unexploredTile)) {
unexplored = getUnexplored()
addActor(unexplored)
determineVisibility()

View File

@ -28,23 +28,23 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
private fun getTerrainImageLocations(terrainSequence: Sequence<String>): List<String> {
val allTerrains = terrainSequence.joinToString("+")
if (strings().tileSetConfig.ruleVariants.containsKey(allTerrains))
return strings().tileSetConfig.ruleVariants[allTerrains]!!.map { strings().getTile(it) }
val allTerrainTile = strings().getTile(allTerrains)
if (strings.tileSetConfig.ruleVariants.containsKey(allTerrains))
return strings.tileSetConfig.ruleVariants[allTerrains]!!.map { strings.getTile(it) }
val allTerrainTile = strings.getTile(allTerrains)
return if (ImageGetter.imageExists(allTerrainTile)) listOf(allTerrainTile)
else terrainSequence.map { strings().orFallback { getTile(it) } }.toList()
else terrainSequence.map { strings.orFallback { getTile(it) } }.toList()
}
private fun getImprovementAndResourceImages(resourceAndImprovementSequence: Sequence<String>): List<String> {
val altogether = resourceAndImprovementSequence.joinToString("+").let { strings().getTile(it) }
val altogether = resourceAndImprovementSequence.joinToString("+").let { strings.getTile(it) }
return if (ImageGetter.imageExists(altogether)) listOf(altogether)
else resourceAndImprovementSequence.map { strings().orFallback { getTile(it) } }.toList()
else resourceAndImprovementSequence.map { strings.orFallback { getTile(it) } }.toList()
}
private fun usePillagedImprovementImage(tile: Tile, viewingCiv: Civilization?): Boolean {
if (!tile.improvementIsPillaged || !UncivGame.Current.settings.showPixelImprovements) return false
val shownImprovement = tile.getShownImprovement(viewingCiv) ?: return false
return ImageGetter.imageExists(strings().getTile("$shownImprovement-Pillaged"))
return ImageGetter.imageExists(strings.getTile("$shownImprovement-Pillaged"))
}
private fun getTileBaseImageLocations(viewingCiv: Civilization?): List<String> {
@ -52,10 +52,10 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
val isForceVisible = tileGroup.isForceVisible
if (viewingCiv == null && !isForceVisible)
return strings().hexagonList
return strings.hexagonList
val baseHexagon = if (strings().tileSetConfig.useColorAsBaseTerrain)
listOf(strings().hexagon)
val baseHexagon = if (strings.tileSetConfig.useColorAsBaseTerrain)
listOf(strings.hexagon)
else emptyList()
val tile = tileGroup.tile
@ -80,14 +80,14 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
else sequenceOf(tile.baseTerrain) + tile.terrainFeatures.asSequence()
val edgeImages = getEdgeTileLocations()
val allTogether = (terrainImages + resourceAndImprovementSequence).joinToString("+")
val allTogetherLocation = strings().getTile(allTogether)
val allTogetherLocation = strings.getTile(allTogether)
// If the tilesetconfig *explicitly* lists the terrains+improvements etc, we can't know where in that list to place the edges
// So we default to placing them over everything else.
// If there is no explicit list, then we can know to place them between the terrain and the improvement
return when {
strings().tileSetConfig.ruleVariants[allTogether] != null -> baseHexagon +
strings().tileSetConfig.ruleVariants[allTogether]!!.map { strings().getTile(it) } + edgeImages
strings.tileSetConfig.ruleVariants[allTogether] != null -> baseHexagon +
strings.tileSetConfig.ruleVariants[allTogether]!!.map { strings.getTile(it) } + edgeImages
ImageGetter.imageExists(allTogetherLocation) -> baseHexagon + allTogetherLocation + edgeImages
tile.naturalWonder != null -> getNaturalWonderBackupImage(baseHexagon) + edgeImages
else -> baseHexagon + getTerrainImageLocations(terrainImages) + edgeImages + getImprovementAndResourceImages(resourceAndImprovementSequence)
@ -95,7 +95,6 @@ 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
@ -106,7 +105,7 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
val vectorToNeighbor = neighborTile.position.cpy().sub(originTile.position)
val direction = NeighborDirection.fromVector(vectorToNeighbor)
?: return emptySequence()
val possibleEdgeFiles = strings().edgeImagesByPosition[direction] ?: return emptySequence()
val possibleEdgeFiles = strings.edgeImagesByPosition[direction] ?: return emptySequence()
// Required for performance - full matchesFilter is too expensive for something that needs to run every update()
fun matchesFilterMinimal(originTile: Tile, filter: String): Boolean {
@ -140,7 +139,7 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
val locationToCheck =
if (tileGroup.tile.owningCity != null)
strings().getOwnedTileImageLocation(baseLocation, tileGroup.tile.getOwner()!!)
strings.getOwnedTileImageLocation(baseLocation, tileGroup.tile.getOwner()!!)
else baseLocation
val existingImages = ArrayList<String>()
@ -160,8 +159,8 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
tileBaseImages.add(image)
addActor(image)
if (strings().tileSetConfig.tileScales.isNotEmpty()) {
val scale = strings().tileSetConfig.tileScales[baseLocation.takeLastWhile { it != '/' }]
if (strings.tileSetConfig.tileScales.isNotEmpty()) {
val scale = strings.tileSetConfig.tileScales[baseLocation.takeLastWhile { it != '/' }]
image.setHexagonSize(scale)
} else {
image.setHexagonSize()
@ -175,21 +174,21 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
val colorPillagedTile = isViewable && tile.isPillaged() && !usePillagedImprovementImage(tile, viewingCiv)
val baseTerrainColor = when {
colorPillagedTile && strings().tileSetConfig.useColorAsBaseTerrain -> tile.getBaseTerrain()
colorPillagedTile && strings.tileSetConfig.useColorAsBaseTerrain -> tile.getBaseTerrain()
.getColor().lerp(Color.BROWN, 0.6f)
colorPillagedTile -> Color.WHITE.cpy().lerp(Color.BROWN, 0.6f)
strings().tileSetConfig.useColorAsBaseTerrain && !isViewable -> tile.getBaseTerrain()
.getColor().lerp(strings().tileSetConfig.fogOfWarColor, 0.6f)
strings().tileSetConfig.useColorAsBaseTerrain -> tile.getBaseTerrain()
strings.tileSetConfig.useColorAsBaseTerrain && !isViewable -> tile.getBaseTerrain()
.getColor().lerp(strings.tileSetConfig.fogOfWarColor, 0.6f)
strings.tileSetConfig.useColorAsBaseTerrain -> tile.getBaseTerrain()
.getColor()
!isViewable -> Color.WHITE.cpy().lerp(strings().tileSetConfig.fogOfWarColor, 0.6f)
!isViewable -> Color.WHITE.cpy().lerp(strings.tileSetConfig.fogOfWarColor, 0.6f)
else -> Color.WHITE.cpy()
}
val color = when {
colorPillagedTile -> Color.WHITE.cpy().lerp(Color.RED.cpy(), 0.5f)
!isViewable -> Color.WHITE.cpy()
.lerp(strings().tileSetConfig.fogOfWarColor, 0.6f)
.lerp(strings.tileSetConfig.fogOfWarColor, 0.6f)
else -> Color.WHITE.cpy()
}
@ -198,9 +197,9 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
}
private fun updateRivers(displayBottomRight: Boolean, displayBottom: Boolean, displayBottomLeft: Boolean) {
bottomRightRiverImage = updateRiver(bottomRightRiverImage,displayBottomRight, strings().bottomRightRiver)
bottomRiverImage = updateRiver(bottomRiverImage, displayBottom, strings().bottomRiver)
bottomLeftRiverImage = updateRiver(bottomLeftRiverImage, displayBottomLeft, strings().bottomLeftRiver)
bottomRightRiverImage = updateRiver(bottomRightRiverImage,displayBottomRight, strings.bottomRightRiver)
bottomRiverImage = updateRiver(bottomRiverImage, displayBottom, strings.bottomRiver)
bottomLeftRiverImage = updateRiver(bottomLeftRiverImage, displayBottomLeft, strings.bottomLeftRiver)
}
private fun updateRiver(currentImage: Image?, shouldDisplay: Boolean, imageName: String): Image? {
@ -244,8 +243,8 @@ class TileLayerTerrain(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup,
}
private fun getNaturalWonderBackupImage(baseHexagon: List<String>): List<String> =
if (strings().tileSetConfig.useSummaryImages) baseHexagon + strings().naturalWonder
else baseHexagon + strings().orFallback{ getTile(tileGroup.tile.naturalWonder!!) }
if (strings.tileSetConfig.useSummaryImages) baseHexagon + strings.naturalWonder
else baseHexagon + strings.orFallback{ getTile(tileGroup.tile.naturalWonder!!) }
}

View File

@ -151,7 +151,7 @@ class TileLayerUnitFlag(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup
fillSlots(viewingCiv)
if (viewingCiv != null) {
val unitsInTile = tile().getUnits()
val unitsInTile = tile.getUnits()
val shouldBeHighlighted = unitsInTile.any()
&& unitsInTile.first().civ.isAtWarWith(viewingCiv)
&& isViewable(viewingCiv)

View File

@ -41,7 +41,7 @@ class TileLayerUnitSprite(tileGroup: TileGroup, size: Float) : TileLayer(tileGro
var nationName = ""
if (unit != null && isShown && UncivGame.Current.settings.showPixelUnits) {
location = strings().getUnitImageLocation(unit)
location = strings.getUnitImageLocation(unit)
nationName = "${unit.civ.civName}-"
}