Resolved #470 - can now click on a building in the city info table to display its effect

Organized city info table
This commit is contained in:
Yair Morgenstern 2019-03-07 23:05:48 +02:00
parent 6f46750c15
commit f15490d0ac
3 changed files with 92 additions and 67 deletions

View File

@ -74,6 +74,10 @@ open class Stats() {
Stat.Science to science) Stat.Science to science)
} }
fun get(stat:Stat):Float{
return this.toHashMap()[stat]!!
}
private fun setStats(hashMap:HashMap<Stat, Float>){ private fun setStats(hashMap:HashMap<Stat, Float>){
culture=hashMap[Stat.Culture]!! culture=hashMap[Stat.Culture]!!
gold=hashMap[Stat.Gold]!! gold=hashMap[Stat.Gold]!!

View File

@ -1,12 +1,15 @@
package com.unciv.ui.cityscreen package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.* import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.GreatPersonManager import com.unciv.logic.civilization.GreatPersonManager
import com.unciv.models.gamebasics.Building import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.tr
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
@ -15,15 +18,17 @@ import java.util.*
class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) { class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) {
val pad = 5f
init { init {
defaults().pad(10f) defaults().pad(pad)
width = cityScreen.stage.width/4
} }
internal fun update() { internal fun update() {
clear() clear()
val cityInfo = cityScreen.city val cityInfo = cityScreen.city
addBuildingInfo(cityInfo) addBuildingsInfo(cityInfo)
addStatInfo() addStatInfo()
@ -32,8 +37,36 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
pack() pack()
} }
private fun addTitle(str:String) {
val titleTable = Table().background(ImageGetter.getBackground(ImageGetter.getBlue()))
titleTable.add(str.toLabel().setFontSize(22))
add(titleTable).width(cityScreen.stage.width/4 - 2*pad).row()
}
private fun addBuildingInfo(cityInfo: CityInfo) { fun addBuildingInfo(building: Building){
val wonderNameAndIconTable = Table()
wonderNameAndIconTable.touchable = Touchable.enabled
wonderNameAndIconTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
wonderNameAndIconTable.add(building.name.toLabel()).pad(5f)
add(wonderNameAndIconTable).pad(5f).fillX().row()
val wonderDetailsTable = Table()
add(wonderDetailsTable).pad(5f).align(Align.left).row()
wonderNameAndIconTable.onClick {
if(wonderDetailsTable.hasChildren())
wonderDetailsTable.clear()
else{
val detailsString = building.getDescription(true,
cityScreen.city.civInfo.policies.adoptedPolicies)
wonderDetailsTable.add(detailsString.toLabel().apply { setWrap(true)})
.width(cityScreen.stage.width/4 - 2*pad ) // when you set wrap, then you need to manually set the size of the label
wonderDetailsTable.addSeparator()
}
}
}
private fun addBuildingsInfo(cityInfo: CityInfo) {
val wonders = mutableListOf<Building>() val wonders = mutableListOf<Building>()
val specialistBuildings = mutableListOf<Building>() val specialistBuildings = mutableListOf<Building>()
val otherBuildings = mutableListOf<Building>() val otherBuildings = mutableListOf<Building>()
@ -47,40 +80,32 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
if (!wonders.isEmpty()) { if (!wonders.isEmpty()) {
val wondersExpander = ExpanderTab("Wonders".tr(), skin) addTitle("Wonders")
for (building in wonders) { for (building in wonders) addBuildingInfo(building)
wondersExpander.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f))
wondersExpander.innerTable.add(building.name.toLabel()).pad(5f).align(Align.left).row()
}
add(wondersExpander).row()
} }
if (!specialistBuildings.isEmpty()) { if (!specialistBuildings.isEmpty()) {
val specialistBuildingsExpander = ExpanderTab("Specialist Buildings".tr(), skin) addTitle("Specialist Buildings")
for (building in specialistBuildings) { for (building in specialistBuildings) {
specialistBuildingsExpander.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f)) addBuildingInfo(building)
specialistBuildingsExpander.innerTable.add(building.name.toLabel()).pad(5f)
val specialistIcons = Table() val specialistIcons = Table()
specialistIcons.row().size(20f).pad(5f) specialistIcons.row().size(20f).pad(5f)
for (stat in building.specialistSlots!!.toHashMap()) for (stat in building.specialistSlots!!.toHashMap())
for (i in 0 until stat.value.toInt()) for (i in 0 until stat.value.toInt())
specialistIcons.add(getSpecialistIcon(stat.key)).size(20f) specialistIcons.add(getSpecialistIcon(stat.key)).size(20f)
specialistBuildingsExpander.innerTable.add(specialistIcons).row() add(specialistIcons).pad(0f).row()
} }
add(specialistBuildingsExpander).row()
// specialist allocation // specialist allocation
addSpecialistAllocation(skin, cityInfo) addSpecialistAllocation(skin, cityInfo)
} }
if (!otherBuildings.isEmpty()) { if (!otherBuildings.isEmpty()) {
val buildingsExpanderTab = ExpanderTab("Buildings".tr(), skin)
for (building in otherBuildings) { addTitle("Buildings")
buildingsExpanderTab.innerTable.add(ImageGetter.getConstructionImage(building.name).surroundWithCircle(30f)) for (building in wonders) addBuildingInfo(building)
buildingsExpanderTab.innerTable.add(building.name.toLabel()).pad(5f).row()
}
add(buildingsExpanderTab).row()
} }
} }
@ -90,7 +115,6 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
for(stats in unifiedStatList.values) stats.happiness=0f for(stats in unifiedStatList.values) stats.happiness=0f
// add happiness to stat list // add happiness to stat list
for(entry in cityStats.getCityHappiness().filter { it.value!=0f }){ for(entry in cityStats.getCityHappiness().filter { it.value!=0f }){
if(!unifiedStatList.containsKey(entry.key)) if(!unifiedStatList.containsKey(entry.key))
@ -99,41 +123,40 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
} }
for(stat in Stat.values()){ for(stat in Stat.values()){
val expander = ExpanderTab(stat.name.tr(),skin) if(unifiedStatList.all { it.value.get(stat)==0f }) continue
expander.innerTable.defaults().pad(2f)
addTitle(stat.name)
val statValuesTable = Table().apply { defaults().pad(2f) }
for(entry in unifiedStatList) { for(entry in unifiedStatList) {
val specificStatValue = entry.value.toHashMap()[stat]!! val specificStatValue = entry.value.get(stat)
if(specificStatValue==0f) continue if(specificStatValue==0f) continue
expander.innerTable.add(entry.key.toLabel()) statValuesTable.add(entry.key.toLabel())
expander.innerTable.add(DecimalFormat("0.#").format(specificStatValue).toLabel()).row() statValuesTable.add(DecimalFormat("0.#").format(specificStatValue).toLabel()).row()
} }
for(entry in cityStats.statPercentBonusList){ for(entry in cityStats.statPercentBonusList){
val specificStatValue = entry.value.toHashMap()[stat]!! val specificStatValue = entry.value.toHashMap()[stat]!!
if(specificStatValue==0f) continue if(specificStatValue==0f) continue
expander.innerTable.add(entry.key.toLabel()) statValuesTable.add(entry.key.toLabel())
val decimal = DecimalFormat("0.#").format(specificStatValue) val decimal = DecimalFormat("0.#").format(specificStatValue)
expander.innerTable.add("+$decimal%".toLabel()).row() statValuesTable.add("+$decimal%".toLabel()).row()
} }
if(stat==Stat.Gold){ if(stat==Stat.Gold){
val maintenance = cityStats.cityInfo.cityConstructions.getMaintenanceCosts() val maintenance = cityStats.cityInfo.cityConstructions.getMaintenanceCosts()
if(maintenance>0){ if(maintenance>0){
expander.innerTable.add("Maintenance".toLabel()) statValuesTable.add("Maintenance".toLabel())
expander.innerTable.add("-$maintenance".toLabel()) statValuesTable.add("-$maintenance".toLabel())
} }
} }
if(stat==Stat.Food){ if(stat==Stat.Food){
expander.innerTable.add("Food eaten".toLabel()) statValuesTable.add("Food eaten".toLabel())
expander.innerTable.add(DecimalFormat("0.#").format(cityStats.foodEaten).toLabel()).row() statValuesTable.add(DecimalFormat("0.#").format(cityStats.foodEaten).toLabel()).row()
val growthBonus = cityStats.getGrowthBonusFromPolicies() val growthBonus = cityStats.getGrowthBonusFromPolicies()
if(growthBonus>0){ if(growthBonus>0){
expander.innerTable.add("Growth bonus".toLabel()) statValuesTable.add("Growth bonus".toLabel())
expander.innerTable.add((growthBonus*100).toInt().toString().toLabel()) statValuesTable.add((growthBonus*100).toInt().toString().toLabel())
} }
} }
add(statValuesTable).row()
if(expander.innerTable.hasChildren())
add(expander).row()
} }
} }
@ -142,76 +165,74 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
val statToGreatPerson = GreatPersonManager().statToGreatPersonMapping val statToGreatPerson = GreatPersonManager().statToGreatPersonMapping
for (stat in Stat.values()) { for (stat in Stat.values()) {
if (!statToGreatPerson.containsKey(stat)) continue if (!statToGreatPerson.containsKey(stat)) continue
if(greatPersonPoints.all { it.value.get(stat)==0f }) continue
val expanderName = "[" + statToGreatPerson[stat]!! + "] points" val expanderName = "[" + statToGreatPerson[stat]!! + "] points"
val expanderTab = ExpanderTab(expanderName.tr(), skin) addTitle(expanderName)
expanderTab.innerTable.defaults().pad(3f) val greatPersonTable = Table()
for (entry in greatPersonPoints) { for (entry in greatPersonPoints) {
val value = entry.value.toHashMap()[stat]!! val value = entry.value.toHashMap()[stat]!!
if (value == 0f) continue if (value == 0f) continue
expanderTab.innerTable.add(entry.key.toLabel()) greatPersonTable.add(entry.key.toLabel()).padRight(10f)
expanderTab.innerTable.add(DecimalFormat("0.#").format(value).toLabel()).row() greatPersonTable.add(DecimalFormat("0.#").format(value).toLabel()).row()
} }
if (expanderTab.innerTable.hasChildren()) add(greatPersonTable).row()
add(expanderTab).row()
} }
} }
private fun addSpecialistAllocation(skin: Skin, cityInfo: CityInfo) { private fun addSpecialistAllocation(skin: Skin, cityInfo: CityInfo) {
val specialistAllocationExpander = ExpanderTab("Specialist Allocation".tr(), skin) addTitle("Specialist Allocation")
specialistAllocationExpander.innerTable.defaults().pad(5f)
val currentSpecialists = cityInfo.population.specialists.toHashMap() val currentSpecialists = cityInfo.population.specialists.toHashMap()
val maximumSpecialists = cityInfo.population.getMaxSpecialists() val maximumSpecialists = cityInfo.population.getMaxSpecialists()
for (statToMaximumSpecialist in maximumSpecialists.toHashMap()) { for (statToMaximumSpecialist in maximumSpecialists.toHashMap()) {
val specialistPickerTable = Table()
if (statToMaximumSpecialist.value == 0f) continue if (statToMaximumSpecialist.value == 0f) continue
val stat = statToMaximumSpecialist.key val stat = statToMaximumSpecialist.key
// these two are conflictingly named compared to above... // these two are conflictingly named compared to above...
val assignedSpecialists = currentSpecialists[statToMaximumSpecialist.key]!!.toInt() val assignedSpecialists = currentSpecialists[stat]!!.toInt()
val maxSpecialists = statToMaximumSpecialist.value.toInt() val maxSpecialists = statToMaximumSpecialist.value.toInt()
if (assignedSpecialists > 0) { if (assignedSpecialists > 0) {
val unassignButton = TextButton("-", skin) val unassignButton = TextButton("-", skin)
unassignButton.label.setFontSize(24) unassignButton.label.setFontSize(24)
unassignButton.onClick { unassignButton.onClick {
cityInfo.population.specialists.add(statToMaximumSpecialist.key, -1f) cityInfo.population.specialists.add(stat, -1f)
cityInfo.cityStats.update() cityInfo.cityStats.update()
cityScreen.update() cityScreen.update()
} }
specialistAllocationExpander.innerTable.add(unassignButton) specialistPickerTable.add(unassignButton)
} else specialistAllocationExpander.innerTable.add() } else specialistPickerTable.add()
val specialistTable = Table() val specialistIconTable = Table()
for (i in 1..maxSpecialists) { for (i in 1..maxSpecialists) {
val icon = getSpecialistIcon(stat, i <= assignedSpecialists) val icon = getSpecialistIcon(stat, i <= assignedSpecialists)
specialistTable.add(icon).size(30f) specialistIconTable.add(icon).size(30f)
} }
specialistAllocationExpander.innerTable.add(specialistTable) specialistPickerTable.add(specialistIconTable)
if (assignedSpecialists < maxSpecialists) { if (assignedSpecialists < maxSpecialists) {
val assignButton = TextButton("+", skin) val assignButton = TextButton("+", skin)
assignButton.label.setFontSize(24) assignButton.label.setFontSize(24)
assignButton.onClick { assignButton.onClick {
cityInfo.population.specialists.add(statToMaximumSpecialist.key, +1f) cityInfo.population.specialists.add(statToMaximumSpecialist.key, 1f)
cityInfo.cityStats.update() cityInfo.cityStats.update()
cityScreen.update() cityScreen.update()
} }
if (cityInfo.population.getFreePopulation() == 0) assignButton.disable() if (cityInfo.population.getFreePopulation() == 0)
specialistAllocationExpander.innerTable.add(assignButton) assignButton.disable()
} else specialistAllocationExpander.innerTable.add() specialistPickerTable.add(assignButton)
} else specialistPickerTable.add()
specialistAllocationExpander.innerTable.row() add(specialistPickerTable).row()
val specialistStatTable = Table().apply { defaults().pad(5f) } val specialistStatTable = Table().apply { defaults().pad(5f) }
val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(stat, cityInfo.civInfo.policies.adoptedPolicies).toHashMap() val specialistStats = cityInfo.cityStats.getStatsOfSpecialist(stat, cityInfo.civInfo.policies.adoptedPolicies).toHashMap()
for (entry in specialistStats) { for (entry in specialistStats) {
if (entry.value == 0f) continue if (entry.value == 0f) continue
specialistStatTable.add(ImageGetter.getStatIcon(entry.key.toString())).size(20f) specialistStatTable.add(ImageGetter.getStatIcon(entry.key.toString())).size(20f)
specialistStatTable.add(Label(entry.value.toInt().toString(), skin)).padRight(10f) specialistStatTable.add(entry.value.toInt().toString().toLabel()).padRight(10f)
} }
specialistAllocationExpander.innerTable.add() add(specialistStatTable).row()
specialistAllocationExpander.innerTable.add(specialistStatTable).row()
} }
add(specialistAllocationExpander).row()
} }
private fun getSpecialistIcon(stat: Stat, isFilled: Boolean =true): Image { private fun getSpecialistIcon(stat: Stat, isFilled: Boolean =true): Image {

View File

@ -27,7 +27,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
private var razeCityButtonHolder = Table() // sits on the top private var razeCityButtonHolder = Table() // sits on the top
/** Displays buildings, specialists and stats drilldown - sits on the top left of the city screen */ /** Displays buildings, specialists and stats drilldown - sits on the top right of the city screen */
private var cityInfoTable = CityInfoTable(this) private var cityInfoTable = CityInfoTable(this)
/** Displays tile info, sits on the bottom right */ /** Displays tile info, sits on the bottom right */
@ -53,7 +53,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
cityInfoTable.update() cityInfoTable.update()
val buildingsScroll = ScrollPane(cityInfoTable) val buildingsScroll = ScrollPane(cityInfoTable)
buildingsTableContainer.add(buildingsScroll) buildingsTableContainer.add(buildingsScroll)
.height(stage.height / 2) .size(stage.width/4,stage.height / 2)
buildingsTableContainer = buildingsTableContainer.addBorder(2f, Color.WHITE) buildingsTableContainer = buildingsTableContainer.addBorder(2f, Color.WHITE)
buildingsTableContainer.setPosition(stage.width - buildingsTableContainer.width-5, buildingsTableContainer.setPosition(stage.width - buildingsTableContainer.width-5,