diff --git a/core/src/com/unciv/ui/overviewscreen/EmpireOverviewScreen.kt b/core/src/com/unciv/ui/overviewscreen/EmpireOverviewScreen.kt index 23cfcf91cf..83123538bf 100644 --- a/core/src/com/unciv/ui/overviewscreen/EmpireOverviewScreen.kt +++ b/core/src/com/unciv/ui/overviewscreen/EmpireOverviewScreen.kt @@ -17,6 +17,7 @@ import com.unciv.logic.trade.TradeOffersList import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.translations.tr import com.unciv.ui.pickerscreens.PromotionPickerScreen +import com.unciv.ui.trade.DiplomacyScreen import com.unciv.ui.utils.* import java.text.DecimalFormat import kotlin.math.abs @@ -103,46 +104,67 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa stage.addActor(table) } - private fun setDiplomacyTable() { + private fun setDiplomacyTable(includeCityStates:Boolean=false) { centerTable.clear() - val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() } - val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() } - val playerKnowsAndDefeatedCivs = relevantCivs.filter { playerKnows(it) && it.isDefeated() } + val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && (includeCityStates || !it.isCityState()) } + val diplomacyGroup = DiplomacyGroup(viewingPlayer, stage.height - topTable.height, includeCityStates) + val playerKnowsAndUndefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && !it.isDefeated() } + val playerKnowsAndDefeatedCivs = relevantCivs.filter { diplomacyGroup.playerKnows(it) && it.isDefeated() } if (playerKnowsAndUndefeatedCivs.size > 1) - centerTable.add(getDiplomacyGroup()) - val civTable = Table() - civTable.background = ImageGetter.getBackground(Color.BLACK) - civTable.add("[${relevantCivs.size}] Civilizations in the game".toLabel()).pad(5f).colspan(4).row() + centerTable.add(diplomacyGroup) + fun getCivMinitable(civInfo: CivilizationInfo):Table{ + val table = Table() + table.add(ImageGetter.getNationIndicator(civInfo.nation, 25f)).pad(5f) + table.add(civInfo.civName.toLabel()).left() + table.touchable = Touchable.enabled + table.onClick { + game.setScreen(DiplomacyScreen(viewingPlayer).apply { updateRightSide(civInfo) }) + } + return table + } + val titleTable = Table() titleTable.add("Our Civilization:".toLabel()) titleTable.add(ImageGetter.getNationIndicator(viewingPlayer.nation, 25f)).pad(5f) titleTable.add(viewingPlayer.civName.toLabel()).left().row() - civTable.add(titleTable).colspan(4).row() + + + val civTable = Table() + civTable.defaults().pad(5f) + civTable.background = ImageGetter.getBackground(Color.BLACK) + civTable.add("[${relevantCivs.size}] Civilizations in the game".toLabel()).pad(5f).colspan(2).row() + civTable.add(titleTable).colspan(2).row() civTable.addSeparator() - civTable.add("Known and alive ([${playerKnowsAndUndefeatedCivs.size - 1}])".toLabel()).pad(5f).colspan(4).row() + civTable.add("Known and alive ([${playerKnowsAndUndefeatedCivs.size - 1}])".toLabel()).pad(5f).colspan(2).row() if (playerKnowsAndUndefeatedCivs.size > 1) { civTable.addSeparator() playerKnowsAndUndefeatedCivs.filter { it != viewingPlayer }.forEach { - civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f) - if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) - civTable.add(it.civName.toLabel()).left().row() - else civTable.add(it.civName.toLabel()).left() + civTable.add(getCivMinitable(it)).left() + if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row() } } civTable.addSeparator() - civTable.add("Known and defeated ([${playerKnowsAndDefeatedCivs.size}])".toLabel()).pad(5f).colspan(4).row() + civTable.add("Known and defeated ([${playerKnowsAndDefeatedCivs.size}])".toLabel()).pad(5f).colspan(2).row() if (playerKnowsAndDefeatedCivs.isNotEmpty()) { civTable.addSeparator() playerKnowsAndDefeatedCivs.forEach { - civTable.add(ImageGetter.getNationIndicator(it.nation, 25f)).pad(5f) - if (playerKnowsAndDefeatedCivs.indexOf(it) % 2 != 0) - civTable.add(it.civName.toLabel()).left().row() - else civTable.add(it.civName.toLabel()).left() + civTable.add(getCivMinitable(it)).left() + if (playerKnowsAndUndefeatedCivs.indexOf(it) % 2 == 0) civTable.row() } } val civTableScrollPane = ScrollPane(civTable) civTableScrollPane.setOverscroll(false, false) - centerTable.add(civTableScrollPane.addBorder(2f, Color.WHITE)).pad(10f) + + val toggleCityStatesButton = "City-States".toTextButton() + toggleCityStatesButton.color = if(includeCityStates)Color.RED else Color.GREEN + toggleCityStatesButton.onClick { setDiplomacyTable(!includeCityStates) } + civTable.add(toggleCityStatesButton).row() + + val floatingTable = Table() + floatingTable.add(toggleCityStatesButton).row() + floatingTable.add(civTableScrollPane.addBorder(2f, Color.WHITE)).pad(10f) + + centerTable.add(floatingTable) centerTable.pack() } @@ -370,89 +392,6 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa } - private fun playerKnows(civ:CivilizationInfo) = civ==viewingPlayer || - viewingPlayer.diplomacy.containsKey(civ.civName) - - private fun getDiplomacyGroup(): Group { - val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && !it.isCityState() } - val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() } - val freeHeight = stage.height - topTable.height - val group = Group() - group.setSize(freeHeight, freeHeight) - val civGroups = HashMap() - val civLines = HashMap>() - for (i in 0..playerKnowsAndUndefeatedCivs.lastIndex) { - val civ = playerKnowsAndUndefeatedCivs[i] - - val civGroup = ImageGetter.getNationIndicator(civ.nation, 30f) - - val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / playerKnowsAndUndefeatedCivs.size) - civGroup.center(group) - civGroup.moveBy(vector.x * freeHeight / 2.25f, vector.y * freeHeight / 2.25f) - civGroup.touchable = Touchable.enabled - civGroup.onClick { - onCivClicked(civLines, civ.civName) - } - - civGroups[civ.civName] = civGroup - group.addActor(civGroup) - } - - for (civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() }) - for (diplomacy in civ.diplomacy.values.filter { - it.otherCiv().isMajorCiv() && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated() - }) { - val civGroup = civGroups[civ.civName]!! - val otherCivGroup = civGroups[diplomacy.otherCivName]!! - - if (!civLines.containsKey(civ.civName)) - civLines[civ.civName] = mutableSetOf() - - val statusLine = ImageGetter.getLine(civGroup.x + civGroup.width / 2, civGroup.y + civGroup.height / 2, - otherCivGroup.x + otherCivGroup.width / 2, otherCivGroup.y + otherCivGroup.height / 2, 2f) - - statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.Peace) Color.GREEN else Color.RED - - civLines[civ.civName]!!.add(statusLine) - - group.addActor(statusLine) - statusLine.toBack() - } - - return group - } - - private fun onCivClicked(civLines: HashMap>, name: String) { - // ignore the clicks on "dead" civilizations, and remember the selected one - val selectedLines = civLines[name] ?: return - - // let's check whether lines of all civs are visible (except selected one) - var atLeastOneLineVisible = false - var allAreLinesInvisible = true - for (lines in civLines.values) { - // skip the civilization selected by user, and civilizations with no lines - if (lines == selectedLines || lines.isEmpty()) continue - - val visibility = lines.first().isVisible - atLeastOneLineVisible = atLeastOneLineVisible || visibility - allAreLinesInvisible = allAreLinesInvisible && visibility - - // check whether both visible and invisible lines are present - if (atLeastOneLineVisible && !allAreLinesInvisible) { - // invert visibility of the selected civ's lines - selectedLines.forEach { it.isVisible = !it.isVisible } - return - } - } - - if (selectedLines.first().isVisible) - // invert visibility of all lines except selected one - civLines.filter { it.key != name }.forEach { it.value.forEach { line -> line.isVisible = !line.isVisible } } - else - // it happens only when all are visible except selected one - // invert visibility of the selected civ's lines - selectedLines.forEach { it.isVisible = !it.isVisible } - } private fun getResourcesTable(): Table { @@ -560,3 +499,87 @@ class EmpireOverviewScreen(private var viewingPlayer:CivilizationInfo, defaultPa } } + + +class DiplomacyGroup(val viewingPlayer: CivilizationInfo, freeHeight: Float, includeCityStates: Boolean): Group() { + private fun onCivClicked(civLines: HashMap>, name: String) { + // ignore the clicks on "dead" civilizations, and remember the selected one + val selectedLines = civLines[name] ?: return + + // let's check whether lines of all civs are visible (except selected one) + var atLeastOneLineVisible = false + var allAreLinesInvisible = true + for (lines in civLines.values) { + // skip the civilization selected by user, and civilizations with no lines + if (lines == selectedLines || lines.isEmpty()) continue + + val visibility = lines.first().isVisible + atLeastOneLineVisible = atLeastOneLineVisible || visibility + allAreLinesInvisible = allAreLinesInvisible && visibility + + // check whether both visible and invisible lines are present + if (atLeastOneLineVisible && !allAreLinesInvisible) { + // invert visibility of the selected civ's lines + selectedLines.forEach { it.isVisible = !it.isVisible } + return + } + } + + if (selectedLines.first().isVisible) + // invert visibility of all lines except selected one + civLines.filter { it.key != name }.forEach { it.value.forEach { line -> line.isVisible = !line.isVisible } } + else + // it happens only when all are visible except selected one + // invert visibility of the selected civ's lines + selectedLines.forEach { it.isVisible = !it.isVisible } + } + + + fun playerKnows(civ: CivilizationInfo) = civ == viewingPlayer || + viewingPlayer.diplomacy.containsKey(civ.civName) + + init { + val relevantCivs = viewingPlayer.gameInfo.civilizations.filter { !it.isBarbarian() && (includeCityStates || !it.isCityState()) } + val playerKnowsAndUndefeatedCivs = relevantCivs.filter { playerKnows(it) && !it.isDefeated() } + setSize(freeHeight, freeHeight) + val civGroups = HashMap() + val civLines = HashMap>() + for (i in 0..playerKnowsAndUndefeatedCivs.lastIndex) { + val civ = playerKnowsAndUndefeatedCivs[i] + + val civGroup = ImageGetter.getNationIndicator(civ.nation, 30f) + + val vector = HexMath.getVectorForAngle(2 * Math.PI.toFloat() * i / playerKnowsAndUndefeatedCivs.size) + civGroup.center(this) + civGroup.moveBy(vector.x * freeHeight / 2.25f, vector.y * freeHeight / 2.25f) + civGroup.touchable = Touchable.enabled + civGroup.onClick { + onCivClicked(civLines, civ.civName) + } + + civGroups[civ.civName] = civGroup + addActor(civGroup) + } + + for (civ in relevantCivs.filter { playerKnows(it) && !it.isDefeated() }) + for (diplomacy in civ.diplomacy.values.filter { + (it.otherCiv().isMajorCiv() || includeCityStates) && playerKnows(it.otherCiv()) && !it.otherCiv().isDefeated() + }) { + val civGroup = civGroups[civ.civName]!! + val otherCivGroup = civGroups[diplomacy.otherCivName]!! + + if (!civLines.containsKey(civ.civName)) + civLines[civ.civName] = mutableSetOf() + + val statusLine = ImageGetter.getLine(civGroup.x + civGroup.width / 2, civGroup.y + civGroup.height / 2, + otherCivGroup.x + otherCivGroup.width / 2, otherCivGroup.y + otherCivGroup.height / 2, 2f) + + statusLine.color = if (diplomacy.diplomaticStatus == DiplomaticStatus.Peace) Color.GREEN else Color.RED + + civLines[civ.civName]!!.add(statusLine) + + addActor(statusLine) + statusLine.toBack() + } + } +} \ No newline at end of file