Split tilemapholder overlay buttons to separate file

This commit is contained in:
yairm210 2024-07-16 15:52:35 +03:00
parent a50982e9bb
commit 1e66c19710
8 changed files with 233 additions and 198 deletions

View File

@ -6,7 +6,7 @@ import com.unciv.logic.civilization.Civilization
import com.unciv.models.metadata.GameSettings import com.unciv.models.metadata.GameSettings
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.clearUndoCheckpoints import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.clearUndoCheckpoints
import com.unciv.ui.screens.worldscreen.WorldMapHolder import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
import com.unciv.ui.screens.worldscreen.WorldScreen import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.ui.screens.worldscreen.unit.UnitTable import com.unciv.ui.screens.worldscreen.unit.UnitTable

View File

@ -49,7 +49,7 @@ import com.unciv.ui.screens.savescreens.LoadGameScreen
import com.unciv.ui.screens.savescreens.QuickSave import com.unciv.ui.screens.savescreens.QuickSave
import com.unciv.ui.screens.savescreens.SaveGameScreen import com.unciv.ui.screens.savescreens.SaveGameScreen
import com.unciv.ui.screens.victoryscreen.VictoryScreen import com.unciv.ui.screens.victoryscreen.VictoryScreen
import com.unciv.ui.screens.worldscreen.WorldMapTileUpdater.updateTiles import com.unciv.ui.screens.worldscreen.worldmap.WorldMapTileUpdater.updateTiles
import com.unciv.ui.screens.worldscreen.bottombar.BattleTable import com.unciv.ui.screens.worldscreen.bottombar.BattleTable
import com.unciv.ui.screens.worldscreen.bottombar.TileInfoTable import com.unciv.ui.screens.worldscreen.bottombar.TileInfoTable
import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMusicPopup import com.unciv.ui.screens.worldscreen.mainmenu.WorldScreenMusicPopup
@ -63,6 +63,7 @@ import com.unciv.ui.screens.worldscreen.topbar.WorldScreenTopBar
import com.unciv.ui.screens.worldscreen.unit.AutoPlay import com.unciv.ui.screens.worldscreen.unit.AutoPlay
import com.unciv.ui.screens.worldscreen.unit.UnitTable import com.unciv.ui.screens.worldscreen.unit.UnitTable
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsTable import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsTable
import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
import com.unciv.utils.Concurrency import com.unciv.utils.Concurrency
import com.unciv.utils.debug import com.unciv.utils.debug
import com.unciv.utils.launchOnGLThread import com.unciv.utils.launchOnGLThread

View File

