More keyboard binding work - World, World Menu Popup, WASD (#9598)

* Groundwork for tooltips for user-bindable keys

* WorldScreen keyboard revisited

* WorldScreen menu popup keyboard support

* WorldScreen WASD bindable
This commit is contained in:
SomeTroglodyte 2023-06-18 17:11:10 +02:00 committed by GitHub
parent 5e9059cd1e
commit d79c68b273
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 210 additions and 107 deletions

View File

@ -18,6 +18,8 @@ import com.unciv.GUI
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.KeyCharAndCode import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.KeyboardBindings
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
/** /**
@ -203,13 +205,15 @@ class UncivTooltip <T: Actor>(
/** /**
* Add a [Label]-based Tooltip with a rounded-corner background to a [Table] or other [Group]. * Add a [Label]-based Tooltip with a rounded-corner background to a [Table] or other [Group].
* *
* Removes any previous tooltips (so this can be used to clear tips by passing an empty [text]).
* Tip is positioned over top right corner, slightly overshooting the receiver widget, longer tip [text]s will extend to the left. * Tip is positioned over top right corner, slightly overshooting the receiver widget, longer tip [text]s will extend to the left.
* Note - since this is mainly used for keyboard tips, this is by default automatically suppressed on devices without keyboard. Use the [always] parameter to override.
* *
* @param text Automatically translated tooltip text * @param text Automatically translated tooltip text
* @param size _Vertical_ size of the entire Tooltip including background * @param size _Vertical_ size of the entire Tooltip including background
* @param always override requirement: presence of physical keyboard
* @param targetAlign Point on the [target] widget to align the Tooltip to * @param targetAlign Point on the [target] widget to align the Tooltip to
* @param tipAlign Point on the Tooltip to align with the given point on the [target] * @param tipAlign Point on the Tooltip to align with the given point on the [target]
* @param hideIcons Do not automatically add ruleset object icons during translation
*/ */
fun Actor.addTooltip( fun Actor.addTooltip(
text: String, text: String,
@ -219,6 +223,11 @@ class UncivTooltip <T: Actor>(
tipAlign: Int = Align.top, tipAlign: Int = Align.top,
hideIcons: Boolean = false hideIcons: Boolean = false
) { ) {
for (tip in listeners.filterIsInstance<UncivTooltip<*>>()) {
tip.hide(true)
removeListener(tip)
}
if (!(always || GUI.keyboardAvailable) || text.isEmpty()) return if (!(always || GUI.keyboardAvailable) || text.isEmpty()) return
val label = text.toLabel(BaseScreen.skinStrings.skinConfig.baseColor, 38, hideIcons = hideIcons) val label = text.toLabel(BaseScreen.skinStrings.skinConfig.baseColor, 38, hideIcons = hideIcons)
@ -252,28 +261,42 @@ class UncivTooltip <T: Actor>(
} }
/** /**
* Add a single Char [Label]-based Tooltip with a rounded-corner background to a [Table] or other [Group]. * Add a single-Char [Label]-based Tooltip with a rounded-corner background to a [Table] or other [Group].
* *
* Note this is automatically suppressed on devices without keyboard.
* Tip is positioned over top right corner, slightly overshooting the receiver widget. * Tip is positioned over top right corner, slightly overshooting the receiver widget.
* *
* @param size _Vertical_ size of the entire Tooltip including background * @param size _Vertical_ size of the entire Tooltip including background
* @param always override requirement: presence of physical keyboard
*/ */
fun Actor.addTooltip(char: Char, size: Float = 26f, always: Boolean = false) { fun Actor.addTooltip(char: Char, size: Float = 26f) {
addTooltip((if (char in "Ii") 'i' else char.uppercaseChar()).toString(), size, always) addTooltip((if (char in "Ii") 'i' else char.uppercaseChar()).toString(), size)
} }
/** /**
* Add a [Label]-based Tooltip for a keyboard binding with a rounded-corner background to a [Table] or other [Group]. * Add a [Label]-based Tooltip for a keyboard binding with a rounded-corner background to a [Table] or other [Group].
* *
* Note this is automatically suppressed on devices without keyboard.
* Tip is positioned over top right corner, slightly overshooting the receiver widget. * Tip is positioned over top right corner, slightly overshooting the receiver widget.
* *
* @param size _Vertical_ size of the entire Tooltip including background * @param size _Vertical_ size of the entire Tooltip including background
* @param always override requirement: presence of physical keyboard
*/ */
fun Actor.addTooltip(key: KeyCharAndCode, size: Float = 26f, always: Boolean = false) { fun Actor.addTooltip(key: KeyCharAndCode, size: Float = 26f) {
if (key != KeyCharAndCode.UNKNOWN) if (key != KeyCharAndCode.UNKNOWN)
addTooltip(key.toString().tr(), size, always) addTooltip(key.toString().tr(), size)
}
/**
* Add a [Label]-based Tooltip for a dynamic keyboard binding with a rounded-corner background to a [Table] or other [Group].
*
* Note this is automatically suppressed on devices without keyboard.
* Tip is positioned over top right corner, slightly overshooting the receiver widget.
*
* @param size _Vertical_ size of the entire Tooltip including background
*/
fun Actor.addTooltip(binding: KeyboardBinding, size: Float = 26f) {
val key = KeyboardBindings[binding]
if (key != KeyCharAndCode.UNKNOWN)
addTooltip(key.toString().tr(), size)
} }
} }
} }

