WASD listener out of WorldScreen and add to map editor (#8947)

This commit is contained in:
SomeTroglodyte
2023-03-18 18:27:25 +01:00
committed by GitHub
parent 9b9620b681
commit 88d329a51d
4 changed files with 94 additions and 79 deletions

View File

@ -0,0 +1,74 @@
package com.unciv.ui.components
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.scenes.scene2d.InputEvent
import com.badlogic.gdx.scenes.scene2d.InputListener
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.actions.RepeatAction
import com.badlogic.gdx.scenes.scene2d.ui.TextField
class KeyboardPanningListener(
private val mapHolder: ZoomableScrollPane,
allowWASD: Boolean,
) : InputListener() {
private val pressedKeys = mutableSetOf<Int>()
private var infiniteAction: RepeatAction? = null
private val amountToMove = 6 / mapHolder.scaleX
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)
else setOf()
)
override fun keyDown(event: InputEvent, keycode: Int): Boolean {
if (event.target is TextField) return false
if (keycode !in allowedKeys) return false
// Without the following Ctrl-S would leave WASD map scrolling stuck
// Might be obsolete with keyboard shortcut refactoring
if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT)) return false
if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)) return false
pressedKeys.add(keycode)
startLoop()
return true
}
override fun keyUp(event: InputEvent?, keycode: Int): Boolean {
if (keycode !in allowedKeys) return false
pressedKeys.remove(keycode)
if (pressedKeys.isEmpty()) stopLoop()
return true
}
private fun startLoop() {
if (infiniteAction != null) return
// create a copy of the action, because removeAction() will destroy this instance
infiniteAction = Actions.forever(
Actions.delay(
0.01f,
Actions.run { whileKeyPressedLoop() })
)
mapHolder.addAction(infiniteAction)
}
private fun stopLoop() {
if (infiniteAction == null) return
// stop the loop otherwise it keeps going even after removal
infiniteAction?.finish()
// remove and nil the action
mapHolder.removeAction(infiniteAction)
infiniteAction = null
}
private fun whileKeyPressedLoop() {
for (keycode in pressedKeys) {
when (keycode) {
Input.Keys.W, Input.Keys.UP -> mapHolder.scrollY = mapHolder.restrictY(-amountToMove)
Input.Keys.S, Input.Keys.DOWN -> mapHolder.scrollY = mapHolder.restrictY(amountToMove)
Input.Keys.A, Input.Keys.LEFT -> mapHolder.scrollX = mapHolder.restrictX(amountToMove)
Input.Keys.D, Input.Keys.RIGHT -> mapHolder.scrollX = mapHolder.restrictX(-amountToMove)
}
}
mapHolder.updateVisualScroll()
}
}

View File

