diff --git a/core/src/com/unciv/ui/tilegroups/CityButton.kt b/core/src/com/unciv/ui/tilegroups/CityButton.kt new file mode 100644 index 0000000000..1917b18711 --- /dev/null +++ b/core/src/com/unciv/ui/tilegroups/CityButton.kt @@ -0,0 +1,108 @@ +package com.unciv.ui.tilegroups + +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.scenes.scene2d.Group +import com.badlogic.gdx.scenes.scene2d.Touchable +import com.badlogic.gdx.scenes.scene2d.ui.Label +import com.badlogic.gdx.scenes.scene2d.ui.Skin +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.utils.Align +import com.unciv.UnCivGame +import com.unciv.logic.city.CityConstructions +import com.unciv.logic.city.CityInfo +import com.unciv.logic.city.SpecialConstruction +import com.unciv.logic.map.RoadStatus +import com.unciv.ui.cityscreen.CityScreen +import com.unciv.ui.utils.* + +class CityButton(val city: CityInfo, skin: Skin): Table(skin){ + init{ + background = ImageGetter.getDrawable("OtherIcons/civTableBackground.png") + .tint(city.civInfo.getNation().getColor()) + isTransform = true // If this is not set then the city button won't scale! + touchable= Touchable.enabled // So you can click anywhere on the button to go to the city + } + + fun update(isCityViewable:Boolean) { + val cityButtonText = city.population.population.toString() + " | " + city.name + val label = Label(cityButtonText, CameraStageBaseScreen.skin) + label.setFontColor(city.civInfo.getNation().getSecondaryColor()) + + clear() + if (city.civInfo.isPlayerCivilization()) { + onClick { + UnCivGame.Current.screen = CityScreen(city) + } + } + + if (isCityViewable && city.health < city.getMaxHealth().toFloat()) { + val healthBar = ImageGetter.getHealthBar(city.health.toFloat(), city.getMaxHealth().toFloat(), 100f) + add(healthBar).colspan(3).row() + } + + if (city.isBeingRazed) { + val fireImage = ImageGetter.getImage("OtherIcons/Fire.png") + add(fireImage).size(20f).pad(2f).padLeft(5f) + } + if (city.isCapital()) { + val starImage = ImageGetter.getImage("OtherIcons/Star.png").apply { color = Color.LIGHT_GRAY } + add(starImage).size(20f).pad(2f).padLeft(5f) + } else if (city.civInfo.isPlayerCivilization() && city.cityStats.isConnectedToCapital(RoadStatus.Road)) { + val connectionImage = ImageGetter.getStatIcon("CityConnection") + add(connectionImage).size(20f).pad(2f).padLeft(5f) + } else { + add() + } // this is so the health bar is always 2 columns wide + add(label).pad(10f) + if (city.civInfo.isPlayerCivilization()) { + add(getConstructionGroup(city.cityConstructions)).padRight(5f) + } + pack() + setOrigin(Align.center) + toFront() + touchable = Touchable.enabled + + } + + + private fun getConstructionGroup(cityConstructions: CityConstructions): Group { + val group= Group() + val groupHeight = 25f + group.setSize(40f,groupHeight) + + val circle = ImageGetter.getImage("OtherIcons/Circle") + circle.setSize(25f,25f) + val image = ImageGetter.getConstructionImage(cityConstructions.currentConstruction) + image.setSize(18f,18f) + image.centerY(group) + image.x = group.width-image.width + + // center the circle on thee production image + circle.x = image.x + (image.width-circle.width)/2 + circle.y = image.y + (image.height-circle.height)/2 + + group.addActor(circle) + group.addActor(image) + + val secondaryColor = cityConstructions.cityInfo.civInfo.getNation().getSecondaryColor() + if(cityConstructions.getCurrentConstruction() !is SpecialConstruction) { + val turnsToConstruction = cityConstructions.turnsToConstruction(cityConstructions.currentConstruction) + val label = Label(turnsToConstruction.toString(), CameraStageBaseScreen.skin) + label.setFontColor(secondaryColor) + label.setFontSize(10) + label.pack() + group.addActor(label) + + val adoptedPolicies = cityConstructions.cityInfo.civInfo.policies.adoptedPolicies + val constructionPercentage = cityConstructions.getWorkDone(cityConstructions.currentConstruction) / + cityConstructions.getCurrentConstruction().getProductionCost(adoptedPolicies).toFloat() + val productionBar = ImageGetter.getProgressBarVertical(2f, groupHeight, constructionPercentage + , Color.BROWN.cpy().lerp(Color.WHITE, 0.5f), Color.BLACK) + productionBar.x = 10f + label.x = productionBar.x - label.width - 3 + group.addActor(productionBar) + } + return group + } + +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/tilegroups/TileGroup.kt b/core/src/com/unciv/ui/tilegroups/TileGroup.kt index 83af70b3b9..d383ad2174 100644 --- a/core/src/com/unciv/ui/tilegroups/TileGroup.kt +++ b/core/src/com/unciv/ui/tilegroups/TileGroup.kt @@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.ui.Image -import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.UnCivGame import com.unciv.logic.HexMath @@ -356,7 +355,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() { if (unit.health < 100) { // add health bar - group.addActor(getHealthBar(unit.health.toFloat(),100f,size)) + group.addActor(ImageGetter.getHealthBar(unit.health.toFloat(),100f,size)) } return group @@ -375,20 +374,5 @@ open class TileGroup(var tileInfo: TileInfo) : Group() { } - protected fun getHealthBar(currentHealth: Float, maxHealth: Float, healthBarSize: Float): Table { - val healthPercent = currentHealth / maxHealth - val healthBar = Table() - val healthPartOfBar = ImageGetter.getWhiteDot() - healthPartOfBar.color = when { - healthPercent > 2 / 3f -> Color.GREEN - healthPercent > 1 / 3f -> Color.ORANGE - else -> Color.RED - } - val emptyPartOfBar = ImageGetter.getWhiteDot().apply { color = Color.BLACK } - healthBar.add(healthPartOfBar).width(healthBarSize * healthPercent).height(5f) - healthBar.add(emptyPartOfBar).width(healthBarSize * (1 - healthPercent)).height(5f) - healthBar.pack() - return healthBar - } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/tilegroups/WorldTileGroup.kt b/core/src/com/unciv/ui/tilegroups/WorldTileGroup.kt index 42f3319316..9b7878d992 100644 --- a/core/src/com/unciv/ui/tilegroups/WorldTileGroup.kt +++ b/core/src/com/unciv/ui/tilegroups/WorldTileGroup.kt @@ -1,24 +1,16 @@ package com.unciv.ui.tilegroups -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.scenes.scene2d.Group -import com.badlogic.gdx.scenes.scene2d.Touchable -import com.badlogic.gdx.scenes.scene2d.ui.Label -import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.utils.Align import com.unciv.UnCivGame -import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityInfo -import com.unciv.logic.city.SpecialConstruction import com.unciv.logic.map.MapUnit -import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo -import com.unciv.ui.cityscreen.CityScreen -import com.unciv.ui.utils.* +import com.unciv.ui.utils.CameraStageBaseScreen +import com.unciv.ui.utils.ImageGetter +import com.unciv.ui.utils.center class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) { - var cityButton: Table? = null + var cityButton: CityButton? = null fun addWhiteHaloAroundUnit(unit: MapUnit) { val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png") @@ -70,6 +62,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) { fogImage.toFront() } + private fun updateCityButton(city: CityInfo?, viewable: Boolean) { if(city==null && cityButton!=null)// there used to be a city here but it was razed { @@ -78,97 +71,15 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) { } if (city != null && tileInfo.isCityCenter()) { if (cityButton == null) { - cityButton = Table() - cityButton!!.background = ImageGetter.getDrawable("OtherIcons/civTableBackground.png") - .tint(city.civInfo.getNation().getColor()) - cityButton!!.isTransform = true // If this is not set then the city button won't scale! - + cityButton = CityButton(city,CameraStageBaseScreen.skin) addActor(cityButton) toFront() // so this tile is rendered over neighboring tiles } - val cityButtonText = city.population.population.toString() +" | " +city.name - val label = Label(cityButtonText, CameraStageBaseScreen.skin) - label.setFontColor(city.civInfo.getNation().getSecondaryColor()) - if (city.civInfo.isPlayerCivilization()) - label.onClick { - UnCivGame.Current.screen = CityScreen(city) - } - - cityButton!!.run { - clear() - if(viewable && city.health 2 / 3f -> Color.GREEN + healthPercent > 1 / 3f -> Color.ORANGE + else -> Color.RED + } + val emptyPartOfBar = ImageGetter.getWhiteDot().apply { color = Color.BLACK } + healthBar.add(healthPartOfBar).width(healthBarSize * healthPercent).height(5f) + healthBar.add(emptyPartOfBar).width(healthBarSize * (1 - healthPercent)).height(5f) + healthBar.pack() + return healthBar + } + } \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt b/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt index 9649b5edbb..6d7190894d 100644 --- a/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/TileMapHolder.kt @@ -12,6 +12,7 @@ import com.unciv.UnCivGame import com.unciv.logic.HexMath import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.map.MapUnit import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap import com.unciv.ui.tilegroups.TileGroup @@ -95,42 +96,46 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit if (selectedUnit != null && selectedUnit.getTile() != tileInfo && selectedUnit.canMoveTo(tileInfo) && selectedUnit.movementAlgs().canReach(tileInfo)) { - val size = 60f - val moveHereButton = Group().apply { width = size;height = size; } - moveHereButton.addActor(ImageGetter.getImage("OtherIcons/Circle").apply { width = size; height = size }) - moveHereButton.addActor(ImageGetter.getStatIcon("Movement").apply { width = size / 2; height = size / 2; center(moveHereButton) }) - - val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size - val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE } - moveHereButton.addActor(numberCircle) - moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin).apply { center(numberCircle); setFontColor(Color.WHITE) }) - - val unitIcon = TileGroup(TileInfo()).getUnitImage(selectedUnit, size / 2) - unitIcon.y = size - unitIcon.height - moveHereButton.addActor(unitIcon) - - if (selectedUnit.currentMovement > 0) - moveHereButton.onClick { - if (selectedUnit.movementAlgs().canReach(tileInfo)) { - selectedUnit.movementAlgs().headTowards(tileInfo) - if (selectedUnit.currentTile != tileInfo) - selectedUnit.action = "moveTo " + tileInfo.position.x.toInt() + "," + tileInfo.position.y.toInt() - } - - worldScreen.update() - moveToOverlay!!.remove() - moveToOverlay = null - } - else moveHereButton.color.a = 0.5f - addOverlayOnTileGroup(tileGroup, moveHereButton).apply { width = size; height = size } - moveHereButton.y += tileGroup.height - moveToOverlay = moveHereButton + addMoveHereButtonToTile(selectedUnit, tileInfo, tileGroup) } worldScreen.bottomBar.unitTable.tileSelected(tileInfo) worldScreen.update() } + private fun addMoveHereButtonToTile(selectedUnit: MapUnit, tileInfo: TileInfo, tileGroup: WorldTileGroup) { + val size = 60f + val moveHereButton = Group().apply { width = size;height = size; } + moveHereButton.addActor(ImageGetter.getImage("OtherIcons/Circle").apply { width = size; height = size }) + moveHereButton.addActor(ImageGetter.getStatIcon("Movement").apply { width = size / 2; height = size / 2; center(moveHereButton) }) + + val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size + val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE } + moveHereButton.addActor(numberCircle) + moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin).apply { center(numberCircle); setFontColor(Color.WHITE) }) + + val unitIcon = TileGroup(TileInfo()).getUnitImage(selectedUnit, size / 2) + unitIcon.y = size - unitIcon.height + moveHereButton.addActor(unitIcon) + + if (selectedUnit.currentMovement > 0) + moveHereButton.onClick { + if (selectedUnit.movementAlgs().canReach(tileInfo)) { + selectedUnit.movementAlgs().headTowards(tileInfo) + if (selectedUnit.currentTile != tileInfo) + selectedUnit.action = "moveTo " + tileInfo.position.x.toInt() + "," + tileInfo.position.y.toInt() + } + + worldScreen.update() + moveToOverlay!!.remove() + moveToOverlay = null + } + else moveHereButton.color.a = 0.5f + addOverlayOnTileGroup(tileGroup, moveHereButton).apply { width = size; height = size } + moveHereButton.y += tileGroup.height + moveToOverlay = moveHereButton + } + private fun addOverlayOnTileGroup(group:WorldTileGroup, actor: Actor) { actor.center(group) actor.x+=group.x @@ -142,13 +147,16 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: internal fun updateTiles(civInfo: CivilizationInfo) { val playerViewableTilePositions = civInfo.getViewableTiles().map { it.position }.toHashSet() - for (WG in tileGroups.values){ - WG.update(playerViewableTilePositions.contains(WG.tileInfo.position)) - val unitsInTile = WG.tileInfo.getUnits() - if((playerViewableTilePositions.contains(WG.tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug) + cityButtonOverlays.forEach{it.remove()} + cityButtonOverlays.clear() + + for (tileGroup in tileGroups.values){ + tileGroup.update(playerViewableTilePositions.contains(tileGroup.tileInfo.position)) + val unitsInTile = tileGroup.tileInfo.getUnits() + if((playerViewableTilePositions.contains(tileGroup.tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug) && unitsInTile.isNotEmpty() && !unitsInTile.first().civInfo.isPlayerCivilization()) - WG.showCircle(Color.RED) - } // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units + tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units + } if(worldScreen.bottomBar.unitTable.selectedUnit!=null){ val unit = worldScreen.bottomBar.unitTable.selectedUnit!!