From cd4e25a4f1734f817ae2f83b6a6abcd5267adb63 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Tue, 4 Apr 2023 09:49:58 +0200 Subject: [PATCH] Victory screen reorg/cleanup (#9111) * VictoryScreen reorg * VictoryScreen reorg - use TabbedPager * VictoryScreen reorg - make helpers reusable * VictoryScreen reorg - fixed headers * VictoryScreen reorg - debug access to Replay * Victories reorg - more cleanup * VictoryScreen reorg - icons and keys * VictoryScreen reorg - RankingType * VictoryScreen reorg - RecreateOnResize * VictoryScreen reorg - Avoid floating text overlapping buttons * VictoryScreen reorg - remove obsolete todo --- .../Civ V - Gods & Kings/VictoryTypes.json | 3 +- .../jsons/Civ V - Vanilla/VictoryTypes.json | 3 +- .../automation/city/ConstructionAutomation.kt | 2 +- .../civilization/NextTurnAutomation.kt | 2 +- .../unciv/logic/civilization/Civilization.kt | 2 +- .../civilization/managers/VictoryManager.kt | 20 +- .../com/unciv/ui/components/TabbedPager.kt | 84 ++++++- .../extensions/Scene2dExtensions.kt | 3 + .../unciv/ui/popups/options/OptionsPopup.kt | 3 +- .../screens/cityscreen/DetailedStatsPopup.kt | 2 +- .../overviewscreen/EmpireOverviewTab.kt | 39 +--- .../ui/screens/victoryscreen/RankingType.kt | 25 +- .../ui/screens/victoryscreen/VictoryScreen.kt | 217 ++++++++---------- .../victoryscreen/VictoryScreenCivGroup.kt | 67 ++++++ .../victoryscreen/VictoryScreenCivRankings.kt | 91 +++----- .../VictoryScreenDemographics.kt | 70 ++++++ .../VictoryScreenGlobalVictory.kt | 61 ++--- .../victoryscreen/VictoryScreenOurVictory.kt | 59 ++--- .../victoryscreen/VictoryScreenReplay.kt | 30 ++- 19 files changed, 461 insertions(+), 322 deletions(-) create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenCivGroup.kt create mode 100644 core/src/com/unciv/ui/screens/victoryscreen/VictoryScreenDemographics.kt diff --git a/android/assets/jsons/Civ V - Gods & Kings/VictoryTypes.json b/android/assets/jsons/Civ V - Gods & Kings/VictoryTypes.json index b4ce95bfce..350787901d 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/VictoryTypes.json +++ b/android/assets/jsons/Civ V - Gods & Kings/VictoryTypes.json @@ -27,7 +27,6 @@ }, { "name": "Diplomatic", - "hiddenInVictoryScreen": false, "victoryScreenHeader": "Build the UN and be voted\nworld leader to win!", "milestones": ["Anyone should build [United Nations]", "Win diplomatic vote"], "victoryString": "You have triumphed over your foes through the art of diplomacy! Your cunning and wisdom have earned you great friends - and divided and sown confusion among your enemies! Forever will you be remembered as the leader who brought peace to this weary world!", @@ -40,4 +39,4 @@ "victoryString": "The world has been convulsed by war. Many great and powerful civilizations have fallen, but you have survived - and emerged victorious! The world will long remember your glorious triumph!", "defeatString": "You have been defeated. Your civilization has been overwhelmed by its many foes. But your people do not despair, for they know that one day you shall return - and lead them forward to victory!" } -] \ No newline at end of file +] diff --git a/android/assets/jsons/Civ V - Vanilla/VictoryTypes.json b/android/assets/jsons/Civ V - Vanilla/VictoryTypes.json index b4ce95bfce..350787901d 100644 --- a/android/assets/jsons/Civ V - Vanilla/VictoryTypes.json +++ b/android/assets/jsons/Civ V - Vanilla/VictoryTypes.json @@ -27,7 +27,6 @@ }, { "name": "Diplomatic", - "hiddenInVictoryScreen": false, "victoryScreenHeader": "Build the UN and be voted\nworld leader to win!", "milestones": ["Anyone should build [United Nations]", "Win diplomatic vote"], "victoryString": "You have triumphed over your foes through the art of diplomacy! Your cunning and wisdom have earned you great friends - and divided and sown confusion among your enemies! Forever will you be remembered as the leader who brought peace to this weary world!", @@ -40,4 +39,4 @@ "victoryString": "The world has been convulsed by war. Many great and powerful civilizations have fallen, but you have survived - and emerged victorious! The world will long remember your glorious triumph!", "defeatString": "You have been defeated. Your civilization has been overwhelmed by its many foes. But your people do not despair, for they know that one day you shall return - and lead them forward to victory!" } -] \ No newline at end of file +] diff --git a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt index cbdab14fdc..ee43d4602a 100644 --- a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt @@ -45,7 +45,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ private val isAtWar = civInfo.isAtWar() private val buildingsForVictory = civInfo.gameInfo.getEnabledVictories().values - .mapNotNull { civInfo.victoryManager.getNextMilestone(it.name) } + .mapNotNull { civInfo.victoryManager.getNextMilestone(it) } .filter { it.type == MilestoneType.BuiltBuilding || it.type == MilestoneType.BuildingBuiltGlobally } .map { it.params[0] } diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index 18e3413449..693234d1c2 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -572,7 +572,7 @@ object NextTurnAutomation { * a unit and selling a building to make room. Can happen due to trades etc */ private fun freeUpSpaceResources(civInfo: Civilization) { // No need to build spaceship parts just yet - if (civInfo.gameInfo.ruleset.victories.none { civInfo.victoryManager.getNextMilestone(it.key)?.type == MilestoneType.AddedSSPartsInCapital } ) + if (civInfo.gameInfo.ruleset.victories.none { civInfo.victoryManager.getNextMilestone(it.value)?.type == MilestoneType.AddedSSPartsInCapital } ) return for (resource in civInfo.gameInfo.spaceResources) { diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index 6c22c4e08f..2eb4b51734 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -541,7 +541,7 @@ class Civilization : IsPartOfGameInfoSerialization { else when (category) { RankingType.Score -> calculateTotalScore().toInt() RankingType.Population -> cities.sumOf { it.population.population } - RankingType.Crop_Yield -> stats.statsForNextTurn.food.roundToInt() + RankingType.CropYield -> stats.statsForNextTurn.food.roundToInt() RankingType.Production -> stats.statsForNextTurn.production.roundToInt() RankingType.Gold -> gold RankingType.Territory -> cities.sumOf { it.tiles.size } diff --git a/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt b/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt index 1b42ed9d01..ae15d7dc8b 100644 --- a/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/VictoryManager.kt @@ -5,6 +5,7 @@ import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.logic.civilization.Civilization import com.unciv.models.Counter import com.unciv.models.ruleset.Milestone +import com.unciv.models.ruleset.Victory import com.unciv.models.ruleset.unique.UniqueType class VictoryManager : IsPartOfGameInfoSerialization { @@ -57,27 +58,28 @@ class VictoryManager : IsPartOfGameInfoSerialization { fun getVictoryTypeAchieved(): String? { if (!civInfo.isMajorCiv()) return null - for (victoryName in civInfo.gameInfo.gameParameters.victoryTypes - .filter { it != Constants.neutralVictoryType && it in civInfo.gameInfo.ruleset.victories}) { - if (getNextMilestone(victoryName) == null) - return victoryName - } + val enabledVictories = civInfo.gameInfo.gameParameters.victoryTypes + val victory = civInfo.gameInfo.ruleset.victories + .filter { it.key != Constants.neutralVictoryType && it.key in enabledVictories } + .map { it.value } + .firstOrNull { getNextMilestone(it) == null } + if (victory != null) return victory.name if (civInfo.hasUnique(UniqueType.TriggersVictory)) return Constants.neutralVictoryType return null } - fun getNextMilestone(victory: String): Milestone? { - for (milestone in civInfo.gameInfo.ruleset.victories[victory]!!.milestoneObjects) { + fun getNextMilestone(victory: Victory): Milestone? { + for (milestone in victory.milestoneObjects) { if (!milestone.hasBeenCompletedBy(civInfo)) return milestone } return null } - fun amountMilestonesCompleted(victory: String): Int { + fun amountMilestonesCompleted(victory: Victory): Int { var completed = 0 - for (milestone in civInfo.gameInfo.ruleset.victories[victory]!!.milestoneObjects) { + for (milestone in victory.milestoneObjects) { if (milestone.hasBeenCompletedBy(civInfo)) ++completed else diff --git a/core/src/com/unciv/ui/components/TabbedPager.kt b/core/src/com/unciv/ui/components/TabbedPager.kt index accffa023b..52cdb960c2 100644 --- a/core/src/com/unciv/ui/components/TabbedPager.kt +++ b/core/src/com/unciv/ui/components/TabbedPager.kt @@ -9,6 +9,7 @@ import com.badlogic.gdx.scenes.scene2d.InputListener import com.badlogic.gdx.scenes.scene2d.ui.Button import com.badlogic.gdx.scenes.scene2d.ui.Cell import com.badlogic.gdx.scenes.scene2d.ui.Image +import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup @@ -24,6 +25,7 @@ import com.unciv.ui.components.extensions.keyShortcuts import com.unciv.ui.components.extensions.onActivation import com.unciv.ui.components.extensions.packIfNeeded import com.unciv.ui.components.extensions.pad +import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.images.IconTextButton import com.unciv.ui.popups.Popup import com.unciv.ui.screens.basescreen.BaseScreen @@ -64,7 +66,7 @@ open class TabbedPager( backgroundColor: Color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f), private val headerPadding: Float = 10f, separatorColor: Color = Color.CLEAR, - private val shorcutScreen: BaseScreen? = null, + private val shortcutScreen: BaseScreen? = null, capacity: Int = 4 ) : Table() { @@ -80,7 +82,7 @@ open class TabbedPager( private set private val header = Table(BaseScreen.skin) - protected val headerScroll = LinkedScrollPane(horizontalOnly = true, header) + val headerScroll = LinkedScrollPane(horizontalOnly = true, header) protected var headerHeight = 0f private val fixedContentScroll = LinkedScrollPane(horizontalOnly = true) @@ -105,6 +107,40 @@ open class TabbedPager( /** @return Optional second content [Actor], will be placed outside the tab's main [ScrollPane] between header and `content`. Scrolls horizontally only. */ fun getFixedContent(): Actor? = null + + /** Sets first row cell's minWidth to the max of the widths of that column over all given tables + * + * Notes: + * - This aligns columns only if the tables are arranged vertically with equal X coordinates. + * - first table determines columns processed, all others must have at least the same column count. + * - Tables are left as needsLayout==true, so while equal width is ensured, you may have to pack if you want to see the value before this is rendered. + */ + fun equalizeColumns(vararg tables: Table) { + for (table in tables) + table.packIfNeeded() + val columns = tables.first().columns + if (tables.any { it.columns < columns }) + throw IllegalStateException("IPageExtensions.equalizeColumns needs all tables to have at least the same number of columns as the first one") + val widths = (0 until columns) + .mapTo(ArrayList(columns)) { column -> + tables.maxOf { it.getColumnWidth(column) } + } + for (table in tables) { + for (column in 0 until columns) + table.cells[column].run { + if (actor == null) + // Empty cells ignore minWidth, so just doing Table.add() for an empty cell in the top row will break this. Fix! + setActor