@ -22,9 +22,7 @@ import com.unciv.models.metadata.GameSetupInfo
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache
import com.unciv.ui.components.AutoScrollPane
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.keyShortcuts
@ -33,21 +31,24 @@ import com.unciv.ui.components.extensions.surroundWithCircle
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.tilegroups.TileGroupMap
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.mapeditorscreen.MapEditorScreen
import com.unciv.ui.screens.multiplayerscreens.MultiplayerScreen
import com.unciv.ui.popups.Popup
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.popups.closeAllPopups
import com.unciv.ui.popups.hasOpenPopups
import com.unciv.ui.popups.popups
import com.unciv.ui.screens.savescreens.LoadGameScreen
import com.unciv.ui.screens.savescreens.QuickSave
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.mainmenuscreen.EasterEggRulesets.modifyForEasterEgg
import com.unciv.ui.screens.mapeditorscreen.EditorMapHolder
import com.unciv.ui.screens.mapeditorscreen.MapEditorScreen
import com.unciv.ui.screens.multiplayerscreens.MultiplayerScreen
import com.unciv.ui.screens.newgamescreen.NewGameScreen
import com.unciv.ui.screens.pickerscreens.ModManagementScreen
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMenuPopup
import com.unciv.ui.screens.mainmenuscreen.EasterEggRulesets.modifyForEasterEgg
import com.unciv.ui.screens.savescreens.LoadGameScreen
import com.unciv.ui.screens.savescreens.QuickSave
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMenuPopup
import com.unciv.utils.concurrency.Concurrency
import com.unciv.utils.concurrency.launchOnGLThread
import kotlin.math.min
@ -132,7 +133,7 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize {
launchOnGLThread { // for GL context
ImageGetter.setNewRuleset(mapRuleset)
val mapHolder = com.unciv.ui.screens.mapeditorscreen.EditorMapHolder(
val mapHolder = EditorMapHolder(
this@MainMenuScreen,
newMap
) {}

View File

@ -18,6 +18,7 @@ import com.unciv.ui.popups.ConfirmPopup
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.KeyboardPanningListener
import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.screens.worldscreen.ZoomButtonPair
@ -64,7 +65,7 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen(), RecreateOnResize {
var tileMatchFuzziness = MapEditorOptionsTab.TileMatchFuzziness.CompleteMatch
// UI
var mapHolder: com.unciv.ui.screens.mapeditorscreen.EditorMapHolder
var mapHolder: EditorMapHolder
val tabs: MapEditorMainTabs
var tileClickHandler: ((tile: Tile)->Unit)? = null
private var zoomController: ZoomButtonPair? = null
@ -117,7 +118,7 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen(), RecreateOnResize {
fun getToolsWidth() = stage.width * 0.4f
private fun newMapHolder(): com.unciv.ui.screens.mapeditorscreen.EditorMapHolder {
private fun newMapHolder(): EditorMapHolder {
ImageGetter.setNewRuleset(ruleset)
// setNewRuleset is missing some graphics - those "EmojiIcons"&co already rendered as font characters
// so to get the "Water" vs "Gold" icons when switching between Deciv and Vanilla to render properly,
@ -130,9 +131,12 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen(), RecreateOnResize {
tileMap.setStartingLocationsTransients()
UncivGame.Current.translations.translationActiveMods = ruleset.mods
val result = com.unciv.ui.screens.mapeditorscreen.EditorMapHolder(this, tileMap) {
val result = EditorMapHolder(this, tileMap) {
tileClickHandler?.invoke(it)
}
for (oldPanningListener in stage.root.listeners.filterIsInstance<KeyboardPanningListener>())
stage.removeListener(oldPanningListener) // otherwise they accumulate
stage.addListener(KeyboardPanningListener(result, allowWASD = false))
stage.root.addActorAt(0, result)
stage.scrollFocus = result

View File

@ -4,13 +4,8 @@ import com.badlogic.gdx.Application
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.InputEvent
import com.badlogic.gdx.scenes.scene2d.InputListener
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.actions.RepeatAction
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.TextField
import com.badlogic.gdx.utils.Align
import com.unciv.Constants
import com.unciv.UncivGame
@ -27,8 +22,9 @@ import com.unciv.logic.trade.TradeEvaluation
import com.unciv.models.TutorialTrigger
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.KeyboardBinding
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.KeyboardBinding
import com.unciv.ui.components.KeyboardPanningListener
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.extensions.isEnabled
@ -277,67 +273,7 @@ class WorldScreen(
}
private fun addKeyboardListener() {
stage.addListener(
object : InputListener() {
private val pressedKeys = mutableSetOf<Int>()
private var infiniteAction: RepeatAction? = null
private val amountToMove = 6 / mapHolder.scaleX
private val ALLOWED_KEYS = setOf(Input.Keys.W, Input.Keys.S, Input.Keys.A, Input.Keys.D,
Input.Keys.UP, Input.Keys.DOWN, Input.Keys.LEFT, Input.Keys.RIGHT)
override fun keyDown(event: InputEvent, keycode: Int): Boolean {
if (event.target !is TextField) {
if (keycode !in ALLOWED_KEYS) return false
// Without the following Ctrl-S would leave WASD map scrolling stuck
// Might be obsolete with keyboard shortcut refactoring
if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(
Input.Keys.CONTROL_RIGHT
)
) return false
pressedKeys.add(keycode)
if (infiniteAction == null) {
// create a copy of the action, because removeAction() will destroy this instance
infiniteAction = Actions.forever(
Actions.delay(
0.01f,
Actions.run { whileKeyPressedLoop() })
)
mapHolder.addAction(infiniteAction)
}
}
return true
}
fun whileKeyPressedLoop() {
for (keycode in pressedKeys) {
when (keycode) {
Input.Keys.W, Input.Keys.UP -> mapHolder.scrollY = mapHolder.restrictY(-amountToMove)
Input.Keys.S, Input.Keys.DOWN -> mapHolder.scrollY = mapHolder.restrictY(amountToMove)
Input.Keys.A, Input.Keys.LEFT -> mapHolder.scrollX = mapHolder.restrictX(amountToMove)
Input.Keys.D, Input.Keys.RIGHT -> mapHolder.scrollX = mapHolder.restrictX(-amountToMove)
}
}
mapHolder.updateVisualScroll()
}
override fun keyUp(event: InputEvent?, keycode: Int): Boolean {
if (keycode !in ALLOWED_KEYS) return false
pressedKeys.remove(keycode)
if (infiniteAction != null && pressedKeys.isEmpty()) {
// stop the loop otherwise it keeps going even after removal
infiniteAction?.finish()
// remove and nil the action
mapHolder.removeAction(infiniteAction)
infiniteAction = null
}
return true
}
}
)
stage.addListener(KeyboardPanningListener(mapHolder, allowWASD = true))
}
private suspend fun loadLatestMultiplayerState(): Unit = coroutineScope {