Rework of City Screen: new current buildings list + misc changes (#8167)

Co-authored-by: tunerzinc@gmail.com <vfylfhby>
This commit is contained in:
vegeta1k95
2022-12-18 18:28:48 +01:00
committed by GitHub
parent 9aa3cb13c5
commit 903d3ab278
6 changed files with 160 additions and 418 deletions

View File

@ -61,7 +61,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
private var preferredBuyStat = Stat.Gold // Used for keyboard buy
private val upperTable = Table(BaseScreen.skin)
private val showCityInfoTableButton = "Show stats drilldown".toTextButton()
private val constructionsQueueScrollPane: ScrollPane
private val constructionsQueueTable = Table()
private val buyButtonsTable = Table()
@ -84,11 +83,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
}
init {
showCityInfoTableButton.onClick {
cityScreen.showConstructionsTable = false
cityScreen.update()
}
constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE))
constructionsQueueScrollPane.setOverscroll(false, false)
constructionsQueueTable.background = BaseScreen.skinStrings.getUiBackground(
@ -97,7 +91,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
)
upperTable.defaults().left().top()
upperTable.add(showCityInfoTableButton).padLeft(pad).padBottom(pad).row()
upperTable.add(constructionsQueueScrollPane)
.maxHeight(stageHeight / 3 - 10f)
.padBottom(pad).row()

View File

