mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 06:16:37 -04:00
Removed Char-only restriction in keyboard support for unit actions, remap a few keys, key tooltips for non-ascii keys (#4606)
This commit is contained in:
parent
f2697ee8a1
commit
e514df5b82
@ -35,9 +35,14 @@ data class KeyCharAndCode(val char: Char, val code: Int) {
|
|||||||
// From Kotlin 1.5? on the Ctrl- line will need Char(char.code+64)
|
// From Kotlin 1.5? on the Ctrl- line will need Char(char.code+64)
|
||||||
// see https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/char-int-conversions.md
|
// see https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/char-int-conversions.md
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
// debug helper
|
// debug helper, but also used for tooltips
|
||||||
|
fun fixedKeysToString(code: Int) = when (code) {
|
||||||
|
Input.Keys.BACKSPACE -> "Backspace" // Gdx displaying this as "Delete" is Bullshit!
|
||||||
|
Input.Keys.FORWARD_DEL -> "Del" // Likewise
|
||||||
|
else -> Input.Keys.toString(code)
|
||||||
|
}
|
||||||
return when {
|
return when {
|
||||||
char == Char.MIN_VALUE -> Input.Keys.toString(code)
|
char == Char.MIN_VALUE -> fixedKeysToString(code)
|
||||||
this == ESC -> "ESC"
|
this == ESC -> "ESC"
|
||||||
char < ' ' -> "Ctrl-" + (char.toInt()+64).toChar()
|
char < ' ' -> "Ctrl-" + (char.toInt()+64).toChar()
|
||||||
else -> "\"$char\""
|
else -> "\"$char\""
|
||||||
@ -51,8 +56,8 @@ data class KeyCharAndCode(val char: Char, val code: Int) {
|
|||||||
val RETURN = KeyCharAndCode(Input.Keys.ENTER)
|
val RETURN = KeyCharAndCode(Input.Keys.ENTER)
|
||||||
val NUMPAD_ENTER = KeyCharAndCode(Input.Keys.NUMPAD_ENTER)
|
val NUMPAD_ENTER = KeyCharAndCode(Input.Keys.NUMPAD_ENTER)
|
||||||
val SPACE = KeyCharAndCode(Input.Keys.SPACE)
|
val SPACE = KeyCharAndCode(Input.Keys.SPACE)
|
||||||
val DEL = KeyCharAndCode(Input.Keys.DEL)
|
val BACKSPACE= KeyCharAndCode(Input.Keys.BACKSPACE)
|
||||||
val FORWARD_DEL = KeyCharAndCode(Input.Keys.FORWARD_DEL) // this is what I see for both 'Del' keys
|
val DEL = KeyCharAndCode(Input.Keys.FORWARD_DEL) // Gdx "DEL" is just plain wrong!
|
||||||
/** Guaranteed to be ignored by [KeyPressDispatcher.set] and never to be generated for an actual event, used as fallback to ensure no action is taken */
|
/** Guaranteed to be ignored by [KeyPressDispatcher.set] and never to be generated for an actual event, used as fallback to ensure no action is taken */
|
||||||
val UNKNOWN = KeyCharAndCode(Input.Keys.UNKNOWN)
|
val UNKNOWN = KeyCharAndCode(Input.Keys.UNKNOWN)
|
||||||
|
|
||||||
@ -116,9 +121,6 @@ class KeyPressDispatcher(val name: String? = null) : HashMap<KeyCharAndCode, (()
|
|||||||
// Likewise always match Back to ESC
|
// Likewise always match Back to ESC
|
||||||
if (key == KeyCharAndCode.BACK)
|
if (key == KeyCharAndCode.BACK)
|
||||||
super.put(KeyCharAndCode.ESC, action)
|
super.put(KeyCharAndCode.ESC, action)
|
||||||
// And make two codes for DEL equivalent
|
|
||||||
if (key == KeyCharAndCode.DEL)
|
|
||||||
super.put(KeyCharAndCode.FORWARD_DEL, action)
|
|
||||||
checkInstall()
|
checkInstall()
|
||||||
}
|
}
|
||||||
override fun remove(key: KeyCharAndCode): (() -> Unit)? {
|
override fun remove(key: KeyCharAndCode): (() -> Unit)? {
|
||||||
@ -128,8 +130,6 @@ class KeyPressDispatcher(val name: String? = null) : HashMap<KeyCharAndCode, (()
|
|||||||
super.remove(KeyCharAndCode.NUMPAD_ENTER)
|
super.remove(KeyCharAndCode.NUMPAD_ENTER)
|
||||||
if (key == KeyCharAndCode.BACK)
|
if (key == KeyCharAndCode.BACK)
|
||||||
super.remove(KeyCharAndCode.ESC)
|
super.remove(KeyCharAndCode.ESC)
|
||||||
if (key == KeyCharAndCode.DEL)
|
|
||||||
super.remove(KeyCharAndCode.FORWARD_DEL)
|
|
||||||
checkInstall()
|
checkInstall()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.*
|
|||||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
|
import com.unciv.models.translations.tr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A **Replacement** for Gdx [Tooltip], placement does not follow the mouse.
|
* A **Replacement** for Gdx [Tooltip], placement does not follow the mouse.
|
||||||
@ -180,7 +181,8 @@ class UncivTooltip <T: Actor>(
|
|||||||
addListener(UncivTooltip(this,
|
addListener(UncivTooltip(this,
|
||||||
labelWithBackground,
|
labelWithBackground,
|
||||||
forceContentSize = Vector2(size * widthHeightRatio, size),
|
forceContentSize = Vector2(size * widthHeightRatio, size),
|
||||||
offset = Vector2(size/4, 0f)
|
offset = Vector2(-size/4, size/4),
|
||||||
|
tipAlign = Align.top
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,10 +198,17 @@ class UncivTooltip <T: Actor>(
|
|||||||
addTooltip((if (char in "Ii") 'i' else char.toUpperCase()).toString(), size, always)
|
addTooltip((if (char in "Ii") 'i' else char.toUpperCase()).toString(), size, always)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unused - template in case we need it - problem: how exactly to handle translation?
|
/**
|
||||||
|
* Add a [Label]-based Tooltip for a keyboard binding with a rounded-corner background to a [Table] or other [Group].
|
||||||
|
*
|
||||||
|
* 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 Group.addTooltip(key: KeyCharAndCode, size: Float = 26f, always: Boolean = false) {
|
fun Group.addTooltip(key: KeyCharAndCode, size: Float = 26f, always: Boolean = false) {
|
||||||
addTooltip(key.toString(), size, always)
|
if (key != KeyCharAndCode.UNKNOWN)
|
||||||
|
addTooltip(key.toString().tr(), size, always)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.unciv.ui.worldscreen.unit
|
package com.unciv.ui.worldscreen.unit
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
@ -17,7 +17,9 @@ import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
|
|||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
private data class UnitIconAndKey(val Icon: Actor, var key: Char = Char.MIN_VALUE)
|
private data class UnitIconAndKey(val icon: Actor, var key: KeyCharAndCode = KeyCharAndCode.UNKNOWN) {
|
||||||
|
constructor(icon: Actor, key: Char) : this(icon, KeyCharAndCode(key))
|
||||||
|
}
|
||||||
|
|
||||||
class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
||||||
|
|
||||||
@ -47,12 +49,12 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
|||||||
"Fortify until healed" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Shield").apply { color = Color.BLACK }, 'h')
|
"Fortify until healed" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Shield").apply { color = Color.BLACK }, 'h')
|
||||||
// Move unit is not actually used anywhere
|
// Move unit is not actually used anywhere
|
||||||
"Move unit" -> return UnitIconAndKey(ImageGetter.getStatIcon("Movement"))
|
"Move unit" -> return UnitIconAndKey(ImageGetter.getStatIcon("Movement"))
|
||||||
"Stop movement" -> return UnitIconAndKey(ImageGetter.getStatIcon("Movement").apply { color = Color.RED }, '.')
|
"Stop movement" -> return UnitIconAndKey(ImageGetter.getStatIcon("Movement").apply { color = Color.RED }, KeyCharAndCode(Input.Keys.END))
|
||||||
"Swap units" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Swap"), 'y')
|
"Swap units" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Swap"), 'y')
|
||||||
"Promote" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Star").apply { color = Color.GOLD }, 'o')
|
"Promote" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Star").apply { color = Color.GOLD }, 'o')
|
||||||
"Construct improvement" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.worker), 'i')
|
"Construct improvement" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.worker), 'i')
|
||||||
"Automate" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'm')
|
"Automate" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'm')
|
||||||
"Stop automation" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'm')
|
"Stop automation" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), KeyCharAndCode(Input.Keys.END))
|
||||||
"Found city" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.settler), 'c')
|
"Found city" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.settler), 'c')
|
||||||
"Hurry Research" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Scientist"), 'g')
|
"Hurry Research" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Scientist"), 'g')
|
||||||
"Start Golden Age" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Artist"), 'g')
|
"Start Golden Age" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Artist"), 'g')
|
||||||
@ -64,10 +66,10 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
|||||||
"Explore" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Scout"), 'x')
|
"Explore" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Scout"), 'x')
|
||||||
"Stop exploration" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'x')
|
"Stop exploration" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'x')
|
||||||
"Pillage" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Pillage"), 'p')
|
"Pillage" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Pillage"), 'p')
|
||||||
"Disband unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/DisbandUnit"))
|
"Disband unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/DisbandUnit"), KeyCharAndCode.DEL)
|
||||||
"Gift unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Present"))
|
"Gift unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Present"))
|
||||||
"Show more" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/ArrowRight"), 'm')
|
"Show more" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/ArrowRight"), KeyCharAndCode(Input.Keys.PAGE_DOWN))
|
||||||
"Back" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/ArrowLeft"))
|
"Back" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/ArrowLeft"), KeyCharAndCode(Input.Keys.PAGE_UP))
|
||||||
else -> {
|
else -> {
|
||||||
// If the unit has been fortifying for some turns
|
// If the unit has been fortifying for some turns
|
||||||
if (unitAction.startsWith("Fortification")) return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Shield"))
|
if (unitAction.startsWith("Fortification")) return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Shield"))
|
||||||
@ -91,10 +93,10 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
|||||||
val iconAndKey = getIconAndKeyForUnitAction(unitAction.title)
|
val iconAndKey = getIconAndKeyForUnitAction(unitAction.title)
|
||||||
|
|
||||||
// If peripheral keyboard not detected, hotkeys will not be displayed
|
// If peripheral keyboard not detected, hotkeys will not be displayed
|
||||||
if (!keyboardAvailable) { iconAndKey.key = Char.MIN_VALUE }
|
if (!keyboardAvailable) { iconAndKey.key = KeyCharAndCode.UNKNOWN }
|
||||||
|
|
||||||
val actionButton = Button(CameraStageBaseScreen.skin)
|
val actionButton = Button(CameraStageBaseScreen.skin)
|
||||||
actionButton.add(iconAndKey.Icon).size(20f).pad(5f)
|
actionButton.add(iconAndKey.icon).size(20f).pad(5f)
|
||||||
val fontColor = if (unitAction.isCurrentAction) Color.YELLOW else Color.WHITE
|
val fontColor = if (unitAction.isCurrentAction) Color.YELLOW else Color.WHITE
|
||||||
actionButton.add(unitAction.title.toLabel(fontColor)).pad(5f)
|
actionButton.add(unitAction.title.toLabel(fontColor)).pad(5f)
|
||||||
actionButton.addTooltip(iconAndKey.key)
|
actionButton.addTooltip(iconAndKey.key)
|
||||||
@ -106,7 +108,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
|||||||
if (unitAction.action == null) actionButton.disable()
|
if (unitAction.action == null) actionButton.disable()
|
||||||
else {
|
else {
|
||||||
actionButton.onClick(unitAction.uncivSound, action)
|
actionButton.onClick(unitAction.uncivSound, action)
|
||||||
if (iconAndKey.key != Char.MIN_VALUE)
|
if (iconAndKey.key != KeyCharAndCode.UNKNOWN)
|
||||||
worldScreen.keyPressDispatcher[iconAndKey.key] = {
|
worldScreen.keyPressDispatcher[iconAndKey.key] = {
|
||||||
thread(name = "Sound") { Sounds.play(unitAction.uncivSound) }
|
thread(name = "Sound") { Sounds.play(unitAction.uncivSound) }
|
||||||
action()
|
action()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user