@ -11,7 +11,7 @@ import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapSize import com.unciv.logic.map.MapSize
import com.unciv.ui.images.ClippingImage import com.unciv.ui.images.ClippingImage
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.worldscreen.WorldMapHolder import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.sqrt import kotlin.math.sqrt
@ -73,8 +73,8 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
} else { } else {
if (mapParameters.shape != MapShape.rectangular) { if (mapParameters.shape != MapShape.rectangular) {
val diameter = mapParameters.mapSize.radius * 2f + 1f val diameter = mapParameters.mapSize.radius * 2f + 1f
height = diameter.toFloat() height = diameter
width = diameter.toFloat() width = diameter
} else { } else {
height = mapParameters.mapSize.height.toFloat() height = mapParameters.mapSize.height.toFloat()
width = mapParameters.mapSize.width.toFloat() width = mapParameters.mapSize.width.toFloat()
@ -167,7 +167,7 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
/**### Transform and set coordinates for the scrollPositionIndicator. /**### Transform and set coordinates for the scrollPositionIndicator.
* *
* Requires [scrollPositionIndicator] to be a [ClippingImage] to keep the displayed portion of the indicator within the bounds of the minimap. * Requires [scrollPositionIndicators] to be [ClippingImage]s to keep the displayed portion of the indicator within the bounds of the minimap.
*/ */
private fun updateScrollPosition( private fun updateScrollPosition(
worldWidth: Float, worldWidth: Float,
@ -178,9 +178,9 @@ class Minimap(val mapHolder: WorldMapHolder, minimapSize: Int, private val civIn
Rectangle(x * other.x, y * other.y, width * other.x, height * other.y) Rectangle(x * other.x, y * other.y, width * other.x, height * other.y)
fun Actor.setViewport(rect: Rectangle) { fun Actor.setViewport(rect: Rectangle) {
x = rect.x; x = rect.x
y = rect.y; y = rect.y
width = rect.width; width = rect.width
height = rect.height height = rect.height
} }

View File

@ -8,7 +8,7 @@ import com.unciv.GUI
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.civilization.Civilization import com.unciv.logic.civilization.Civilization
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.worldscreen.WorldMapHolder import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
class MinimapHolder(val mapHolder: WorldMapHolder) : Table() { class MinimapHolder(val mapHolder: WorldMapHolder) : Table() {
private val worldScreen = mapHolder.worldScreen private val worldScreen = mapHolder.worldScreen

View File

@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.worldscreen.WorldMapHolder import com.unciv.ui.screens.worldscreen.worldmap.WorldMapHolder
import com.unciv.ui.components.input.onClick import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.pad import com.unciv.ui.components.extensions.pad

View File

@ -0,0 +1,202 @@
package com.unciv.ui.screens.worldscreen.worldmap
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.utils.Align
import com.unciv.logic.automation.unit.UnitAutomation
import com.unciv.logic.city.City
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.logic.map.tile.Tile
import com.unciv.models.Spy
import com.unciv.models.UncivSound
import com.unciv.models.UnitActionType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.SoundPlayer
import com.unciv.ui.components.extensions.*
import com.unciv.ui.components.input.KeyCharAndCode
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.widgets.UnitIconGroup
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.overviewscreen.EspionageOverviewScreen
/** Interface for creating floating "action" buttons on tiles */
interface OverlayButtonData{
fun createButton(worldMapHolder: WorldMapHolder): Actor
}
const val buttonSize = 60f
val smallerCircleSizes = 25f
class MoveHereOverlayButtonData(val unitToTurnsToDestination: HashMap<MapUnit, Int>, val tile: Tile) :
OverlayButtonData {
override fun createButton(worldMapHolder: WorldMapHolder): Actor {
return getMoveHereButton(worldMapHolder)
}
private fun getMoveHereButton(worldMapHolder: WorldMapHolder): Group {
val isParadrop = unitToTurnsToDestination.keys.all { it.isPreparingParadrop() }
val image = if (isParadrop)
ImageGetter.getUnitActionPortrait("Paradrop", buttonSize / 2)
else ImageGetter.getStatIcon("Movement")
.apply { color = Color.BLACK; width = buttonSize / 2; height = buttonSize / 2 }
val moveHereButton = image
.surroundWithCircle(buttonSize - 2, false)
.surroundWithCircle(buttonSize, false, Color.BLACK)
if (!isParadrop) {
val numberCircle = unitToTurnsToDestination.values.maxOrNull()!!.tr().toLabel(fontSize = 14)
.apply { setAlignment(Align.center) }
.surroundWithCircle(smallerCircleSizes - 2, color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.3f))
.surroundWithCircle(smallerCircleSizes, false)
moveHereButton.addActor(numberCircle)
}
val firstUnit = unitToTurnsToDestination.keys.first()
val unitIcon = if (unitToTurnsToDestination.size == 1) UnitIconGroup(firstUnit, smallerCircleSizes)
else unitToTurnsToDestination.size.tr().toLabel(fontColor = firstUnit.civ.nation.getInnerColor()).apply { setAlignment(
Align.center) }
.surroundWithCircle(smallerCircleSizes).apply { circle.color = firstUnit.civ.nation.getOuterColor() }
unitIcon.y = buttonSize - unitIcon.height
moveHereButton.addActor(unitIcon)
val unitsThatCanMove = unitToTurnsToDestination.keys.filter { it.currentMovement > 0 }
if (unitsThatCanMove.isEmpty()) moveHereButton.color.a = 0.5f
else {
moveHereButton.onActivation(UncivSound.Silent) {
worldMapHolder.moveUnitToTargetTile(unitsThatCanMove, tile)
}
moveHereButton.keyShortcuts.add(KeyCharAndCode.TAB)
}
return moveHereButton
}
}
// Contains the data required to draw a "swap with" button
class SwapWithOverlayButtonData(val unit: MapUnit, val tile: Tile) : OverlayButtonData {
override fun createButton(worldMapHolder: WorldMapHolder): Actor {
return getSwapWithButton(worldMapHolder)
}
fun getSwapWithButton(worldMapHolder: WorldMapHolder): Group {
val swapWithButton = Group()
swapWithButton.setSize(buttonSize, buttonSize)
swapWithButton.addActor(ImageGetter.getCircle(size = buttonSize))
swapWithButton.addActor(
ImageGetter.getImage("OtherIcons/Swap").apply {
color = Color.BLACK
setSize(buttonSize / 2)
center(swapWithButton)
}
)
val unitIcon = UnitIconGroup(unit, smallerCircleSizes)
unitIcon.y = buttonSize - unitIcon.height
swapWithButton.addActor(unitIcon)
swapWithButton.onActivation(UncivSound.Silent) {
worldMapHolder.swapMoveUnitToTargetTile(unit, tile)
}
swapWithButton.keyShortcuts.add(KeyCharAndCode.TAB)
return swapWithButton
}
}
// Contains the data required to draw a "connect road" button
class ConnectRoadOverlayButtonData(val unit: MapUnit, val tile: Tile) : OverlayButtonData {
override fun createButton(worldMapHolder: WorldMapHolder): Actor {
return getConnectRoadButton(worldMapHolder)
}
private fun getConnectRoadButton(worldMapHolder: WorldMapHolder): Group {
val connectRoadButton = Group()
connectRoadButton.setSize(buttonSize, buttonSize)
connectRoadButton.addActor(ImageGetter.getUnitActionPortrait("RoadConnection", buttonSize * 0.8f).apply {
center(connectRoadButton)
}
)
val unitIcon = UnitIconGroup(unit, smallerCircleSizes)
unitIcon.y = buttonSize - unitIcon.height
connectRoadButton.addActor(unitIcon)
connectRoadButton.onActivation(UncivSound.Silent) {
connectRoadToTargetTile(worldMapHolder, unit, tile)
}
connectRoadButton.keyShortcuts.add(KeyboardBinding.ConnectRoad)
return connectRoadButton
}
private fun connectRoadToTargetTile(worldMapHolder: WorldMapHolder, selectedUnit: MapUnit, targetTile: Tile) {
selectedUnit.automatedRoadConnectionDestination = targetTile.position
selectedUnit.automatedRoadConnectionPath = null
selectedUnit.action = UnitActionType.ConnectRoad.value
selectedUnit.automated = true
UnitAutomation.automateUnitMoves(selectedUnit)
SoundPlayer.play(UncivSound("wagon"))
worldMapHolder.worldScreen.shouldUpdate = true
worldMapHolder.removeUnitActionOverlay()
// Make highlighting go away
worldMapHolder.worldScreen.bottomUnitTable.selectedUnitIsConnectingRoad = false
}
}
// Contains the data required to draw a "move spy" button
class MoveSpyOverlayButtonData(val spy: Spy, val city: City?) : OverlayButtonData {
override fun createButton(worldMapHolder: WorldMapHolder): Actor {
return getMoveSpyButton(worldMapHolder)
}
private fun getMoveSpyButton(worldMapHolder: WorldMapHolder): Group {
val spyActionButton = Group()
spyActionButton.setSize(buttonSize, buttonSize)
spyActionButton.addActor(ImageGetter.getCircle(size = buttonSize))
if (city != null) {
spyActionButton.addActor(
ImageGetter.getStatIcon("Movement").apply {
name = "Button"
color = Color.BLACK
setSize(buttonSize / 2)
center(spyActionButton)
}
)
} else {
spyActionButton.addActor(
ImageGetter.getImage("OtherIcons/Close").apply {
name = "Button"
color = Color.RED
setSize(buttonSize / 2)
center(spyActionButton)
}
)
}
val worldScreen = worldMapHolder.worldScreen
spyActionButton.onActivation(UncivSound.Silent) {
if (city != null) {
spy.moveTo(city)
worldScreen.game.pushScreen(EspionageOverviewScreen(worldScreen.selectedCiv, worldScreen))
} else {
worldScreen.game.pushScreen(EspionageOverviewScreen(worldScreen.selectedCiv, worldScreen))
worldScreen.bottomUnitTable.selectedSpy = null
}
worldMapHolder.removeUnitActionOverlay()
worldMapHolder.selectedTile = null
worldScreen.shouldUpdate = true
worldScreen.bottomUnitTable.selectSpy(null)
}
spyActionButton.keyShortcuts.add(KeyCharAndCode.TAB)
spyActionButton.keyShortcuts.add(KeyCharAndCode.RETURN)
spyActionButton.keyShortcuts.add(KeyCharAndCode.NUMPAD_ENTER)
return spyActionButton
}
}

View File

@ -1,4 +1,4 @@
package com.unciv.ui.screens.worldscreen package com.unciv.ui.screens.worldscreen.worldmap
import com.badlogic.gdx.Application import com.badlogic.gdx.Application
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
@ -13,7 +13,6 @@ import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.automation.unit.UnitAutomation
import com.unciv.logic.battle.Battle import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.MapUnitCombatant import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.battle.TargetHelper import com.unciv.logic.battle.TargetHelper
@ -26,24 +25,25 @@ import com.unciv.logic.map.mapunit.movement.UnitMovement
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
import com.unciv.models.Spy import com.unciv.models.Spy
import com.unciv.models.UncivSound import com.unciv.models.UncivSound
import com.unciv.models.UnitActionType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.SoundPlayer import com.unciv.ui.audio.SoundPlayer
import com.unciv.ui.components.MapArrowType import com.unciv.ui.components.MapArrowType
import com.unciv.ui.components.MiscArrowTypes import com.unciv.ui.components.MiscArrowTypes
import com.unciv.ui.components.extensions.* import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.input.* import com.unciv.ui.components.extensions.isShiftKeyPressed
import com.unciv.ui.components.extensions.surroundWithCircle
import com.unciv.ui.components.input.ActivationTypes
import com.unciv.ui.components.input.ClickableCircle
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.tilegroups.TileGroup import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileGroupMap import com.unciv.ui.components.tilegroups.TileGroupMap
import com.unciv.ui.components.tilegroups.TileSetStrings import com.unciv.ui.components.tilegroups.TileSetStrings
import com.unciv.ui.components.tilegroups.WorldTileGroup import com.unciv.ui.components.tilegroups.WorldTileGroup
import com.unciv.ui.components.widgets.UnitIconGroup import com.unciv.ui.components.widgets.UnitIconGroup
import com.unciv.ui.components.widgets.ZoomableScrollPane import com.unciv.ui.components.widgets.ZoomableScrollPane
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.basescreen.UncivStage import com.unciv.ui.screens.basescreen.UncivStage
import com.unciv.ui.screens.overviewscreen.EspionageOverviewScreen
import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.recordUndoCheckpoint import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.recordUndoCheckpoint
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimation import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimation
import com.unciv.utils.Concurrency import com.unciv.utils.Concurrency
import com.unciv.utils.Log import com.unciv.utils.Log
@ -58,6 +58,7 @@ class WorldMapHolder(
internal var selectedTile: Tile? = null internal var selectedTile: Tile? = null
val tileGroups = HashMap<Tile, WorldTileGroup>() val tileGroups = HashMap<Tile, WorldTileGroup>()
/** Holds buttons created by [OverlayButtonData] implementations */
internal val unitActionOverlays: ArrayList<Actor> = ArrayList() internal val unitActionOverlays: ArrayList<Actor> = ArrayList()
internal val unitMovementPaths: HashMap<MapUnit, ArrayList<Tile>> = HashMap() internal val unitMovementPaths: HashMap<MapUnit, ArrayList<Tile>> = HashMap()
@ -98,20 +99,6 @@ class WorldMapHolder(
onZoomStopListener = { setActHit() } onZoomStopListener = { setActHit() }
} }
// Interface for classes that contain the data required to draw a button
interface ButtonDto
// Contains the data required to draw a "move here" button
class MoveHereButtonDto(val unitToTurnsToDestination: HashMap<MapUnit, Int>, val tile: Tile) :
ButtonDto
// Contains the data required to draw a "swap with" button
class SwapWithButtonDto(val unit: MapUnit, val tile: Tile) : ButtonDto
// Contains the data required to draw a "connect road" button
class ConnectRoadButtonDto(val unit: MapUnit, val tile: Tile) : ButtonDto
// Contains the data required to draw a "move spy" button
class MoveSpyButtonDto(val spy: Spy, val city: City?) : ButtonDto
internal fun addTiles() { internal fun addTiles() {
val tileSetStrings = TileSetStrings() val tileSetStrings = TileSetStrings()
@ -266,7 +253,7 @@ class WorldMapHolder(
UncivGame.Current.settings.addCompletedTutorialTask(key) UncivGame.Current.settings.addCompletedTutorialTask(key)
} }
private fun moveUnitToTargetTile(selectedUnits: List<MapUnit>, targetTile: Tile) { internal fun moveUnitToTargetTile(selectedUnits: List<MapUnit>, targetTile: Tile) {
// this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread // this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread
// THIS PART IS REALLY ANNOYING // THIS PART IS REALLY ANNOYING
// So lets say you have 2 units you want to move in the same direction, right // So lets say you have 2 units you want to move in the same direction, right
@ -381,7 +368,7 @@ class WorldMapHolder(
) )
} }
private fun swapMoveUnitToTargetTile(selectedUnit: MapUnit, targetTile: Tile) { internal fun swapMoveUnitToTargetTile(selectedUnit: MapUnit, targetTile: Tile) {
markUnitMoveTutorialComplete(selectedUnit) markUnitMoveTutorialComplete(selectedUnit)
selectedUnit.movement.swapMoveToTile(targetTile) selectedUnit.movement.swapMoveToTile(targetTile)
@ -397,24 +384,6 @@ class WorldMapHolder(
removeUnitActionOverlay() removeUnitActionOverlay()
} }
private fun connectRoadToTargetTile(selectedUnit: MapUnit, targetTile: Tile) {
selectedUnit.automatedRoadConnectionDestination = targetTile.position
selectedUnit.automatedRoadConnectionPath = null
selectedUnit.action = UnitActionType.ConnectRoad.value
selectedUnit.automated = true
UnitAutomation.automateUnitMoves(selectedUnit)
SoundPlayer.play(UncivSound("wagon"))
worldScreen.shouldUpdate = true
removeUnitActionOverlay()
// Make highlighting go away
worldScreen.bottomUnitTable.selectedUnitIsConnectingRoad = false
}
private fun addTileOverlaysWithUnitMovement(selectedUnits: List<MapUnit>, tile: Tile) { private fun addTileOverlaysWithUnitMovement(selectedUnits: List<MapUnit>, tile: Tile) {
Concurrency.run("TurnsToGetThere") { Concurrency.run("TurnsToGetThere") {
/** LibGdx sometimes has these weird errors when you try to edit the UI layout from 2 separate threads. /** LibGdx sometimes has these weird errors when you try to edit the UI layout from 2 separate threads.
@ -460,7 +429,7 @@ class WorldMapHolder(
worldScreen.bottomUnitTable.selectUnit(selectedUnit) // keep moved unit selected worldScreen.bottomUnitTable.selectUnit(selectedUnit) // keep moved unit selected
} else { } else {
// add "move to" button if there is a path to tileInfo // add "move to" button if there is a path to tileInfo
val moveHereButtonDto = MoveHereButtonDto(unitsWhoCanMoveThere, tile) val moveHereButtonDto = MoveHereOverlayButtonData(unitsWhoCanMoveThere, tile)
addTileOverlays(tile, moveHereButtonDto) addTileOverlays(tile, moveHereButtonDto)
} }
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
@ -479,7 +448,7 @@ class WorldMapHolder(
} }
else { else {
// Add "swap with" button // Add "swap with" button
val swapWithButtonDto = SwapWithButtonDto(selectedUnit, tile) val swapWithButtonDto = SwapWithOverlayButtonData(selectedUnit, tile)
addTileOverlays(tile, swapWithButtonDto) addTileOverlays(tile, swapWithButtonDto)
} }
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
@ -500,7 +469,7 @@ class WorldMapHolder(
return@launchOnGLThread return@launchOnGLThread
} }
unitConnectRoadPaths[selectedUnit] = roadPath unitConnectRoadPaths[selectedUnit] = roadPath
val connectRoadButtonDto = ConnectRoadButtonDto(selectedUnit, tile) val connectRoadButtonDto = ConnectRoadOverlayButtonData(selectedUnit, tile)
addTileOverlays(tile, connectRoadButtonDto) addTileOverlays(tile, connectRoadButtonDto)
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
} }
@ -510,22 +479,14 @@ class WorldMapHolder(
private fun addMovingSpyOverlay(spy: Spy, tile: Tile) { private fun addMovingSpyOverlay(spy: Spy, tile: Tile) {
val city: City? = if (tile.isCityCenter() && spy.canMoveTo(tile.getCity()!!)) tile.getCity() else null val city: City? = if (tile.isCityCenter() && spy.canMoveTo(tile.getCity()!!)) tile.getCity() else null
addTileOverlays(tile, MoveSpyButtonDto(spy, city)) addTileOverlays(tile, MoveSpyOverlayButtonData(spy, city))
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
} }
private fun addTileOverlays(tile: Tile, buttonDto: ButtonDto? = null) { private fun addTileOverlays(tile: Tile, buttonDto: OverlayButtonData? = null) {
val table = Table().apply { defaults().pad(10f) } val table = Table().apply { defaults().pad(10f) }
if (buttonDto != null && worldScreen.canChangeState) if (buttonDto != null && worldScreen.canChangeState)
table.add( table.add(buttonDto.createButton(this))
when (buttonDto) {
is MoveHereButtonDto -> getMoveHereButton(buttonDto)
is SwapWithButtonDto -> getSwapWithButton(buttonDto)
is ConnectRoadButtonDto -> getConnectRoadButton(buttonDto)
is MoveSpyButtonDto -> getMoveSpyButton(buttonDto)
else -> null
}
)
val unitList = ArrayList<MapUnit>() val unitList = ArrayList<MapUnit>()
if (tile.isCityCenter() if (tile.isCityCenter()
@ -553,134 +514,6 @@ class WorldMapHolder(
addOverlayOnTileGroup(tileGroups[tile]!!, table) addOverlayOnTileGroup(tileGroups[tile]!!, table)
table.moveBy(0f, 48f) table.moveBy(0f, 48f)
}
val buttonSize = 60f
val smallerCircleSizes = 25f
private fun getMoveHereButton(dto: MoveHereButtonDto): Group {
val isParadrop = dto.unitToTurnsToDestination.keys.all { it.isPreparingParadrop() }
val image = if (isParadrop)
ImageGetter.getUnitActionPortrait("Paradrop", buttonSize / 2)
else ImageGetter.getStatIcon("Movement")
.apply { color = Color.BLACK; width = buttonSize / 2; height = buttonSize / 2 }
val moveHereButton = image
.surroundWithCircle(buttonSize - 2, false)
.surroundWithCircle(buttonSize, false, Color.BLACK)
if (!isParadrop) {
val numberCircle = dto.unitToTurnsToDestination.values.maxOrNull()!!.tr().toLabel(fontSize = 14)
.apply { setAlignment(Align.center) }
.surroundWithCircle(smallerCircleSizes - 2, color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.3f))
.surroundWithCircle(smallerCircleSizes, false)
moveHereButton.addActor(numberCircle)
}
val firstUnit = dto.unitToTurnsToDestination.keys.first()
val unitIcon = if (dto.unitToTurnsToDestination.size == 1) UnitIconGroup(firstUnit, smallerCircleSizes)
else dto.unitToTurnsToDestination.size.tr().toLabel(fontColor = firstUnit.civ.nation.getInnerColor()).apply { setAlignment(Align.center) }
.surroundWithCircle(smallerCircleSizes).apply { circle.color = firstUnit.civ.nation.getOuterColor() }
unitIcon.y = buttonSize - unitIcon.height
moveHereButton.addActor(unitIcon)
val unitsThatCanMove = dto.unitToTurnsToDestination.keys.filter { it.currentMovement > 0 }
if (unitsThatCanMove.isEmpty()) moveHereButton.color.a = 0.5f
else {
moveHereButton.onActivation(UncivSound.Silent) {
moveUnitToTargetTile(unitsThatCanMove, dto.tile)
}
moveHereButton.keyShortcuts.add(KeyCharAndCode.TAB)
}
return moveHereButton
}
private fun getSwapWithButton(dto: SwapWithButtonDto): Group {
val swapWithButton = Group()
swapWithButton.setSize(buttonSize, buttonSize)
swapWithButton.addActor(ImageGetter.getCircle(size = buttonSize))
swapWithButton.addActor(
ImageGetter.getImage("OtherIcons/Swap").apply {
color = Color.BLACK
setSize(buttonSize / 2)
center(swapWithButton)
}
)
val unitIcon = UnitIconGroup(dto.unit, smallerCircleSizes)
unitIcon.y = buttonSize - unitIcon.height
swapWithButton.addActor(unitIcon)
swapWithButton.onActivation(UncivSound.Silent) {
swapMoveUnitToTargetTile(dto.unit, dto.tile)
}
swapWithButton.keyShortcuts.add(KeyCharAndCode.TAB)
return swapWithButton
}
private fun getConnectRoadButton(dto: ConnectRoadButtonDto): Group {
val connectRoadButton = Group()
connectRoadButton.setSize(buttonSize, buttonSize)
connectRoadButton.addActor(ImageGetter.getUnitActionPortrait("RoadConnection", buttonSize * 0.8f).apply {
center(connectRoadButton)
}
)
val unitIcon = UnitIconGroup(dto.unit, smallerCircleSizes)
unitIcon.y = buttonSize - unitIcon.height
connectRoadButton.addActor(unitIcon)
connectRoadButton.onActivation(UncivSound.Silent) {
connectRoadToTargetTile(dto.unit, dto.tile)
}
connectRoadButton.keyShortcuts.add(KeyboardBinding.ConnectRoad)
return connectRoadButton
}
private fun getMoveSpyButton(dto: MoveSpyButtonDto): Group {
val spyActionButton = Group()
spyActionButton.setSize(buttonSize, buttonSize)
spyActionButton.addActor(ImageGetter.getCircle(size = buttonSize))
if (dto.city != null) {
spyActionButton.addActor(
ImageGetter.getStatIcon("Movement").apply {
name = "Button"
color = Color.BLACK
setSize(buttonSize / 2)
center(spyActionButton)
}
)
} else {
spyActionButton.addActor(
ImageGetter.getImage("OtherIcons/Close").apply {
name = "Button"
color = Color.RED
setSize(buttonSize / 2)
center(spyActionButton)
}
)
}
spyActionButton.onActivation(UncivSound.Silent) {
if (dto.city != null) {
dto.spy.moveTo(dto.city)
worldScreen.game.pushScreen(EspionageOverviewScreen(worldScreen.selectedCiv, worldScreen))
} else {
worldScreen.game.pushScreen(EspionageOverviewScreen(worldScreen.selectedCiv, worldScreen))
worldScreen.bottomUnitTable.selectedSpy = null
}
removeUnitActionOverlay()
selectedTile = null
worldScreen.shouldUpdate = true
worldScreen.bottomUnitTable.selectSpy(null)
}
spyActionButton.keyShortcuts.add(KeyCharAndCode.TAB)
spyActionButton.keyShortcuts.add(KeyCharAndCode.RETURN)
spyActionButton.keyShortcuts.add(KeyCharAndCode.NUMPAD_ENTER)
return spyActionButton
} }
fun addOverlayOnTileGroup(group: TileGroup, actor: Actor) { fun addOverlayOnTileGroup(group: TileGroup, actor: Actor) {
@ -862,7 +695,6 @@ class WorldMapHolder(
return result return result
} }
// For debugging purposes // For debugging purposes
override fun draw(batch: Batch?, parentAlpha: Float) = super.draw(batch, parentAlpha) override fun draw(batch: Batch?, parentAlpha: Float) = super.draw(batch, parentAlpha)
override fun act(delta: Float) = super.act(delta) override fun act(delta: Float) = super.act(delta)

View File

@ -1,4 +1,4 @@
package com.unciv.ui.screens.worldscreen package com.unciv.ui.screens.worldscreen.worldmap
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.Constants import com.unciv.Constants