@ -1,357 +0,0 @@
package com.unciv.ui.cityscreen
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.Cell
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.CityStats
import com.unciv.logic.city.StatTreeNode
import com.unciv.models.UncivSound
import com.unciv.models.ruleset.Building
import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popup.ConfirmPopup
import com.unciv.ui.popup.closeAllPopups
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.ExpanderTab
import com.unciv.ui.utils.extensions.addBorder
import com.unciv.ui.utils.extensions.addSeparator
import com.unciv.ui.utils.extensions.darken
import com.unciv.ui.utils.extensions.disable
import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.utils.extensions.surroundWithCircle
import com.unciv.ui.utils.extensions.toLabel
import com.unciv.ui.utils.extensions.toTextButton
import java.text.DecimalFormat
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin) {
private val pad = 10f
private val showConstructionsTableButton = "Show construction queue".toTextButton()
private val scrollPane: ScrollPane
private val innerTable = Table(skin)
private val allExpanders = mutableListOf<ExpanderTab>()
private val hideShowAllCell: Cell<Group>
private var hideShowAllShouldClose = false
init {
align(Align.topLeft)
showConstructionsTableButton.onClick {
cityScreen.showConstructionsTable = true
cityScreen.update()
}
innerTable.width = cityScreen.stage.width / 4
innerTable.background = BaseScreen.skinStrings.getUiBackground(
"CityScreen/CityInfoTable",
tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f)
)
scrollPane = ScrollPane(innerTable.addBorder(2f, Color.WHITE))
scrollPane.setOverscroll(false, false)
val hideShowAllButton = Group()
add(showConstructionsTableButton).left().padLeft(pad).padBottom(pad)
hideShowAllCell = add(hideShowAllButton).size(30f) // size as the cell won't be resized when the actor is replaced
hideShowAllCell.left().padLeft(pad).padBottom(pad).expandX().row()
add(scrollPane).colspan(2).left().row()
}
internal fun update() {
val cityInfo = cityScreen.city
allExpanders.clear()
innerTable.clear()
innerTable.apply {
addBuildingsInfo(cityInfo)
addStatInfo()
addGreatPersonPointInfo(cityInfo)
}
updateHideShowAllButton()
getCell(scrollPane).maxHeight(stage.height - showConstructionsTableButton.height - pad - 10f)
onContentResize()
}
private fun updateHideShowAllButton() {
val anyExpanderOpen = allExpanders.map { it.isOpen }.maxOrNull() ?: false
if (anyExpanderOpen == hideShowAllShouldClose) return
hideShowAllShouldClose = anyExpanderOpen
val hideShowAllButton = getToggleButton(hideShowAllShouldClose)
hideShowAllButton.touchable = Touchable.enabled
hideShowAllButton.onClick {
for (expander in allExpanders) {
if (expander.isOpen == hideShowAllShouldClose) expander.toggle()
}
updateHideShowAllButton()
}
hideShowAllCell.setActor(hideShowAllButton)
}
private fun onContentResize() {
pack()
setPosition(CityScreen.posFromEdge, stage.height - CityScreen.posFromEdge, Align.topLeft)
}
private fun Table.addCategory(category: String, showHideTable: Table) {
val categoryWidth = cityScreen.stage.width / 4
val expander = ExpanderTab(category, persistenceID = "CityInfo.$category"
, onChange = {
onContentResize()
updateHideShowAllButton()
}
) {
it.add(showHideTable).minWidth(categoryWidth)
}
addSeparator()
add(expander).minWidth(categoryWidth).expandX().fillX().row()
allExpanders += expander
}
private fun addBuildingInfo(building: Building, destinationTable: Table) {
val icon = ImageGetter.getPortraitImage(building.name, 30f)
val isFree = building.name in cityScreen.city.civInfo.civConstructions.getFreeBuildings(cityScreen.city.id)
val displayName = if (isFree) "{${building.name}} ({Free})" else building.name
val buildingNameAndIconTable = ExpanderTab(
displayName, Constants.defaultFontSize, icon,
startsOutOpened = false, defaultPad = 5f,
onChange = { onContentResize() }
) {
val detailsString = building.getDescription(cityScreen.city, false)
it.add(detailsString.toLabel().apply { wrap = true })
.width(cityScreen.stage.width / 4 - 2 * pad).row() // when you set wrap, then you need to manually set the size of the label
if (building.isSellable() && !isFree) {
val sellAmount = cityScreen.city.getGoldForSellingBuilding(building.name)
val sellText = "Sell for [$sellAmount] gold"
val sellBuildingButton = sellText.toTextButton()
it.add(sellBuildingButton).pad(5f).row()
sellBuildingButton.onClick(UncivSound.Coin) {
sellBuildingButton.disable()
cityScreen.closeAllPopups()
ConfirmPopup(
cityScreen,
"Are you sure you want to sell this [${building.name}]?",
sellText,
restoreDefault = {
cityScreen.update()
}
) {
cityScreen.city.sellBuilding(building.name)
cityScreen.update()
}.open()
}
if (cityScreen.city.hasSoldBuildingThisTurn && !cityScreen.city.civInfo.gameInfo.gameParameters.godMode
|| cityScreen.city.isPuppet
|| !UncivGame.Current.worldScreen!!.isPlayersTurn || !cityScreen.canChangeState)
sellBuildingButton.disable()
}
it.addSeparator()
}
destinationTable.add(buildingNameAndIconTable).pad(5f).fillX().row()
}
private fun Table.addBuildingsInfo(cityInfo: CityInfo) {
val wonders = mutableListOf<Building>()
val specialistBuildings = mutableListOf<Building>()
val otherBuildings = mutableListOf<Building>()
for (building in cityInfo.cityConstructions.getBuiltBuildings()) {
when {
building.isAnyWonder() -> wonders.add(building)
!building.newSpecialists().isEmpty() -> specialistBuildings.add(building)
else -> otherBuildings.add(building)
}
}
if (wonders.isNotEmpty()) {
val wondersTable = Table()
addCategory("Wonders", wondersTable)
for (building in wonders) addBuildingInfo(building, wondersTable)
}
if (specialistBuildings.isNotEmpty()) {
val specialistBuildingsTable = Table()
addCategory("Specialist Buildings", specialistBuildingsTable)
for (building in specialistBuildings) {
addBuildingInfo(building, specialistBuildingsTable)
val specialistIcons = Table()
specialistIcons.row().size(20f).pad(5f)
for ((specialistName, amount) in building.newSpecialists()) {
val specialist = cityInfo.getRuleset().specialists[specialistName]
?: continue // probably a mod that doesn't have the specialist defined yet
for (i in 0 until amount)
specialistIcons.add(ImageGetter.getSpecialistIcon(specialist.colorObject)).size(20f)
}
specialistBuildingsTable.add(specialistIcons).pad(0f).row()
}
}
if (otherBuildings.isNotEmpty()) {
val regularBuildingsTable = Table()
addCategory("Buildings", regularBuildingsTable)
for (building in otherBuildings) addBuildingInfo(building, regularBuildingsTable)
}
}
private fun addStatsToHashmap(
statTreeNode: StatTreeNode,
hashMap: HashMap<String, Float>,
stat: Stat,
showDetails: Boolean,
indentation: Int = 0
) {
for ((name, child) in statTreeNode.children) {
val statAmount = child.totalStats[stat]
if (statAmount == 0f) continue
hashMap["- ".repeat(indentation) + name.tr()] = statAmount
if (showDetails) addStatsToHashmap(child, hashMap, stat, showDetails, indentation + 1)
}
}
private fun Table.addStatInfo() {
val cityStats = cityScreen.city.cityStats
val showFaith = cityScreen.city.civInfo.gameInfo.isReligionEnabled()
for (stat in Stat.values()) {
if (stat == Stat.Faith && !showFaith) continue
val statValuesTable = Table()
statValuesTable.touchable = Touchable.enabled
addCategory(stat.name, statValuesTable)
updateStatValuesTable(stat, cityStats, statValuesTable)
}
}
private fun updateStatValuesTable(
stat: Stat,
cityStats: CityStats,
statValuesTable: Table,
showDetails:Boolean = false
) {
statValuesTable.clear()
statValuesTable.defaults().pad(2f)
statValuesTable.onClick {
updateStatValuesTable(
stat,
cityStats,
statValuesTable,
!showDetails
)
onContentResize()
}
val relevantBaseStats = LinkedHashMap<String, Float>()
if (stat != Stat.Happiness)
addStatsToHashmap(cityStats.baseStatTree, relevantBaseStats, stat, showDetails)
else relevantBaseStats.putAll(cityStats.happinessList)
for (key in relevantBaseStats.keys.toList())
if (relevantBaseStats[key] == 0f) relevantBaseStats.remove(key)
if (relevantBaseStats.isEmpty()) return
statValuesTable.add("Base values".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).pad(4f)
.colspan(2).row()
var sumOfAllBaseValues = 0f
for (entry in relevantBaseStats) {
val specificStatValue = entry.value
if (!entry.key.startsWith('-'))
sumOfAllBaseValues += specificStatValue
statValuesTable.add(entry.key.toLabel()).left()
statValuesTable.add(specificStatValue.toOneDecimalLabel()).row()
}
statValuesTable.addSeparator()
statValuesTable.add("Total".toLabel())
statValuesTable.add(sumOfAllBaseValues.toOneDecimalLabel()).row()
val relevantBonuses = LinkedHashMap<String, Float>()
addStatsToHashmap(cityStats.statPercentBonusTree, relevantBonuses, stat, showDetails)
val totalBonusStats = cityStats.statPercentBonusTree.totalStats
if (totalBonusStats[stat] != 0f) {
statValuesTable.add("Bonuses".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).colspan(2)
.padTop(20f).row()
for ((source, bonusAmount) in relevantBonuses) {
statValuesTable.add(source.toLabel()).left()
statValuesTable.add(bonusAmount.toPercentLabel()).row() // negative bonus
}
statValuesTable.addSeparator()
statValuesTable.add("Total".toLabel())
statValuesTable.add(totalBonusStats[stat].toPercentLabel()).row() // negative bonus
statValuesTable.add("Final".toLabel(fontSize = FONT_SIZE_STAT_INFO_HEADER)).colspan(2)
.padTop(20f).row()
var finalTotal = 0f
for (entry in cityStats.finalStatList) {
val specificStatValue = entry.value[stat]
finalTotal += specificStatValue
if (specificStatValue == 0f) continue
statValuesTable.add(entry.key.toLabel())
statValuesTable.add(specificStatValue.toOneDecimalLabel()).row()
}
statValuesTable.addSeparator()
statValuesTable.add("Total".toLabel())
statValuesTable.add(finalTotal.toOneDecimalLabel()).row()
}
statValuesTable.pack()
if (stat != Stat.Happiness) {
val toggleButton = getToggleButton(showDetails)
statValuesTable.addActor(toggleButton)
toggleButton.setPosition(0f, statValuesTable.height, Align.topLeft)
}
statValuesTable.padBottom(4f)
}
private fun getToggleButton(showDetails: Boolean): IconCircleGroup {
val label = (if (showDetails) "-" else "+").toLabel()
label.setAlignment(Align.center)
return label
.surroundWithCircle(25f, color = BaseScreen.skinStrings.skinConfig.baseColor)
.surroundWithCircle(27f, false)
}
private fun Table.addGreatPersonPointInfo(cityInfo: CityInfo) {
val greatPersonPoints = cityInfo.getGreatPersonPointsForNextTurn()
val allGreatPersonNames = greatPersonPoints.asSequence().flatMap { it.value.keys }.distinct()
for (greatPersonName in allGreatPersonNames) {
val expanderName = "[$greatPersonName] points"
val greatPersonTable = Table()
addCategory(expanderName, greatPersonTable)
for ((source, gppCounter) in greatPersonPoints) {
val gppPointsFromSource = gppCounter[greatPersonName]!!
if (gppPointsFromSource == 0) continue
greatPersonTable.add(source.toLabel()).padRight(10f)
greatPersonTable.add(gppPointsFromSource.toLabel()).row()
}
}
}
companion object {
private const val FONT_SIZE_STAT_INFO_HEADER = 22
private fun Float.toPercentLabel() =
"${if (this>0f) "+" else ""}${DecimalFormat("0.#").format(this)}%".toLabel()
private fun Float.toOneDecimalLabel() =
DecimalFormat("0.#").format(this).toLabel()
}
}

