mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-04 14:44:10 +07:00
Resolved #3470 - popups now make the rest of the screen unclickable to avoid exploits
Resolved #3468 the same way
This commit is contained in:
parent
e07fd6d0bc
commit
ca04093321
@ -1,6 +1,8 @@
|
||||
package com.unciv.ui.utils
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Colors
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
@ -13,13 +15,18 @@ import com.unciv.Constants
|
||||
* Base class for all Popups, i.e. Tables that get rendered in the middle of a screen and on top of everything else
|
||||
*/
|
||||
open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen.skin) {
|
||||
val innerTable = Table(CameraStageBaseScreen.skin)
|
||||
init {
|
||||
background = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK, 0.5f))
|
||||
background = ImageGetter.getBackground(Color.GRAY.cpy().apply { a=.5f })
|
||||
innerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().lerp(Color.BLACK, 0.5f))
|
||||
|
||||
this.pad(20f)
|
||||
this.defaults().pad(5f)
|
||||
innerTable.pad(20f)
|
||||
innerTable.defaults().pad(5f)
|
||||
super.add(innerTable)
|
||||
|
||||
this.isVisible = false
|
||||
touchable = Touchable.enabled // don't allow clicking behind
|
||||
setFillParent(true)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,6 +39,7 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen
|
||||
}
|
||||
|
||||
screen.stage.addActor(this)
|
||||
innerTable.pack()
|
||||
pack()
|
||||
center(screen.stage)
|
||||
}
|
||||
@ -42,6 +50,11 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen
|
||||
if (nextPopup != null) nextPopup.isVisible = true
|
||||
}
|
||||
|
||||
/** All additions to the popup are to the inner table - we shouldn't care that there's an inner table at all */
|
||||
override fun <T : Actor?> add(actor: T) = innerTable.add(actor)
|
||||
override fun row() = innerTable.row()
|
||||
fun addSeparator() = innerTable.addSeparator()
|
||||
|
||||
fun addGoodSizedLabel(text: String, size:Int=18): Cell<Label> {
|
||||
val label = text.toLabel(fontSize = size)
|
||||
label.setWrap(true)
|
||||
@ -55,13 +68,6 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen
|
||||
return add(button).apply { row() }
|
||||
}
|
||||
|
||||
fun addSquareButton(text: String, action: () -> Unit): Cell<Table> {
|
||||
val button = Table()
|
||||
button.add(text.toLabel())
|
||||
button.onClick(action)
|
||||
button.touchable = Touchable.enabled
|
||||
return add(button).apply { row() }
|
||||
}
|
||||
|
||||
fun addCloseButton(action: (()->Unit)? = null): Cell<TextButton> {
|
||||
return if (action==null)
|
||||
|
@ -28,14 +28,14 @@ class Language(val language:String, val percentComplete:Int){
|
||||
class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScreen) {
|
||||
var selectedLanguage: String = "English"
|
||||
private val settings = previousScreen.game.settings
|
||||
private val innerTable = Table(CameraStageBaseScreen.skin)
|
||||
val innerTable2 = Table(CameraStageBaseScreen.skin)
|
||||
|
||||
init {
|
||||
settings.addCompletedTutorialTask("Open the options table")
|
||||
|
||||
rebuildInnerTable()
|
||||
|
||||
val scrollPane = ScrollPane(innerTable, skin)
|
||||
val scrollPane = ScrollPane(innerTable2, skin)
|
||||
scrollPane.setOverscroll(false, false)
|
||||
scrollPane.fadeScrollBars = false
|
||||
scrollPane.setScrollingDisabled(true, false)
|
||||
@ -51,18 +51,18 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
private fun addHeader (text: String) {
|
||||
innerTable.add(text.toLabel(fontSize = 24)).colspan(2).padTop(if (innerTable.cells.isEmpty) 0f else 20f).row()
|
||||
innerTable2.add(text.toLabel(fontSize = 24)).colspan(2).padTop(if (innerTable2.cells.isEmpty) 0f else 20f).row()
|
||||
}
|
||||
|
||||
private fun addYesNoRow (text: String, initialValue: Boolean, updateWorld: Boolean = false, action: ((Boolean) -> Unit)) {
|
||||
innerTable.add(text.toLabel())
|
||||
val button = YesNoButton(initialValue, skin) {
|
||||
innerTable2.add(text.toLabel())
|
||||
val button = YesNoButton(initialValue, CameraStageBaseScreen.skin) {
|
||||
action(it)
|
||||
settings.save()
|
||||
if (updateWorld && previousScreen is WorldScreen)
|
||||
previousScreen.shouldUpdate = true
|
||||
}
|
||||
innerTable.add(button).row()
|
||||
innerTable2.add(button).row()
|
||||
}
|
||||
|
||||
private fun reloadWorldAndOptions() {
|
||||
@ -78,7 +78,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
|
||||
private fun rebuildInnerTable() {
|
||||
settings.save()
|
||||
innerTable.clear()
|
||||
innerTable2.clear()
|
||||
|
||||
addHeader("Display options")
|
||||
|
||||
@ -102,7 +102,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
val continuousRenderingDescription = "When disabled, saves battery life but certain animations will be suspended"
|
||||
innerTable.add(continuousRenderingDescription.toLabel(fontSize = 14)).colspan(2).padTop(20f).row()
|
||||
innerTable2.add(continuousRenderingDescription.toLabel(fontSize = 14)).colspan(2).padTop(20f).row()
|
||||
|
||||
addHeader("Gameplay options")
|
||||
|
||||
@ -136,8 +136,8 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
addModPopup()
|
||||
addSetUserId()
|
||||
|
||||
innerTable.add("Version".toLabel()).pad(10f)
|
||||
innerTable.add(previousScreen.game.version.toLabel()).pad(10f).row()
|
||||
innerTable2.add("Version".toLabel()).pad(10f)
|
||||
innerTable2.add(previousScreen.game.version.toLabel()).pad(10f).row()
|
||||
}
|
||||
|
||||
private fun addSetUserId() {
|
||||
@ -159,8 +159,8 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
idSetLabel.setFontColor(Color.RED).setText("Invalid ID!".tr())
|
||||
}
|
||||
}
|
||||
innerTable.add(takeUserIdFromClipboardButton).pad(5f).colspan(2).row()
|
||||
innerTable.add(idSetLabel).colspan(2).row()
|
||||
innerTable2.add(takeUserIdFromClipboardButton).pad(5f).colspan(2).row()
|
||||
innerTable2.add(idSetLabel).colspan(2).row()
|
||||
}
|
||||
|
||||
private fun addNotificationOptions() {
|
||||
@ -190,7 +190,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
generateTranslationsButton.setText("Translation files are generated successfully.".tr())
|
||||
generateTranslationsButton.disable()
|
||||
}
|
||||
innerTable.add(generateTranslationsButton).colspan(2).row()
|
||||
innerTable2.add(generateTranslationsButton).colspan(2).row()
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,11 +209,11 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
popup.addCloseButton()
|
||||
popup.open(true)
|
||||
}
|
||||
innerTable.add(generateTranslationsButton).colspan(2).row()
|
||||
innerTable2.add(generateTranslationsButton).colspan(2).row()
|
||||
}
|
||||
|
||||
private fun addSoundEffectsVolumeSlider() {
|
||||
innerTable.add("Sound effects volume".tr())
|
||||
innerTable2.add("Sound effects volume".tr())
|
||||
|
||||
val soundEffectsVolumeSlider = Slider(0f, 1.0f, 0.1f, false, skin)
|
||||
soundEffectsVolumeSlider.value = settings.soundEffectsVolume
|
||||
@ -222,13 +222,13 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
settings.save()
|
||||
Sounds.play(UncivSound.Click)
|
||||
}
|
||||
innerTable.add(soundEffectsVolumeSlider).pad(10f).row()
|
||||
innerTable2.add(soundEffectsVolumeSlider).pad(10f).row()
|
||||
}
|
||||
|
||||
private fun addMusicVolumeSlider() {
|
||||
val musicLocation = Gdx.files.local(previousScreen.game.musicLocation)
|
||||
if (musicLocation.exists()) {
|
||||
innerTable.add("Music volume".tr())
|
||||
innerTable2.add("Music volume".tr())
|
||||
|
||||
val musicVolumeSlider = Slider(0f, 1.0f, 0.1f, false, skin)
|
||||
musicVolumeSlider.value = settings.musicVolume
|
||||
@ -242,12 +242,12 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
|
||||
music?.volume = 0.4f * musicVolumeSlider.value
|
||||
}
|
||||
innerTable.add(musicVolumeSlider).pad(10f).row()
|
||||
innerTable2.add(musicVolumeSlider).pad(10f).row()
|
||||
} else {
|
||||
val downloadMusicButton = "Download music".toTextButton()
|
||||
innerTable.add(downloadMusicButton).colspan(2).row()
|
||||
innerTable2.add(downloadMusicButton).colspan(2).row()
|
||||
val errorTable = Table()
|
||||
innerTable.add(errorTable).colspan(2).row()
|
||||
innerTable2.add(errorTable).colspan(2).row()
|
||||
|
||||
downloadMusicButton.onClick {
|
||||
downloadMusicButton.disable()
|
||||
@ -275,14 +275,14 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
private fun addResolutionSelectBox() {
|
||||
innerTable.add("Resolution".toLabel())
|
||||
innerTable2.add("Resolution".toLabel())
|
||||
|
||||
val resolutionSelectBox = SelectBox<String>(skin)
|
||||
val resolutionArray = Array<String>()
|
||||
resolutionArray.addAll("750x500", "900x600", "1050x700", "1200x800", "1500x1000")
|
||||
resolutionSelectBox.items = resolutionArray
|
||||
resolutionSelectBox.selected = settings.resolution
|
||||
innerTable.add(resolutionSelectBox).minWidth(240f).pad(10f).row()
|
||||
innerTable2.add(resolutionSelectBox).minWidth(240f).pad(10f).row()
|
||||
|
||||
resolutionSelectBox.onChange {
|
||||
settings.resolution = resolutionSelectBox.selected
|
||||
@ -291,7 +291,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
private fun addTileSetSelectBox() {
|
||||
innerTable.add("Tileset".toLabel())
|
||||
innerTable2.add("Tileset".toLabel())
|
||||
|
||||
val tileSetSelectBox = SelectBox<String>(skin)
|
||||
val tileSetArray = Array<String>()
|
||||
@ -300,7 +300,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
for (tileset in tileSets) tileSetArray.add(tileset)
|
||||
tileSetSelectBox.items = tileSetArray
|
||||
tileSetSelectBox.selected = settings.tileSet
|
||||
innerTable.add(tileSetSelectBox).minWidth(240f).pad(10f).row()
|
||||
innerTable2.add(tileSetSelectBox).minWidth(240f).pad(10f).row()
|
||||
|
||||
tileSetSelectBox.onChange {
|
||||
settings.tileSet = tileSetSelectBox.selected
|
||||
@ -309,7 +309,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
private fun addAutosaveTurnsSelectBox() {
|
||||
innerTable.add("Turns between autosaves".toLabel())
|
||||
innerTable2.add("Turns between autosaves".toLabel())
|
||||
|
||||
val autosaveTurnsSelectBox = SelectBox<Int>(skin)
|
||||
val autosaveTurnsArray = Array<Int>()
|
||||
@ -317,7 +317,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
autosaveTurnsSelectBox.items = autosaveTurnsArray
|
||||
autosaveTurnsSelectBox.selected = settings.turnsBetweenAutosaves
|
||||
|
||||
innerTable.add(autosaveTurnsSelectBox).pad(10f).row()
|
||||
innerTable2.add(autosaveTurnsSelectBox).pad(10f).row()
|
||||
|
||||
autosaveTurnsSelectBox.onChange {
|
||||
settings.turnsBetweenAutosaves = autosaveTurnsSelectBox.selected
|
||||
@ -326,7 +326,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
}
|
||||
|
||||
private fun addMultiplayerTurnCheckerDelayBox() {
|
||||
innerTable.add("Time between turn checks out-of-game (in minutes)".toLabel())
|
||||
innerTable2.add("Time between turn checks out-of-game (in minutes)".toLabel())
|
||||
|
||||
val checkDelaySelectBox = SelectBox<Int>(skin)
|
||||
val possibleDelaysArray = Array<Int>()
|
||||
@ -334,7 +334,7 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
checkDelaySelectBox.items = possibleDelaysArray
|
||||
checkDelaySelectBox.selected = settings.multiplayerTurnCheckerDelayInMinutes
|
||||
|
||||
innerTable.add(checkDelaySelectBox).pad(10f).row()
|
||||
innerTable2.add(checkDelaySelectBox).pad(10f).row()
|
||||
|
||||
checkDelaySelectBox.onChange {
|
||||
settings.multiplayerTurnCheckerDelayInMinutes = checkDelaySelectBox.selected
|
||||
@ -351,11 +351,11 @@ class OptionsPopup(val previousScreen:CameraStageBaseScreen) : Popup(previousScr
|
||||
.forEach { languageArray.add(it) }
|
||||
if (languageArray.size == 0) return
|
||||
|
||||
innerTable.add("Language".toLabel())
|
||||
innerTable2.add("Language".toLabel())
|
||||
languageSelectBox.items = languageArray
|
||||
val matchingLanguage = languageArray.firstOrNull { it.language == settings.language }
|
||||
languageSelectBox.selected = if (matchingLanguage != null) matchingLanguage else languageArray.first()
|
||||
innerTable.add(languageSelectBox).minWidth(240f).pad(10f).row()
|
||||
innerTable2.add(languageSelectBox).minWidth(240f).pad(10f).row()
|
||||
|
||||
languageSelectBox.onChange {
|
||||
// Sometimes the "changed" is triggered even when we didn't choose something
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.unciv.ui.worldscreen.mainmenu
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.Constants
|
||||
import com.unciv.MainMenuScreen
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.CivilopediaScreen
|
||||
import com.unciv.ui.newgamescreen.GameSetupInfo
|
||||
import com.unciv.ui.newgamescreen.NewGameScreen
|
||||
@ -11,69 +13,52 @@ import com.unciv.ui.saves.LoadGameScreen
|
||||
import com.unciv.ui.saves.SaveGameScreen
|
||||
import com.unciv.ui.utils.Popup
|
||||
import com.unciv.ui.utils.addSeparator
|
||||
import com.unciv.ui.utils.onClick
|
||||
import com.unciv.ui.utils.toLabel
|
||||
import com.unciv.ui.victoryscreen.VictoryScreen
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
|
||||
class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||
|
||||
val buttonWidth = 200f
|
||||
val buttonHeight = 30f
|
||||
|
||||
init {
|
||||
val width = 200f
|
||||
val height = 30f
|
||||
addSquareButton("Main menu".tr()){
|
||||
worldScreen.game.setScreen(MainMenuScreen())
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
addMenuButton("Main menu") { worldScreen.game.setScreen(MainMenuScreen()) }
|
||||
addMenuButton("Civilopedia") { worldScreen.game.setScreen(CivilopediaScreen(worldScreen.gameInfo.ruleSet)) }
|
||||
addMenuButton("Save game") { worldScreen.game.setScreen(SaveGameScreen()) }
|
||||
addMenuButton("Load game") { worldScreen.game.setScreen(LoadGameScreen(worldScreen)) }
|
||||
|
||||
addSquareButton("Civilopedia".tr()){
|
||||
worldScreen.game.setScreen(CivilopediaScreen(worldScreen.gameInfo.ruleSet))
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
addMenuButton("Start new game") {
|
||||
val newGameScreen = NewGameScreen(worldScreen, GameSetupInfo(worldScreen.gameInfo))
|
||||
worldScreen.game.setScreen(newGameScreen)
|
||||
}
|
||||
|
||||
addSquareButton("Save game".tr()){
|
||||
worldScreen.game.setScreen(SaveGameScreen())
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
addMenuButton("Victory status") { worldScreen.game.setScreen(VictoryScreen(worldScreen)) }
|
||||
addMenuButton("Options") { OptionsPopup(worldScreen).open(force = true) }
|
||||
addMenuButton("Community") { WorldScreenCommunityPopup(worldScreen).open(force = true) }
|
||||
|
||||
addSquareButton("Load game".tr()){
|
||||
worldScreen.game.setScreen(LoadGameScreen(worldScreen))
|
||||
addSquareButton(Constants.close) {
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
}.size(buttonWidth, buttonHeight)
|
||||
}
|
||||
|
||||
addSquareButton("Start new game".tr()){
|
||||
worldScreen.game.setScreen(NewGameScreen(worldScreen, GameSetupInfo(worldScreen.gameInfo)))
|
||||
fun addMenuButton(text: String, action: () -> Unit) {
|
||||
addSquareButton(text) {
|
||||
action()
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
|
||||
addSquareButton("Victory status".tr()){
|
||||
worldScreen.game.setScreen(VictoryScreen(worldScreen))
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
|
||||
addSquareButton("Options".tr()){
|
||||
OptionsPopup(worldScreen).open(force = true)
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
|
||||
addSquareButton("Community"){
|
||||
WorldScreenCommunityPopup(worldScreen).open(force = true)
|
||||
close()
|
||||
}.size(width,height)
|
||||
addSeparator()
|
||||
|
||||
addSquareButton(Constants.close){
|
||||
close()
|
||||
}.size(width,height)
|
||||
}.size(buttonWidth, buttonHeight)
|
||||
innerTable.addSeparator()
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun addSquareButton(text: String, action: () -> Unit): Cell<Table> {
|
||||
val button = Table()
|
||||
button.add(text.toLabel())
|
||||
button.onClick(action)
|
||||
button.touchable = Touchable.enabled
|
||||
return add(button).apply { row() }
|
||||
}
|
||||
}
|
||||
|
||||
class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
|
||||
@ -95,4 +80,4 @@ class WorldScreenCommunityPopup(val worldScreen: WorldScreen) : Popup(worldScree
|
||||
|
||||
addCloseButton()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user