mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-29 23:10:39 -04:00
Show garrison in City overview (#8906)
* Add a Garrison column to City Overview * Add a Garrison column to City Overview - clickable
This commit is contained in:
parent
461fc4f191
commit
9262beb9a5
@ -9,13 +9,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.city.CityFlags
|
|
||||||
import com.unciv.logic.city.City
|
import com.unciv.logic.city.City
|
||||||
|
import com.unciv.logic.city.CityFlags
|
||||||
import com.unciv.logic.civilization.Civilization
|
import com.unciv.logic.civilization.Civilization
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.screens.cityscreen.CityScreen
|
|
||||||
import com.unciv.ui.images.ImageGetter
|
|
||||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||||
import com.unciv.ui.components.extensions.addSeparator
|
import com.unciv.ui.components.extensions.addSeparator
|
||||||
import com.unciv.ui.components.extensions.center
|
import com.unciv.ui.components.extensions.center
|
||||||
@ -24,6 +22,8 @@ import com.unciv.ui.components.extensions.pad
|
|||||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
import com.unciv.ui.components.extensions.toTextButton
|
import com.unciv.ui.components.extensions.toTextButton
|
||||||
|
import com.unciv.ui.images.ImageGetter
|
||||||
|
import com.unciv.ui.screens.cityscreen.CityScreen
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class CityOverviewTab(
|
class CityOverviewTab(
|
||||||
@ -48,7 +48,8 @@ class CityOverviewTab(
|
|||||||
private const val CITY = "City"
|
private const val CITY = "City"
|
||||||
private const val WLTK = "WLTK"
|
private const val WLTK = "WLTK"
|
||||||
private const val CONSTRUCTION = "Construction"
|
private const val CONSTRUCTION = "Construction"
|
||||||
private val alphabeticColumns = listOf(CITY, CONSTRUCTION, WLTK)
|
private const val GARRISON = "Garrison"
|
||||||
|
private val alphabeticColumns = listOf(CITY, CONSTRUCTION, WLTK, GARRISON)
|
||||||
|
|
||||||
private val citySortIcon = ImageGetter.getUnitIcon("Settler")
|
private val citySortIcon = ImageGetter.getUnitIcon("Settler")
|
||||||
.surroundWithCircle(iconSize)
|
.surroundWithCircle(iconSize)
|
||||||
@ -61,6 +62,10 @@ class CityOverviewTab(
|
|||||||
.apply { color = Color.BLACK }
|
.apply { color = Color.BLACK }
|
||||||
.surroundWithCircle(iconSize, color = Color.LIGHT_GRAY)
|
.surroundWithCircle(iconSize, color = Color.LIGHT_GRAY)
|
||||||
.apply { addTooltip("Current construction", 18f, tipAlign = Align.center) }
|
.apply { addTooltip("Current construction", 18f, tipAlign = Align.center) }
|
||||||
|
private val garrisonSortIcon = ImageGetter.getImage("OtherIcons/Shield")
|
||||||
|
.apply { color = Color.BLACK }
|
||||||
|
.surroundWithCircle(iconSize, color = Color.LIGHT_GRAY)
|
||||||
|
.apply { addTooltip("Garrisoned by unit", 18f, tipAlign = Align.center) }
|
||||||
|
|
||||||
// Readability helpers
|
// Readability helpers
|
||||||
private fun String.isStat() = Stat.isStat(this)
|
private fun String.isStat() = Stat.isStat(this)
|
||||||
@ -103,7 +108,7 @@ class CityOverviewTab(
|
|||||||
add(cityInfoTableTotal)
|
add(cityInfoTableTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSort(sortBy: String) {
|
private fun toggleSort(sortBy: String) {
|
||||||
if (sortBy == persistableData.sortedBy) {
|
if (sortBy == persistableData.sortedBy) {
|
||||||
persistableData.descending = !persistableData.descending
|
persistableData.descending = !persistableData.descending
|
||||||
} else {
|
} else {
|
||||||
@ -112,7 +117,7 @@ class CityOverviewTab(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getComparator() = Comparator { city2: City, city1: City ->
|
private fun getComparator() = Comparator { city2: City, city1: City ->
|
||||||
when(persistableData.sortedBy) {
|
when(persistableData.sortedBy) {
|
||||||
CITY -> collator.compare(city2.name.tr(), city1.name.tr())
|
CITY -> collator.compare(city2.name.tr(), city1.name.tr())
|
||||||
CONSTRUCTION -> collator.compare(
|
CONSTRUCTION -> collator.compare(
|
||||||
@ -120,6 +125,10 @@ class CityOverviewTab(
|
|||||||
city1.cityConstructions.currentConstructionFromQueue.tr())
|
city1.cityConstructions.currentConstructionFromQueue.tr())
|
||||||
"Population" -> city2.population.population - city1.population.population
|
"Population" -> city2.population.population - city1.population.population
|
||||||
WLTK -> city2.isWeLoveTheKingDayActive().compareTo(city1.isWeLoveTheKingDayActive())
|
WLTK -> city2.isWeLoveTheKingDayActive().compareTo(city1.isWeLoveTheKingDayActive())
|
||||||
|
GARRISON -> collator.compare(
|
||||||
|
city2.getCenterTile().militaryUnit?.name?.tr() ?: "",
|
||||||
|
city1.getCenterTile().militaryUnit?.name?.tr() ?: "",
|
||||||
|
)
|
||||||
else -> {
|
else -> {
|
||||||
val stat = Stat.safeValueOf(persistableData.sortedBy)!!
|
val stat = Stat.safeValueOf(persistableData.sortedBy)!!
|
||||||
city2.getStat(stat) - city1.getStat(stat)
|
city2.getStat(stat) - city1.getStat(stat)
|
||||||
@ -172,6 +181,7 @@ class CityOverviewTab(
|
|||||||
addSortIcon(name)
|
addSortIcon(name)
|
||||||
}
|
}
|
||||||
addSortIcon(WLTK, wltkSortIcon)
|
addSortIcon(WLTK, wltkSortIcon)
|
||||||
|
addSortIcon(GARRISON, garrisonSortIcon)
|
||||||
cityInfoTableHeader.pack()
|
cityInfoTableHeader.pack()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,11 +231,23 @@ class CityOverviewTab(
|
|||||||
city.demandedResource.isNotEmpty() -> {
|
city.demandedResource.isNotEmpty() -> {
|
||||||
val image = ImageGetter.getResourcePortrait(city.demandedResource, iconSize *0.7f)
|
val image = ImageGetter.getResourcePortrait(city.demandedResource, iconSize *0.7f)
|
||||||
image.addTooltip("Demanding [${city.demandedResource}]", 18f, tipAlign = Align.topLeft)
|
image.addTooltip("Demanding [${city.demandedResource}]", 18f, tipAlign = Align.topLeft)
|
||||||
cityInfoTableDetails.add(image).padLeft(iconSize *0.3f)
|
cityInfoTableDetails.add(image)
|
||||||
}
|
}
|
||||||
else -> cityInfoTableDetails.add()
|
else -> cityInfoTableDetails.add()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val garrisonUnit = city.getCenterTile().militaryUnit
|
||||||
|
if (garrisonUnit == null) {
|
||||||
|
cityInfoTableDetails.add()
|
||||||
|
} else {
|
||||||
|
val garrisonUnitName = garrisonUnit.displayName()
|
||||||
|
val garrisonUnitIcon = ImageGetter.getConstructionPortrait(garrisonUnit.baseUnit.getIconName(), iconSize * 0.7f)
|
||||||
|
garrisonUnitIcon.addTooltip(garrisonUnitName, 18f, tipAlign = Align.topLeft)
|
||||||
|
garrisonUnitIcon.onClick {
|
||||||
|
overviewScreen.select(EmpireOverviewCategories.Units, UnitOverviewTab.getUnitIdentifier(garrisonUnit) )
|
||||||
|
}
|
||||||
|
cityInfoTableDetails.add(garrisonUnitIcon)
|
||||||
|
}
|
||||||
cityInfoTableDetails.row()
|
cityInfoTableDetails.row()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +270,7 @@ class CityOverviewTab(
|
|||||||
else cityInfoTableTotal.add(viewingPlayer.cities.sumOf { it.getStat(stat) }.toCenteredLabel())
|
else cityInfoTableTotal.add(viewingPlayer.cities.sumOf { it.getStat(stat) }.toCenteredLabel())
|
||||||
}
|
}
|
||||||
cityInfoTableTotal.add(viewingPlayer.cities.count { it.isWeLoveTheKingDayActive() }.toCenteredLabel())
|
cityInfoTableTotal.add(viewingPlayer.cities.count { it.isWeLoveTheKingDayActive() }.toCenteredLabel())
|
||||||
|
cityInfoTableTotal.add(viewingPlayer.cities.count { it.getCenterTile().militaryUnit != null }.toCenteredLabel())
|
||||||
cityInfoTableTotal.pack()
|
cityInfoTableTotal.pack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class EmpireOverviewScreen(
|
|||||||
)
|
)
|
||||||
if (category.name == page) {
|
if (category.name == page) {
|
||||||
tabbedPager.selectPage(index)
|
tabbedPager.selectPage(index)
|
||||||
pageObject.select(selection)
|
select(pageObject, selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,4 +94,14 @@ class EmpireOverviewScreen(
|
|||||||
val category = (pageObjects.entries.find { it.value == tab } ?: return).key
|
val category = (pageObjects.entries.find { it.value == tab } ?: return).key
|
||||||
tabbedPager.replacePage(category.name, tab)
|
tabbedPager.replacePage(category.name, tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun select(category: EmpireOverviewCategories, selection: String) {
|
||||||
|
tabbedPager.selectPage(category.name)
|
||||||
|
select(pageObjects[category], selection)
|
||||||
|
}
|
||||||
|
private fun select(tab: EmpireOverviewTab?, selection: String) {
|
||||||
|
if (tab == null) return
|
||||||
|
val scrollY = tab.select(selection) ?: return
|
||||||
|
tabbedPager.setPageScrollY(tabbedPager.activePage, scrollY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,10 @@ abstract class EmpireOverviewTab (
|
|||||||
settings.lastOverviewPage = caption
|
settings.lastOverviewPage = caption
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Override if the tab can _select_ something specific */
|
/** Override if the tab can _select_ something specific.
|
||||||
open fun select(selection: String) {}
|
* @return non-null to set that tab's ScrollPane.scrollY
|
||||||
|
*/
|
||||||
|
open fun select(selection: String): Float? = null
|
||||||
|
|
||||||
val gameInfo = viewingPlayer.gameInfo
|
val gameInfo = viewingPlayer.gameInfo
|
||||||
|
|
||||||
|
@ -125,10 +125,11 @@ class ReligionOverviewTab(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun select(selection: String) {
|
override fun select(selection: String): Float? {
|
||||||
persistableData.selectedReligion = selection
|
persistableData.selectedReligion = selection
|
||||||
loadReligionButtons() // so the icon is "highlighted"
|
loadReligionButtons() // so the icon is "highlighted"
|
||||||
loadReligion(selection)
|
loadReligion(selection)
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
private fun loadReligion(religionName: String?) {
|
private fun loadReligion(religionName: String?) {
|
||||||
if (religionName == null) return
|
if (religionName == null) return
|
||||||
|
@ -2,7 +2,10 @@ package com.unciv.ui.screens.overviewscreen
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Action
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Group
|
import com.badlogic.gdx.scenes.scene2d.Group
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
@ -28,6 +31,7 @@ import com.unciv.ui.components.extensions.darken
|
|||||||
import com.unciv.ui.components.extensions.onClick
|
import com.unciv.ui.components.extensions.onClick
|
||||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
|
import com.unciv.ui.components.extensions.toPrettyString
|
||||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade
|
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
@ -53,6 +57,7 @@ class UnitOverviewTab(
|
|||||||
}
|
}
|
||||||
override fun deactivated(index: Int, caption: String, pager: TabbedPager) {
|
override fun deactivated(index: Int, caption: String, pager: TabbedPager) {
|
||||||
persistableData.scrollY = pager.getPageScrollY(index)
|
persistableData.scrollY = pager.getPageScrollY(index)
|
||||||
|
removeBlinkAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val supplyTableWidth = (overviewScreen.stage.width * 0.25f).coerceAtLeast(240f)
|
private val supplyTableWidth = (overviewScreen.stage.width * 0.25f).coerceAtLeast(240f)
|
||||||
@ -60,6 +65,16 @@ class UnitOverviewTab(
|
|||||||
private val unitHeaderTable = Table()
|
private val unitHeaderTable = Table()
|
||||||
private val fixedContent = Table()
|
private val fixedContent = Table()
|
||||||
|
|
||||||
|
// used for select()
|
||||||
|
private var blinkAction: Action? = null
|
||||||
|
private var blinkActor: Actor? = null
|
||||||
|
private fun removeBlinkAction() {
|
||||||
|
if (blinkAction == null || blinkActor == null) return
|
||||||
|
blinkActor!!.removeAction(blinkAction)
|
||||||
|
blinkAction = null
|
||||||
|
blinkActor = null
|
||||||
|
}
|
||||||
|
|
||||||
override fun getFixedContent() = fixedContent
|
override fun getFixedContent() = fixedContent
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -170,6 +185,7 @@ class UnitOverviewTab(
|
|||||||
UnitGroup(unit, 20f),
|
UnitGroup(unit, 20f),
|
||||||
fontColor = if (unit.due && unit.isIdle()) Color.WHITE else Color.LIGHT_GRAY
|
fontColor = if (unit.due && unit.isIdle()) Color.WHITE else Color.LIGHT_GRAY
|
||||||
)
|
)
|
||||||
|
button.name = getUnitIdentifier(unit) // Marker to find a unit in select()
|
||||||
button.onClick {
|
button.onClick {
|
||||||
showWorldScreenAt(unit)
|
showWorldScreenAt(unit)
|
||||||
}
|
}
|
||||||
@ -248,4 +264,27 @@ class UnitOverviewTab(
|
|||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getUnitIdentifier(unit: MapUnit) = unit.run { "$name@${getTile().position.toPrettyString()}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun select(selection: String): Float? {
|
||||||
|
val cell = unitListTable.cells.asSequence()
|
||||||
|
.filter { it.actor is IconTextButton && it.actor.name == selection }
|
||||||
|
.firstOrNull() ?: return null
|
||||||
|
val button = cell.actor as IconTextButton
|
||||||
|
val scrollY = (0 until cell.row)
|
||||||
|
.map { unitListTable.getRowHeight(it) }.sum() -
|
||||||
|
(parent.height - unitListTable.getRowHeight(cell.row)) / 2
|
||||||
|
|
||||||
|
removeBlinkAction()
|
||||||
|
blinkAction = Actions.repeat(3, Actions.sequence(
|
||||||
|
Actions.fadeOut(0.17f),
|
||||||
|
Actions.fadeIn(0.17f)
|
||||||
|
))
|
||||||
|
blinkActor = button
|
||||||
|
button.addAction(blinkAction)
|
||||||
|
return scrollY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user