Font download now preceded by a "requires fonts, do you want to download?" message that allows you to opt out
This commit is contained in:
parent
d1df5a2fdf
commit
1ba0929869
6 changed files with 220 additions and 118 deletions
|
@ -244,6 +244,8 @@
|
|||
Portuguese:"Desfazer unidade"
|
||||
}
|
||||
|
||||
"Explore":{}
|
||||
|
||||
"Do you really want to disband this unit?":{
|
||||
Italian:"Vuoi davvero sciogliere questa unità?"
|
||||
Russian:"Вы действительно хотите распустить этот юнит?"
|
||||
|
@ -1894,7 +1896,7 @@
|
|||
Portuguese:"Drenar pântano"
|
||||
}
|
||||
|
||||
"Ancient Ruins":{
|
||||
"Ancient ruins":{
|
||||
Simplified_Chinese:"远古遗址"
|
||||
}
|
||||
"City Ruins":{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.unciv.ui
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
|
@ -9,9 +10,9 @@ import com.unciv.UnCivGame
|
|||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.tr
|
||||
import com.unciv.ui.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.enable
|
||||
import com.unciv.ui.utils.onClick
|
||||
import com.unciv.ui.utils.*
|
||||
import com.unciv.ui.worldscreen.optionstable.PopupTable
|
||||
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable
|
||||
|
||||
|
||||
class LanguageTable(val language:String,skin: Skin):Table(skin){
|
||||
|
@ -71,12 +72,44 @@ class LanguagePickerScreen: PickerScreen(){
|
|||
}
|
||||
|
||||
rightSideButton.setText("Pick language".tr())
|
||||
|
||||
|
||||
rightSideButton.onClick {
|
||||
UnCivGame.Current.settings.language = chosenLanguage
|
||||
UnCivGame.Current.settings.save()
|
||||
UnCivGame.Current.startNewGame()
|
||||
dispose()
|
||||
if (Fonts().containsFont(Fonts().getFontForLanguage(chosenLanguage)))
|
||||
pickLanguage()
|
||||
else {
|
||||
YesNoPopupTable("This language requires you to download fonts.\n" +
|
||||
"Do you want to download fonts for $chosenLanguage?",
|
||||
{
|
||||
val downloading = PopupTable()
|
||||
downloading.add(Label("Downloading...",skin))
|
||||
downloading.pack()
|
||||
downloading.center(stage)
|
||||
stage.addActor(downloading)
|
||||
Gdx.input.inputProcessor = null // no interaction until download is over
|
||||
|
||||
kotlin.concurrent.thread {
|
||||
Fonts().downloadFontForLanguage(chosenLanguage)
|
||||
shouldPickLanguage = true
|
||||
}
|
||||
},this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun pickLanguage(){
|
||||
UnCivGame.Current.settings.language = chosenLanguage
|
||||
UnCivGame.Current.settings.save()
|
||||
CameraStageBaseScreen.resetFonts()
|
||||
UnCivGame.Current.startNewGame()
|
||||
dispose()
|
||||
}
|
||||
|
||||
var shouldPickLanguage=false
|
||||
override fun render(delta: Float) {
|
||||
if(shouldPickLanguage)
|
||||
pickLanguage()
|
||||
super.render(delta)
|
||||
}
|
||||
|
||||
}
|
|
@ -5,19 +5,13 @@ import com.badlogic.gdx.Input
|
|||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.Batch
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator
|
||||
import com.badlogic.gdx.scenes.scene2d.*
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
|
||||
import com.badlogic.gdx.utils.viewport.ExtendViewport
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import java.io.FileOutputStream
|
||||
import java.net.URL
|
||||
|
||||
open class CameraStageBaseScreen : Screen {
|
||||
|
||||
|
@ -69,14 +63,14 @@ open class CameraStageBaseScreen : Screen {
|
|||
}
|
||||
|
||||
fun resetFonts(){
|
||||
skin.get<TextButton.TextButtonStyle>(TextButton.TextButtonStyle::class.java).font = getFont(20)
|
||||
skin.get<TextButton.TextButtonStyle>(TextButton.TextButtonStyle::class.java).font = Fonts().getFont(20)
|
||||
skin.get<Label.LabelStyle>(Label.LabelStyle::class.java).apply {
|
||||
font = getFont(18)
|
||||
font = Fonts().getFont(18)
|
||||
fontColor= Color.WHITE
|
||||
}
|
||||
skin.get<TextField.TextFieldStyle>(TextField.TextFieldStyle::class.java).font = getFont(18)
|
||||
skin.get<SelectBox.SelectBoxStyle>(SelectBox.SelectBoxStyle::class.java).font = getFont(20)
|
||||
skin.get<SelectBox.SelectBoxStyle>(SelectBox.SelectBoxStyle::class.java).listStyle.font = getFont(20)
|
||||
skin.get<TextField.TextFieldStyle>(TextField.TextFieldStyle::class.java).font = Fonts().getFont(18)
|
||||
skin.get<SelectBox.SelectBoxStyle>(SelectBox.SelectBoxStyle::class.java).font = Fonts().getFont(20)
|
||||
skin.get<SelectBox.SelectBoxStyle>(SelectBox.SelectBoxStyle::class.java).listStyle.font = Fonts().getFont(20)
|
||||
}
|
||||
internal var batch: Batch = SpriteBatch()
|
||||
}
|
||||
|
@ -121,85 +115,9 @@ fun Actor.center(parent:Stage){ centerX(parent); centerY(parent)}
|
|||
|
||||
fun Label.setFontColor(color:Color): Label {style=Label.LabelStyle(style).apply { fontColor=color }; return this}
|
||||
|
||||
|
||||
// Contains e.g. "Arial 22", fontname and size, to BitmapFont
|
||||
val fontCache = HashMap<String,BitmapFont>()
|
||||
|
||||
fun getFontForLanguage(): String {
|
||||
if(UnCivGame.Current.settings.language.contains("Chinese")) return chineseFont
|
||||
else return "Arial"
|
||||
}
|
||||
|
||||
val chineseFont = "SimSun"
|
||||
|
||||
fun getCharsForFont(font:String): String {
|
||||
val defaultText = "ABCČĆDĐEFGHIJKLMNOPQRSŠTUVWXYZŽaäàâăbcčćdđeéfghiîjklmnoöpqrsșštțuüvwxyzž" +
|
||||
"АБВГҐДЂЕЁЄЖЗЅИІЇЙЈКЛЉМНЊОПРСТЋУЎФХЦЧЏШЩЪЫЬЭЮЯабвгґдђеёєжзѕиіїйјклљмнњопрстћуўфхцчџшщъыьэюя" +
|
||||
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωάΆέΈέΉίϊΐΊόΌύΰϋΎΫΏĂÂÊÉÔƠƯăâêôơưáéèíóú1234567890" +
|
||||
"‘?’'“!”(%)[#]{@}/&\\<-+÷×=>®©\$€£¥¢:;,.*|"
|
||||
if(font=="Arial") return defaultText
|
||||
if(font== chineseFont) {
|
||||
val constants = "‘?’'“!”(%)[#]{@}/&\\<-+÷×=>®©\$€£¥¢:;,.*|"
|
||||
val charSet = HashSet<Char>()
|
||||
charSet.addAll(constants.asIterable())
|
||||
charSet.addAll(defaultText.asIterable())
|
||||
for (entry in GameBasics.Translations.entries) {
|
||||
for(lang in entry.value){
|
||||
if(lang.key.contains("Chinese")) charSet.addAll(lang.value.asIterable())
|
||||
}
|
||||
}
|
||||
return charSet.joinToString()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fun download(link: String, path: String) {
|
||||
val input = URL(link).openStream()
|
||||
val output = FileOutputStream(Gdx.files.local(path).file())
|
||||
input.use {
|
||||
output.use {
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFont(size: Int): BitmapFont {
|
||||
val fontForLanguage = getFontForLanguage()
|
||||
val keyForFont = "$fontForLanguage $size"
|
||||
if(fontCache.containsKey(keyForFont)) return fontCache[keyForFont]!!
|
||||
val generator:FreeTypeFontGenerator
|
||||
|
||||
if(Gdx.files.internal("skin/$fontForLanguage.ttf").exists())
|
||||
generator = FreeTypeFontGenerator(Gdx.files.internal("skin/$fontForLanguage.ttf"))
|
||||
else {
|
||||
val localPath = "fonts/$fontForLanguage.ttf"
|
||||
if (!Gdx.files.local("fonts/$fontForLanguage.ttf").exists()) {
|
||||
if(!Gdx.files.local("fonts").exists())
|
||||
Gdx.files.local("fonts").mkdirs()
|
||||
|
||||
if(fontForLanguage == chineseFont)
|
||||
download("https://github.com/micmro/Stylify-Me/raw/master/.fonts/SimSun.ttf",localPath)
|
||||
}
|
||||
|
||||
generator = FreeTypeFontGenerator(Gdx.files.internal(localPath))
|
||||
}
|
||||
|
||||
val parameter = FreeTypeFontGenerator.FreeTypeFontParameter()
|
||||
parameter.size = size
|
||||
parameter.minFilter = Texture.TextureFilter.Linear
|
||||
parameter.magFilter = Texture.TextureFilter.Linear
|
||||
|
||||
parameter.characters = getCharsForFont(fontForLanguage)
|
||||
|
||||
val font = generator.generateFont(parameter)
|
||||
generator.dispose() // don't forget to dispose to avoid memory leaks!
|
||||
fontCache[keyForFont]=font
|
||||
return font
|
||||
}
|
||||
|
||||
fun Label.setFontSize(size:Int): Label {
|
||||
style = Label.LabelStyle(style)
|
||||
style.font = getFont(size)
|
||||
style.font = Fonts().getFont(size)
|
||||
style = style // because we need it to call the SetStyle function. Yuk, I know.
|
||||
return this // for chaining
|
||||
}
|
||||
|
|
104
core/src/com/unciv/ui/utils/Fonts.kt
Normal file
104
core/src/com/unciv/ui/utils/Fonts.kt
Normal file
|
@ -0,0 +1,104 @@
|
|||
package com.unciv.ui.utils
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import java.io.FileOutputStream
|
||||
import java.net.URL
|
||||
|
||||
class Fonts {
|
||||
companion object {
|
||||
// Contains e.g. "Arial 22", fontname and size, to BitmapFont
|
||||
val fontCache = HashMap<String, BitmapFont>()
|
||||
}
|
||||
|
||||
fun getFontForLanguage(language:String): String {
|
||||
if (language.contains("Chinese")) return chineseFont
|
||||
else return "Arial"
|
||||
}
|
||||
|
||||
val chineseFont = "SimSun"
|
||||
|
||||
fun getCharsForFont(font: String): String {
|
||||
val defaultText = "ABCČĆDĐEFGHIJKLMNOPQRSŠTUVWXYZŽaäàâăbcčćdđeéfghiîjklmnoöpqrsșštțuüvwxyzž" +
|
||||
"АБВГҐДЂЕЁЄЖЗЅИІЇЙЈКЛЉМНЊОПРСТЋУЎФХЦЧЏШЩЪЫЬЭЮЯабвгґдђеёєжзѕиіїйјклљмнњопрстћуўфхцчџшщъыьэюя" +
|
||||
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωάΆέΈέΉίϊΐΊόΌύΰϋΎΫΏĂÂÊÉÔƠƯăâêôơưáéèíóú1234567890" +
|
||||
"‘?’'“!”(%)[#]{@}/&\\<-+÷×=>®©\$€£¥¢:;,.*|"
|
||||
if (font == "Arial") return defaultText
|
||||
if (font == chineseFont) {
|
||||
val constants = "‘?’'“!”(%)[#]{@}/&\\<-+÷×=>®©\$€£¥¢:;,.*|"
|
||||
val charSet = HashSet<Char>()
|
||||
charSet.addAll(constants.asIterable())
|
||||
charSet.addAll(defaultText.asIterable())
|
||||
for (entry in GameBasics.Translations.entries) {
|
||||
for (lang in entry.value) {
|
||||
if (lang.key.contains("Chinese")) charSet.addAll(lang.value.asIterable())
|
||||
}
|
||||
}
|
||||
return charSet.joinToString()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fun download(link: String, path: String) {
|
||||
val input = URL(link).openStream()
|
||||
val output = FileOutputStream(Gdx.files.local(path).file())
|
||||
input.use {
|
||||
output.use {
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun containsFont(font:String): Boolean {
|
||||
if (Gdx.files.internal("skin/$font.ttf").exists())
|
||||
return true
|
||||
if (Gdx.files.local("fonts/$font.ttf").exists())
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun downloadFontForLanguage(language:String){
|
||||
val font = getFontForLanguage(language)
|
||||
if(containsFont(language)) return
|
||||
|
||||
if (!Gdx.files.local("fonts").exists())
|
||||
Gdx.files.local("fonts").mkdirs()
|
||||
|
||||
val localPath = "fonts/$font.ttf"
|
||||
if (font == chineseFont)
|
||||
download("https://github.com/micmro/Stylify-Me/raw/master/.fonts/SimSun.ttf", localPath)
|
||||
}
|
||||
|
||||
fun getFont(size: Int): BitmapFont {
|
||||
val language = UnCivGame.Current.settings.language
|
||||
val fontForLanguage = getFontForLanguage(language)
|
||||
val keyForFont = "$fontForLanguage $size"
|
||||
if (fontCache.containsKey(keyForFont)) return fontCache[keyForFont]!!
|
||||
val generator: FreeTypeFontGenerator
|
||||
|
||||
if (Gdx.files.internal("skin/$fontForLanguage.ttf").exists())
|
||||
generator = FreeTypeFontGenerator(Gdx.files.internal("skin/$fontForLanguage.ttf"))
|
||||
else {
|
||||
val localPath = "fonts/$fontForLanguage.ttf"
|
||||
if(!containsFont(fontForLanguage)) downloadFontForLanguage(language)
|
||||
generator = FreeTypeFontGenerator(Gdx.files.internal(localPath))
|
||||
}
|
||||
|
||||
val parameter = FreeTypeFontGenerator.FreeTypeFontParameter()
|
||||
parameter.size = size
|
||||
parameter.minFilter = Texture.TextureFilter.Linear
|
||||
parameter.magFilter = Texture.TextureFilter.Linear
|
||||
|
||||
parameter.characters = getCharsForFont(fontForLanguage)
|
||||
|
||||
val font = generator.generateFont(parameter)
|
||||
generator.dispose() // don't forget to dispose to avoid memory leaks!
|
||||
fontCache[keyForFont] = font
|
||||
return font
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ import com.unciv.ui.utils.ImageGetter
|
|||
import com.unciv.ui.utils.center
|
||||
import com.unciv.ui.utils.onClick
|
||||
|
||||
open class PopupTable: Table(){
|
||||
open class PopupTable: Table(CameraStageBaseScreen.skin){
|
||||
init {
|
||||
val tileTableBackground = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK, 0.5f))
|
||||
background = tileTableBackground
|
||||
|
@ -21,7 +21,7 @@ open class PopupTable: Table(){
|
|||
}
|
||||
|
||||
fun addButton(text:String, action:()->Unit){
|
||||
val button = TextButton(text.tr(), CameraStageBaseScreen.skin).apply { color= ImageGetter.getBlue() }
|
||||
val button = TextButton(text.tr(), skin).apply { color= ImageGetter.getBlue() }
|
||||
button.onClick(action)
|
||||
add(button).row()
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ class YesNoPopupTable(question:String, action:()->Unit,
|
|||
init{
|
||||
if(!isOpen) {
|
||||
isOpen=true
|
||||
val skin = CameraStageBaseScreen.skin
|
||||
add(Label(question, skin)).colspan(2).row()
|
||||
|
||||
add(TextButton("No".tr(), skin).apply { onClick { close() } })
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.unciv.ui.worldscreen.optionstable
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.g2d.Batch
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
|
@ -7,14 +9,31 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
|||
import com.unciv.UnCivGame
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.center
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
|
||||
class Language(val language:String){
|
||||
val percentComplete:Int
|
||||
init{
|
||||
val availableTranslations = GameBasics.Translations.filter { it.value.containsKey(language) }
|
||||
if(language=="English") percentComplete = 100
|
||||
else percentComplete = (availableTranslations.size*100 / GameBasics.Translations.size)
|
||||
}
|
||||
override fun toString(): String {
|
||||
return "$language - $percentComplete%"
|
||||
}
|
||||
}
|
||||
|
||||
class WorldScreenDisplayOptionsTable : PopupTable(){
|
||||
val languageSelectBox = SelectBox<Language>(CameraStageBaseScreen.skin)
|
||||
|
||||
init {
|
||||
update()
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun update() {
|
||||
val settings = UnCivGame.Current.settings
|
||||
settings.save()
|
||||
|
@ -28,33 +47,39 @@ class WorldScreenDisplayOptionsTable : PopupTable(){
|
|||
else addButton("{Show} {resources and improvements}") { settings.showResourcesAndImprovements = true; update() }
|
||||
|
||||
|
||||
class Language(val language:String){
|
||||
val percentComplete:Int
|
||||
init{
|
||||
val availableTranslations = GameBasics.Translations.filter { it.value.containsKey(language) }
|
||||
if(language=="English") percentComplete = 100
|
||||
else percentComplete = (availableTranslations.size*100 / GameBasics.Translations.size)
|
||||
}
|
||||
override fun toString(): String {
|
||||
return "$language - $percentComplete%"
|
||||
}
|
||||
}
|
||||
|
||||
val languageSelectBox = SelectBox<Language>(CameraStageBaseScreen.skin)
|
||||
val languageArray = com.badlogic.gdx.utils.Array<Language>()
|
||||
GameBasics.Translations.getLanguages().map { Language(it) }.sortedByDescending { it.percentComplete }
|
||||
.forEach { languageArray.add(it) }
|
||||
languageSelectBox.items = languageArray
|
||||
languageSelectBox.selected = languageArray.first { it.language== UnCivGame.Current.settings.language}
|
||||
add(languageSelectBox).pad(10f).row()
|
||||
|
||||
languageSelectBox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
UnCivGame.Current.settings.language = languageSelectBox.selected.language
|
||||
UnCivGame.Current.settings.save()
|
||||
CameraStageBaseScreen.resetFonts()
|
||||
UnCivGame.Current.worldScreen = WorldScreen()
|
||||
UnCivGame.Current.setWorldScreen()
|
||||
UnCivGame.Current.worldScreen.stage.addActor(WorldScreenDisplayOptionsTable())
|
||||
val selectedLanguage = languageSelectBox.selected.language
|
||||
if (Fonts().containsFont(Fonts().getFontForLanguage(selectedLanguage)))
|
||||
selectLanguage()
|
||||
else {
|
||||
YesNoPopupTable("This language requires you to download fonts.\n" +
|
||||
"Do you want to download fonts for $selectedLanguage?",
|
||||
{
|
||||
|
||||
val downloading = PopupTable()
|
||||
downloading.add(Label("Downloading...", CameraStageBaseScreen.skin))
|
||||
downloading.pack()
|
||||
downloading.center(stage)
|
||||
stage.addActor(downloading)
|
||||
Gdx.input.inputProcessor = null // no interaction until download is over
|
||||
|
||||
kotlin.concurrent.thread {
|
||||
Fonts().downloadFontForLanguage(selectedLanguage)
|
||||
// The language selection must be done on the render thread, because it requires a GL context.
|
||||
// This means that we have to tell the table to create it on render.
|
||||
shouldSelectLanguage=true
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -92,4 +117,25 @@ class WorldScreenDisplayOptionsTable : PopupTable(){
|
|||
center(UnCivGame.Current.worldScreen.stage)
|
||||
UnCivGame.Current.worldScreen.shouldUpdate=true
|
||||
}
|
||||
|
||||
|
||||
fun selectLanguage(){
|
||||
UnCivGame.Current.settings.language = languageSelectBox.selected.language
|
||||
UnCivGame.Current.settings.save()
|
||||
|
||||
CameraStageBaseScreen.resetFonts()
|
||||
|
||||
UnCivGame.Current.worldScreen = WorldScreen()
|
||||
UnCivGame.Current.setWorldScreen()
|
||||
UnCivGame.Current.worldScreen.stage.addActor(WorldScreenDisplayOptionsTable())
|
||||
}
|
||||
|
||||
var shouldSelectLanguage = false
|
||||
override fun draw(batch: Batch?, parentAlpha: Float) {
|
||||
if(shouldSelectLanguage){
|
||||
shouldSelectLanguage=false
|
||||
selectLanguage()
|
||||
}
|
||||
super.draw(batch, parentAlpha)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue