Keyboard support for Next-button and Unit actions redone (#2372)

This commit is contained in:
SomeTroglodyte 2020-04-10 09:16:22 +02:00 committed by GitHub
parent 33da0e3a7f
commit 25a5559969
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 34 deletions

View file

@ -64,6 +64,9 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
private var backButtonListener : InputListener
// An initialized val always turned out to illegally be null...
lateinit var keyPressDispatcher: HashMap<Char,(() -> Unit)>
init {
topBar.setPosition(0f, stage.height - topBar.height)
topBar.width = stage.width
@ -110,7 +113,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
stage.addActor(unitActionsTable)
createNextTurnButton() // needs civ table to be positioned
// still a zombie: createNextTurnButton() // needs civ table to be positioned
val tileToCenterOn: Vector2 =
when {
@ -142,6 +145,11 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
shouldUpdate = true
}
private fun cleanupKeyDispatcher() {
val delKeys = keyPressDispatcher.keys.filter { it!=' ' && it!='n' }
delKeys.forEach { keyPressDispatcher.remove(it) }
}
private fun addKeyboardListener() {
stage.addListener(
object : InputListener() {
@ -187,6 +195,17 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
}
return true
}
override fun keyTyped(event: InputEvent?, character: Char): Boolean {
if (character.toLowerCase() in keyPressDispatcher && !hasOpenPopups()) {
//try-catch mainly for debugging. Breakpoints in the vicinity can make the event fire twice in rapid succession, second time the context can be invalid
try {
keyPressDispatcher[character.toLowerCase()]?.invoke()
} catch (ex: Exception) {}
return true
}
return super.keyTyped(event, character)
}
}
)
}
@ -244,6 +263,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
}
minimapWrapper.update(viewingCiv)
cleanupKeyDispatcher()
unitActionsTable.update(bottomUnitTable.selectedUnit)
unitActionsTable.y = bottomUnitTable.height
@ -398,7 +418,11 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
val nextTurnButton = TextButton("", skin) // text is set in update()
nextTurnButton.label.setFontSize(30)
nextTurnButton.labelCell.pad(10f)
nextTurnButton.onClick { nextTurnAction() }
val nextTurnActionWrapped = { nextTurnAction() }
nextTurnButton.onClick (nextTurnActionWrapped)
if (!::keyPressDispatcher.isInitialized) keyPressDispatcher = hashMapOf()
keyPressDispatcher[' '] = nextTurnActionWrapped
keyPressDispatcher['n'] = nextTurnActionWrapped
return nextTurnButton
}

View file

