Memory performance improvements!

- .tr() no longer tries to regex replace every entry in the dictionary - instead, we save the shortened version of each translation in its place!
 - when counting language completion percentage, we only count the numbers, not save them to a list!
 - label coloring and size now baked-in to .toLabel(). meaning we don't need to reassign styles and rebuild font caches!
This commit is contained in:
Yair Morgenstern 2019-10-31 12:01:23 +02:00
parent c39c1a4c15
commit de30382536
31 changed files with 161 additions and 138 deletions

View file

@ -4,19 +4,27 @@ import com.badlogic.gdx.utils.JsonReader
import com.unciv.UnCivGame
import java.util.*
class Translations : HashMap<String, HashMap<String, String>>(){
class TranslationEntry(val entry:String) : HashMap<String, String>(){
/** For memory performance on .tr(), which was atrociously memory-expensive */
var entryWithShortenedSquareBrackets =""
}
class Translations : HashMap<String, TranslationEntry>(){
fun add(json:String){
val jsonValue = JsonReader().parse(json)!!
var currentEntry = jsonValue.child
while(currentEntry!=null){
val entryMap = HashMap<String,String>()
this[currentEntry.name!!]=entryMap
val currentEntryName = currentEntry.name!!
val translationEntry = TranslationEntry(currentEntryName)
this[currentEntryName]=translationEntry
if(currentEntryName.contains('['))
translationEntry.entryWithShortenedSquareBrackets=currentEntryName.replace(squareBraceRegex,"[]")
var currentLanguage = currentEntry.child
while(currentLanguage!=null){
entryMap[currentLanguage.name!!]=currentLanguage.asString()
translationEntry[currentLanguage.name!!]=currentLanguage.asString()
currentLanguage = currentLanguage.next
}
currentEntry = currentEntry.next
@ -35,7 +43,7 @@ class Translations : HashMap<String, HashMap<String, String>>(){
fun getLanguages(): List<String> {
val toReturn = mutableListOf<String>()
toReturn.addAll(values.flatMap { it.keys }.distinct())
toReturn.remove("Japanese")
toReturn.remove("Japanese") // These were for tests but were never actually seriously translated
toReturn.remove("Thai")
return toReturn
}
@ -56,7 +64,12 @@ class Translations : HashMap<String, HashMap<String, String>>(){
}
val squareBraceRegex = Regex("\\[(.*?)\\]") // we don't need to allocate different memory for this every time we .tr()
val eitherSquareBraceRegex=Regex("\\[|\\]")
fun String.tr(): String {
// THIS IS INCREDIBLY INEFFICIENT and causes loads of memory problems!
if(contains("[")){ // Placeholders!
/**
* I'm SURE there's an easier way to do this but I can't think of it =\
@ -64,7 +77,7 @@ fun String.tr(): String {
* Well, not all languages are like English. So say I want to say "work on Library has completed in Akkad",
* but in a completely different language like Japanese or German,
* It could come out "Akkad hast die worken onner Library gerfinishen" or whatever,
* basically, the order of the words in the sentance is not guaranteed.
* basically, the order of the words in the sentence is not guaranteed.
* So to translate this, I give a sentence like "work on [building] has completed in [city]"
* and the german can put those placeholders where he wants, so "[city] hast die worken onner [building] gerfinishen"
* The string on which we call tr() will look like "work on [library] has completed in [Akkad]"
@ -72,32 +85,32 @@ fun String.tr(): String {
*/
val translationStringWithSquareBracketsOnly = replace(squareBraceRegex,"[]")
val translationStringUntilFirstSquareBracket = substringBefore('[')
val englishTranslationPlaceholder = GameBasics.Translations.keys
.firstOrNull {
// this is to filter out obvious non-candidates, which is most of them, before we start using the "heavy lifting" of the regex replacement
it.startsWith(translationStringUntilFirstSquareBracket)
&& it.replace(squareBraceRegex,"[]") == translationStringWithSquareBracketsOnly }
if(englishTranslationPlaceholder==null ||
!GameBasics.Translations[englishTranslationPlaceholder]!!.containsKey(UnCivGame.Current.settings.language)){
// Translation placeholder doesn't exist for this language
return this.replace("[","").replace("]","")
val translationEntry = GameBasics.Translations.values
.firstOrNull { translationStringWithSquareBracketsOnly == it.entryWithShortenedSquareBrackets }
if(translationEntry==null ||
!translationEntry.containsKey(UnCivGame.Current.settings.language)){
// Translation placeholder doesn't exist for this language, default to English
return this.replace(eitherSquareBraceRegex,"")
}
val termsInMessage = squareBraceRegex.findAll(this).map { it.groups[1]!!.value }.toMutableList()
val termsInTranslationPlaceholder = squareBraceRegex.findAll(englishTranslationPlaceholder).map { it.value }.toMutableList()
val termsInMessage = squareBraceRegex.findAll(this).map { it.groups[1]!!.value }.toList()
val termsInTranslationPlaceholder = squareBraceRegex.findAll(translationEntry.entry).map { it.value }.toList()
if(termsInMessage.size!=termsInTranslationPlaceholder.size)
throw Exception("Message $this has a different number of terms than the placeholder $englishTranslationPlaceholder!")
throw Exception("Message $this has a different number of terms than the placeholder $translationEntry!")
var languageSpecificPlaceholder = GameBasics.Translations[englishTranslationPlaceholder]!![UnCivGame.Current.settings.language]!!
for(i in 0 until termsInMessage.size){
var languageSpecificPlaceholder = translationEntry[UnCivGame.Current.settings.language]!!
for(i in termsInMessage.indices){
languageSpecificPlaceholder = languageSpecificPlaceholder.replace(termsInTranslationPlaceholder[i], termsInMessage[i].tr())
}
return languageSpecificPlaceholder.tr()
}
if(contains("{")){ // sentence
return Regex("\\{(.*?)\\}").replace(this) { it.groups[1]!!.value.tr() }
}
val translation = GameBasics.Translations.get(this, UnCivGame.Current.settings.language) // single word
return translation
}

View file

@ -123,11 +123,11 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
val table = Table()
table.defaults().pad(10f)
table.background = ImageGetter.getBackground(civ.nation.getOuterColor())
table.add(civ.civName.toLabel().setFontColor(civ.nation.getInnerColor())).row()
table.add(civ.civName.toLabel(civ.nation.getInnerColor())).row()
table.addSeparator()
for(offer in offersList){
val offerText = offer.getOfferText()
table.add(offerText.toLabel().setFontColor(civ.nation.getInnerColor())).row()
table.add(offerText.toLabel(civ.nation.getInnerColor())).row()
}
for(i in 1..numberOfOtherSidesOffers - offersList.size)
table.add("".toLabel()).row() // we want both sides of the general table to have the same number of rows
@ -138,7 +138,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
private fun getHappinessTable(): Table {
val happinessTable = Table(skin)
happinessTable.defaults().pad(5f)
happinessTable.add("Happiness".toLabel().setFontSize(24)).colspan(2).row()
happinessTable.add("Happiness".toLabel(fontSize = 24)).colspan(2).row()
happinessTable.addSeparator()
val happinessBreakdown = currentPlayerCivInfo.stats().getHappinessBreakdown()
@ -156,7 +156,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
private fun getGoldTable(): Table {
val goldTable = Table(skin)
goldTable.defaults().pad(5f)
goldTable.add("Gold".toLabel().setFontSize(24)).colspan(2).row()
goldTable.add("Gold".toLabel(fontSize = 24)).colspan(2).row()
goldTable.addSeparator()
var total=0f
for (entry in currentPlayerCivInfo.stats().getStatMapForNextTurn()) {
@ -175,7 +175,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
private fun getScienceTable(): Table {
val scienceTable = Table(skin)
scienceTable.defaults().pad(5f)
scienceTable.add("Science".toLabel().setFontSize(24)).colspan(2).row()
scienceTable.add("Science".toLabel(fontSize = 24)).colspan(2).row()
scienceTable.addSeparator()
val scienceStats = currentPlayerCivInfo.stats().getStatMapForNextTurn()
.filter { it.value.science!=0f }
@ -198,7 +198,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
val pointsToGreatPerson = currentPlayerCivInfo.greatPeople.pointsForNextGreatPerson
greatPeopleTable.defaults().pad(5f)
greatPeopleTable.add("Great person points".toLabel().setFontSize(24)).colspan(3).row()
greatPeopleTable.add("Great person points".toLabel(fontSize = 24)).colspan(3).row()
greatPeopleTable.addSeparator()
greatPeopleTable.add()
greatPeopleTable.add("Current points".tr())
@ -227,7 +227,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
val cityInfoTableIcons = Table(skin)
cityInfoTableIcons.defaults().pad(padding).align(Align.center)
cityInfoTableIcons.add("Cities".toLabel().setFontSize(24)).colspan(8).align(Align.center).row()
cityInfoTableIcons.add("Cities".toLabel(fontSize = 24)).colspan(8).align(Align.center).row()
cityInfoTableIcons.add()
cityInfoTableIcons.add(ImageGetter.getStatIcon("Population")).size(iconSize)
cityInfoTableIcons.add(ImageGetter.getStatIcon("Food")).size(iconSize)
@ -406,23 +406,25 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
val civGroup = Table()
val civGroupBackground = ImageGetter.getDrawable("OtherIcons/civTableBackground")
val civNameText = civ.civName.tr()+afterCivNameText
val label = civNameText.toLabel()
label.setAlignment(Align.center)
var labelText = civ.civName.tr()+afterCivNameText
var labelColor=Color.WHITE
if (civ.isDefeated()) {
civGroup.add(ImageGetter.getImage("OtherIcons/DisbandUnit")).size(30f)
civGroup.background = civGroupBackground.tint(Color.LIGHT_GRAY)
label.setFontColor(Color.BLACK)
labelColor = Color.BLACK
} else if (currentPlayer==civ || UnCivGame.Current.viewEntireMapForDebug || currentPlayer.knows(civ)) {
civGroup.add(ImageGetter.getNationIndicator(civ.nation, 30f))
civGroup.background = civGroupBackground.tint(civ.nation.getOuterColor())
label.setFontColor(civ.nation.getInnerColor())
labelColor = civ.nation.getInnerColor()
} else {
civGroup.background = civGroupBackground.tint(Color.DARK_GRAY)
label.setText("???")
labelText = "???"
}
val label = labelText.toLabel(labelColor)
label.setAlignment(Align.center)
civGroup.add(label).pad(10f)
civGroup.pack()
return civGroup

View file

@ -43,7 +43,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
val width = cityScreen.stage.width/4 - 2*pad
val showHideTableWrapper = Table()
showHideTableWrapper.add(showHideTable).width(width)
titleTable.add(str.toLabel().setFontSize(24))
titleTable.add(str.toLabel(fontSize = 24))
titleTable.onClick {
if(showHideTableWrapper.hasChildren()) showHideTableWrapper.clear()
else showHideTableWrapper.add(showHideTable).width(width)
@ -147,7 +147,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
val statValuesTable = Table().apply { defaults().pad(2f) }
addCategory(stat.name, statValuesTable)
statValuesTable.add("Base values".toLabel().setFontSize(24)).colspan(2).row()
statValuesTable.add("Base values".toLabel(fontSize= 24)).colspan(2).row()
var sumOfAllBaseValues = 0f
for(entry in relevantBaseStats) {
val specificStatValue = entry.value.get(stat)
@ -161,7 +161,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
val relevantBonuses = cityStats.statPercentBonusList.filter { it.value.get(stat)!=0f }
if(relevantBonuses.isNotEmpty()) {
statValuesTable.add("Bonuses".toLabel().setFontSize(24)).colspan(2).padTop(20f).row()
statValuesTable.add("Bonuses".toLabel(fontSize = 24)).colspan(2).padTop(20f).row()
var sumOfBonuses = 0f
for (entry in relevantBonuses) {
val specificStatValue = entry.value.get(stat)
@ -179,7 +179,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
}
statValuesTable.add("Final".toLabel().setFontSize(24)).colspan(2).padTop(20f).row()
statValuesTable.add("Final".toLabel(fontSize = 24)).colspan(2).padTop(20f).row()
var finalTotal = 0f
for (entry in cityStats.finalStatList) {
val specificStatValue = entry.value.get(stat)

View file

@ -4,10 +4,7 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.utils.Align
import com.unciv.models.gamebasics.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.setFontSize
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.PopupTable
class CityScreenCityPickerTable(val cityScreen: CityScreen) : Table(){
@ -49,8 +46,7 @@ class CityScreenCityPickerTable(val cityScreen: CityScreen) : Table(){
cityNameTable.add(resistanceImage).size(20f).padRight(5f)
}
val currentCityLabel = Label(city.name, CameraStageBaseScreen.skin)
currentCityLabel.setFontSize(30)
val currentCityLabel = city.name.toLabel(fontSize = 30)
currentCityLabel.onClick {
val editCityNamePopup = PopupTable(cityScreen)
val textArea = TextField(city.name, CameraStageBaseScreen.skin)

View file

@ -46,7 +46,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
pickProductionButton.background = ImageGetter.getBackground(Color.BLACK)
pickProductionButton.add(ImageGetter.getConstructionImage(construction).surroundWithCircle(40f)).padRight(10f)
pickProductionButton.add(buttonText.toLabel().setFontColor(Color.WHITE))
pickProductionButton.add(buttonText.toLabel())
if(rejectionReason=="" && UnCivGame.Current.worldScreen.isPlayersTurn) { // no rejection reason means we can build it!
pickProductionButton.onClick {
@ -63,7 +63,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
else {
pickProductionButton.color = Color.GRAY
pickProductionButton.row()
pickProductionButton.add(rejectionReason.toLabel().setFontColor(Color.RED)).colspan(pickProductionButton.columns)
pickProductionButton.add(rejectionReason.toLabel(Color.RED)).colspan(pickProductionButton.columns)
}
if(construction==cityScreen.city.cityConstructions.currentConstruction)
@ -75,7 +75,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if(list.isEmpty()) return
val titleTable = Table()
titleTable.background = ImageGetter.getBackground(ImageGetter.getBlue())
titleTable.add(title.toLabel().setFontSize(24))
titleTable.add(title.toLabel(fontSize = 24))
addSeparator()
add(titleTable).fill().row()
@ -185,7 +185,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
.pad(5f)
val buildingText = city.cityConstructions.getCityProductionTextForCityButton()
currentConstructionTable.add(buildingText.toLabel().setFontColor(Color.WHITE)).row()
currentConstructionTable.add(buildingText.toLabel()).row()
}
else{
currentConstructionTable.add() // no icon

View file

@ -5,7 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.setFontSize
import com.unciv.ui.utils.toLabel
class ExpanderTab(private val title:String,skin: Skin): Table(skin){
private val toggle = Table(skin) // the show/hide toggler
@ -17,7 +17,7 @@ class ExpanderTab(private val title:String,skin: Skin): Table(skin){
toggle.defaults().pad(10f)
toggle.touchable= Touchable.enabled
toggle.background(ImageGetter.getBackground(ImageGetter.getBlue()))
toggle.add("+ $title").apply { actor.setFontSize(24) }
toggle.add("+ $title".toLabel(fontSize = 24))
toggle.onClick {
if(isOpen) close()
else open()
@ -30,7 +30,7 @@ class ExpanderTab(private val title:String,skin: Skin): Table(skin){
fun close(){
if(!isOpen) return
toggle.clearChildren()
toggle.add("- $title").apply { actor.setFontSize(24) }
toggle.add("- $title".toLabel(fontSize = 24))
tab.clear()
isOpen=false
}
@ -38,7 +38,7 @@ class ExpanderTab(private val title:String,skin: Skin): Table(skin){
fun open(){
if(isOpen) return
toggle.clearChildren()
toggle.add("+ $title").apply { actor.setFontSize(24) }
toggle.add("+ $title".toLabel(fontSize = 24))
tab.add(innerTable)
isOpen=true
}

View file

@ -7,7 +7,10 @@ import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.Nation
import com.unciv.models.gamebasics.Translations
import com.unciv.models.gamebasics.tr
import com.unciv.ui.utils.*
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
class NationTable(val nation: Nation, width:Float, onClick:()->Unit)
: Table(CameraStageBaseScreen.skin) {
@ -20,13 +23,10 @@ class NationTable(val nation: Nation, width:Float, onClick:()->Unit)
val titleTable = Table()
titleTable.add(ImageGetter.getNationIndicator(nation, 50f)).pad(10f)
titleTable.add(nation.getLeaderDisplayName().toLabel()
.apply { setFontColor(nation.getInnerColor()); setFontSize(24) })
titleTable.add(nation.getLeaderDisplayName().toLabel(nation.getInnerColor(),24))
innerTable.add(titleTable).row()
innerTable.add(getUniqueLabel(nation)
.apply { setWrap(true);setFontColor(nation.getInnerColor()) })
.width(width)
innerTable.add(getUniqueLabel(nation).apply { setWrap(true) }).width(width)
onClick { onClick() }
touchable = Touchable.enabled
add(innerTable)
@ -44,7 +44,7 @@ class NationTable(val nation: Nation, width:Float, onClick:()->Unit)
addUniqueUnitsText(nation, textList)
addUniqueImprovementsText(nation, textList)
return textList.joinToString("\n").tr().trim().toLabel()
return textList.joinToString("\n").tr().trim().toLabel(nation.getInnerColor())
}
private fun addUniqueBuildingsText(nation: Nation, textList: ArrayList<String>) {

View file

@ -33,8 +33,8 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
for (player in newGameParameters.players)
playerListTable.add(getPlayerTable(player)).pad(10f).row()
if(newGameParameters.players.count() < GameBasics.Nations.values.count { it.isMajorCiv() }) {
playerListTable.add("+".toLabel().setFontSize(30).apply { this.setAlignment(Align.center) }
.setFontColor(Color.BLACK).surroundWithCircle(50f).onClick { newGameParameters.players.add(Player()); update() })
playerListTable.add("+".toLabel(Color.BLACK,30).apply { this.setAlignment(Align.center) }
.surroundWithCircle(50f).onClick { newGameParameters.players.add(Player()); update() })
}
}
@ -62,7 +62,7 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
val playerIdTextfield = TextField(player.playerId, CameraStageBaseScreen.skin)
playerIdTable.add(playerIdTextfield).colspan(2)
val errorLabel = "Not a valid user id!".toLabel().setFontColor(Color.RED)
val errorLabel = "Not a valid user id!".toLabel(Color.RED)
errorLabel.isVisible=false
playerIdTable.add(errorLabel)
@ -103,9 +103,9 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
private fun getNationTable(player: Player): Table {
val nationTable = Table()
val nationImage = if (player.chosenCiv == "Random") "?".toLabel()
.apply { this.setAlignment(Align.center) }.setFontSize(30)
.setFontColor(Color.BLACK).surroundWithCircle(50f)
val nationImage = if (player.chosenCiv == "Random") "?".toLabel(Color.BLACK,30)
.apply { this.setAlignment(Align.center) }
.surroundWithCircle(50f)
else ImageGetter.getNationIndicator(GameBasics.Nations[player.chosenCiv]!!, 50f)
nationTable.add(nationImage)
nationTable.add(player.chosenCiv.toLabel()).pad(20f)

View file

@ -1,6 +1,5 @@
package com.unciv.ui.pickerscreens
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.unciv.UnCivGame
import com.unciv.logic.civilization.GreatPersonManager
@ -9,7 +8,6 @@ import com.unciv.models.gamebasics.tr
import com.unciv.models.gamebasics.unit.BaseUnit
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.setFontColor
import com.unciv.ui.utils.toLabel
class GreatPersonPickerScreen : PickerScreen() {
@ -24,11 +22,11 @@ class GreatPersonPickerScreen : PickerScreen() {
val button = Button(skin)
button.add(ImageGetter.getUnitIcon(unit.name)).size(30f).pad(10f)
button.add(unit.name.toLabel().setFontColor(Color.WHITE)).pad(10f)
button.add(unit.name.toLabel()).pad(10f)
button.pack()
button.onClick {
theChosenOne = unit
var unitDescription=HashSet<String>()
val unitDescription=HashSet<String>()
unit.uniques.forEach { unitDescription.add(it.tr()) }
pick("Get ".tr() +unit.name.tr())
descriptionLabel.setText(unitDescription.joinToString())

View file

@ -58,7 +58,7 @@ class ImprovementPickerScreen(tileInfo: TileInfo, onAccept: ()->Unit) : PickerSc
&& improvement.name!=RoadStatus.Railroad.name && !improvement.name.startsWith("Remove"))
labelText += "\n" + "Replaces [${tileInfo.improvement}]".tr()
group.add(labelText.toLabel().setFontColor(Color.WHITE)).pad(10f)
group.add(labelText.toLabel()).pad(10f)
group.touchable = Touchable.enabled
group.onClick {

View file

@ -51,8 +51,7 @@ class PromotionPickerScreen(val mapUnit: MapUnit) : PickerScreen() {
val group = Table()
group.add(ImageGetter.getPromotionIcon(promotion.name)).size(30f).pad(10f)
group.add(promotion.name.toLabel()
.setFontColor(Color.WHITE)).pad(10f).padRight(20f)
group.add(promotion.name.toLabel()).pad(10f).padRight(20f)
group.touchable = Touchable.enabled
group.onClick {

View file

@ -2,18 +2,17 @@ package com.unciv.ui.pickerscreens
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
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.TechManager
import com.unciv.models.gamebasics.GameBasics
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.setFontColor
import com.unciv.ui.utils.surroundWithCircle
import com.unciv.ui.utils.toLabel
class TechButton(techName:String, val techManager: TechManager, isWorldScreen: Boolean = true) : Table(CameraStageBaseScreen.skin) {
val text= Label("", skin).setFontColor(Color.WHITE).apply { setAlignment(Align.center) }
val text= "".toLabel().apply { setAlignment(Align.center) }
init {
touchable = Touchable.enabled

View file

@ -55,8 +55,8 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, switchfromWorldSc
val erasName = arrayOf("Ancient","Classical","Medieval","Renaissance","Industrial","Modern","Information","Future")
for (i in 0..7) {
val j = if (erasName[i]!="Ancient" && erasName[i]!="Future") 2 else 3
if (i%2==0) topTable.add((erasName[i]+" era").toLabel().setFontColor(Color.WHITE).addBorder(2f, Color.BLUE)).fill().colspan(j)
else topTable.add((erasName[i]+" era").toLabel().setFontColor(Color.WHITE).addBorder(2f, Color.FIREBRICK)).fill().colspan(j)
if (i%2==0) topTable.add((erasName[i]+" era").toLabel().addBorder(2f, Color.BLUE)).fill().colspan(j)
else topTable.add((erasName[i]+" era").toLabel().addBorder(2f, Color.FIREBRICK)).fill().colspan(j)
}
// Create tech table (row by row)

View file

@ -12,7 +12,10 @@ import com.unciv.UnCivGame
import com.unciv.logic.GameSaver
import com.unciv.models.gamebasics.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.*
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
import com.unciv.ui.worldscreen.optionstable.PopupTable
import java.text.SimpleDateFormat
import java.util.*
@ -54,7 +57,7 @@ class LoadGameScreen : PickerScreen() {
private fun getRightSideTable(): Table {
val rightSideTable = Table()
val errorLabel = "".toLabel().setFontColor(Color.RED)
val errorLabel = "".toLabel(Color.RED)
val loadFromClipboardButton = TextButton("Load copied data".tr(), skin)
loadFromClipboardButton.onClick {
try {

View file

@ -40,7 +40,7 @@ class LoadMapScreen(previousMap: TileMap) : PickerScreen(){
val rightSideTable = Table().apply { defaults().pad(10f) }
val loadFromClipboardButton = TextButton("Load copied data".tr(), skin)
val couldNotLoadMapLabel = "Could not load map!".toLabel().setFontColor(Color.RED).apply { isVisible=false }
val couldNotLoadMapLabel = "Could not load map!".toLabel(Color.RED).apply { isVisible=false }
loadFromClipboardButton.onClick {
try {
val clipboardContentsString = Gdx.app.clipboard.contents.trim()

View file

@ -44,7 +44,7 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
}
private fun addAirUnitTable() {
if (!tileGroup.tileInfo.airUnits.isNotEmpty()) return
if (tileGroup.tileInfo.airUnits.isEmpty()) return
val secondarycolor = city.civInfo.nation.getInnerColor()
val airUnitTable = Table().apply { defaults().pad(5f) }
airUnitTable.background = ImageGetter.getDrawable("OtherIcons/civTableBackground")
@ -52,8 +52,7 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
val aircraftImage = ImageGetter.getImage("OtherIcons/Aircraft")
aircraftImage.color = secondarycolor
airUnitTable.add(aircraftImage).size(15f)
airUnitTable.add(tileGroup.tileInfo.airUnits.size.toString().toLabel()
.setFontColor(secondarycolor).setFontSize(14))
airUnitTable.add(tileGroup.tileInfo.airUnits.size.toString().toLabel(secondarycolor,14))
add(airUnitTable).row()
}
@ -128,8 +127,7 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
}
val cityButtonText = city.population.population.toString() + " | " + city.name
val label = cityButtonText.toLabel()
label.setFontColor(secondaryColor)
val label = cityButtonText.toLabel(secondaryColor)
iconTable.add(label).pad(10f) // sufficient horizontal padding
.fillY() // provide full-height clicking area
@ -182,9 +180,7 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
val cityCurrentConstruction = cityConstructions.getCurrentConstruction()
if(cityCurrentConstruction !is SpecialConstruction) {
val turnsToConstruction = cityConstructions.turnsToConstruction(cityCurrentConstruction.name)
val label = turnsToConstruction.toString().toLabel()
label.setFontColor(secondaryColor)
label.setFontSize(14)
val label = turnsToConstruction.toString().toLabel(secondaryColor,14)
label.pack()
group.addActor(label)

View file

@ -93,7 +93,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
val diplomacyTable = Table()
diplomacyTable.defaults().pad(10f)
diplomacyTable.add(otherCiv.getLeaderDisplayName().toLabel().setFontSize(24)).row()
diplomacyTable.add(otherCiv.getLeaderDisplayName().toLabel(fontSize = 24)).row()
diplomacyTable.add(("Type: ".tr() + otherCiv.getCityStateType().toString().tr()).toLabel()).row()
diplomacyTable.add(("Influence: ".tr() + otherCivDiplomacyManager.influence.toInt() + "/30").toLabel()).row()
@ -106,14 +106,16 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
CityStateType.Militaristic -> "Provides land units every 20 turns at [30] Influence".tr()
}
val friendBonusLabel = friendBonusText.toLabel()
diplomacyTable.add(friendBonusLabel).row()
val friendBonusLabelColor:Color
if (otherCivDiplomacyManager.relationshipLevel() >= RelationshipLevel.Friend) {
friendBonusLabel.setFontColor(Color.GREEN)
friendBonusLabelColor = Color.GREEN
val turnsToRelationshipChange = otherCivDiplomacyManager.influence.toInt() - 30 + 1
diplomacyTable.add("Relationship changes in another [$turnsToRelationshipChange] turns".toLabel()).row()
} else
friendBonusLabel.setFontColor(Color.GRAY)
friendBonusLabelColor = Color.GRAY
val friendBonusLabel = friendBonusText.toLabel(friendBonusLabelColor)
diplomacyTable.add(friendBonusLabel).row()
diplomacyTable.addSeparator()
@ -158,7 +160,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
val diplomacyTable = Table()
diplomacyTable.defaults().pad(10f)
diplomacyTable.add(otherCiv.getLeaderDisplayName().toLabel().setFontSize(24)).row()
diplomacyTable.add(otherCiv.getLeaderDisplayName().toLabel(fontSize = 24)).row()
val translatedNation = otherCiv.getTranslatedNation()
if(otherCivDiplomacyManager.relationshipLevel()<=RelationshipLevel.Enemy)
diplomacyTable.add(translatedNation.hateHello.toLabel()).row()
@ -262,7 +264,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
if (modifier.value > 0) text += "+"
text += modifier.value.roundToInt()
val color = if (modifier.value < 0) Color.RED else Color.GREEN
diplomacyModifiersTable.add(text.toLabel().setFontColor(color)).row()
diplomacyModifiersTable.add(text.toLabel(color)).row()
}
return diplomacyModifiersTable
}
@ -300,7 +302,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
else -> Color.RED
}
relationshipTable.add(relationshipText.toLabel().setFontColor(relationshipColor))
relationshipTable.add(relationshipText.toLabel(relationshipColor))
return relationshipTable
}

View file

@ -113,15 +113,6 @@ fun Actor.centerX(parent:Stage){ x = parent.width/2 - width/2 }
fun Actor.centerY(parent:Stage){ y = parent.height/2- height/2}
fun Actor.center(parent:Stage){ centerX(parent); centerY(parent)}
fun Label.setFontColor(color:Color): Label {style=Label.LabelStyle(style).apply { fontColor=color }; return this}
fun Label.setFontSize(size:Int): Label {
style = Label.LabelStyle(style)
style.font = Fonts().getFont(size)
style = style // because we need it to call the SetStyle function. Yuk, I know.
return this // for chaining
}
/** same as [onClick], but sends the [InputEvent] and coordinates along */
fun Actor.onClickEvent(sound: String = "click", function: (event: InputEvent?, x: Float, y: Float) -> Unit) {
@ -208,4 +199,26 @@ fun <T> HashSet<T>.withoutItem(item:T): HashSet<T> {
}
/** also translates */
fun String.toLabel() = Label(this.tr(),CameraStageBaseScreen.skin)
fun String.toLabel() = Label(this.tr(),CameraStageBaseScreen.skin)
// We don't want to use setFontSize and setFontColor because they set the font,
// which means we need to rebuild the font cache which means more memory allocation.
fun String.toLabel(fontColor:Color= Color.WHITE, fontSize:Int=18): Label {
var labelStyle = CameraStageBaseScreen.skin.get(Label.LabelStyle::class.java)
if(fontColor!= Color.WHITE || fontSize!=18) { // if we want the default we don't need to create another style
labelStyle = Label.LabelStyle(labelStyle) // clone this to another
labelStyle.fontColor = fontColor
if (fontSize != 18) labelStyle.font = Fonts().getFont(fontSize)
}
return Label(this.tr(),labelStyle)
}
fun Label.setFontColor(color:Color): Label {style=Label.LabelStyle(style).apply { fontColor=color }; return this}
fun Label.setFontSize(size:Int): Label {
style = Label.LabelStyle(style)
style.font = Fonts().getFont(size)
style = style // because we need it to call the SetStyle function. Yuk, I know.
return this // for chaining
}

View file

@ -60,8 +60,8 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
}
AlertType.CityConquered -> {
val city = worldScreen.gameInfo.civilizations.flatMap { it.cities }.first { it.name == popupAlert.value}
addGoodSizedLabel("What would you like to do with the city?")
.apply { this.actor.setFontSize(24) }.padBottom(20f).row()
addGoodSizedLabel("What would you like to do with the city?",24)
.padBottom(20f).row()
val conqueringCiv = worldScreen.gameInfo.currentPlayerCiv
if (city.foundingCiv != ""

View file

@ -5,7 +5,9 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.logic.civilization.Notification
import com.unciv.ui.utils.*
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
import kotlin.math.min
class NotificationsScroll(internal val worldScreen: WorldScreen) : ScrollPane(null) {
@ -28,7 +30,7 @@ class NotificationsScroll(internal val worldScreen: WorldScreen) : ScrollPane(nu
notificationsTable.clearChildren()
for (notification in notifications.toList()) { // toList to avoid concurrency problems
val label = notification.text.toLabel().setFontColor(Color.BLACK).setFontSize(14)
val label = notification.text.toLabel(Color.BLACK,14)
val listItem = Table()
listItem.add(ImageGetter.getCircle()

View file

@ -4,7 +4,10 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UnCivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.ui.utils.*
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
class PlayerReadyScreen(currentPlayerCiv: CivilizationInfo) : CameraStageBaseScreen(){
init {
@ -12,8 +15,7 @@ class PlayerReadyScreen(currentPlayerCiv: CivilizationInfo) : CameraStageBaseScr
table.touchable= Touchable.enabled
table.background= ImageGetter.getBackground(currentPlayerCiv.nation.getOuterColor())
table.add("[$currentPlayerCiv] ready?".toLabel().setFontSize(24)
.setFontColor(currentPlayerCiv.nation.getInnerColor()))
table.add("[$currentPlayerCiv] ready?".toLabel(currentPlayerCiv.nation.getInnerColor(),24))
table.onClick {
UnCivGame.Current.worldScreen = WorldScreen(currentPlayerCiv)

View file

@ -34,6 +34,7 @@ class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): G
val cityButtonLayers = ArrayList<Group>()
val circleCrosshairFogLayers = ArrayList<Group>()
// Apparently the sortedByDescending is kinda memory-intensive because it needs to sort ALL the tiles
for(group in tileGroups.sortedByDescending { it.tileInfo.position.x + it.tileInfo.position.y }){
// now, we steal the subgroups from all the tilegroups, that's how we form layers!
baseLayers.add(group.baseLayerGroup.apply { setPosition(group.x,group.y) })

View file

@ -189,8 +189,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
val numberCircle = ImageGetter.getCircle().apply { width = size / 2; height = size / 2;color = Color.BLUE }
moveHereButton.addActor(numberCircle)
moveHereButton.addActor(dto.turnsToGetThere.toString().toLabel()
.apply { center(numberCircle); setFontColor(Color.WHITE) })
moveHereButton.addActor(dto.turnsToGetThere.toString().toLabel().apply { center(numberCircle) })
val unitIcon = UnitGroup(dto.unit, size / 2)
unitIcon.y = size - unitIcon.height

View file

@ -263,7 +263,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
buttonPic.background = ImageGetter.getDrawable("OtherIcons/civTableBackground")
.tint(colorFromRGB(7, 46, 43))
buttonPic.defaults().pad(20f)
buttonPic.add("{Pick a tech}!".toLabel().setFontColor(Color.WHITE).setFontSize(30))
buttonPic.add("{Pick a tech}!".toLabel(Color.WHITE,30))
techButtonHolder.add(buttonPic)
}
else {

View file

@ -22,11 +22,11 @@ import kotlin.math.roundToInt
class WorldScreenTopBar(val screen: WorldScreen) : Table() {
private val turnsLabel = "Turns: 0/400".toLabel().setFontColor(Color.WHITE)
private val goldLabel = "Gold:".toLabel().setFontColor(colorFromRGB(225, 217, 71) )
private val scienceLabel = "Science:".toLabel().setFontColor(colorFromRGB(78, 140, 151) )
private val turnsLabel = "Turns: 0/400".toLabel()
private val goldLabel = "Gold:".toLabel(colorFromRGB(225, 217, 71) )
private val scienceLabel = "Science:".toLabel(colorFromRGB(78, 140, 151) )
private val happinessLabel = "Happiness:".toLabel()
private val cultureLabel = "Culture:".toLabel().setFontColor(colorFromRGB(210, 94, 210) )
private val cultureLabel = "Culture:".toLabel(colorFromRGB(210, 94, 210) )
private val resourceLabels = HashMap<String, Label>()
private val resourceImages = HashMap<String, Actor>()
private val happinessImage = Group()

View file

@ -110,8 +110,8 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
else listOf()
for(i in 0..max(attackerModifiers.size,defenderModifiers.size)){
if (attackerModifiers.size > i) add(attackerModifiers[i]).actor.setFontSize(14) else add()
if (defenderModifiers.size > i) add(defenderModifiers[i]).actor.setFontSize(14) else add()
if (attackerModifiers.size > i) add(attackerModifiers[i].toLabel(fontSize = 14)) else add()
if (defenderModifiers.size > i) add(defenderModifiers[i].toLabel(fontSize = 14)) else add()
row().pad(2f)
}

View file

@ -29,8 +29,8 @@ open class PopupTable(val screen: CameraStageBaseScreen): Table(CameraStageBaseS
remove()
}
fun addGoodSizedLabel(text: String): Cell<Label> {
val label = text.toLabel()
fun addGoodSizedLabel(text: String, size:Int=18): Cell<Label> {
val label = text.toLabel(fontSize = size)
label.setWrap(true)
label.setAlignment(Align.center)
return add(label).width(screen.stage.width / 2)

View file

@ -13,7 +13,6 @@ import com.unciv.ui.saves.LoadGameScreen
import com.unciv.ui.saves.SaveGameScreen
import com.unciv.ui.utils.addSeparator
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.setFontColor
import com.unciv.ui.utils.toLabel
import com.unciv.ui.worldscreen.WorldScreen
import java.util.*
@ -108,7 +107,7 @@ class WorldScreenMenuTable(val worldScreen: WorldScreen) : PopupTable(worldScree
copyGameIdButton.actor.disable()
multiplayerPopup.addGoodSizedLabel("Players can enter your game by copying the game ID to the clipboard, and clicking on the Join Game button").row()
val badGameIdLabel = "".toLabel().setFontColor(Color.RED)
val badGameIdLabel = "".toLabel(Color.RED)
badGameIdLabel.isVisible = false
multiplayerPopup.addButton("Join Game") {
val gameId = Gdx.app.clipboard.contents

View file

@ -16,9 +16,9 @@ import kotlin.concurrent.thread
class Language(val language:String){
val percentComplete:Int
init{
val availableTranslations = GameBasics.Translations.filter { it.value.containsKey(language) }
val availableTranslations = GameBasics.Translations.count() { it.value.containsKey(language) }
if(language=="English") percentComplete = 100
else percentComplete = (availableTranslations.size*100 / GameBasics.Translations.size)
else percentComplete = (availableTranslations*100 / GameBasics.Translations.size)
}
override fun toString(): String {
val spaceSplitLang = language.replace("_"," ")
@ -183,7 +183,7 @@ class WorldScreenOptionsTable(val worldScreen:WorldScreen) : PopupTable(worldScr
UnCivGame.Current.startMusic()
} catch (ex: Exception) {
errorTable.clear()
errorTable.add("Could not download music!".toLabel().setFontColor(Color.RED))
errorTable.add("Could not download music!".toLabel(Color.RED))
}
}
}
@ -267,8 +267,11 @@ class WorldScreenOptionsTable(val worldScreen:WorldScreen) : PopupTable(worldScr
languageSelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
// Sometimes the "changed" is triggered even when we didn't choose something that isn't the
selectedLanguage = languageSelectBox.selected.language
selectLanguage()
if(selectedLanguage!=UnCivGame.Current.settings.language )
selectLanguage()
}
})

View file

@ -4,12 +4,10 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.Constants
import com.unciv.UnCivGame
import com.unciv.logic.map.MapUnit
import com.unciv.models.gamebasics.tr
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen
@ -69,10 +67,8 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
private fun getUnitActionButton(unitAction: UnitAction): Button {
val actionButton = Button(CameraStageBaseScreen.skin)
actionButton.add(getIconForUnitAction(unitAction.name)).size(20f).pad(5f)
actionButton.add(
Label(unitAction.title.tr(),CameraStageBaseScreen.skin)
.setFontColor(if(unitAction.currentAction) Color.YELLOW else Color.WHITE))
.pad(5f)
val fontColor = if(unitAction.currentAction) Color.YELLOW else Color.WHITE
actionButton.add(unitAction.title.toLabel(fontColor)).pad(5f)
actionButton.pack()
actionButton.onClick(unitAction.sound) { unitAction.action(); UnCivGame.Current.worldScreen.shouldUpdate=true }
if (!unitAction.canAct) actionButton.disable()

View file

@ -41,13 +41,13 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
add(VerticalGroup().apply {
pad(5f)
deselectUnitButton.add(Label("X",CameraStageBaseScreen.skin).setFontColor(Color.WHITE)).pad(10f)
deselectUnitButton.add(Label("X",CameraStageBaseScreen.skin)).pad(10f)
deselectUnitButton.pack()
deselectUnitButton.touchable = Touchable.enabled
deselectUnitButton.onClick { selectedUnit=null; selectedCity=null; worldScreen.shouldUpdate=true;this@UnitTable.isVisible=false }
addActor(deselectUnitButton)
helpUnitButton.add(Label("?",CameraStageBaseScreen.skin).setFontColor(Color.WHITE)).pad(10f)
helpUnitButton.add(Label("?",CameraStageBaseScreen.skin)).pad(10f)
helpUnitButton.pack()
helpUnitButton.touchable = Touchable.enabled
helpUnitButton.onClick {