Arbitrary images in font!!! (#9167)

* Arbitrary images in font!!!

* Added unit, promotion, and improvement icons to text

* Fixed icons in notifications

* Removed icons from formatted lines to avoid double-icons

* Removed nation icon from next to menu to not have double-icons

* Removed nation icon from next to menu to not have double-icons

* Icons do not appear in Civilopedia twice

* Better Nation texts
This commit is contained in:
Yair Morgenstern 2023-04-13 16:00:50 +03:00 committed by GitHub
parent 193114078b
commit 36a8b368c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 138 additions and 61 deletions

View File

@ -191,6 +191,7 @@ class Nation : RulesetObject() {
building.hasUnique(UniqueType.HiddenFromCivilopedia) -> continue building.hasUnique(UniqueType.HiddenFromCivilopedia) -> continue
!religionEnabled && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue !religionEnabled && building.hasUnique(UniqueType.HiddenWithoutReligion) -> continue
} }
yield(FormattedLine(separator = true))
yield(FormattedLine("{${building.name}} -", link=building.makeLink())) yield(FormattedLine("{${building.name}} -", link=building.makeLink()))
if (building.replaces != null && ruleset.buildings.containsKey(building.replaces!!)) { if (building.replaces != null && ruleset.buildings.containsKey(building.replaces!!)) {
val originalBuilding = ruleset.buildings[building.replaces!!]!! val originalBuilding = ruleset.buildings[building.replaces!!]!!
@ -222,6 +223,7 @@ class Nation : RulesetObject() {
private fun getUniqueUnitsText(ruleset: Ruleset) = sequence { private fun getUniqueUnitsText(ruleset: Ruleset) = sequence {
for (unit in ruleset.units.values) { for (unit in ruleset.units.values) {
if (unit.uniqueTo != name || unit.hasUnique(UniqueType.HiddenFromCivilopedia)) continue if (unit.uniqueTo != name || unit.hasUnique(UniqueType.HiddenFromCivilopedia)) continue
yield(FormattedLine(separator = true))
yield(FormattedLine("{${unit.name}} -", link="Unit/${unit.name}")) yield(FormattedLine("{${unit.name}} -", link="Unit/${unit.name}"))
if (unit.replaces != null && ruleset.units.containsKey(unit.replaces!!)) { if (unit.replaces != null && ruleset.units.containsKey(unit.replaces!!)) {
val originalUnit = ruleset.units[unit.replaces!!]!! val originalUnit = ruleset.units[unit.replaces!!]!!
@ -260,7 +262,7 @@ class Nation : RulesetObject() {
// "{$promotion} ({$effect})" won't work as effect may contain [] and tr() does not support that kind of nesting // "{$promotion} ({$effect})" won't work as effect may contain [] and tr() does not support that kind of nesting
yield( yield(
FormattedLine( FormattedLine(
"${promotion.tr()} (${effect.joinToString(",") { it.tr() }})", "${promotion.tr(true)} (${effect.joinToString(",") { it.tr() }})",
link = "Promotion/$promotion", indent = 1 ) link = "Promotion/$promotion", indent = 1 )
) )
} }
@ -280,6 +282,7 @@ class Nation : RulesetObject() {
for (improvement in ruleset.tileImprovements.values) { for (improvement in ruleset.tileImprovements.values) {
if (improvement.uniqueTo != name || improvement.hasUnique(UniqueType.HiddenFromCivilopedia)) continue if (improvement.uniqueTo != name || improvement.hasUnique(UniqueType.HiddenFromCivilopedia)) continue
yield(FormattedLine(separator = true))
yield(FormattedLine(improvement.name, link = "Improvement/${improvement.name}")) yield(FormattedLine(improvement.name, link = "Improvement/${improvement.name}"))
yield(FormattedLine(improvement.cloneStats().toString(), indent = 1)) // = (improvement as Stats).toString minus import plus copy overhead yield(FormattedLine(improvement.cloneStats().toString(), indent = 1)) // = (improvement as Stats).toString minus import plus copy overhead
if (improvement.terrainsCanBeBuiltOn.isNotEmpty()) { if (improvement.terrainsCanBeBuiltOn.isNotEmpty()) {

View File

@ -7,6 +7,7 @@ import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.ui.components.Fonts
import com.unciv.utils.Log import com.unciv.utils.Log
import com.unciv.utils.debug import com.unciv.utils.debug
import java.util.* import java.util.*
@ -291,7 +292,7 @@ object TranslationActiveModsCache {
* defaults to the input string if no translation is available, * defaults to the input string if no translation is available,
* but with placeholder or sentence brackets removed. * but with placeholder or sentence brackets removed.
*/ */
fun String.tr(): String { fun String.tr(hideIcons:Boolean = false): String {
val language:String = UncivGame.Current.settings.language val language:String = UncivGame.Current.settings.language
if (contains('<') && contains('>')) { // Conditionals! if (contains('<') && contains('>')) { // Conditionals!
/** /**
@ -307,13 +308,13 @@ fun String.tr(): String {
* together into the final fully translated string. * together into the final fully translated string.
*/ */
var translatedBaseUnique = this.removeConditionals().tr() var translatedBaseUnique = this.removeConditionals().tr(hideIcons)
val conditionals = this.getConditionals().map { it.placeholderText } val conditionals = this.getConditionals().map { it.placeholderText }
val conditionsWithTranslation: LinkedHashMap<String, String> = linkedMapOf() val conditionsWithTranslation: LinkedHashMap<String, String> = linkedMapOf()
for (conditional in this.getConditionals()) for (conditional in this.getConditionals())
conditionsWithTranslation[conditional.placeholderText] = conditional.text.tr() conditionsWithTranslation[conditional.placeholderText] = conditional.text.tr(hideIcons)
val translatedConditionals: MutableList<String> = mutableListOf() val translatedConditionals: MutableList<String> = mutableListOf()
@ -401,14 +402,14 @@ fun String.tr(): String {
for (i in termsInMessage.indices) { for (i in termsInMessage.indices) {
languageSpecificPlaceholder = languageSpecificPlaceholder.replace( languageSpecificPlaceholder = languageSpecificPlaceholder.replace(
"[${termsInTranslationPlaceholder[i]}]", // re-add square brackets to placeholder terms "[${termsInTranslationPlaceholder[i]}]", // re-add square brackets to placeholder terms
termsInMessage[i].tr() termsInMessage[i].tr(hideIcons)
) )
} }
return languageSpecificPlaceholder // every component is already translated return languageSpecificPlaceholder // every component is already translated
} }
if (processCurly) { // Translating partial sentences if (processCurly) { // Translating partial sentences
return curlyBraceRegex.replace(this) { it.groups[1]!!.value.tr() } return curlyBraceRegex.replace(this) { it.groups[1]!!.value.tr(hideIcons) }
} }
if (Stats.isStats(this)) return Stats.parse(this).toString() if (Stats.isStats(this)) return Stats.parse(this).toString()
@ -418,6 +419,9 @@ fun String.tr(): String {
val stat = Stat.safeValueOf(this) val stat = Stat.safeValueOf(this)
if (stat != null) return stat.character + translation if (stat != null) return stat.character + translation
if (!hideIcons && Fonts.rulesetObjectNameToChar.containsKey(this))
return Fonts.rulesetObjectNameToChar[this]!! + translation
return translation return translation
} }

View File

@ -114,7 +114,7 @@ class ColorMarkupLabel private constructor(
val sb = StringBuilder(translated.length + 42) val sb = StringBuilder(translated.length + 42)
var currentColor = ' ' var currentColor = ' '
for (char in translated) { for (char in translated) {
val newColor = if (char in Fonts.allSymbols) 'S' else 'T' val newColor = if (char in Fonts.allSymbols || char in Fonts.charToRulesetImageActor) 'S' else 'T'
if (newColor != currentColor) { if (newColor != currentColor) {
if (currentColor != ' ') sb.append("[]") if (currentColor != ' ') sb.append("[]")
sb.append('[') sb.append('[')

View File

@ -1,6 +1,8 @@
package com.unciv.ui.components package com.unciv.ui.components
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.BitmapFont import com.badlogic.gdx.graphics.g2d.BitmapFont
@ -8,12 +10,16 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont.BitmapFontData
import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph
import com.badlogic.gdx.graphics.g2d.GlyphLayout import com.badlogic.gdx.graphics.g2d.GlyphLayout
import com.badlogic.gdx.graphics.g2d.PixmapPacker import com.badlogic.gdx.graphics.g2d.PixmapPacker
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.utils.Array import com.badlogic.gdx.utils.Array
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import com.unciv.Constants import com.unciv.Constants
import com.unciv.GUI import com.unciv.GUI
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
@ -154,6 +160,8 @@ class NativeBitmapFontData(
MayaCalendar.katun -> getPixmap(MayaCalendar.katunIcon) MayaCalendar.katun -> getPixmap(MayaCalendar.katunIcon)
MayaCalendar.baktun -> getPixmap(MayaCalendar.baktunIcon) MayaCalendar.baktun -> getPixmap(MayaCalendar.baktunIcon)
in MayaCalendar.digits -> getPixmap(MayaCalendar.digitIcon(ch)) in MayaCalendar.digits -> getPixmap(MayaCalendar.digitIcon(ch))
in Fonts.charToRulesetImageActor -> Fonts.getPixmapFromActor(
Fonts.charToRulesetImageActor[ch]!!)
else -> fontImplementation.getCharPixmap(ch) else -> fontImplementation.getCharPixmap(ch)
} }
} }
@ -191,6 +199,7 @@ object Fonts {
val settings = GUI.getSettings() val settings = GUI.getSettings()
fontImplementation.setFontFamily(settings.fontFamilyData, settings.getFontSize()) fontImplementation.setFontFamily(settings.fontFamilyData, settings.getFontSize())
font = fontImplementation.getBitmapFont() font = fontImplementation.getBitmapFont()
font.data.markupEnabled = true
} }
/** Reduce the font list returned by platform-specific code to font families (plain variant if possible) */ /** Reduce the font list returned by platform-specific code to font families (plain variant if possible) */
@ -231,6 +240,73 @@ object Fonts {
return pixmap return pixmap
} }
val rulesetObjectNameToChar =HashMap<String, Char>()
val charToRulesetImageActor = HashMap<Char, Actor>()
// See https://en.wikipedia.org/wiki/Private_Use_Areas - char encodings 57344 63743 are not assigned
var nextUnusedCharacterNumber = 57344
fun addRulesetImages(ruleset:Ruleset) {
rulesetObjectNameToChar.clear()
charToRulesetImageActor.clear()
nextUnusedCharacterNumber = 57344
fun addChar(objectName:String, objectActor: Actor){
val char = Char(nextUnusedCharacterNumber)
nextUnusedCharacterNumber++
rulesetObjectNameToChar[objectName] = char
charToRulesetImageActor[char] = objectActor
}
for (resourceName in ruleset.tileResources.keys)
addChar(resourceName, ImageGetter.getResourcePortrait(resourceName, ORIGINAL_FONT_SIZE))
for (buildingName in ruleset.buildings.keys)
addChar(buildingName, ImageGetter.getConstructionPortrait(buildingName, ORIGINAL_FONT_SIZE))
for (unitName in ruleset.units.keys)
addChar(unitName, ImageGetter.getConstructionPortrait(unitName, ORIGINAL_FONT_SIZE))
for (promotionName in ruleset.unitPromotions.keys)
addChar(promotionName, ImageGetter.getPromotionPortrait(promotionName, ORIGINAL_FONT_SIZE))
for (improvementName in ruleset.tileImprovements.keys)
addChar(improvementName, ImageGetter.getImprovementPortrait(improvementName, ORIGINAL_FONT_SIZE))
for (techName in ruleset.technologies.keys)
addChar(techName, ImageGetter.getTechIconPortrait(techName, ORIGINAL_FONT_SIZE))
for (nation in ruleset.nations.values)
addChar(nation.name, ImageGetter.getNationPortrait(nation, ORIGINAL_FONT_SIZE))
}
fun getPixmapFromActor(actor: Actor): Pixmap {
val spriteBatch = SpriteBatch()
val frameBuffer =
FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width, Gdx.graphics.height, false)
frameBuffer.begin()
spriteBatch.begin()
actor.draw(spriteBatch, 1f)
spriteBatch.end()
val w = actor.width.toInt()
val h = actor.height.toInt()
val pixmap = Pixmap(w, h, Pixmap.Format.RGBA8888)
Gdx.gl.glReadPixels(0, 0, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixmap.pixels)
frameBuffer.end()
// Pixmap is now *upside down* so we need to flip it around the y axis
for (i in 0..w)
for (j in 0..h/2) {
val topPixel = pixmap.getPixel(i,j)
val bottomPixel = pixmap.getPixel(i, h-j)
pixmap.drawPixel(i,j,bottomPixel)
pixmap.drawPixel(i,h-j,topPixel)
}
return pixmap
}
const val turn = '⏳' // U+23F3 'hourglass' const val turn = '⏳' // U+23F3 'hourglass'
const val strength = '†' // U+2020 'dagger' const val strength = '†' // U+2020 'dagger'
const val rangedStrength = '‡' // U+2021 'double dagger' const val rangedStrength = '‡' // U+2021 'double dagger'

View File

@ -17,8 +17,9 @@ class WrappableLabel(
text: String, text: String,
private val expectedWidth: Float, private val expectedWidth: Float,
fontColor: Color = Color.WHITE, fontColor: Color = Color.WHITE,
private val fontSize: Int = Constants.defaultFontSize private val fontSize: Int = Constants.defaultFontSize,
) : Label(text.tr(), BaseScreen.skin) { hideIcons: Boolean = false
) : Label(text.tr(hideIcons), BaseScreen.skin) {
private var _measuredWidth = 0f private var _measuredWidth = 0f
private var optimizedWidth = Float.MAX_VALUE private var optimizedWidth = Float.MAX_VALUE

View File

@ -30,13 +30,16 @@ import com.unciv.Constants
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.audio.SoundPlayer import com.unciv.ui.audio.SoundPlayer
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.Fonts import com.unciv.ui.components.Fonts
import com.unciv.ui.components.KeyCharAndCode import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.KeyShortcutDispatcher import com.unciv.ui.components.KeyShortcutDispatcher
import com.unciv.ui.components.KeyboardBinding import com.unciv.ui.components.KeyboardBinding
import com.unciv.ui.components.extensions.GdxKeyCodeFixes.DEL
import com.unciv.ui.components.extensions.GdxKeyCodeFixes.toString
import com.unciv.ui.components.extensions.GdxKeyCodeFixes.valueOf
import com.unciv.ui.images.IconCircleGroup import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.utils.concurrency.Concurrency import com.unciv.utils.concurrency.Concurrency
/** /**
@ -494,7 +497,8 @@ fun Int.toLabel() = this.toString().toLabel()
/** Translate a [String] and make a [Label] widget from it with a specified font color and size */ /** Translate a [String] and make a [Label] widget from it with a specified font color and size */
fun String.toLabel(fontColor: Color = Color.WHITE, fun String.toLabel(fontColor: Color = Color.WHITE,
fontSize: Int = Constants.defaultFontSize, fontSize: Int = Constants.defaultFontSize,
alignment: Int = Align.left ): Label { alignment: Int = Align.left,
hideIcons: Boolean = false): Label {
// We don't want to use setFontSize and setFontColor because they set the font, // 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. // which means we need to rebuild the font cache which means more memory allocation.
var labelStyle = BaseScreen.skin.get(Label.LabelStyle::class.java) var labelStyle = BaseScreen.skin.get(Label.LabelStyle::class.java)
@ -503,7 +507,7 @@ fun String.toLabel(fontColor: Color = Color.WHITE,
labelStyle.fontColor = fontColor labelStyle.fontColor = fontColor
if (fontSize != Constants.defaultFontSize) labelStyle.font = Fonts.font if (fontSize != Constants.defaultFontSize) labelStyle.font = Fonts.font
} }
return Label(this.tr(), labelStyle).apply { return Label(this.tr(hideIcons), labelStyle).apply {
setFontScale(fontSize / Fonts.ORIGINAL_FONT_SIZE) setFontScale(fontSize / Fonts.ORIGINAL_FONT_SIZE)
setAlignment(alignment) setAlignment(alignment)
} }

View File

@ -20,8 +20,8 @@ import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.json.json import com.unciv.json.json
import com.unciv.logic.city.PerpetualConstruction import com.unciv.logic.city.PerpetualConstruction
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.skins.SkinCache import com.unciv.models.skins.SkinCache
import com.unciv.models.tilesets.TileSetCache import com.unciv.models.tilesets.TileSetCache
import com.unciv.ui.components.* import com.unciv.ui.components.*
@ -74,6 +74,9 @@ object ImageGetter {
TileSetCache.assembleTileSetConfigs(ruleset.mods) TileSetCache.assembleTileSetConfigs(ruleset.mods)
SkinCache.assembleSkinConfigs(ruleset.mods) SkinCache.assembleSkinConfigs(ruleset.mods)
Fonts.resetFont()
Fonts.addRulesetImages(ruleset)
} }
/** Loads all atlas/texture files from a folder, as controlled by an Atlases.json */ /** Loads all atlas/texture files from a folder, as controlled by an Atlases.json */

View File

@ -70,7 +70,7 @@ open class Portrait(val type: Type, val imageName: String, val size: Float, val
} }
/** Inner image */ /** Inner image */
private fun getMainImage() : Image { fun getMainImage() : Image {
return when { return when {
ImageGetter.imageExists(pathPortrait) -> { ImageGetter.imageExists(pathPortrait) -> {
isPortrait = true isPortrait = true

View File

@ -42,7 +42,7 @@ object TechnologyDescriptions {
if (enabledUnits.any()) { if (enabledUnits.any()) {
lineList += "{Units enabled}: " lineList += "{Units enabled}: "
for (unit in enabledUnits) for (unit in enabledUnits)
lineList += "" + unit.name.tr() + " (" + unit.getShortDescription() + ")" lineList += "${unit.name.tr()} (${unit.getShortDescription()})\n"
} }
val (wonders, regularBuildings) = getEnabledBuildings(name, ruleset, viewingCiv) val (wonders, regularBuildings) = getEnabledBuildings(name, ruleset, viewingCiv)
@ -51,13 +51,13 @@ object TechnologyDescriptions {
if (regularBuildings.isNotEmpty()) { if (regularBuildings.isNotEmpty()) {
lineList += "{Buildings enabled}: " lineList += "{Buildings enabled}: "
for (building in regularBuildings) for (building in regularBuildings)
lineList += "" + building.name.tr() + " (" + building.getShortDescription() + ")" lineList += "${building.name.tr()} (${building.getShortDescription()})\n"
} }
if (wonders.isNotEmpty()) { if (wonders.isNotEmpty()) {
lineList += "{Wonders enabled}: " lineList += "{Wonders enabled}: "
for (wonder in wonders) for (wonder in wonders)
lineList += "" + wonder.name.tr() + " (" + wonder.getShortDescription() + ")" lineList += "${wonder.name.tr()} (${wonder.getShortDescription()})\n"
} }
for (obj in getObsoletedObjects(name, ruleset, viewingCiv)) for (obj in getObsoletedObjects(name, ruleset, viewingCiv))
@ -204,7 +204,7 @@ object TechnologyDescriptions {
lineList += FormattedLine() lineList += FormattedLine()
lineList += FormattedLine("{Units enabled}:") lineList += FormattedLine("{Units enabled}:")
for (unit in enabledUnits) for (unit in enabledUnits)
lineList += FormattedLine(unit.name.tr() + " (" + unit.getShortDescription() + ")", link = unit.makeLink()) lineList += FormattedLine(unit.name.tr(true) + " (" + unit.getShortDescription() + ")", link = unit.makeLink())
} }
val (wonders, regularBuildings) = getEnabledBuildings(name, ruleset, null) val (wonders, regularBuildings) = getEnabledBuildings(name, ruleset, null)
@ -214,14 +214,14 @@ object TechnologyDescriptions {
lineList += FormattedLine() lineList += FormattedLine()
lineList += FormattedLine("{Wonders enabled}:") lineList += FormattedLine("{Wonders enabled}:")
for (wonder in wonders) for (wonder in wonders)
lineList += FormattedLine(wonder.name.tr() + " (" + wonder.getShortDescription() + ")", link = wonder.makeLink()) lineList += FormattedLine(wonder.name.tr(true) + " (" + wonder.getShortDescription() + ")", link = wonder.makeLink())
} }
if (regularBuildings.isNotEmpty()) { if (regularBuildings.isNotEmpty()) {
lineList += FormattedLine() lineList += FormattedLine()
lineList += FormattedLine("{Buildings enabled}:") lineList += FormattedLine("{Buildings enabled}:")
for (building in regularBuildings) for (building in regularBuildings)
lineList += FormattedLine(building.name.tr() + " (" + building.getShortDescription() + ")", link = building.makeLink()) lineList += FormattedLine(building.name.tr(true) + " (" + building.getShortDescription() + ")", link = building.makeLink())
} }
val obsoletedObjects = getObsoletedObjects(name, ruleset, null).toList() val obsoletedObjects = getObsoletedObjects(name, ruleset, null).toList()

View File

@ -122,7 +122,7 @@ class CivilopediaScreen(
compareBy<CivilopediaEntry>{ it.sortBy } compareBy<CivilopediaEntry>{ it.sortBy }
.thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { .thenBy (UncivGame.Current.settings.getCollatorFromLocale()) {
// In order for the extra icons on Happiness and Faith to not affect sort order // In order for the extra icons on Happiness and Faith to not affect sort order
it.name.tr().replace(Fonts.happiness.toString(),"").replace(Fonts.faith.toString(),"") }) it.name.tr(true).replace(Fonts.happiness.toString(),"").replace(Fonts.faith.toString(),"") })
var currentY = -1f var currentY = -1f
@ -139,7 +139,8 @@ class CivilopediaScreen(
entryButton.add(entry.image).padLeft(20f).padRight(10f) entryButton.add(entry.image).padLeft(20f).padRight(10f)
else else
entryButton.add(entry.image).padLeft(10f) entryButton.add(entry.image).padLeft(10f)
entryButton.left().add(entry.name.toLabel(Color.WHITE, 25)).pad(10f) entryButton.left().add(entry.name
.toLabel(Color.WHITE, 25, hideIcons=true)).pad(10f)
entryButton.onClick { selectEntry(entry) } entryButton.onClick { selectEntry(entry) }
entryButton.name = entry.name // make button findable entryButton.name = entry.name // make button findable
val cell = entrySelectTable.add(entryButton).height(75f).expandX().fillX() val cell = entrySelectTable.add(entryButton).height(75f).expandX().fillX()

View File

@ -11,9 +11,9 @@ import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.extensions.toLabel
import com.unciv.utils.Log import com.unciv.utils.Log
import kotlin.math.max import kotlin.math.max
@ -285,8 +285,7 @@ class FormattedLine (
else -> (indent-1) * indentPad + else -> (indent-1) * indentPad +
indentOneAtNumIcons * (minIconSize + iconPad) + iconPad - usedWidth indentOneAtNumIcons * (minIconSize + iconPad) + iconPad - usedWidth
} }
val label = if (fontSize == Constants.defaultFontSize && labelColor == defaultColor) textToDisplay.toLabel() val label = textToDisplay.toLabel(labelColor, fontSize, hideIcons = iconCount!=0)
else textToDisplay.toLabel(labelColor,fontSize)
label.wrap = !centered && labelWidth > 0f label.wrap = !centered && labelWidth > 0f
label.setAlignment(align) label.setAlignment(align)
if (labelWidth == 0f) if (labelWidth == 0f)

View File

@ -1,9 +1,9 @@
package com.unciv.ui.screens.civilopediascreen package com.unciv.ui.screens.civilopediascreen
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.UncivGame // Kdoc only
/** Addon common to most ruleset game objects managing civilopedia display /** Addon common to most ruleset game objects managing civilopedia display

View File

@ -6,14 +6,14 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.Constants import com.unciv.Constants
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.ui.screens.civilopediascreen.FormattedLine.IconDisplay import com.unciv.models.ruleset.nation.Nation
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.WrappableLabel import com.unciv.ui.components.WrappableLabel
import com.unciv.ui.components.extensions.pad import com.unciv.ui.components.extensions.pad
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.civilopediascreen.FormattedLine.IconDisplay
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
// The ruleset also acts as a secondary parameter to determine if this is the right or self side of the player picker // The ruleset also acts as a secondary parameter to determine if this is the right or self side of the player picker
class NationTable(val nation: Nation, width: Float, minHeight: Float, ruleset: Ruleset? = null) class NationTable(val nation: Nation, width: Float, minHeight: Float, ruleset: Ruleset? = null)
@ -40,7 +40,7 @@ class NationTable(val nation: Nation, width: Float, minHeight: Float, ruleset: R
val titleText = if (ruleset == null || nation.name == Constants.random || nation.name == Constants.spectator) val titleText = if (ruleset == null || nation.name == Constants.random || nation.name == Constants.spectator)
nation.name else nation.getLeaderDisplayName() nation.name else nation.getLeaderDisplayName()
val leaderDisplayNameMaxWidth = internalWidth - 70f // for the nation indicator with padding val leaderDisplayNameMaxWidth = internalWidth - 70f // for the nation indicator with padding
val leaderDisplayLabel = WrappableLabel(titleText, leaderDisplayNameMaxWidth, innerColor, Constants.headingFontSize) val leaderDisplayLabel = WrappableLabel(titleText, leaderDisplayNameMaxWidth, innerColor, Constants.headingFontSize, hideIcons = true)
if (leaderDisplayLabel.prefWidth > leaderDisplayNameMaxWidth - 2f) { if (leaderDisplayLabel.prefWidth > leaderDisplayNameMaxWidth - 2f) {
leaderDisplayLabel.wrap = true leaderDisplayLabel.wrap = true
titleTable.add(leaderDisplayLabel).width(leaderDisplayNameMaxWidth) titleTable.add(leaderDisplayLabel).width(leaderDisplayNameMaxWidth)

View File

@ -280,7 +280,7 @@ class PlayerPickerTable(
ImageGetter.getRandomNationPortrait(40f) ImageGetter.getRandomNationPortrait(40f)
else ImageGetter.getNationPortrait(nationImageName, 40f) else ImageGetter.getNationPortrait(nationImageName, 40f)
nationTable.add(nationImage).pad(5f) nationTable.add(nationImage).pad(5f)
nationTable.add(player.chosenCiv.toLabel()).pad(5f) nationTable.add(player.chosenCiv.toLabel(hideIcons = true)).pad(5f)
nationTable.touchable = Touchable.enabled nationTable.touchable = Touchable.enabled
return nationTable return nationTable
} }

View File

@ -15,10 +15,6 @@ import com.unciv.models.UncivSound
import com.unciv.models.ruleset.tech.Technology import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.components.Fonts import com.unciv.ui.components.Fonts
import com.unciv.ui.components.extensions.colorFromRGB import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.components.extensions.darken import com.unciv.ui.components.extensions.darken
@ -27,6 +23,10 @@ import com.unciv.ui.components.extensions.onClick
import com.unciv.ui.components.extensions.onDoubleClick import com.unciv.ui.components.extensions.onDoubleClick
import com.unciv.ui.components.extensions.surroundWithCircle import com.unciv.ui.components.extensions.surroundWithCircle
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.utils.concurrency.Concurrency import com.unciv.utils.concurrency.Concurrency
import kotlin.math.abs import kotlin.math.abs
@ -220,7 +220,7 @@ class TechPickerScreen(
techButton.turns.setText(turnsToTech[techName] + "${Fonts.turn}".tr()) techButton.turns.setText(turnsToTech[techName] + "${Fonts.turn}".tr())
} }
techButton.text.setText(techName.tr()) techButton.text.setText(techName.tr(true))
} }
addConnectingLines() addConnectingLines()

View File

@ -14,13 +14,12 @@ import com.unciv.GUI
import com.unciv.logic.civilization.Notification import com.unciv.logic.civilization.Notification
import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.NotificationCategory
import com.unciv.ui.components.ColorMarkupLabel import com.unciv.ui.components.ColorMarkupLabel
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.WrappableLabel
import com.unciv.ui.components.extensions.onClick import com.unciv.ui.components.extensions.onClick
import com.unciv.ui.components.extensions.packIfNeeded import com.unciv.ui.components.extensions.packIfNeeded
import com.unciv.ui.components.extensions.surroundWithCircle import com.unciv.ui.components.extensions.surroundWithCircle
import com.unciv.ui.images.IconCircleGroup import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.AutoScrollPane as ScrollPane import com.unciv.ui.components.AutoScrollPane as ScrollPane
/*TODO /*TODO
@ -251,14 +250,11 @@ class NotificationsScroll(
listItem.background = backgroundDrawable listItem.background = backgroundDrawable
val maxLabelWidth = maxEntryWidth - (iconSize + 5f) * notification.icons.size - 10f val maxLabelWidth = maxEntryWidth - (iconSize + 5f) * notification.icons.size - 10f
val label = WrappableLabel(notification.text, maxLabelWidth, Color.BLACK, fontSize) val label = ColorMarkupLabel(notification.text, Color.BLACK, fontSize= fontSize)
label.setAlignment(Align.center) label.width = maxLabelWidth
if (label.prefWidth > maxLabelWidth * scaleFactor) { // can't explain why the comparison needs scaleFactor
label.wrap = true label.wrap = true
listItem.add(label).maxWidth(label.optimizePrefWidth()).padRight(10f) label.setAlignment(Align.center)
} else {
listItem.add(label).padRight(10f) listItem.add(label).padRight(10f)
}
notification.addNotificationIconsTo(listItem, worldScreen.gameInfo.ruleset, iconSize) notification.addNotificationIconsTo(listItem, worldScreen.gameInfo.ruleset, iconSize)

View File

@ -105,7 +105,7 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
innerButton.setButtonColor(colorFromRGB(7, 46, 43)) innerButton.setButtonColor(colorFromRGB(7, 46, 43))
techButtonHolder.actor = innerButton techButtonHolder.actor = innerButton
val turnsToTech = viewingCiv.tech.turnsToTech(currentTech) val turnsToTech = viewingCiv.tech.turnsToTech(currentTech)
innerButton.text.setText(currentTech.tr()) innerButton.text.setText(currentTech.tr(true))
innerButton.turns.setText(turnsToTech + Fonts.turn) innerButton.turns.setText(turnsToTech + Fonts.turn)
} else { } else {
val canResearch = viewingCiv.tech.canResearchTech() val canResearch = viewingCiv.tech.canResearchTech()

View File

@ -5,7 +5,6 @@ import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Cell 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.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
@ -203,7 +202,6 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
private class SelectedCivilizationTable(worldScreen: WorldScreen) : Table(BaseScreen.skin) { private class SelectedCivilizationTable(worldScreen: WorldScreen) : Table(BaseScreen.skin) {
private var selectedCiv = "" private var selectedCiv = ""
private val selectedCivLabel = "".toLabel() private val selectedCivLabel = "".toLabel()
private val selectedCivIconHolder = Container<Actor>()
private val menuButton = ImageGetter.getImage("OtherIcons/MenuIcon") private val menuButton = ImageGetter.getImage("OtherIcons/MenuIcon")
init { init {
@ -227,13 +225,8 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
worldScreen.game.pushScreen(civilopediaScreen) worldScreen.game.pushScreen(civilopediaScreen)
} }
selectedCivIconHolder.onClick {
worldScreen.openEmpireOverview()
}
add(menuButton).size(50f).padRight(0f) add(menuButton).size(50f).padRight(0f)
add(selectedCivLabel).padRight(0f) add(selectedCivLabel).padRight(10f)
add(selectedCivIconHolder).size(35f)
pack() pack()
} }
@ -243,9 +236,6 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
this.selectedCiv = newCiv this.selectedCiv = newCiv
selectedCivLabel.setText(newCiv.tr()) selectedCivLabel.setText(newCiv.tr())
val nation = worldScreen.gameInfo.ruleset.nations[worldScreen.selectedCiv.civName]!!
val selectedCivIcon = ImageGetter.getNationPortrait(nation, 35f)
selectedCivIconHolder.actor = selectedCivIcon
invalidate() invalidate()
pack() pack()
} }