mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 15:27:50 +07:00
WordScreenTopBar rework, portrait-friendlier (#6945)
* WordScreenTopBar rework, portrait-friendlier * WordScreenTopBar rework, portrait-friendlier - NotificationsScroll * WordScreenTopBar rework, portrait-friendlier - Rounded corners * WordScreenTopBar rework, portrait-friendlier - Tweak padding * WordScreenTopBar rework, portrait-friendlier - review
This commit is contained in:
61
core/src/com/unciv/ui/worldscreen/BackgroundActor.kt
Normal file
61
core/src/com/unciv/ui/worldscreen/BackgroundActor.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package com.unciv.ui.worldscreen
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.Batch
|
||||
import com.badlogic.gdx.graphics.g2d.NinePatch
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.Drawable
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
|
||||
/** An Actor that just draws a Drawable [background], preferably a [NinePatchDrawable] created
|
||||
* by [BackgroundActor.getRoundedEdgeRectangle], meant to work in Table Cells and to be overlaid with other Widgets.
|
||||
* The drawable's center can be moved to any of the corners or vertex centers using `align`, which will also scale the
|
||||
* drawable up by factor 2 and clip to the original rectangle. This can be used to draw rectangles with one or two rounded corners.
|
||||
* @param align An [Align] constant - In which corner of the [BackgroundActor] rectangle the center of the [background] should be.
|
||||
*/
|
||||
class BackgroundActor(val background: Drawable, align: Int) : Actor() {
|
||||
private val widthMultiplier = if (Align.isCenterHorizontal(align)) 1f else 2f
|
||||
private val heightMultiplier = if (Align.isCenterVertical(align)) 1f else 2f
|
||||
private val noClip = Align.isCenterHorizontal(align) && Align.isCenterVertical(align)
|
||||
private val xOffset = if (Align.isLeft(align)) 0.5f else 0f
|
||||
private val yOffset = if (Align.isBottom(align)) 0.5f else 0f
|
||||
|
||||
init {
|
||||
touchable = Touchable.disabled
|
||||
}
|
||||
|
||||
override fun hit(x: Float, y: Float, touchable: Boolean): Actor? = null
|
||||
|
||||
override fun draw(batch: Batch?, parentAlpha: Float) {
|
||||
if (batch == null) return
|
||||
if (noClip) return drawBackground(batch, parentAlpha)
|
||||
|
||||
batch.flush()
|
||||
if (!clipBegin()) return
|
||||
val w = width * widthMultiplier
|
||||
val h = height * heightMultiplier
|
||||
drawBackground(batch, parentAlpha, x - xOffset * w, y - yOffset * h, w, h)
|
||||
batch.flush()
|
||||
clipEnd()
|
||||
}
|
||||
|
||||
private fun drawBackground(batch: Batch, parentAlpha: Float) =
|
||||
drawBackground(batch, parentAlpha, x, y, width, height)
|
||||
private fun drawBackground(batch: Batch, parentAlpha: Float, x: Float, y: Float, w: Float, h: Float) {
|
||||
val color = color
|
||||
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha)
|
||||
background.draw(batch, x, y, w, h)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getRoundedEdgeRectangle(tintColor: Color): NinePatchDrawable {
|
||||
val region = ImageGetter.getDrawable("Skin/roundedEdgeRectangle").region
|
||||
val drawable = NinePatchDrawable(NinePatch(region, 25, 25, 24, 24))
|
||||
drawable.setPadding(15f, 15f, 15f, 15f)
|
||||
return drawable.tint(tintColor)
|
||||
}
|
||||
}
|
||||
}
|
@ -14,8 +14,7 @@ import kotlin.math.min
|
||||
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
|
||||
|
||||
class NotificationsScroll(
|
||||
private val worldScreen: WorldScreen,
|
||||
private val maxNotificationsHeight: Float
|
||||
private val worldScreen: WorldScreen
|
||||
) : ScrollPane(null) {
|
||||
private companion object {
|
||||
/** Scale the entire ScrollPane by this factor */
|
||||
@ -41,15 +40,26 @@ class NotificationsScroll(
|
||||
setScale(scaleFactor)
|
||||
}
|
||||
|
||||
internal fun update(notifications: MutableList<Notification>, tileInfoTableHeight: Float) {
|
||||
/**
|
||||
* Update widget contents if necessary and recalculate layout
|
||||
* @param notifications Data to display
|
||||
* @param maxNotificationsHeight Total height in world screen coordinates
|
||||
* @param tileInfoTableHeight Height of the portion that may be covered on the bottom - make sure we can scroll up far enough so the bottom entry is visible above this
|
||||
*/
|
||||
internal fun update(
|
||||
notifications: MutableList<Notification>,
|
||||
maxNotificationsHeight: Float,
|
||||
tileInfoTableHeight: Float
|
||||
) {
|
||||
updateContent(notifications)
|
||||
updateLayout(maxNotificationsHeight, tileInfoTableHeight)
|
||||
}
|
||||
|
||||
private fun updateContent(notifications: MutableList<Notification>) {
|
||||
// no news? - keep our list as it is, especially don't reset scroll position
|
||||
if (notificationsHash == notifications.hashCode()) {
|
||||
sizeScrollingSpacer(tileInfoTableHeight)
|
||||
layout()
|
||||
return
|
||||
}
|
||||
notificationsHash = notifications.hashCode()
|
||||
val newHash = notifications.hashCode()
|
||||
if (notificationsHash == newHash) return
|
||||
notificationsHash = newHash
|
||||
|
||||
notificationsTable.clearChildren()
|
||||
endOfTableSpacerCell = null
|
||||
@ -93,12 +103,17 @@ class NotificationsScroll(
|
||||
}
|
||||
|
||||
notificationsTable.pack() // needed to get height - prefHeight is set and close but not quite the same value
|
||||
val filledHeight = notificationsTable.height
|
||||
}
|
||||
|
||||
private fun updateLayout(maxNotificationsHeight: Float, tileInfoTableHeight: Float) {
|
||||
val newHeight = min(notificationsTable.height, maxNotificationsHeight * inverseScaleFactor)
|
||||
|
||||
sizeScrollingSpacer(tileInfoTableHeight)
|
||||
|
||||
pack()
|
||||
height = min(filledHeight, maxNotificationsHeight * inverseScaleFactor) // after this, maxY is still incorrect until layout()
|
||||
if (height == newHeight) return
|
||||
height = newHeight // after this, maxY is still incorrect until layout()
|
||||
invalidateHierarchy()
|
||||
}
|
||||
|
||||
/** Add some empty space that can be scrolled under the TileInfoTable which is covering our lower part */
|
||||
|
@ -16,7 +16,6 @@ import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.MainMenuScreen
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.utils.debug
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.ReligionState
|
||||
@ -58,7 +57,6 @@ import com.unciv.ui.trade.DiplomacyScreen
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.KeyCharAndCode
|
||||
import com.unciv.ui.utils.UncivDateFormat.formatDate
|
||||
import com.unciv.ui.utils.centerX
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
import com.unciv.ui.utils.darken
|
||||
@ -79,8 +77,8 @@ import com.unciv.ui.worldscreen.status.NextTurnButton
|
||||
import com.unciv.ui.worldscreen.status.StatusButtons
|
||||
import com.unciv.ui.worldscreen.unit.UnitActionsTable
|
||||
import com.unciv.ui.worldscreen.unit.UnitTable
|
||||
import com.unciv.utils.debug
|
||||
import kotlinx.coroutines.Job
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Unciv's world screen
|
||||
@ -122,8 +120,8 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
private val statusButtons = StatusButtons(nextTurnButton)
|
||||
private val tutorialTaskTable = Table().apply { background = ImageGetter.getBackground(
|
||||
ImageGetter.getBlue().darken(0.5f)) }
|
||||
private val notificationsScroll = NotificationsScroll(this)
|
||||
|
||||
private val notificationsScroll: NotificationsScroll
|
||||
var shouldUpdate = false
|
||||
|
||||
private val zoomController = ZoomButtonPair(mapHolder)
|
||||
@ -134,12 +132,6 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
|
||||
|
||||
init {
|
||||
topBar.setPosition(0f, stage.height - topBar.height)
|
||||
topBar.width = stage.width
|
||||
|
||||
val maxNotificationsHeight = topBar.y - nextTurnButton.height -
|
||||
(if (game.settings.showMinimap) minimapWrapper.height else 0f) - 25f
|
||||
notificationsScroll = NotificationsScroll(this, maxNotificationsHeight)
|
||||
// notifications are right-aligned, they take up only as much space as necessary.
|
||||
notificationsScroll.width = stage.width / 2
|
||||
|
||||
@ -443,8 +435,6 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
techPolicyAndVictoryHolder.setPosition(10f, topBar.y - techPolicyAndVictoryHolder.height - 5f)
|
||||
updateDiplomacyButton(viewingCiv)
|
||||
|
||||
topBar.unitSupplyImage.isVisible = selectedCiv.stats().getUnitSupplyDeficit() > 0
|
||||
|
||||
if (!hasOpenPopups() && isPlayersTurn) {
|
||||
when {
|
||||
viewingCiv.shouldShowDiplomaticVotingResults() ->
|
||||
@ -465,8 +455,12 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateGameplayButtons()
|
||||
notificationsScroll.update(viewingCiv.notifications, bottomTileInfoTable.height)
|
||||
|
||||
val maxNotificationsHeight = statusButtons.y -
|
||||
(if (game.settings.showMinimap) minimapWrapper.height else 0f) - 5f
|
||||
notificationsScroll.update(viewingCiv.notifications, maxNotificationsHeight, bottomTileInfoTable.height)
|
||||
notificationsScroll.setTopRight(stage.width - 10f, statusButtons.y - 5f)
|
||||
|
||||
val posZoomFromRight = if (game.settings.showMinimap) minimapWrapper.width
|
||||
|
@ -3,9 +3,15 @@ package com.unciv.ui.worldscreen
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Container
|
||||
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.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.models.ruleset.tile.TileResource
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.CivilopediaCategories
|
||||
@ -15,31 +21,39 @@ import com.unciv.ui.overviewscreen.EmpireOverviewScreen
|
||||
import com.unciv.ui.pickerscreens.PolicyPickerScreen
|
||||
import com.unciv.ui.pickerscreens.TechPickerScreen
|
||||
import com.unciv.ui.popup.popups
|
||||
import com.unciv.ui.utils.*
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.MayaCalendar
|
||||
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
import com.unciv.ui.utils.darken
|
||||
import com.unciv.ui.utils.onClick
|
||||
import com.unciv.ui.utils.setFontColor
|
||||
import com.unciv.ui.utils.setFontSize
|
||||
import com.unciv.ui.utils.toLabel
|
||||
import com.unciv.ui.utils.toTextButton
|
||||
import com.unciv.ui.victoryscreen.VictoryScreen
|
||||
import com.unciv.ui.worldscreen.mainmenu.WorldScreenMenuPopup
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
/**
|
||||
* Table consisting of the menu button, current civ, some stats and the overview button for the top of [WorldScreen]
|
||||
*/
|
||||
//region Fields
|
||||
class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
|
||||
private var selectedCivLabel = worldScreen.selectedCiv.civName.toLabel()
|
||||
private var selectedCivIconHolder = Container<Actor>()
|
||||
|
||||
private val turnsLabel = "Turns: 0/400".toLabel()
|
||||
private val goldLabel = "0".toLabel(colorFromRGB(225, 217, 71))
|
||||
private val scienceLabel = "0".toLabel(colorFromRGB(78, 140, 151))
|
||||
private val happinessLabel = "0".toLabel()
|
||||
private val cultureLabel = "0".toLabel(colorFromRGB(210, 94, 210))
|
||||
private val faithLabel = "0".toLabel(colorFromRGB(210, 94, 210)) // TODO: This colour should be changed at some point
|
||||
private val resourceLabels = HashMap<String, Label>()
|
||||
private val resourceImages = HashMap<String, Actor>()
|
||||
private val faithLabel = "0".toLabel(colorFromRGB(168, 196, 241))
|
||||
private data class ResourceActors(val resource: TileResource, val Label: Label, val icon: Group)
|
||||
private val resourceActors = ArrayList<ResourceActors>(12)
|
||||
private val happinessImage = Group()
|
||||
|
||||
// These are all to improve performance IE reduce update time (was 150 ms on my phone, which is a lot!)
|
||||
@ -48,27 +62,81 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
private val malcontentGroup = ImageGetter.getStatIcon("Malcontent")
|
||||
private val happinessGroup = ImageGetter.getStatIcon("Happiness")
|
||||
|
||||
val unitSupplyImage = ImageGetter.getImage("OtherIcons/ExclamationMark")
|
||||
.apply { color = Color.FIREBRICK }
|
||||
private val statsTable = getStatsTable()
|
||||
private val resourcesWrapper = Table()
|
||||
private val resourceTable = getResourceTable()
|
||||
private val selectedCivTable = SelectedCivilizationTable(worldScreen)
|
||||
private val overviewButton = OverviewAndSupplyTable(worldScreen)
|
||||
private val leftFillerCell: Cell<BackgroundActor>
|
||||
private val rightFillerCell: Cell<BackgroundActor>
|
||||
|
||||
//endregion
|
||||
|
||||
init {
|
||||
background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f))
|
||||
|
||||
add(getStatsTable()).row()
|
||||
add(getResourceTable())
|
||||
|
||||
pad(5f)
|
||||
// Not the Table, the Cells (all except one) have the background. To avoid gaps, _no_
|
||||
// padding except inside the cell actors, and all actors need to _fill_ their cell.
|
||||
val backColor = ImageGetter.getBlue().darken(0.5f)
|
||||
val backgroundDrawable = ImageGetter.getBackground(backColor)
|
||||
statsTable.background = backgroundDrawable
|
||||
resourceTable.background = backgroundDrawable
|
||||
add(statsTable).colspan(3).growX().row()
|
||||
add(resourceTable).colspan(3).growX().row()
|
||||
val leftFillerBG = BackgroundActor.getRoundedEdgeRectangle(backColor)
|
||||
leftFillerCell = add(BackgroundActor(leftFillerBG, Align.topLeft))
|
||||
add().growX()
|
||||
val rightFillerBG = BackgroundActor.getRoundedEdgeRectangle(backColor)
|
||||
rightFillerCell = add(BackgroundActor(rightFillerBG, Align.topRight))
|
||||
pack()
|
||||
addActor(getMenuButton()) // needs to be after pack
|
||||
}
|
||||
|
||||
addActor(getSelectedCivilizationTable())
|
||||
private fun getStatsTable(): Table {
|
||||
val statsTable = Table()
|
||||
statsTable.defaults().pad(8f, 3f, 3f, 3f)
|
||||
|
||||
addActor(getOverviewAndSupplyButton())
|
||||
fun addStat(label: Label, icon: String, isLast: Boolean = false, screenFactory: ()->BaseScreen) {
|
||||
val image = ImageGetter.getStatIcon(icon)
|
||||
val action = {
|
||||
worldScreen.game.setScreen(screenFactory())
|
||||
}
|
||||
label.onClick(action)
|
||||
image.onClick(action)
|
||||
statsTable.add(label)
|
||||
statsTable.add(image).padBottom(6f).size(20f).apply {
|
||||
if (!isLast) padRight(20f)
|
||||
}
|
||||
}
|
||||
fun addStat(label: Label, icon: String, overviewPage: String, isLast: Boolean = false) =
|
||||
addStat(label, icon, isLast) { EmpireOverviewScreen(worldScreen.selectedCiv, overviewPage) }
|
||||
|
||||
addStat(goldLabel, "Gold", "Stats")
|
||||
addStat(scienceLabel, "Science") { TechPickerScreen(worldScreen.selectedCiv) }
|
||||
|
||||
statsTable.add(happinessImage).padBottom(6f).size(20f)
|
||||
statsTable.add(happinessLabel).padRight(20f)
|
||||
val invokeResourcesPage = {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Resources"))
|
||||
}
|
||||
happinessImage.onClick(invokeResourcesPage)
|
||||
happinessLabel.onClick(invokeResourcesPage)
|
||||
|
||||
addStat(cultureLabel, "Culture") { PolicyPickerScreen(worldScreen, worldScreen.selectedCiv) }
|
||||
if (worldScreen.gameInfo.isReligionEnabled()) {
|
||||
addStat(faithLabel, "Faith", "Religion", isLast = true)
|
||||
} else {
|
||||
statsTable.add("Religion: Off".toLabel())
|
||||
}
|
||||
|
||||
statsTable.pack()
|
||||
return statsTable
|
||||
}
|
||||
|
||||
private fun getResourceTable(): Table {
|
||||
// Since cells with invisible actors still occupy the full actor dimensions, we only prepare
|
||||
// the future contents for resourcesWrapper here, they're added to the Table in updateResourcesTable
|
||||
val resourceTable = Table()
|
||||
resourceTable.defaults().pad(5f)
|
||||
resourcesWrapper.defaults().pad(5f, 5f, 10f, 5f)
|
||||
resourcesWrapper.touchable = Touchable.enabled
|
||||
|
||||
turnsLabel.onClick {
|
||||
if (worldScreen.selectedCiv.isLongCountDisplay()) {
|
||||
val gameInfo = worldScreen.selectedCiv.gameInfo
|
||||
@ -77,169 +145,171 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
worldScreen.game.setScreen(VictoryScreen(worldScreen))
|
||||
}
|
||||
}
|
||||
resourceTable.add(turnsLabel).padRight(20f)
|
||||
val revealedStrategicResources = worldScreen.gameInfo.ruleSet.tileResources.values
|
||||
.filter { it.resourceType == ResourceType.Strategic } // && currentPlayerCivInfo.tech.isResearched(it.revealedBy!!) }
|
||||
for (resource in revealedStrategicResources) {
|
||||
val resourceImage = ImageGetter.getResourceImage(resource.name, 20f)
|
||||
resourceImages[resource.name] = resourceImage
|
||||
resourceTable.add(resourceImage).padRight(0f)
|
||||
val resourceLabel = "0".toLabel()
|
||||
resourceLabels[resource.name] = resourceLabel
|
||||
resourceTable.add(resourceLabel)
|
||||
val invokeResourcesPage = {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Resources"))
|
||||
}
|
||||
resourceLabel.onClick(invokeResourcesPage)
|
||||
resourceImage.onClick(invokeResourcesPage)
|
||||
resourcesWrapper.onClick {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Resources"))
|
||||
}
|
||||
resourceTable.pack()
|
||||
|
||||
val strategicResources = worldScreen.gameInfo.ruleSet.tileResources.values
|
||||
.filter { it.resourceType == ResourceType.Strategic }
|
||||
for (resource in strategicResources) {
|
||||
val resourceImage = ImageGetter.getResourceImage(resource.name, 20f)
|
||||
val resourceLabel = "0".toLabel()
|
||||
resourceActors += ResourceActors(resource, resourceLabel, resourceImage)
|
||||
}
|
||||
|
||||
// in case the icons are configured higher than a label, we add a dummy - height will be measured once before it's updated
|
||||
resourcesWrapper.add(resourceActors[0].icon)
|
||||
resourceTable.add(turnsLabel).pad(5f, 5f, 10f, 5f)
|
||||
resourceTable.add(resourcesWrapper)
|
||||
return resourceTable
|
||||
}
|
||||
|
||||
private fun getStatsTable(): Table {
|
||||
val statsTable = Table()
|
||||
statsTable.defaults().pad(3f)//.align(Align.top)
|
||||
private class OverviewAndSupplyTable(worldScreen: WorldScreen) : Table(BaseScreen.skin) {
|
||||
val unitSupplyImage = ImageGetter.getImage("OtherIcons/ExclamationMark")
|
||||
.apply { color = Color.FIREBRICK }
|
||||
val unitSupplyCell: Cell<Actor?>
|
||||
|
||||
statsTable.add(goldLabel)
|
||||
val goldImage = ImageGetter.getStatIcon("Gold")
|
||||
statsTable.add(goldImage).padRight(20f).padBottom(6f).size(20f)
|
||||
val invokeStatsPage = {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Stats"))
|
||||
}
|
||||
goldLabel.onClick(invokeStatsPage)
|
||||
goldImage.onClick(invokeStatsPage)
|
||||
|
||||
statsTable.add(scienceLabel) //.apply { setAlignment(Align.center) }).align(Align.top)
|
||||
val scienceImage = ImageGetter.getStatIcon("Science")
|
||||
statsTable.add(scienceImage).padRight(20f).padBottom(6f).size(20f)
|
||||
val invokeTechScreen = {
|
||||
worldScreen.game.setScreen(TechPickerScreen(worldScreen.selectedCiv))
|
||||
}
|
||||
scienceLabel.onClick(invokeTechScreen)
|
||||
scienceImage.onClick(invokeTechScreen)
|
||||
|
||||
statsTable.add(happinessImage).padBottom(6f).size(20f)
|
||||
statsTable.add(happinessLabel).padRight(20f)
|
||||
val invokeResourcesPage = {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Resources"))
|
||||
}
|
||||
happinessImage.onClick(invokeResourcesPage)
|
||||
happinessLabel.onClick(invokeResourcesPage)
|
||||
|
||||
statsTable.add(cultureLabel)
|
||||
val cultureImage = ImageGetter.getStatIcon("Culture")
|
||||
statsTable.add(cultureImage).padBottom(6f).size(20f)
|
||||
val invokePoliciesPage = {
|
||||
worldScreen.game.setScreen(PolicyPickerScreen(worldScreen, worldScreen.selectedCiv))
|
||||
}
|
||||
cultureLabel.onClick(invokePoliciesPage)
|
||||
cultureImage.onClick(invokePoliciesPage)
|
||||
|
||||
if(worldScreen.gameInfo.isReligionEnabled()) {
|
||||
statsTable.add(faithLabel).padLeft(20f)
|
||||
val faithImage = ImageGetter.getStatIcon("Faith")
|
||||
statsTable.add(faithImage).padBottom(6f).size(20f)
|
||||
|
||||
val invokeFaithOverview = {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Religion"))
|
||||
init {
|
||||
unitSupplyImage.onClick {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Units"))
|
||||
}
|
||||
|
||||
faithLabel.onClick(invokeFaithOverview)
|
||||
faithImage.onClick(invokeFaithOverview)
|
||||
} else {
|
||||
statsTable.add("Religion: Off".toLabel()).padLeft(20f)
|
||||
|
||||
val overviewButton = "Overview".toTextButton()
|
||||
overviewButton.addTooltip('e')
|
||||
overviewButton.onClick { worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv)) }
|
||||
|
||||
unitSupplyCell = add()
|
||||
add(overviewButton).pad(10f)
|
||||
pack()
|
||||
}
|
||||
|
||||
statsTable.pack()
|
||||
statsTable.width = worldScreen.stage.width - 20
|
||||
return statsTable
|
||||
fun update(worldScreen: WorldScreen) {
|
||||
val newVisible = worldScreen.selectedCiv.stats().getUnitSupplyDeficit() > 0
|
||||
if (newVisible == unitSupplyCell.hasActor()) return
|
||||
if (newVisible) unitSupplyCell.setActor(unitSupplyImage)
|
||||
.size(50f).padLeft(10f)
|
||||
else unitSupplyCell.setActor(null).size(0f).pad(0f)
|
||||
invalidate()
|
||||
pack()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMenuButton(): Image {
|
||||
val menuButton = ImageGetter.getImage("OtherIcons/MenuIcon")
|
||||
.apply { setSize(50f, 50f) }
|
||||
menuButton.color = Color.WHITE
|
||||
menuButton.onClick {
|
||||
val worldScreenMenuPopup = worldScreen.popups.firstOrNull { it is WorldScreenMenuPopup }
|
||||
if(worldScreenMenuPopup!=null)
|
||||
worldScreenMenuPopup.close()
|
||||
else WorldScreenMenuPopup(worldScreen).open(force = true)
|
||||
private class SelectedCivilizationTable(worldScreen: WorldScreen) : Table(BaseScreen.skin) {
|
||||
private var selectedCiv = ""
|
||||
private val selectedCivLabel = "".toLabel()
|
||||
private val selectedCivIconHolder = Container<Actor>()
|
||||
private val menuButton = ImageGetter.getImage("OtherIcons/MenuIcon")
|
||||
|
||||
init {
|
||||
left()
|
||||
defaults().pad(10f)
|
||||
|
||||
menuButton.color = Color.WHITE
|
||||
menuButton.onClick {
|
||||
val worldScreenMenuPopup = worldScreen.popups.firstOrNull { it is WorldScreenMenuPopup }
|
||||
if (worldScreenMenuPopup != null) worldScreenMenuPopup.close()
|
||||
else WorldScreenMenuPopup(worldScreen).open(force = true)
|
||||
}
|
||||
|
||||
selectedCivLabel.setFontSize(25)
|
||||
selectedCivLabel.onClick {
|
||||
val civilopediaScreen = CivilopediaScreen(
|
||||
worldScreen.selectedCiv.gameInfo.ruleSet,
|
||||
worldScreen,
|
||||
CivilopediaCategories.Nation,
|
||||
worldScreen.selectedCiv.civName
|
||||
)
|
||||
worldScreen.game.setScreen(civilopediaScreen)
|
||||
}
|
||||
|
||||
selectedCivIconHolder.onClick {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv))
|
||||
}
|
||||
|
||||
add(menuButton).size(50f).padRight(0f)
|
||||
add(selectedCivLabel).padRight(0f)
|
||||
add(selectedCivIconHolder).size(35f)
|
||||
pack()
|
||||
}
|
||||
|
||||
fun update(worldScreen: WorldScreen) {
|
||||
val newCiv = worldScreen.selectedCiv.civName
|
||||
if (this.selectedCiv == newCiv) return
|
||||
this.selectedCiv = newCiv
|
||||
|
||||
selectedCivLabel.setText(newCiv.tr())
|
||||
val nation = worldScreen.gameInfo.ruleSet.nations[worldScreen.selectedCiv.civName]!!
|
||||
val selectedCivIcon = ImageGetter.getNationIndicator(nation, 35f)
|
||||
selectedCivIconHolder.actor = selectedCivIcon
|
||||
invalidate()
|
||||
pack()
|
||||
}
|
||||
menuButton.centerY(this)
|
||||
menuButton.x = menuButton.y
|
||||
return menuButton
|
||||
}
|
||||
|
||||
private fun getOverviewAndSupplyButton(): Table {
|
||||
val rightTable = Table(BaseScreen.skin).apply{ defaults().pad(10f) }
|
||||
private fun layoutButtons() {
|
||||
removeActor(selectedCivTable)
|
||||
removeActor(overviewButton)
|
||||
validate()
|
||||
|
||||
unitSupplyImage.onClick {
|
||||
worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv, "Units"))
|
||||
}
|
||||
unitSupplyImage.isVisible = worldScreen.selectedCiv.stats().getUnitSupplyDeficit() > 0
|
||||
val statsWidth = statsTable.minWidth
|
||||
val resourceWidth = resourceTable.minWidth
|
||||
val overviewWidth = overviewButton.minWidth
|
||||
val selectedCivWidth = selectedCivTable.minWidth
|
||||
val leftRightNeeded = max(selectedCivWidth, overviewWidth)
|
||||
val statsRowHeight = getRowHeight(0)
|
||||
val baseHeight = statsRowHeight + getRowHeight(1)
|
||||
|
||||
val overviewButton = "Overview".toTextButton()
|
||||
overviewButton.addTooltip('e')
|
||||
overviewButton.onClick { worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv)) }
|
||||
|
||||
rightTable.add(unitSupplyImage).size(50f)
|
||||
rightTable.add(overviewButton)
|
||||
|
||||
rightTable.pack()
|
||||
rightTable.centerY(this)
|
||||
rightTable.x = worldScreen.stage.width - rightTable.width - 10
|
||||
|
||||
return rightTable
|
||||
}
|
||||
|
||||
private fun getSelectedCivilizationTable(): Table {
|
||||
val selectedCivTable = Table()
|
||||
selectedCivTable.centerY(this)
|
||||
selectedCivTable.left()
|
||||
selectedCivTable.x = getMenuButton().width + 20f
|
||||
|
||||
selectedCivLabel.setFontSize(25)
|
||||
|
||||
selectedCivLabel.onClick {
|
||||
val civilopeidaScreen = CivilopediaScreen(
|
||||
worldScreen.selectedCiv.gameInfo.ruleSet,
|
||||
worldScreen,
|
||||
CivilopediaCategories.Nation,
|
||||
worldScreen.selectedCiv.civName
|
||||
)
|
||||
worldScreen.game.setScreen(civilopeidaScreen)
|
||||
// Check whether it gets cramped on narrow aspect ratios
|
||||
val fillerHeight: Float // Height of the background filler cells
|
||||
val buttonY: Float // Vertical center of Civ+Overview buttons relative to this.y
|
||||
when {
|
||||
leftRightNeeded * 2f > stage.width - resourceWidth -> {
|
||||
// Need to shift buttons down to below both stats and resources
|
||||
fillerHeight = baseHeight
|
||||
buttonY = overviewButton.minHeight / 2f
|
||||
}
|
||||
leftRightNeeded * 2f > stage.width - statsWidth -> {
|
||||
// Shifting buttons down to below stats row is enough
|
||||
fillerHeight = statsRowHeight
|
||||
buttonY = overviewButton.minHeight / 2f
|
||||
}
|
||||
else -> {
|
||||
// Enough space to keep buttons to the left and right of stats and resources
|
||||
fillerHeight = 0f
|
||||
buttonY = baseHeight / 2f
|
||||
}
|
||||
}
|
||||
|
||||
val nation = worldScreen.gameInfo.ruleSet.nations[worldScreen.selectedCiv.civName]!!
|
||||
val selectedCivIcon = ImageGetter.getNationIndicator(nation, 35f)
|
||||
selectedCivIconHolder.actor = selectedCivIcon
|
||||
selectedCivIconHolder.onClick { worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv)) }
|
||||
val leftFillerWidth = if (fillerHeight > 0f) selectedCivWidth else 0f
|
||||
val rightFillerWidth = if (fillerHeight > 0f) overviewWidth else 0f
|
||||
if (leftFillerCell.minHeight != fillerHeight
|
||||
|| leftFillerCell.minWidth != leftFillerWidth
|
||||
|| rightFillerCell.minWidth != rightFillerWidth) {
|
||||
// Gdx fail: containing Table isn't invalidated when setting Cell size
|
||||
leftFillerCell.width(leftFillerWidth).height(fillerHeight)
|
||||
rightFillerCell.width(rightFillerWidth).height(fillerHeight)
|
||||
invalidate() // Without this all attempts to get a recalculated height are doomed
|
||||
pack() // neither validate nor layout will include the new row height in height
|
||||
}
|
||||
|
||||
selectedCivTable.add(selectedCivLabel).padRight(10f)
|
||||
selectedCivTable.add(selectedCivIconHolder)
|
||||
return selectedCivTable
|
||||
width = stage.width
|
||||
setPosition(0f, stage.height, Align.topLeft)
|
||||
|
||||
selectedCivTable.setPosition(1f, buttonY, Align.left)
|
||||
overviewButton.setPosition(stage.width, buttonY, Align.right)
|
||||
addActor(selectedCivTable) // needs to be after pack
|
||||
addActor(overviewButton)
|
||||
}
|
||||
|
||||
internal fun update(civInfo: CivilizationInfo) {
|
||||
val revealedStrategicResources = civInfo.gameInfo.ruleSet.tileResources.values
|
||||
.filter { it.resourceType == ResourceType.Strategic }
|
||||
val civResources = civInfo.getCivResources()
|
||||
for (resource in revealedStrategicResources) {
|
||||
val isRevealed = resource.revealedBy == null || civInfo.tech.isResearched(resource.revealedBy!!)
|
||||
resourceLabels[resource.name]!!.isVisible = isRevealed
|
||||
resourceImages[resource.name]!!.isVisible = isRevealed
|
||||
val amountText = (civResources.get(resource, "All")?.amount ?: 0).toString()
|
||||
resourceLabels[resource.name]!!.setText(amountText)
|
||||
}
|
||||
|
||||
val year = civInfo.gameInfo.getYear()
|
||||
val yearText = if (civInfo.isLongCountDisplay()) MayaCalendar.yearToMayaDate(year)
|
||||
else "[" + abs(year) + "] " + (if (year < 0) "BC" else "AD")
|
||||
turnsLabel.setText(Fonts.turn + "" + civInfo.gameInfo.turns + " | " + yearText.tr())
|
||||
updateStatsTable(civInfo)
|
||||
updateResourcesTable(civInfo)
|
||||
selectedCivTable.update(worldScreen)
|
||||
overviewButton.update(worldScreen)
|
||||
layoutButtons()
|
||||
}
|
||||
|
||||
private fun updateStatsTable(civInfo: CivilizationInfo) {
|
||||
val nextTurnStats = civInfo.statsForNextTurn
|
||||
val goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + nextTurnStats.gold.roundToInt() + ")"
|
||||
goldLabel.setText(civInfo.gold.toString() + goldPerTurn)
|
||||
@ -260,19 +330,28 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
|
||||
cultureLabel.setText(getCultureText(civInfo, nextTurnStats))
|
||||
faithLabel.setText(civInfo.religionManager.storedFaith.toString() + "(+" + nextTurnStats.faith.roundToInt() + ")")
|
||||
|
||||
updateSelectedCivTable()
|
||||
}
|
||||
|
||||
private fun updateSelectedCivTable() {
|
||||
if (selectedCivLabel.text.toString() == worldScreen.selectedCiv.civName.tr()) return
|
||||
private fun updateResourcesTable(civInfo: CivilizationInfo) {
|
||||
val year = civInfo.gameInfo.getYear()
|
||||
val yearText = if (civInfo.isLongCountDisplay()) MayaCalendar.yearToMayaDate(year)
|
||||
else "[" + abs(year) + "] " + (if (year < 0) "BC" else "AD")
|
||||
turnsLabel.setText(Fonts.turn + "" + civInfo.gameInfo.turns + " | " + yearText.tr())
|
||||
|
||||
selectedCivLabel.setText(worldScreen.selectedCiv.civName.tr())
|
||||
resourcesWrapper.clearChildren()
|
||||
var firstPadLeft = 20f // We want a distance from the turns entry to the first resource, but only if any resource is displayed
|
||||
val civResources = civInfo.getCivResources()
|
||||
for ((resource, label, icon) in resourceActors) {
|
||||
if (resource.revealedBy != null && !civInfo.tech.isResearched(resource.revealedBy!!))
|
||||
continue
|
||||
resourcesWrapper.add(icon).padLeft(firstPadLeft).padRight(0f)
|
||||
firstPadLeft = 5f
|
||||
val amount = civResources.get(resource, "All")?.amount ?: 0
|
||||
label.setText(amount)
|
||||
resourcesWrapper.add(label).padTop(8f) // digits don't have descenders, so push them down a little
|
||||
}
|
||||
|
||||
val nation = worldScreen.gameInfo.ruleSet.nations[worldScreen.selectedCiv.civName]!!
|
||||
val selectedCivIcon = ImageGetter.getNationIndicator(nation, 35f)
|
||||
selectedCivIconHolder.actor = selectedCivIcon
|
||||
selectedCivIconHolder.onClick { worldScreen.game.setScreen(EmpireOverviewScreen(worldScreen.selectedCiv)) }
|
||||
resourceTable.pack()
|
||||
}
|
||||
|
||||
private fun getCultureText(civInfo: CivilizationInfo, nextTurnStats: Stats): String {
|
||||
@ -288,7 +367,7 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
private fun getHappinessText(civInfo: CivilizationInfo): String {
|
||||
var happinessText = civInfo.getHappiness().toString()
|
||||
val goldenAges = civInfo.goldenAges
|
||||
happinessText +=
|
||||
happinessText +=
|
||||
if (goldenAges.isGoldenAge())
|
||||
" {GOLDEN AGE}(${goldenAges.turnsLeftForCurrentGoldenAge})".tr()
|
||||
else
|
||||
|
Reference in New Issue
Block a user