@ -2,9 +2,12 @@ package com.unciv.ui.worldscreen.unit
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.InputEvent
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.map.MapUnit
@ -12,48 +15,60 @@ import com.unciv.models.UnitAction
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen
private data class UnitIconAndKey (val Icon: Actor, val key: Char = 0.toChar())
class UnitActionButtonOnHoverListener(private val item: Actor, private val keyLabel: Label) : ClickListener() {
override fun enter(event: InputEvent, x: Float, y: Float, pointer: Int, fromActor: Actor?) {
super.enter(event, x, y, pointer, fromActor)
keyLabel.isVisible = true
}
override fun exit(event: InputEvent, x: Float, y: Float, pointer: Int, toActor: Actor?) {
super.exit(event, x, y, pointer, toActor)
keyLabel.isVisible = false
}
}
class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
init {
touchable = Touchable.enabled
}
private fun getIconForUnitAction(unitAction:String): Actor {
private fun getIconAnKeyForUnitAction(unitAction:String): UnitIconAndKey {
when {
unitAction.startsWith("Upgrade to") -> {
// Regexplaination: start with a [, take as many non-] chars as you can, until you reach a ].
// What you find between the first [ and the first ] that comes after it, will be group no. 1
val unitToUpgradeTo = Regex("""Upgrade to \[([^\]]*)\]""").find(unitAction)!!.groups[1]!!.value
return ImageGetter.getUnitIcon(unitToUpgradeTo)
return UnitIconAndKey(ImageGetter.getUnitIcon(unitToUpgradeTo), 'u')
}
unitAction.startsWith("Sleep") -> return ImageGetter.getImage("OtherIcons/Sleep")
unitAction.startsWith("Fortify") -> return ImageGetter.getImage("OtherIcons/Shield").apply { color= Color.BLACK }
unitAction.startsWith("Sleep") -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Sleep"),'f')
unitAction.startsWith("Fortify") -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Shield").apply { color= Color.BLACK },'f')
else -> when(unitAction){
"Move unit" -> return ImageGetter.getStatIcon("Movement")
"Stop movement"-> return ImageGetter.getStatIcon("Movement").apply { color= Color.RED }
"Promote" -> return ImageGetter.getImage("OtherIcons/Star").apply { color= Color.GOLD }
"Construct improvement" -> return ImageGetter.getUnitIcon(Constants.worker)
"Automate" -> return ImageGetter.getUnitIcon("Great Engineer")
"Stop automation" -> return ImageGetter.getImage("OtherIcons/Stop")
"Found city" -> return ImageGetter.getUnitIcon(Constants.settler)
"Hurry Research" -> return ImageGetter.getUnitIcon("Great Scientist")
"Construct Academy" -> return ImageGetter.getImprovementIcon("Academy")
"Start Golden Age" -> return ImageGetter.getUnitIcon("Great Artist")
"Construct Landmark" -> return ImageGetter.getImprovementIcon("Landmark")
"Construct Citadel" -> return ImageGetter.getImprovementIcon("Citadel")
"Hurry Wonder" -> return ImageGetter.getUnitIcon("Great Engineer")
"Construct Manufactory" -> return ImageGetter.getImprovementIcon("Manufactory")
"Conduct Trade Mission" -> return ImageGetter.getUnitIcon("Great Merchant")
"Construct Customs House" -> return ImageGetter.getImprovementIcon("Customs house")
"Set up" -> return ImageGetter.getUnitIcon("Catapult")
"Disband unit" -> return ImageGetter.getImage("OtherIcons/DisbandUnit")
"Explore" -> return ImageGetter.getUnitIcon("Scout")
"Stop exploration" -> return ImageGetter.getImage("OtherIcons/Stop")
"Create Fishing Boats" -> return ImageGetter.getImprovementIcon("Fishing Boats")
"Create Oil well" -> return ImageGetter.getImprovementIcon("Oil well")
"Pillage" -> return ImageGetter.getImage("OtherIcons/Pillage")
"Construct road" -> return ImageGetter.getImprovementIcon("Road")
else -> return ImageGetter.getImage("OtherIcons/Star")
"Move unit" -> return UnitIconAndKey(ImageGetter.getStatIcon("Movement"))
"Stop movement"-> return UnitIconAndKey(ImageGetter.getStatIcon("Movement").apply { color= Color.RED }, '.')
"Promote" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Star").apply { color= Color.GOLD }, 'o')
"Construct improvement" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.worker),'i')
"Automate" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'm')
"Stop automation" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'm')
"Found city" -> return UnitIconAndKey(ImageGetter.getUnitIcon(Constants.settler),'f')
"Hurry Research" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Scientist"), 'g')
"Construct Academy" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Academy"), 'i')
"Start Golden Age" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Artist"), 'g')
"Construct Landmark" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Landmark"), 'i')
"Construct Citadel" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Citadel"), 'i')
"Hurry Wonder" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'g')
"Construct Manufactory" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Manufactory"), 'i')
"Conduct Trade Mission" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Merchant"), 'g')
"Construct Customs House" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Customs house"), 'i')
"Set up" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Catapult"), 't')
"Disband unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/DisbandUnit"))
"Explore" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Scout"), 'x')
"Stop exploration" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'x')
"Create Fishing Boats" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Fishing Boats"),'i')
"Create Oil well" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Oil well"),'i')
"Pillage" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Pillage"),'p')
"Construct road" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Road"),'r')
else -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Star"))
}
}
}
@ -69,16 +84,28 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
private fun getUnitActionButton(unitAction: UnitAction): Button {
val iconAndKey = getIconAnKeyForUnitAction(unitAction.title)
val actionButton = Button(CameraStageBaseScreen.skin)
actionButton.add(getIconForUnitAction(unitAction.title)).size(20f).pad(5f)
actionButton.add(iconAndKey.Icon).size(20f).pad(5f)
val fontColor = if(unitAction.isCurrentAction) Color.YELLOW else Color.WHITE
actionButton.add(unitAction.title.toLabel(fontColor)).pad(5f)
if (iconAndKey.key != 0.toChar()) {
val keyLabel = "(${iconAndKey.key.toUpperCase()})".toLabel(Color.WHITE).apply { isVisible = false }
actionButton.add(keyLabel)
actionButton.addListener(UnitActionButtonOnHoverListener(actionButton, keyLabel))
}
actionButton.pack()
actionButton.onClick(unitAction.uncivSound) {
val action = {
unitAction.action?.invoke()
UncivGame.Current.worldScreen.shouldUpdate=true
UncivGame.Current.worldScreen.shouldUpdate = true
}
if (unitAction.action == null) actionButton.disable()
else {
actionButton.onClick(unitAction.uncivSound,action)
if (iconAndKey.key != 0.toChar())
worldScreen.keyPressDispatcher[iconAndKey.key] = action
}
return actionButton
}
}