View File

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.scenes.scene2d.utils.Disableable import com.badlogic.gdx.scenes.scene2d.utils.Disableable
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
/** Used to stop activation events if this returns `true`. */ /** Used to stop activation events if this returns `true`. */
internal fun Actor.isActive(): Boolean = isVisible && ((this as? Disableable)?.isDisabled != true) internal fun Actor.isActive(): Boolean = isVisible && ((this as? Disableable)?.isDisabled != true)
@ -38,6 +39,18 @@ fun Actor.onActivation(
return this return this
} }
/** Assigns an activation [handler][action] to your Widget, which reacts to clicks and a [key stroke][binding].
* A tooltip is attached automatically, if there is a keyboard and the [binding] has a mapping.
* A [sound] will be played (concurrently) on activation unless you specify [UncivSound.Silent].
* @return `this` to allow chaining
*/
fun Actor.onActivation(sound: UncivSound = UncivSound.Click, binding: KeyboardBinding, action: ActivationAction): Actor {
onActivation(ActivationTypes.Tap, sound, action = action)
keyShortcuts.add(binding)
addTooltip(binding)
return this
}
/** Routes clicks and [keyboard shortcuts][keyShortcuts] to your handler [action]. /** Routes clicks and [keyboard shortcuts][keyShortcuts] to your handler [action].
* A [sound] will be played (concurrently) on activation unless you specify [UncivSound.Silent]. * A [sound] will be played (concurrently) on activation unless you specify [UncivSound.Silent].
* @return `this` to allow chaining * @return `this` to allow chaining

View File

@ -18,34 +18,60 @@ enum class KeyboardBinding(
None(Category.None, KeyCharAndCode.UNKNOWN), None(Category.None, KeyCharAndCode.UNKNOWN),
// Worldscreen // Worldscreen
Menu(Category.WorldScreen, KeyCharAndCode.TAB),
NextTurn(Category.WorldScreen), NextTurn(Category.WorldScreen),
NextTurnAlternate(Category.WorldScreen, KeyCharAndCode.SPACE), NextTurnAlternate(Category.WorldScreen, KeyCharAndCode.SPACE),
Civilopedia(Category.WorldScreen, Input.Keys.F1),
EmpireOverview(Category.WorldScreen), EmpireOverview(Category.WorldScreen),
EmpireOverviewTrades(Category.WorldScreen, Input.Keys.F2), MusicPlayer(Category.WorldScreen, KeyCharAndCode.ctrl('m')),
EmpireOverviewUnits(Category.WorldScreen, Input.Keys.F3),
EmpireOverviewPolitics(Category.WorldScreen, Input.Keys.F4), /*
SocialPolicies(Category.WorldScreen, Input.Keys.F5), * These try to be faithful to default Civ5 key bindings as found in several places online
TechnologyTree(Category.WorldScreen, Input.Keys.F6), * Some are a little arbitrary, e.g. Economic info, Military info
EmpireOverviewNotifications(Category.WorldScreen, Input.Keys.F7), * Some are very much so as Unciv *is* Strategic View.
VictoryScreen(Category.WorldScreen, "Victory status", Input.Keys.F8), * The comments show a description like found in the mentioned sources for comparison.
EmpireOverviewStats(Category.WorldScreen, Input.Keys.F9), * @see http://gaming.stackexchange.com/questions/8122/ddg#8125
EmpireOverviewResources(Category.WorldScreen, Input.Keys.F10), */
QuickSave(Category.WorldScreen, Input.Keys.F11), Civilopedia(Category.WorldScreen, Input.Keys.F1), // Civilopedia
QuickLoad(Category.WorldScreen, Input.Keys.F12), EmpireOverviewTrades(Category.WorldScreen, Input.Keys.F2), // Economic info
ViewCapitalCity(Category.WorldScreen, Input.Keys.HOME), EmpireOverviewUnits(Category.WorldScreen, Input.Keys.F3), // Military info
Options(Category.WorldScreen, KeyCharAndCode.ctrl('o')), EmpireOverviewPolitics(Category.WorldScreen, Input.Keys.F4), // Diplomacy info
SaveGame(Category.WorldScreen, KeyCharAndCode.ctrl('s')), SocialPolicies(Category.WorldScreen, Input.Keys.F5), // Social Policies Screen
LoadGame(Category.WorldScreen, KeyCharAndCode.ctrl('l')), TechnologyTree(Category.WorldScreen, Input.Keys.F6), // Tech Screen
EmpireOverviewNotifications(Category.WorldScreen, Input.Keys.F7), // Notification Log
VictoryScreen(Category.WorldScreen, "Victory status", Input.Keys.F8), // Victory Progress
EmpireOverviewStats(Category.WorldScreen, Input.Keys.F9), // Demographics
EmpireOverviewResources(Category.WorldScreen, Input.Keys.F10), // originally Strategic View
QuickSave(Category.WorldScreen, Input.Keys.F11), // Quick Save
QuickLoad(Category.WorldScreen, Input.Keys.F12), // Quick Load
ViewCapitalCity(Category.WorldScreen, Input.Keys.HOME), // Capital City View
Options(Category.WorldScreen, KeyCharAndCode.ctrl('o')), // Game Options
SaveGame(Category.WorldScreen, KeyCharAndCode.ctrl('s')), // Save
LoadGame(Category.WorldScreen, KeyCharAndCode.ctrl('l')), // Load
ToggleResourceDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('r')), // Show Resources Icons
ToggleYieldDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('y')), // Yield Icons, originally just "Y"
// End of Civ5-inspired bindings
QuitGame(Category.WorldScreen, KeyCharAndCode.ctrl('q')), QuitGame(Category.WorldScreen, KeyCharAndCode.ctrl('q')),
NewGame(Category.WorldScreen, KeyCharAndCode.ctrl('n')),
Diplomacy(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
Espionage(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
Undo(Category.WorldScreen, KeyCharAndCode.ctrl('z')),
ToggleUI(Category.WorldScreen, "Toggle UI", KeyCharAndCode.ctrl('u')), ToggleUI(Category.WorldScreen, "Toggle UI", KeyCharAndCode.ctrl('u')),
ToggleResourceDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('r')),
ToggleYieldDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('y')),
ToggleWorkedTilesDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN), ToggleWorkedTilesDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
ToggleMovementDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN), ToggleMovementDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
ZoomIn(Category.WorldScreen, Input.Keys.NUMPAD_ADD), ZoomIn(Category.WorldScreen, Input.Keys.NUMPAD_ADD),
ZoomOut(Category.WorldScreen, Input.Keys.NUMPAD_SUBTRACT), ZoomOut(Category.WorldScreen, Input.Keys.NUMPAD_SUBTRACT),
// Map Panning - separate to get own expander. Map editor use will need to check this - it's arrows only
PanUp(Category.MapPanning, Input.Keys.UP),
PanLeft(Category.MapPanning, Input.Keys.LEFT),
PanDown(Category.MapPanning, Input.Keys.DOWN),
PanRight(Category.MapPanning, Input.Keys.RIGHT),
PanUpAlternate(Category.MapPanning, 'W'),
PanLeftAlternate(Category.MapPanning, 'A'),
PanDownAlternate(Category.MapPanning, 'S'),
PanRightAlternate(Category.MapPanning, 'D'),
// Unit actions - name MUST correspond to UnitActionType.name because the shorthand constructor // Unit actions - name MUST correspond to UnitActionType.name because the shorthand constructor
// there looks up bindings here by name - which also means we must not use UnitActionType // there looks up bindings here by name - which also means we must not use UnitActionType
// here as it will not be guaranteed to already be fully initialized. // here as it will not be guaranteed to already be fully initialized.
@ -97,7 +123,10 @@ enum class KeyboardBinding(
None, None,
WorldScreen { WorldScreen {
// Conflict checking within group plus keys assigned to UnitActions are a problem // Conflict checking within group plus keys assigned to UnitActions are a problem
override fun checkConflictsIn() = sequenceOf(this, UnitActions) override fun checkConflictsIn() = sequenceOf(this, MapPanning, UnitActions)
},
MapPanning {
override fun checkConflictsIn() = sequenceOf(this, WorldScreen)
}, },
UnitActions { UnitActions {
// Conflict checking within group disabled, but any key assigned on WorldScreen is a problem // Conflict checking within group disabled, but any key assigned on WorldScreen is a problem

View File

@ -20,9 +20,19 @@ class KeyboardPanningListener(
private val pressedKeys = mutableSetOf<Int>() private val pressedKeys = mutableSetOf<Int>()
private var infiniteAction: RepeatAction? = null private var infiniteAction: RepeatAction? = null
private val keycodeUp = KeyboardBindings[KeyboardBinding.PanUp].code
private val keycodeLeft = KeyboardBindings[KeyboardBinding.PanLeft].code
private val keycodeDown = KeyboardBindings[KeyboardBinding.PanDown].code
private val keycodeRight = KeyboardBindings[KeyboardBinding.PanRight].code
private val keycodeUpAlt = KeyboardBindings[KeyboardBinding.PanUpAlternate].code
private val keycodeLeftAlt = KeyboardBindings[KeyboardBinding.PanLeftAlternate].code
private val keycodeDownAlt = KeyboardBindings[KeyboardBinding.PanDownAlternate].code
private val keycodeRightAlt = KeyboardBindings[KeyboardBinding.PanRightAlternate].code
private val allowedKeys = private val allowedKeys =
setOf(Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT) + ( setOf(keycodeUp, keycodeLeft, keycodeDown, keycodeRight) + (
if (allowWASD) setOf(Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D) if (allowWASD) setOf(keycodeUpAlt, keycodeLeftAlt, keycodeDownAlt, keycodeRightAlt)
else setOf() else setOf()
) )
@ -70,10 +80,10 @@ class KeyboardPanningListener(
var deltaY = 0f var deltaY = 0f
for (keycode in pressedKeys) { for (keycode in pressedKeys) {
when (keycode) { when (keycode) {
Input.Keys.W, Input.Keys.UP -> deltaY -= 1f keycodeUp, keycodeUpAlt -> deltaY -= 1f
Input.Keys.S, Input.Keys.DOWN -> deltaY += 1f keycodeDown, keycodeDownAlt -> deltaY += 1f
Input.Keys.A, Input.Keys.LEFT -> deltaX += 1f keycodeLeft, keycodeLeftAlt -> deltaX += 1f
Input.Keys.D, Input.Keys.RIGHT -> deltaX -= 1f keycodeRight, keycodeRightAlt -> deltaX -= 1f
} }
} }
mapHolder.doKeyOrMousePanning(deltaX, deltaY) mapHolder.doKeyOrMousePanning(deltaX, deltaY)

View File

@ -20,16 +20,20 @@ import com.badlogic.gdx.utils.Align
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.event.EventBus import com.unciv.logic.event.EventBus
import com.unciv.ui.components.AutoScrollPane import com.unciv.ui.components.AutoScrollPane
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.KeyboardBindings
import com.unciv.ui.components.extensions.addSeparator import com.unciv.ui.components.extensions.addSeparator
import com.unciv.ui.components.extensions.center import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.darken import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.KeyboardBindings
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.popups.Popup.Scrollability
import com.unciv.ui.popups.Popup.Scrollability.All
import com.unciv.ui.popups.Popup.Scrollability.None
import com.unciv.ui.popups.Popup.Scrollability.WithoutButtons
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.basescreen.UncivStage import com.unciv.ui.screens.basescreen.UncivStage
@ -292,6 +296,11 @@ open class Popup(
@Suppress("unused") // Keep the offer to pass an Input.keys value @Suppress("unused") // Keep the offer to pass an Input.keys value
fun addButton(text: String, key: Int, style: TextButtonStyle? = null, action: () -> Unit) fun addButton(text: String, key: Int, style: TextButtonStyle? = null, action: () -> Unit)
= addButton(text, KeyCharAndCode(key), style, action).apply { row() } = addButton(text, KeyCharAndCode(key), style, action).apply { row() }
fun addButton(text: String, binding: KeyboardBinding, style: TextButtonStyle? = null, action: () -> Unit): Cell<TextButton> {
val button = text.toTextButton(style)
button.onActivation(binding = binding) { action() }
return bottomTable.add(button)
}
/** /**
* Adds a [TextButton] that closes the popup, with [BACK][KeyCharAndCode.BACK] already mapped. * Adds a [TextButton] that closes the popup, with [BACK][KeyCharAndCode.BACK] already mapped.

View File

@ -7,10 +7,10 @@ import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.components.ExpanderTab import com.unciv.ui.components.ExpanderTab
import com.unciv.ui.components.KeyCapturingButton import com.unciv.ui.components.KeyCapturingButton
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.TabbedPager import com.unciv.ui.components.TabbedPager
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.civilopediascreen.FormattedLine import com.unciv.ui.screens.civilopediascreen.FormattedLine
@ -109,7 +109,7 @@ class KeyBindingsTab(
} }
} }
fun save () { fun save() {
for ((binding, widget) in groupedWidgets.asSequence().flatMap { it.value.entries }) { for ((binding, widget) in groupedWidgets.asSequence().flatMap { it.value.entries }) {
keyBindings[binding] = widget.current keyBindings[binding] = widget.current
} }

View File

@ -20,9 +20,9 @@ import com.unciv.models.TutorialTrigger
import com.unciv.models.skins.SkinStrings import com.unciv.models.skins.SkinStrings
import com.unciv.ui.components.Fonts import com.unciv.ui.components.Fonts
import com.unciv.ui.components.extensions.isNarrowerThan4to3 import com.unciv.ui.components.extensions.isNarrowerThan4to3
import com.unciv.ui.components.input.DispatcherVetoer
import com.unciv.ui.components.input.KeyShortcutDispatcher import com.unciv.ui.components.input.KeyShortcutDispatcher
import com.unciv.ui.components.input.KeyShortcutDispatcherVeto import com.unciv.ui.components.input.KeyShortcutDispatcherVeto
import com.unciv.ui.components.input.DispatcherVetoer
import com.unciv.ui.components.input.installShortcutDispatcher import com.unciv.ui.components.input.installShortcutDispatcher
import com.unciv.ui.components.input.keyShortcuts import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.crashhandling.CrashScreen import com.unciv.ui.crashhandling.CrashScreen
@ -174,7 +174,7 @@ abstract class BaseScreen : Screen {
/** @return `true` if the screen is narrower than 4:3 landscape */ /** @return `true` if the screen is narrower than 4:3 landscape */
fun isNarrowerThan4to3() = stage.isNarrowerThan4to3() fun isNarrowerThan4to3() = stage.isNarrowerThan4to3()
fun openOptionsPopup(startingPage: Int = OptionsPopup.defaultPage, onClose: () -> Unit = {}) { open fun openOptionsPopup(startingPage: Int = OptionsPopup.defaultPage, onClose: () -> Unit = {}) {
OptionsPopup(this, startingPage, onClose).open(force = true) OptionsPopup(this, startingPage, onClose).open(force = true)
} }
} }

View File

@ -9,8 +9,10 @@ import com.unciv.models.UncivSound
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
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.input.onClick import com.unciv.ui.components.extensions.disable
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.onActivation
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.screens.diplomacyscreen.DiplomacyScreen import com.unciv.ui.screens.diplomacyscreen.DiplomacyScreen
@ -51,31 +53,28 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
pickTechButton.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/PickTechButton", BaseScreen.skinStrings.roundedEdgeRectangleShape, colorFromRGB(7, 46, 43)) pickTechButton.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/PickTechButton", BaseScreen.skinStrings.roundedEdgeRectangleShape, colorFromRGB(7, 46, 43))
pickTechButton.defaults().pad(20f) pickTechButton.defaults().pad(20f)
pickTechButton.add(pickTechLabel) pickTechButton.add(pickTechLabel)
techButtonHolder.onClick(UncivSound.Paper) { techButtonHolder.onActivation(UncivSound.Paper, KeyboardBinding.TechnologyTree) {
game.pushScreen(TechPickerScreen(viewingCiv)) game.pushScreen(TechPickerScreen(viewingCiv))
} }
undoButton.add(ImageGetter.getImage("OtherIcons/Resume")).size(30f).pad(15f) undoButton.add(ImageGetter.getImage("OtherIcons/Resume")).size(30f).pad(15f)
undoButton.onClick { undoButton.onActivation(binding = KeyboardBinding.Undo) {
Concurrency.run { handleUndo()
// Most of the time we won't load this, so we only set transients once we see it's relevant
worldScreen.preActionGameInfo.setTransients()
game.loadGame(worldScreen.preActionGameInfo)
}
} }
policyScreenButton.add(ImageGetter.getImage("PolicyIcons/Constitution")).size(30f).pad(15f) policyScreenButton.add(ImageGetter.getImage("PolicyIcons/Constitution")).size(30f).pad(15f)
policyButtonHolder.onClick { policyButtonHolder.onActivation(binding = KeyboardBinding.SocialPolicies) {
game.pushScreen(PolicyPickerScreen(worldScreen.selectedCiv, worldScreen.canChangeState)) game.pushScreen(PolicyPickerScreen(worldScreen.selectedCiv, worldScreen.canChangeState))
} }
diplomacyButton.add(ImageGetter.getImage("OtherIcons/DiplomacyW")).size(30f).pad(15f) diplomacyButton.add(ImageGetter.getImage("OtherIcons/DiplomacyW")).size(30f).pad(15f)
diplomacyButtonHolder.onClick { diplomacyButtonHolder.onActivation(binding = KeyboardBinding.Diplomacy) {
game.pushScreen(DiplomacyScreen(viewingCiv)) game.pushScreen(DiplomacyScreen(viewingCiv))
} }
if (game.gameInfo!!.isEspionageEnabled()) { if (game.gameInfo!!.isEspionageEnabled()) {
espionageButton.add(ImageGetter.getImage("OtherIcons/Spy_White")).size(30f).pad(15f) espionageButton.add(ImageGetter.getImage("OtherIcons/Spy_White")).size(30f).pad(15f)
espionageButtonHolder.onClick { espionageButtonHolder.onActivation(binding = KeyboardBinding.Espionage) {
game.pushScreen(EspionageOverviewScreen(viewingCiv)) game.pushScreen(EspionageOverviewScreen(viewingCiv))
} }
} }
@ -162,4 +161,13 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
espionageButtonHolder.actor = espionageButton espionageButtonHolder.actor = espionageButton
} }
} }
private fun handleUndo() {
undoButton.disable()
Concurrency.run {
// Most of the time we won't load this, so we only set transients once we see it's relevant
worldScreen.preActionGameInfo.setTransients()
game.loadGame(worldScreen.preActionGameInfo)
}
}
} }

