mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 18:59:15 +07:00
Custom desktop font (#6377)
* Custom desktop font * Add `getDesktopAllFonts` to setting custom desktop font. * Custom font. `desktopFontFamily` change to `fontFamily`. Add GameSettings.getSettingsForPlatformLaunchers(). * Add `Custom font` setting UI. * Add `Custom font` on Android. * `Default Font` use translations. * format * remove open fun. Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
@ -2,12 +2,16 @@ package com.unciv.models.metadata
|
||||
|
||||
import com.badlogic.gdx.Application
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.unciv.JsonParser
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameSaver
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import java.text.Collator
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
import kotlin.io.path.Path
|
||||
|
||||
data class WindowState (val width: Int = 900, val height: Int = 600)
|
||||
|
||||
@ -65,6 +69,8 @@ class GameSettings {
|
||||
/** Saves the last successful new game's setup */
|
||||
var lastGameSetup: GameSetupInfo? = null
|
||||
|
||||
var fontFamily: String = Fonts.DEFAULT_FONT_FAMILY
|
||||
|
||||
init {
|
||||
// 26 = Android Oreo. Versions below may display permanent icon in notification bar.
|
||||
if (Gdx.app?.type == Application.ApplicationType.Android && Gdx.app.version < 26) {
|
||||
@ -104,6 +110,24 @@ class GameSettings {
|
||||
fun getCollatorFromLocale(): Collator {
|
||||
return Collator.getInstance(getCurrentLocale())
|
||||
}
|
||||
|
||||
companion object {
|
||||
/** Specialized function to access settings before Gdx is initialized.
|
||||
*
|
||||
* @param base Path to the directory where the file should be - if not set, the OS current directory is used (which is "/" on Android)
|
||||
*/
|
||||
fun getSettingsForPlatformLaunchers(base: String = ""): GameSettings {
|
||||
// FileHandle is Gdx, but the class and JsonParser are not dependent on app initialization
|
||||
// If fact, at this point Gdx.app or Gdx.files are null but this still works.
|
||||
val file = FileHandle(Path(base, GameSaver.settingsFileName).toString())
|
||||
return if (file.exists())
|
||||
JsonParser().getFromJson(
|
||||
GameSettings::class.java,
|
||||
file
|
||||
)
|
||||
else GameSettings().apply { isFreshlyCreated = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class LocaleCode(var language: String, var country: String) {
|
||||
|
@ -18,6 +18,23 @@ import com.unciv.models.stats.Stat
|
||||
interface NativeFontImplementation {
|
||||
fun getFontSize(): Int
|
||||
fun getCharPixmap(char: Char): Pixmap
|
||||
fun getAvailableFont(): Collection<FontData>
|
||||
}
|
||||
|
||||
// If save in `GameSettings` need use enName.
|
||||
// If show to user need use localName.
|
||||
// If save localName in `GameSettings` may generate garbled characters by encoding.
|
||||
data class FontData(val localName: String, val enName: String = localName) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is FontData) enName == other.enName
|
||||
else super.equals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = localName.hashCode()
|
||||
result = 31 * result + enName.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// This class is loosely based on libgdx's FreeTypeBitmapFontData
|
||||
@ -128,8 +145,9 @@ object Fonts {
|
||||
* This has several advantages: It means we only render each character once (good for both runtime and RAM),
|
||||
* AND it means that our 'custom' emojis only need to be once size (50px) and they'll be rescaled for what's needed. */
|
||||
const val ORIGINAL_FONT_SIZE = 50f
|
||||
const val DEFAULT_FONT_FAMILY = ""
|
||||
|
||||
lateinit var font:BitmapFont
|
||||
lateinit var font: BitmapFont
|
||||
fun resetFont() {
|
||||
val fontData = NativeBitmapFontData(UncivGame.Current.fontImplementation!!)
|
||||
font = BitmapFont(fontData, fontData.regions, false)
|
||||
@ -137,6 +155,11 @@ object Fonts {
|
||||
font.data.setScale(Constants.defaultFontSize / ORIGINAL_FONT_SIZE)
|
||||
}
|
||||
|
||||
fun getAvailableFontFamilyNames(): Collection<FontData> {
|
||||
if (UncivGame.Current.fontImplementation == null) return emptyList()
|
||||
return UncivGame.Current.fontImplementation!!.getAvailableFont()
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a TextureRegion into a Pixmap.
|
||||
*
|
||||
@ -145,15 +168,15 @@ object Fonts {
|
||||
* @return New Pixmap with all the size and pixel data from this TextureRegion copied into it.
|
||||
*/
|
||||
// From https://stackoverflow.com/questions/29451787/libgdx-textureregion-to-pixmap
|
||||
fun extractPixmapFromTextureRegion(textureRegion:TextureRegion):Pixmap {
|
||||
fun extractPixmapFromTextureRegion(textureRegion: TextureRegion): Pixmap {
|
||||
val textureData = textureRegion.texture.textureData
|
||||
if (!textureData.isPrepared) {
|
||||
textureData.prepare()
|
||||
}
|
||||
val pixmap = Pixmap(
|
||||
textureRegion.regionWidth,
|
||||
textureRegion.regionHeight,
|
||||
textureData.format
|
||||
textureRegion.regionWidth,
|
||||
textureRegion.regionHeight,
|
||||
textureData.format
|
||||
)
|
||||
val textureDataPixmap = textureData.consumePixmap()
|
||||
pixmap.drawPixmap(
|
||||
|
@ -368,6 +368,8 @@ class OptionsPopup(val previousScreen: BaseScreen) : Popup(previousScreen) {
|
||||
}
|
||||
}
|
||||
|
||||
addFontFamilySelect(Fonts.getAvailableFontFamilyNames())
|
||||
|
||||
addTranslationGeneration()
|
||||
|
||||
addSetUserId()
|
||||
@ -879,6 +881,34 @@ class OptionsPopup(val previousScreen: BaseScreen) : Popup(previousScreen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Table.addFontFamilySelect(fonts: Collection<FontData>) {
|
||||
if (fonts.isEmpty()) return
|
||||
|
||||
add("Font family".toLabel()).left().fillX()
|
||||
|
||||
val fontSelectBox = SelectBox<String>(skin)
|
||||
val fontsLocalName = GdxArray<String>().apply { add("Default Font".tr()) }
|
||||
val fontsEnName = GdxArray<String>().apply { add("") }
|
||||
for (font in fonts) {
|
||||
fontsLocalName.add(font.localName)
|
||||
fontsEnName.add(font.enName)
|
||||
}
|
||||
|
||||
val selectedIndex = fontsEnName.indexOf(settings.fontFamily).let { if (it == -1) 0 else it }
|
||||
|
||||
fontSelectBox.items = fontsLocalName
|
||||
fontSelectBox.selected = fontsLocalName[selectedIndex]
|
||||
|
||||
add(fontSelectBox).minWidth(selectBoxMinWidth).pad(10f).row()
|
||||
|
||||
fontSelectBox.onChange {
|
||||
settings.fontFamily = fontsEnName[fontSelectBox.selectedIndex]
|
||||
ToastPopup(
|
||||
"You need to restart the game for this change to take effect.", previousScreen
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Table.addTranslationGeneration() {
|
||||
if (Gdx.app.type == Application.ApplicationType.Desktop) {
|
||||
val generateTranslationsButton = "Generate translation files".toTextButton()
|
||||
|
Reference in New Issue
Block a user