mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-10 07:48:31 +07:00
WASD listener out of WorldScreen and add to map editor (#8947)
This commit is contained in:
74
core/src/com/unciv/ui/components/KeyboardPanningListener.kt
Normal file
74
core/src/com/unciv/ui/components/KeyboardPanningListener.kt
Normal 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()
|
||||
}
|
||||
}
|
@ -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
|
||||
) {}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user