View File

@ -21,19 +21,20 @@ import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
import com.unciv.logic.trade.TradeEvaluation import com.unciv.logic.trade.TradeEvaluation
import com.unciv.models.TutorialTrigger import com.unciv.models.TutorialTrigger
import com.unciv.models.metadata.GameSetupInfo
import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.KeyboardPanningListener
import com.unciv.ui.components.extensions.centerX import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.darken import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.extensions.isEnabled import com.unciv.ui.components.extensions.isEnabled
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.setFontSize import com.unciv.ui.components.extensions.setFontSize
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyShortcutDispatcherVeto import com.unciv.ui.components.input.KeyShortcutDispatcherVeto
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.KeyboardPanningListener
import com.unciv.ui.components.input.onClick
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.AuthPopup import com.unciv.ui.popups.AuthPopup
import com.unciv.ui.popups.Popup import com.unciv.ui.popups.Popup
@ -43,18 +44,18 @@ import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.cityscreen.CityScreen import com.unciv.ui.screens.cityscreen.CityScreen
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.mainmenuscreen.MainMenuScreen import com.unciv.ui.screens.mainmenuscreen.MainMenuScreen
import com.unciv.ui.screens.newgamescreen.NewGameScreen
import com.unciv.ui.screens.overviewscreen.EmpireOverviewCategories import com.unciv.ui.screens.overviewscreen.EmpireOverviewCategories
import com.unciv.ui.screens.overviewscreen.EmpireOverviewScreen import com.unciv.ui.screens.overviewscreen.EmpireOverviewScreen
import com.unciv.ui.screens.pickerscreens.DiplomaticVoteResultScreen import com.unciv.ui.screens.pickerscreens.DiplomaticVoteResultScreen
import com.unciv.ui.screens.pickerscreens.GreatPersonPickerScreen import com.unciv.ui.screens.pickerscreens.GreatPersonPickerScreen
import com.unciv.ui.screens.pickerscreens.PolicyPickerScreen
import com.unciv.ui.screens.pickerscreens.TechPickerScreen
import com.unciv.ui.screens.savescreens.LoadGameScreen import com.unciv.ui.screens.savescreens.LoadGameScreen
import com.unciv.ui.screens.savescreens.QuickSave import com.unciv.ui.screens.savescreens.QuickSave
import com.unciv.ui.screens.savescreens.SaveGameScreen import com.unciv.ui.screens.savescreens.SaveGameScreen
import com.unciv.ui.screens.victoryscreen.VictoryScreen import com.unciv.ui.screens.victoryscreen.VictoryScreen
import com.unciv.ui.screens.worldscreen.bottombar.BattleTable import com.unciv.ui.screens.worldscreen.bottombar.BattleTable
import com.unciv.ui.screens.worldscreen.bottombar.TileInfoTable import com.unciv.ui.screens.worldscreen.bottombar.TileInfoTable
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMusicPopup
import com.unciv.ui.screens.worldscreen.minimap.MinimapHolder import com.unciv.ui.screens.worldscreen.minimap.MinimapHolder
import com.unciv.ui.screens.worldscreen.status.MultiplayerStatusButton import com.unciv.ui.screens.worldscreen.status.MultiplayerStatusButton
import com.unciv.ui.screens.worldscreen.status.NextTurnButton import com.unciv.ui.screens.worldscreen.status.NextTurnButton
@ -63,10 +64,10 @@ import com.unciv.ui.screens.worldscreen.status.StatusButtons
import com.unciv.ui.screens.worldscreen.unit.UnitTable import com.unciv.ui.screens.worldscreen.unit.UnitTable
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsTable import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsTable
import com.unciv.utils.Concurrency import com.unciv.utils.Concurrency
import com.unciv.utils.debug
import com.unciv.utils.launchOnGLThread import com.unciv.utils.launchOnGLThread
import com.unciv.utils.launchOnThreadPool import com.unciv.utils.launchOnThreadPool
import com.unciv.utils.withGLContext import com.unciv.utils.withGLContext
import com.unciv.utils.debug
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@ -224,27 +225,27 @@ class WorldScreen(
game.pushScreen(EmpireOverviewScreen(selectedCiv, category)) game.pushScreen(EmpireOverviewScreen(selectedCiv, category))
} }
fun openNewGameScreen() {
val newGameSetupInfo = GameSetupInfo(gameInfo)
newGameSetupInfo.mapParameters.reseed()
val newGameScreen = NewGameScreen(newGameSetupInfo)
game.pushScreen(newGameScreen)
}
private fun addKeyboardPresses() { private fun addKeyboardPresses() {
// Space and N are assigned in NextTurnButton constructor // Space and N are assigned in NextTurnButton constructor
// Functions that have a big button are assigned there (WorldScreenTopBar, TechPolicyDiplomacyButtons..)
globalShortcuts.add(KeyboardBinding.Civilopedia) { game.pushScreen(CivilopediaScreen(gameInfo.ruleset)) } globalShortcuts.add(KeyboardBinding.Civilopedia) { game.pushScreen(CivilopediaScreen(gameInfo.ruleset)) }
globalShortcuts.add(KeyboardBinding.EmpireOverview) { openEmpireOverview() } // Empire overview last used page globalShortcuts.add(KeyboardBinding.EmpireOverviewTrades) { openEmpireOverview(EmpireOverviewCategories.Trades) }
/* globalShortcuts.add(KeyboardBinding.EmpireOverviewUnits) { openEmpireOverview(EmpireOverviewCategories.Units) }
* These try to be faithful to default Civ5 key bindings as found in several places online globalShortcuts.add(KeyboardBinding.EmpireOverviewPolitics) { openEmpireOverview(EmpireOverviewCategories.Politics) }
* Some are a little arbitrary, e.g. Economic info, Military info globalShortcuts.add(KeyboardBinding.EmpireOverviewNotifications) { openEmpireOverview(EmpireOverviewCategories.Notifications) }
* Some are very much so as Unciv *is* Strategic View globalShortcuts.add(KeyboardBinding.VictoryScreen) { game.pushScreen(VictoryScreen(this)) }
*/ globalShortcuts.add(KeyboardBinding.EmpireOverviewStats) { openEmpireOverview(EmpireOverviewCategories.Stats) }
globalShortcuts.add(KeyboardBinding.EmpireOverviewTrades) { openEmpireOverview(EmpireOverviewCategories.Trades) } // Economic info globalShortcuts.add(KeyboardBinding.EmpireOverviewResources) { openEmpireOverview(EmpireOverviewCategories.Resources) }
globalShortcuts.add(KeyboardBinding.EmpireOverviewUnits) { openEmpireOverview(EmpireOverviewCategories.Units) } // Military info globalShortcuts.add(KeyboardBinding.QuickSave) { QuickSave.save(gameInfo, this) }
globalShortcuts.add(KeyboardBinding.EmpireOverviewPolitics) { openEmpireOverview(EmpireOverviewCategories.Politics) } // Diplomacy info globalShortcuts.add(KeyboardBinding.QuickLoad) { QuickSave.load(this) }
globalShortcuts.add(KeyboardBinding.SocialPolicies) { game.pushScreen(PolicyPickerScreen(selectedCiv, canChangeState)) } // Social Policies Screen globalShortcuts.add(KeyboardBinding.ViewCapitalCity) {
globalShortcuts.add(KeyboardBinding.TechnologyTree) { game.pushScreen(TechPickerScreen(viewingCiv)) } // Tech Screen
globalShortcuts.add(KeyboardBinding.EmpireOverviewNotifications) { openEmpireOverview(EmpireOverviewCategories.Notifications) } // Notification Log
globalShortcuts.add(KeyboardBinding.VictoryScreen) { game.pushScreen(VictoryScreen(this)) } // Victory Progress
globalShortcuts.add(KeyboardBinding.EmpireOverviewStats) { openEmpireOverview(EmpireOverviewCategories.Stats) } // Demographics
globalShortcuts.add(KeyboardBinding.EmpireOverviewResources) { openEmpireOverview(EmpireOverviewCategories.Resources) } // originally Strategic View
globalShortcuts.add(KeyboardBinding.QuickSave) { QuickSave.save(gameInfo, this) } // Quick Save
globalShortcuts.add(KeyboardBinding.QuickLoad) { QuickSave.load(this) } // Quick Load
globalShortcuts.add(KeyboardBinding.ViewCapitalCity) { // Capital City View
val capital = gameInfo.getCurrentPlayerCivilization().getCapital() val capital = gameInfo.getCurrentPlayerCivilization().getCapital()
if (capital != null && !mapHolder.setCenterPosition(capital.location)) if (capital != null && !mapHolder.setCenterPosition(capital.location))
game.pushScreen(CityScreen(capital)) game.pushScreen(CityScreen(capital))
@ -257,6 +258,10 @@ class WorldScreen(
globalShortcuts.add(KeyboardBinding.SaveGame) { game.pushScreen(SaveGameScreen(gameInfo)) } // Save globalShortcuts.add(KeyboardBinding.SaveGame) { game.pushScreen(SaveGameScreen(gameInfo)) } // Save
globalShortcuts.add(KeyboardBinding.LoadGame) { game.pushScreen(LoadGameScreen()) } // Load globalShortcuts.add(KeyboardBinding.LoadGame) { game.pushScreen(LoadGameScreen()) } // Load
globalShortcuts.add(KeyboardBinding.QuitGame) { game.popScreen() } // WorldScreen is the last screen, so this quits globalShortcuts.add(KeyboardBinding.QuitGame) { game.popScreen() } // WorldScreen is the last screen, so this quits
globalShortcuts.add(KeyboardBinding.NewGame) { openNewGameScreen() }
globalShortcuts.add(KeyboardBinding.MusicPlayer) {
WorldScreenMusicPopup(this).open(force = true)
}
globalShortcuts.add(Input.Keys.NUMPAD_ADD) { this.mapHolder.zoomIn() } // '+' Zoom globalShortcuts.add(Input.Keys.NUMPAD_ADD) { this.mapHolder.zoomIn() } // '+' Zoom
globalShortcuts.add(Input.Keys.NUMPAD_SUBTRACT) { this.mapHolder.zoomOut() } // '-' Zoom globalShortcuts.add(Input.Keys.NUMPAD_SUBTRACT) { this.mapHolder.zoomOut() } // '-' Zoom
globalShortcuts.add(KeyboardBinding.ToggleUI) { toggleUI() } globalShortcuts.add(KeyboardBinding.ToggleUI) { toggleUI() }
@ -266,6 +271,16 @@ class WorldScreen(
globalShortcuts.add(KeyboardBinding.ToggleMovementDisplay) { minimapWrapper.movementsImageButton.toggle() } globalShortcuts.add(KeyboardBinding.ToggleMovementDisplay) { minimapWrapper.movementsImageButton.toggle() }
} }
// Handle disabling and re-enabling WASD listener while Options are open
override fun openOptionsPopup(startingPage: Int, onClose: () -> Unit) {
val oldListener = stage.root.listeners.filterIsInstance<KeyboardPanningListener>().firstOrNull()
if (oldListener != null) stage.removeListener(oldListener)
super.openOptionsPopup(startingPage) {
addKeyboardListener()
onClose()
}
}
private fun toggleUI() { private fun toggleUI() {
uiEnabled = !uiEnabled uiEnabled = !uiEnabled
topBar.isVisible = uiEnabled topBar.isVisible = uiEnabled

View File

@ -16,18 +16,18 @@ import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.components.Fonts import com.unciv.ui.components.Fonts
import com.unciv.ui.components.MayaCalendar import com.unciv.ui.components.MayaCalendar
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.YearTextUtil import com.unciv.ui.components.YearTextUtil
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
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.setFontColor import com.unciv.ui.components.extensions.setFontColor
import com.unciv.ui.components.extensions.setFontSize import com.unciv.ui.components.extensions.setFontSize
import com.unciv.ui.components.extensions.toLabel import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toStringSigned import com.unciv.ui.components.extensions.toStringSigned
import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.input.onClick
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.popups
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
@ -180,8 +180,9 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
} }
val overviewButton = "Overview".toTextButton() val overviewButton = "Overview".toTextButton()
overviewButton.addTooltip('e') overviewButton.onActivation(binding = KeyboardBinding.EmpireOverview) {
overviewButton.onClick { worldScreen.openEmpireOverview() } worldScreen.openEmpireOverview()
}
unitSupplyCell = add() unitSupplyCell = add()
add(overviewButton).pad(10f) add(overviewButton).pad(10f)
@ -209,10 +210,8 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
defaults().pad(10f) defaults().pad(10f)
menuButton.color = Color.WHITE menuButton.color = Color.WHITE
menuButton.onClick { menuButton.onActivation(binding = KeyboardBinding.Menu) {
val worldScreenMenuPopup = worldScreen.popups.firstOrNull { it is WorldScreenMenuPopup } WorldScreenMenuPopup(worldScreen).open(force = true)
if (worldScreenMenuPopup != null) worldScreenMenuPopup.close()
else WorldScreenMenuPopup(worldScreen).open(force = true)
} }
selectedCivLabel.setFontSize(25) selectedCivLabel.setFontSize(25)

View File

@ -1,9 +1,8 @@
package com.unciv.ui.screens.worldscreen.mainmenu package com.unciv.ui.screens.worldscreen.mainmenu
import com.unciv.models.metadata.GameSetupInfo import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.popups.Popup import com.unciv.ui.popups.Popup
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.newgamescreen.NewGameScreen
import com.unciv.ui.screens.savescreens.LoadGameScreen import com.unciv.ui.screens.savescreens.LoadGameScreen
import com.unciv.ui.screens.savescreens.SaveGameScreen import com.unciv.ui.screens.savescreens.SaveGameScreen
import com.unciv.ui.screens.victoryscreen.VictoryScreen import com.unciv.ui.screens.victoryscreen.VictoryScreen
@ -16,32 +15,27 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, sc
addButton("Main menu") { addButton("Main menu") {
worldScreen.game.goToMainMenu() worldScreen.game.goToMainMenu()
}.row() }.row()
addButton("Civilopedia") { addButton("Civilopedia", KeyboardBinding.Civilopedia) {
close() close()
worldScreen.game.pushScreen(CivilopediaScreen(worldScreen.gameInfo.ruleset)) worldScreen.game.pushScreen(CivilopediaScreen(worldScreen.gameInfo.ruleset))
}.row() }.row()
addButton("Save game") { addButton("Save game", KeyboardBinding.SaveGame) {
close() close()
worldScreen.game.pushScreen(SaveGameScreen(worldScreen.gameInfo)) worldScreen.game.pushScreen(SaveGameScreen(worldScreen.gameInfo))
}.row() }.row()
addButton("Load game") { addButton("Load game", KeyboardBinding.LoadGame) {
close() close()
worldScreen.game.pushScreen(LoadGameScreen()) worldScreen.game.pushScreen(LoadGameScreen())
}.row() }.row()
addButton("Start new game", KeyboardBinding.NewGame) {
addButton("Start new game") {
close() close()
val newGameSetupInfo = GameSetupInfo(worldScreen.gameInfo) worldScreen.openNewGameScreen()
newGameSetupInfo.mapParameters.reseed()
val newGameScreen = NewGameScreen(newGameSetupInfo)
worldScreen.game.pushScreen(newGameScreen)
}.row() }.row()
addButton("Victory status", KeyboardBinding.VictoryScreen) {
addButton("Victory status") {
close() close()
worldScreen.game.pushScreen(VictoryScreen(worldScreen)) worldScreen.game.pushScreen(VictoryScreen(worldScreen))
}.row() }.row()
addButton("Options") { addButton("Options", KeyboardBinding.Options) {
close() close()
worldScreen.openOptionsPopup() worldScreen.openOptionsPopup()
}.row() }.row()
@ -49,10 +43,11 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, sc
close() close()
WorldScreenCommunityPopup(worldScreen).open(force = true) WorldScreenCommunityPopup(worldScreen).open(force = true)
}.row() }.row()
addButton("Music") { addButton("Music", KeyboardBinding.MusicPlayer) {
close() close()
WorldScreenMusicPopup(worldScreen).open(force = true) WorldScreenMusicPopup(worldScreen).open(force = true)
}.row() }.row()
addCloseButton() addCloseButton()
pack() pack()
} }