View File

@ -50,9 +50,6 @@ class CityScreen(
/** Toggles or adds/removes all state changing buttons */
val canChangeState = UncivGame.Current.worldScreen!!.canChangeState
/** Toggle between Constructions and cityInfo (buildings, specialists etc. */
var showConstructionsTable = true
// Clockwise from the top-left
/** Displays current production, production queue and available productions list
@ -61,9 +58,6 @@ class CityScreen(
*/
private var constructionsTable = CityConstructionsTable(this)
/** Displays stats, buildings, specialists and stats drilldown - sits on TOP LEFT, can be toggled to */
private var cityInfoTable = CityInfoTable(this)
/** Displays raze city button - sits on TOP CENTER */
private var razeCityButtonHolder = Table()
@ -129,7 +123,6 @@ class CityScreen(
//stage.setDebugTableUnderMouse(true)
stage.addActor(cityStatsTable)
constructionsTable.addActorsToStage()
stage.addActor(cityInfoTable)
stage.addActor(selectedConstructionTable)
stage.addActor(tileTable)
stage.addActor(cityPickerTable) // add late so it's top in Z-order and doesn't get covered in cramped portrait
@ -144,17 +137,8 @@ class CityScreen(
// Recalculate Stats
city.cityStats.update()
// Left side, top and bottom: Construction queue / details
if (showConstructionsTable) {
constructionsTable.isVisible = true
cityInfoTable.isVisible = false
constructionsTable.update(selectedConstruction)
} else {
constructionsTable.isVisible = false
cityInfoTable.isVisible = true
cityInfoTable.update()
// CityInfoTable sets its relative position itself
}
constructionsTable.isVisible = true
constructionsTable.update(selectedConstruction)
// Bottom right: Tile or selected construction info
tileTable.update(selectedTile)
@ -171,8 +155,7 @@ class CityScreen(
}
val leftMargin = when {
!isPortrait() -> 0f
showConstructionsTable -> constructionsTable.getLowerWidth()
else -> cityInfoTable.packIfNeeded().width
else -> constructionsTable.getLowerWidth()
}
// Bottom center: Name, paging, exit city button
@ -434,7 +417,6 @@ class CityScreen(
val indexOfCity = civInfo.cities.indexOf(city)
val indexOfNextCity = (indexOfCity + delta + numCities) % numCities
val newCityScreen = CityScreen(civInfo.cities[indexOfNextCity])
newCityScreen.showConstructionsTable = showConstructionsTable // stay on stats drilldown between cities
newCityScreen.update()
game.replaceCurrentScreen(newCityScreen)
}

View File

@ -6,15 +6,18 @@ import com.badlogic.gdx.scenes.scene2d.ui.Cell
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.Constants
import com.unciv.UncivGame
import com.unciv.logic.city.CityFlags
import com.unciv.logic.city.CityFocus
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.ExpanderTab
import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.extensions.addSeparator
import com.unciv.ui.utils.extensions.colorFromRGB
@ -100,6 +103,8 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
if (cityInfo.religion.getNumberOfFollowers().isNotEmpty() && cityInfo.civInfo.gameInfo.isReligionEnabled())
addReligionInfo()
addBuildingsInfo()
upperTable.pack()
lowerTable.pack()
lowerPane.layout()
@ -110,6 +115,15 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
pack() // update self last
}
private fun onContentResize() {
pack()
setPosition(
stage.width - CityScreen.posFromEdge,
stage.height - CityScreen.posFromEdge,
Align.topRight
)
}
private fun addText() {
val unassignedPopString = "{Unassigned population}: ".tr() +
cityInfo.population.getFreePopulation().toString() + "/" + cityInfo.population.population
@ -171,36 +185,111 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
}
private fun addCitizenManagement() {
val expanderTab = CitizenManagementTable(cityScreen).asExpander {
pack()
setPosition(
stage.width - CityScreen.posFromEdge,
stage.height - CityScreen.posFromEdge,
Align.topRight
)
}
val expanderTab = CitizenManagementTable(cityScreen).asExpander { onContentResize() }
lowerTable.add(expanderTab).growX().row()
}
private fun addSpecialistInfo() {
val expanderTab = SpecialistAllocationTable(cityScreen).asExpander {
pack()
setPosition(
stage.width - CityScreen.posFromEdge,
stage.height - CityScreen.posFromEdge,
Align.topRight
)
}
val expanderTab = SpecialistAllocationTable(cityScreen).asExpander { onContentResize() }
lowerTable.add(expanderTab).growX().row()
}
private fun addReligionInfo() {
val expanderTab = CityReligionInfoTable(cityInfo.religion).asExpander {
pack()
// We have to re-anchor as our position in the city screen, otherwise it expands upwards.
// ToDo: This probably should be refactored so its placed somewhere else in due time
setPosition(stage.width - CityScreen.posFromEdge, stage.height - CityScreen.posFromEdge, Align.topRight)
val expanderTab = CityReligionInfoTable(cityInfo.religion).asExpander { onContentResize() }
lowerTable.add(expanderTab).growX().row()
}
private fun addBuildingsInfo() {
val wonders = mutableListOf<Building>()
val specialistBuildings = mutableListOf<Building>()
val otherBuildings = mutableListOf<Building>()
for (building in cityInfo.cityConstructions.getBuiltBuildings()) {
when {
building.isAnyWonder() -> wonders.add(building)
!building.newSpecialists().isEmpty() -> specialistBuildings.add(building)
else -> otherBuildings.add(building)
}
}
if (specialistBuildings.isNotEmpty()) {
val specialistBuildingsTable = Table()
addCategory("Specialist Buildings", specialistBuildingsTable)
for (building in specialistBuildings) addBuildingButton(building, specialistBuildingsTable)
}
if (wonders.isNotEmpty()) {
val wondersTable = Table()
addCategory("Wonders", wondersTable)
for (building in wonders) addBuildingButton(building, wondersTable)
}
if (otherBuildings.isNotEmpty()) {
val regularBuildingsTable = Table()
addCategory("Buildings", regularBuildingsTable)
for (building in otherBuildings) addBuildingButton(building, regularBuildingsTable)
}
}
private fun addBuildingButton(building: Building, destinationTable: Table) {
val button = Table()
val info = Table()
val statsAndSpecialists = Table()
val icon = ImageGetter.getPortraitImage(building.name, 50f)
val isFree = building.name in cityScreen.city.civInfo.civConstructions.getFreeBuildings(cityScreen.city.id)
val displayName = if (isFree) "{${building.name}} ({Free})" else building.name
info.add(displayName.toLabel(fontSize = Constants.defaultFontSize)).padBottom(5f).right().row()
val stats = building.getStats(cityInfo).joinToString(separator = " ") {
"" + it.value.toInt() + it.key.character
}
statsAndSpecialists.add(stats.toLabel(fontSize = Constants.defaultFontSize)).right()
val assignedSpec = cityInfo.population.getNewSpecialists().clone()
val specialistIcons = Table()
for ((specialistName, amount) in building.newSpecialists()) {
val specialist = cityInfo.getRuleset().specialists[specialistName]
?: continue // probably a mod that doesn't have the specialist defined yet
for (i in 0 until amount) {
if (assignedSpec[specialistName]!! > 0) {
specialistIcons.add(ImageGetter.getSpecialistIcon(specialist.colorObject))
.size(20f)
assignedSpec.add(specialistName, -1)
} else {
specialistIcons.add(ImageGetter.getSpecialistIcon(Color.GRAY)).size(20f)
}
}
}
statsAndSpecialists.add(specialistIcons).right()
info.add(statsAndSpecialists).right()
button.add(info).right().top().padRight(10f).padTop(5f)
button.add(icon).right()
button.onClick {
cityScreen.selectConstruction(building)
cityScreen.update()
}
destinationTable.add(button).pad(1f).expandX().right().row()
}
private fun addCategory(category: String, showHideTable: Table) {
val expanderTab = ExpanderTab(
title = category,
fontSize = Constants.defaultFontSize,
persistenceID = "CityInfo.$category",
onChange = { onContentResize() }
) {
it.add(showHideTable).fillX().right()
}
lowerTable.add(expanderTab).growX().row()
}
}

View File

@ -46,11 +46,11 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin
when {
tileInfo.getOwner() != city.civInfo -> { // outside of civ boundary
dim(0.3f)
yieldGroup.isVisible = false
yieldGroup.isVisible = true
}
tileInfo !in city.tilesInRange -> { // within city but not close enough to be workable
yieldGroup.isVisible = false
yieldGroup.isVisible = true
dim(0.5f)
}
@ -74,7 +74,6 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin
unitLayerGroup.isVisible = false
terrainFeatureLayerGroup.color.a = 0.5f
icons.improvementIcon?.setColor(1f, 1f, 1f, 0.5f)
resourceImage?.setColor(1f, 1f, 1f, 0.5f)
updatePopulationIcon()
updateYieldGroup()
}
@ -94,7 +93,7 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin
private fun updatePopulationIcon() {
val populationIcon = icons.populationIcon
if (populationIcon != null) {
populationIcon.setSize(30f, 30f)
populationIcon.setSize(25f, 25f)
populationIcon.setPosition(width / 2 - populationIcon.width / 2,
height * 0.85f - populationIcon.height / 2)

View File

@ -8,16 +8,21 @@ import com.unciv.UncivGame
import com.unciv.logic.city.IConstruction
import com.unciv.logic.city.PerpetualConstruction
import com.unciv.logic.city.PerpetualStatConversion
import com.unciv.models.UncivSound
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.IRulesetObject
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popup.ConfirmPopup
import com.unciv.ui.popup.closeAllPopups
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.extensions.darken
import com.unciv.ui.utils.extensions.disable
import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.utils.extensions.surroundWithCircle
import com.unciv.ui.utils.extensions.toTextButton
class ConstructionInfoTable(val cityScreen: CityScreen): Table() {
private val selectedConstructionTable = Table()
@ -56,8 +61,14 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() {
selectedConstructionTable.run {
pad(10f)
add(ImageGetter.getPortraitImage(construction.name, 50f))
.pad(5f)
add(ImageGetter.getPortraitImage(construction.name, 50f).apply {
val link = (construction as? IRulesetObject)?.makeLink() ?: return
if (link.isEmpty()) return
touchable = Touchable.enabled
this.onClick {
UncivGame.Current.pushScreen(CivilopediaScreen(city.getRuleset(), link = link))
}
}).pad(5f)
var buildingText = construction.name.tr()
val specialConstruction = PerpetualConstruction.perpetualConstructionsMap[construction.name]
@ -78,11 +89,36 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() {
descriptionLabel.wrap = true
add(descriptionLabel).colspan(2).width(stage.width / 4)
val link = (construction as? IRulesetObject)?.makeLink() ?: return
if (link.isEmpty()) return
touchable = Touchable.enabled
onClick {
UncivGame.Current.pushScreen(CivilopediaScreen(city.getRuleset(), link = link))
// Show sell button if construction is a currently sellable building
if (construction is Building && cityConstructions.isBuilt(construction.name)
&& construction.isSellable()) {
val sellAmount = cityScreen.city.getGoldForSellingBuilding(construction.name)
val sellText = "Sell [$sellAmount] " + Fonts.gold
val sellBuildingButton = sellText.toTextButton()
row()
add(sellBuildingButton).padTop(5f).colspan(2).center()
sellBuildingButton.onClick(UncivSound.Coin) {
sellBuildingButton.disable()
cityScreen.closeAllPopups()
ConfirmPopup(
cityScreen,
"Are you sure you want to sell this [${construction.name}]?",
sellText,
restoreDefault = {
cityScreen.update()
}
) {
cityScreen.city.sellBuilding(construction.name)
cityScreen.clearSelection()
cityScreen.update()
}.open()
}
if (cityScreen.city.hasSoldBuildingThisTurn && !cityScreen.city.civInfo.gameInfo.gameParameters.godMode
|| cityScreen.city.isPuppet
|| !UncivGame.Current.worldScreen!!.isPlayersTurn || !cityScreen.canChangeState)
sellBuildingButton.disable()
}
}
}