mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 05:46:43 -04:00
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:
parent
5e9059cd1e
commit
d79c68b273
@ -18,6 +18,8 @@ import com.unciv.GUI
|
||||
import com.unciv.models.translations.tr
|
||||
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.components.input.KeyboardBindings
|
||||
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].
|
||||
*
|
||||
* 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.
|
||||
* 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 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 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(
|
||||
text: String,
|
||||
@ -219,6 +223,11 @@ class UncivTooltip <T: Actor>(
|
||||
tipAlign: Int = Align.top,
|
||||
hideIcons: Boolean = false
|
||||
) {
|
||||
for (tip in listeners.filterIsInstance<UncivTooltip<*>>()) {
|
||||
tip.hide(true)
|
||||
removeListener(tip)
|
||||
}
|
||||
|
||||
if (!(always || GUI.keyboardAvailable) || text.isEmpty()) return
|
||||
|
||||
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.
|
||||
*
|
||||
* @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) {
|
||||
addTooltip((if (char in "Ii") 'i' else char.uppercaseChar()).toString(), size, always)
|
||||
fun Actor.addTooltip(char: Char, size: Float = 26f) {
|
||||
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].
|
||||
*
|
||||
* 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
|
||||
* @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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.Disableable
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
|
||||
/** Used to stop activation events if this returns `true`. */
|
||||
internal fun Actor.isActive(): Boolean = isVisible && ((this as? Disableable)?.isDisabled != true)
|
||||
@ -38,6 +39,18 @@ fun Actor.onActivation(
|
||||
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].
|
||||
* A [sound] will be played (concurrently) on activation unless you specify [UncivSound.Silent].
|
||||
* @return `this` to allow chaining
|
||||
|
@ -18,34 +18,60 @@ enum class KeyboardBinding(
|
||||
None(Category.None, KeyCharAndCode.UNKNOWN),
|
||||
|
||||
// Worldscreen
|
||||
Menu(Category.WorldScreen, KeyCharAndCode.TAB),
|
||||
NextTurn(Category.WorldScreen),
|
||||
NextTurnAlternate(Category.WorldScreen, KeyCharAndCode.SPACE),
|
||||
Civilopedia(Category.WorldScreen, Input.Keys.F1),
|
||||
EmpireOverview(Category.WorldScreen),
|
||||
EmpireOverviewTrades(Category.WorldScreen, Input.Keys.F2),
|
||||
EmpireOverviewUnits(Category.WorldScreen, Input.Keys.F3),
|
||||
EmpireOverviewPolitics(Category.WorldScreen, Input.Keys.F4),
|
||||
SocialPolicies(Category.WorldScreen, Input.Keys.F5),
|
||||
TechnologyTree(Category.WorldScreen, Input.Keys.F6),
|
||||
EmpireOverviewNotifications(Category.WorldScreen, Input.Keys.F7),
|
||||
VictoryScreen(Category.WorldScreen, "Victory status", Input.Keys.F8),
|
||||
EmpireOverviewStats(Category.WorldScreen, Input.Keys.F9),
|
||||
EmpireOverviewResources(Category.WorldScreen, Input.Keys.F10),
|
||||
QuickSave(Category.WorldScreen, Input.Keys.F11),
|
||||
QuickLoad(Category.WorldScreen, Input.Keys.F12),
|
||||
ViewCapitalCity(Category.WorldScreen, Input.Keys.HOME),
|
||||
Options(Category.WorldScreen, KeyCharAndCode.ctrl('o')),
|
||||
SaveGame(Category.WorldScreen, KeyCharAndCode.ctrl('s')),
|
||||
LoadGame(Category.WorldScreen, KeyCharAndCode.ctrl('l')),
|
||||
MusicPlayer(Category.WorldScreen, KeyCharAndCode.ctrl('m')),
|
||||
|
||||
/*
|
||||
* These try to be faithful to default Civ5 key bindings as found in several places online
|
||||
* Some are a little arbitrary, e.g. Economic info, Military info
|
||||
* Some are very much so as Unciv *is* Strategic View.
|
||||
* The comments show a description like found in the mentioned sources for comparison.
|
||||
* @see http://gaming.stackexchange.com/questions/8122/ddg#8125
|
||||
*/
|
||||
Civilopedia(Category.WorldScreen, Input.Keys.F1), // Civilopedia
|
||||
EmpireOverviewTrades(Category.WorldScreen, Input.Keys.F2), // Economic info
|
||||
EmpireOverviewUnits(Category.WorldScreen, Input.Keys.F3), // Military info
|
||||
EmpireOverviewPolitics(Category.WorldScreen, Input.Keys.F4), // Diplomacy info
|
||||
SocialPolicies(Category.WorldScreen, Input.Keys.F5), // Social Policies Screen
|
||||
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')),
|
||||
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')),
|
||||
ToggleResourceDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('r')),
|
||||
ToggleYieldDisplay(Category.WorldScreen, KeyCharAndCode.ctrl('y')),
|
||||
ToggleWorkedTilesDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
|
||||
ToggleMovementDisplay(Category.WorldScreen, KeyCharAndCode.UNKNOWN),
|
||||
ZoomIn(Category.WorldScreen, Input.Keys.NUMPAD_ADD),
|
||||
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
|
||||
// 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.
|
||||
@ -97,7 +123,10 @@ enum class KeyboardBinding(
|
||||
None,
|
||||
WorldScreen {
|
||||
// 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 {
|
||||
// Conflict checking within group disabled, but any key assigned on WorldScreen is a problem
|
||||
|
@ -20,9 +20,19 @@ class KeyboardPanningListener(
|
||||
|
||||
private val pressedKeys = mutableSetOf<Int>()
|
||||
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 =
|
||||
setOf(Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT) + (
|
||||
if (allowWASD) setOf(Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D)
|
||||
setOf(keycodeUp, keycodeLeft, keycodeDown, keycodeRight) + (
|
||||
if (allowWASD) setOf(keycodeUpAlt, keycodeLeftAlt, keycodeDownAlt, keycodeRightAlt)
|
||||
else setOf()
|
||||
)
|
||||
|
||||
@ -70,10 +80,10 @@ class KeyboardPanningListener(
|
||||
var deltaY = 0f
|
||||
for (keycode in pressedKeys) {
|
||||
when (keycode) {
|
||||
Input.Keys.W, Input.Keys.UP -> deltaY -= 1f
|
||||
Input.Keys.S, Input.Keys.DOWN -> deltaY += 1f
|
||||
Input.Keys.A, Input.Keys.LEFT -> deltaX += 1f
|
||||
Input.Keys.D, Input.Keys.RIGHT -> deltaX -= 1f
|
||||
keycodeUp, keycodeUpAlt -> deltaY -= 1f
|
||||
keycodeDown, keycodeDownAlt -> deltaY += 1f
|
||||
keycodeLeft, keycodeLeftAlt -> deltaX += 1f
|
||||
keycodeRight, keycodeRightAlt -> deltaX -= 1f
|
||||
}
|
||||
}
|
||||
mapHolder.doKeyOrMousePanning(deltaX, deltaY)
|
||||
|
@ -20,16 +20,20 @@ import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.event.EventBus
|
||||
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.center
|
||||
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.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.UncivStage
|
||||
|
||||
@ -292,6 +296,11 @@ open class Popup(
|
||||
@Suppress("unused") // Keep the offer to pass an Input.keys value
|
||||
fun addButton(text: String, key: Int, style: TextButtonStyle? = null, action: () -> Unit)
|
||||
= 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.
|
||||
|
@ -7,10 +7,10 @@ import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.ExpanderTab
|
||||
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.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.civilopediascreen.CivilopediaScreen
|
||||
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 }) {
|
||||
keyBindings[binding] = widget.current
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ import com.unciv.models.TutorialTrigger
|
||||
import com.unciv.models.skins.SkinStrings
|
||||
import com.unciv.ui.components.Fonts
|
||||
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.KeyShortcutDispatcherVeto
|
||||
import com.unciv.ui.components.input.DispatcherVetoer
|
||||
import com.unciv.ui.components.input.installShortcutDispatcher
|
||||
import com.unciv.ui.components.input.keyShortcuts
|
||||
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 */
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,10 @@ import com.unciv.models.UncivSound
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.Fonts
|
||||
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.input.KeyboardBinding
|
||||
import com.unciv.ui.components.input.onActivation
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
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.defaults().pad(20f)
|
||||
pickTechButton.add(pickTechLabel)
|
||||
techButtonHolder.onClick(UncivSound.Paper) {
|
||||
techButtonHolder.onActivation(UncivSound.Paper, KeyboardBinding.TechnologyTree) {
|
||||
game.pushScreen(TechPickerScreen(viewingCiv))
|
||||
}
|
||||
|
||||
undoButton.add(ImageGetter.getImage("OtherIcons/Resume")).size(30f).pad(15f)
|
||||
undoButton.onClick {
|
||||
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)
|
||||
}
|
||||
undoButton.onActivation(binding = KeyboardBinding.Undo) {
|
||||
handleUndo()
|
||||
}
|
||||
|
||||
policyScreenButton.add(ImageGetter.getImage("PolicyIcons/Constitution")).size(30f).pad(15f)
|
||||
policyButtonHolder.onClick {
|
||||
policyButtonHolder.onActivation(binding = KeyboardBinding.SocialPolicies) {
|
||||
game.pushScreen(PolicyPickerScreen(worldScreen.selectedCiv, worldScreen.canChangeState))
|
||||
}
|
||||
|
||||
diplomacyButton.add(ImageGetter.getImage("OtherIcons/DiplomacyW")).size(30f).pad(15f)
|
||||
diplomacyButtonHolder.onClick {
|
||||
diplomacyButtonHolder.onActivation(binding = KeyboardBinding.Diplomacy) {
|
||||
game.pushScreen(DiplomacyScreen(viewingCiv))
|
||||
}
|
||||
|
||||
if (game.gameInfo!!.isEspionageEnabled()) {
|
||||
espionageButton.add(ImageGetter.getImage("OtherIcons/Spy_White")).size(30f).pad(15f)
|
||||
espionageButtonHolder.onClick {
|
||||
espionageButtonHolder.onActivation(binding = KeyboardBinding.Espionage) {
|
||||
game.pushScreen(EspionageOverviewScreen(viewingCiv))
|
||||
}
|
||||
}
|
||||
@ -162,4 +161,13 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,19 +21,20 @@ import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
|
||||
import com.unciv.logic.trade.TradeEvaluation
|
||||
import com.unciv.models.TutorialTrigger
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
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.darken
|
||||
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.toLabel
|
||||
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.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.popups.AuthPopup
|
||||
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.civilopediascreen.CivilopediaScreen
|
||||
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.EmpireOverviewScreen
|
||||
import com.unciv.ui.screens.pickerscreens.DiplomaticVoteResultScreen
|
||||
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.QuickSave
|
||||
import com.unciv.ui.screens.savescreens.SaveGameScreen
|
||||
import com.unciv.ui.screens.victoryscreen.VictoryScreen
|
||||
import com.unciv.ui.screens.worldscreen.bottombar.BattleTable
|
||||
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.status.MultiplayerStatusButton
|
||||
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.actions.UnitActionsTable
|
||||
import com.unciv.utils.Concurrency
|
||||
import com.unciv.utils.debug
|
||||
import com.unciv.utils.launchOnGLThread
|
||||
import com.unciv.utils.launchOnThreadPool
|
||||
import com.unciv.utils.withGLContext
|
||||
import com.unciv.utils.debug
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
|
||||
@ -224,27 +225,27 @@ class WorldScreen(
|
||||
game.pushScreen(EmpireOverviewScreen(selectedCiv, category))
|
||||
}
|
||||
|
||||
fun openNewGameScreen() {
|
||||
val newGameSetupInfo = GameSetupInfo(gameInfo)
|
||||
newGameSetupInfo.mapParameters.reseed()
|
||||
val newGameScreen = NewGameScreen(newGameSetupInfo)
|
||||
game.pushScreen(newGameScreen)
|
||||
}
|
||||
|
||||
private fun addKeyboardPresses() {
|
||||
// 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.EmpireOverview) { openEmpireOverview() } // Empire overview last used page
|
||||
/*
|
||||
* These try to be faithful to default Civ5 key bindings as found in several places online
|
||||
* Some are a little arbitrary, e.g. Economic info, Military info
|
||||
* Some are very much so as Unciv *is* Strategic View
|
||||
*/
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewTrades) { openEmpireOverview(EmpireOverviewCategories.Trades) } // Economic info
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewUnits) { openEmpireOverview(EmpireOverviewCategories.Units) } // Military info
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewPolitics) { openEmpireOverview(EmpireOverviewCategories.Politics) } // Diplomacy info
|
||||
globalShortcuts.add(KeyboardBinding.SocialPolicies) { game.pushScreen(PolicyPickerScreen(selectedCiv, canChangeState)) } // Social Policies Screen
|
||||
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
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewTrades) { openEmpireOverview(EmpireOverviewCategories.Trades) }
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewUnits) { openEmpireOverview(EmpireOverviewCategories.Units) }
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewPolitics) { openEmpireOverview(EmpireOverviewCategories.Politics) }
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewNotifications) { openEmpireOverview(EmpireOverviewCategories.Notifications) }
|
||||
globalShortcuts.add(KeyboardBinding.VictoryScreen) { game.pushScreen(VictoryScreen(this)) }
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewStats) { openEmpireOverview(EmpireOverviewCategories.Stats) }
|
||||
globalShortcuts.add(KeyboardBinding.EmpireOverviewResources) { openEmpireOverview(EmpireOverviewCategories.Resources) }
|
||||
globalShortcuts.add(KeyboardBinding.QuickSave) { QuickSave.save(gameInfo, this) }
|
||||
globalShortcuts.add(KeyboardBinding.QuickLoad) { QuickSave.load(this) }
|
||||
globalShortcuts.add(KeyboardBinding.ViewCapitalCity) {
|
||||
val capital = gameInfo.getCurrentPlayerCivilization().getCapital()
|
||||
if (capital != null && !mapHolder.setCenterPosition(capital.location))
|
||||
game.pushScreen(CityScreen(capital))
|
||||
@ -257,6 +258,10 @@ class WorldScreen(
|
||||
globalShortcuts.add(KeyboardBinding.SaveGame) { game.pushScreen(SaveGameScreen(gameInfo)) } // Save
|
||||
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.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_SUBTRACT) { this.mapHolder.zoomOut() } // '-' Zoom
|
||||
globalShortcuts.add(KeyboardBinding.ToggleUI) { toggleUI() }
|
||||
@ -266,6 +271,16 @@ class WorldScreen(
|
||||
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() {
|
||||
uiEnabled = !uiEnabled
|
||||
topBar.isVisible = uiEnabled
|
||||
|
@ -16,18 +16,18 @@ import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.Fonts
|
||||
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.extensions.colorFromRGB
|
||||
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.setFontSize
|
||||
import com.unciv.ui.components.extensions.toLabel
|
||||
import com.unciv.ui.components.extensions.toStringSigned
|
||||
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.popups.popups
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories
|
||||
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
|
||||
@ -180,8 +180,9 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
}
|
||||
|
||||
val overviewButton = "Overview".toTextButton()
|
||||
overviewButton.addTooltip('e')
|
||||
overviewButton.onClick { worldScreen.openEmpireOverview() }
|
||||
overviewButton.onActivation(binding = KeyboardBinding.EmpireOverview) {
|
||||
worldScreen.openEmpireOverview()
|
||||
}
|
||||
|
||||
unitSupplyCell = add()
|
||||
add(overviewButton).pad(10f)
|
||||
@ -209,10 +210,8 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
|
||||
defaults().pad(10f)
|
||||
|
||||
menuButton.color = Color.WHITE
|
||||
menuButton.onClick {
|
||||
val worldScreenMenuPopup = worldScreen.popups.firstOrNull { it is WorldScreenMenuPopup }
|
||||
if (worldScreenMenuPopup != null) worldScreenMenuPopup.close()
|
||||
else WorldScreenMenuPopup(worldScreen).open(force = true)
|
||||
menuButton.onActivation(binding = KeyboardBinding.Menu) {
|
||||
WorldScreenMenuPopup(worldScreen).open(force = true)
|
||||
}
|
||||
|
||||
selectedCivLabel.setFontSize(25)
|
||||
|
@ -1,9 +1,8 @@
|
||||
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.screens.civilopediascreen.CivilopediaScreen
|
||||
import com.unciv.ui.screens.newgamescreen.NewGameScreen
|
||||
import com.unciv.ui.screens.savescreens.LoadGameScreen
|
||||
import com.unciv.ui.screens.savescreens.SaveGameScreen
|
||||
import com.unciv.ui.screens.victoryscreen.VictoryScreen
|
||||
@ -16,32 +15,27 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, sc
|
||||
addButton("Main menu") {
|
||||
worldScreen.game.goToMainMenu()
|
||||
}.row()
|
||||
addButton("Civilopedia") {
|
||||
addButton("Civilopedia", KeyboardBinding.Civilopedia) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(CivilopediaScreen(worldScreen.gameInfo.ruleset))
|
||||
}.row()
|
||||
addButton("Save game") {
|
||||
addButton("Save game", KeyboardBinding.SaveGame) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(SaveGameScreen(worldScreen.gameInfo))
|
||||
}.row()
|
||||
addButton("Load game") {
|
||||
addButton("Load game", KeyboardBinding.LoadGame) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(LoadGameScreen())
|
||||
}.row()
|
||||
|
||||
addButton("Start new game") {
|
||||
addButton("Start new game", KeyboardBinding.NewGame) {
|
||||
close()
|
||||
val newGameSetupInfo = GameSetupInfo(worldScreen.gameInfo)
|
||||
newGameSetupInfo.mapParameters.reseed()
|
||||
val newGameScreen = NewGameScreen(newGameSetupInfo)
|
||||
worldScreen.game.pushScreen(newGameScreen)
|
||||
worldScreen.openNewGameScreen()
|
||||
}.row()
|
||||
|
||||
addButton("Victory status") {
|
||||
addButton("Victory status", KeyboardBinding.VictoryScreen) {
|
||||
close()
|
||||
worldScreen.game.pushScreen(VictoryScreen(worldScreen))
|
||||
}.row()
|
||||
addButton("Options") {
|
||||
addButton("Options", KeyboardBinding.Options) {
|
||||
close()
|
||||
worldScreen.openOptionsPopup()
|
||||
}.row()
|
||||
@ -49,10 +43,11 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen, sc
|
||||
close()
|
||||
WorldScreenCommunityPopup(worldScreen).open(force = true)
|
||||
}.row()
|
||||
addButton("Music") {
|
||||
addButton("Music", KeyboardBinding.MusicPlayer) {
|
||||
close()
|
||||
WorldScreenMusicPopup(worldScreen).open(force = true)
|
||||
}.row()
|
||||
|
||||
addCloseButton()
|
||||
pack()
|
||||
}
|
||||
|
@ -5,13 +5,14 @@ import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.managers.ReligionState
|
||||
import com.unciv.models.ruleset.BeliefType
|
||||
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.enable
|
||||
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.onActivation
|
||||
import com.unciv.ui.components.extensions.setSize
|
||||
import com.unciv.ui.images.IconTextButton
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.popups.ConfirmPopup
|
||||
@ -45,6 +46,8 @@ class NextTurnButton : IconTextButton("", null, 30) {
|
||||
|
||||
isEnabled = !worldScreen.hasOpenPopups() && worldScreen.isPlayersTurn
|
||||
&& !worldScreen.waitingForAutosave && !worldScreen.isNextTurnUpdateRunning()
|
||||
|
||||
if (isEnabled) addTooltip(KeyboardBinding.NextTurn) else addTooltip("")
|
||||
}
|
||||
internal fun updateButton(nextTurnAction: NextTurnAction) {
|
||||
label.setText(nextTurnAction.text.tr())
|
||||
|
@ -12,7 +12,6 @@ import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.UpgradeUnitAction
|
||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
||||
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.onActivation
|
||||
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)
|
||||
actionButton.color = Color.GREEN.cpy().lerp(Color.WHITE, 0.5f)
|
||||
|
||||
actionButton.addTooltip(KeyboardBindings[binding])
|
||||
actionButton.addTooltip(binding)
|
||||
actionButton.pack()
|
||||
|
||||
if (unitAction.action == null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user