View File

@ -5,13 +5,14 @@ import com.unciv.Constants
import com.unciv.logic.civilization.managers.ReligionState import com.unciv.logic.civilization.managers.ReligionState
import com.unciv.models.ruleset.BeliefType import com.unciv.models.ruleset.BeliefType
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.components.input.KeyboardBinding import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.disable import com.unciv.ui.components.extensions.disable
import com.unciv.ui.components.extensions.enable import com.unciv.ui.components.extensions.enable
import com.unciv.ui.components.extensions.isEnabled import com.unciv.ui.components.extensions.isEnabled
import com.unciv.ui.components.extensions.setSize
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.keyShortcuts import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.extensions.setSize
import com.unciv.ui.images.IconTextButton import com.unciv.ui.images.IconTextButton
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.ConfirmPopup import com.unciv.ui.popups.ConfirmPopup
@ -45,6 +46,8 @@ class NextTurnButton : IconTextButton("", null, 30) {
isEnabled = !worldScreen.hasOpenPopups() && worldScreen.isPlayersTurn isEnabled = !worldScreen.hasOpenPopups() && worldScreen.isPlayersTurn
&& !worldScreen.waitingForAutosave && !worldScreen.isNextTurnUpdateRunning() && !worldScreen.waitingForAutosave && !worldScreen.isNextTurnUpdateRunning()
if (isEnabled) addTooltip(KeyboardBinding.NextTurn) else addTooltip("")
} }
internal fun updateButton(nextTurnAction: NextTurnAction) { internal fun updateButton(nextTurnAction: NextTurnAction) {
label.setText(nextTurnAction.text.tr()) label.setText(nextTurnAction.text.tr())

View File

@ -12,7 +12,6 @@ import com.unciv.models.UnitActionType
import com.unciv.models.UpgradeUnitAction import com.unciv.models.UpgradeUnitAction
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.disable import com.unciv.ui.components.extensions.disable
import com.unciv.ui.components.input.KeyboardBindings
import com.unciv.ui.components.input.keyShortcuts import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.input.onRightClick import com.unciv.ui.components.input.onRightClick
@ -53,7 +52,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
if (unitAction.type == UnitActionType.Promote && unitAction.action != null) if (unitAction.type == UnitActionType.Promote && unitAction.action != null)
actionButton.color = Color.GREEN.cpy().lerp(Color.WHITE, 0.5f) actionButton.color = Color.GREEN.cpy().lerp(Color.WHITE, 0.5f)
actionButton.addTooltip(KeyboardBindings[binding]) actionButton.addTooltip(binding)
actionButton.pack() actionButton.pack()
if (unitAction.action == null) { if (unitAction.action == null) {