Multiselect & move works! Currently very restricted and not all selected units are visible to user

This commit is contained in:
Yair Morgenstern 2020-09-11 16:55:35 +03:00
parent c659af8762
commit f63005ad3c
6 changed files with 64 additions and 58 deletions

View File

@ -213,7 +213,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
stage.removeListener(keyListener) stage.removeListener(keyListener)
game.setWorldScreen() game.setWorldScreen()
game.worldScreen.mapHolder.setCenterPosition(city.location) game.worldScreen.mapHolder.setCenterPosition(city.location)
game.worldScreen.bottomUnitTable.selectUnits() game.worldScreen.bottomUnitTable.selectUnit()
} }
fun page(delta: Int) { fun page(delta: Int) {
val civInfo = city.civInfo val civInfo = city.civInfo

View File

@ -9,6 +9,7 @@ import com.badlogic.gdx.scenes.scene2d.*
import com.badlogic.gdx.scenes.scene2d.actions.FloatAction import com.badlogic.gdx.scenes.scene2d.actions.FloatAction
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
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.automation.BattleHelper import com.unciv.logic.automation.BattleHelper
@ -23,7 +24,6 @@ import com.unciv.ui.map.TileGroupMap
import com.unciv.ui.tilegroups.TileSetStrings import com.unciv.ui.tilegroups.TileSetStrings
import com.unciv.ui.tilegroups.WorldTileGroup import com.unciv.ui.tilegroups.WorldTileGroup
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.concurrent.thread import kotlin.concurrent.thread
@ -93,11 +93,10 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap
&& previousSelectedUnits.any { it.movement.canMoveTo(tileInfo) }) { && previousSelectedUnits.any { it.movement.canMoveTo(tileInfo) }) {
// 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
addTileOverlaysWithUnitMovement(previousSelectedUnits, tileInfo) addTileOverlaysWithUnitMovement(previousSelectedUnits, tileInfo)
} } else addTileOverlays(tileInfo) // no unit movement but display the units in the tile etc.
else addTileOverlays(tileInfo) // no unit movement but display the units in the tile etc.
if(newSelectedUnit==null || newSelectedUnit.type==UnitType.Civilian) { if (newSelectedUnit == null || newSelectedUnit.type == UnitType.Civilian) {
val unitsInTile = selectedTile!!.getUnits() val unitsInTile = selectedTile!!.getUnits()
if (previousSelectedCity != null && !previousSelectedCity.attackedThisTurn if (previousSelectedCity != null && !previousSelectedCity.attackedThisTurn
&& selectedTile!!.getTilesInDistance(2).contains(previousSelectedCity.getCenterTile()) && selectedTile!!.getTilesInDistance(2).contains(previousSelectedCity.getCenterTile())
@ -137,7 +136,7 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap
Sounds.play(UncivSound.Whoosh) Sounds.play(UncivSound.Whoosh)
if (selectedUnit.currentTile != targetTile) if (selectedUnit.currentTile != targetTile)
selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt() selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt()
if (selectedUnit.currentMovement > 0) worldScreen.bottomUnitTable.selectUnits(selectedUnit) if (selectedUnit.currentMovement > 0) worldScreen.bottomUnitTable.selectUnit(selectedUnit)
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
unitActionOverlay?.remove() unitActionOverlay?.remove()
@ -165,24 +164,25 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap
} }
Gdx.app.postRunnable { Gdx.app.postRunnable {
val unitsWhoCanMoveThere = unitToTurnsToTile.filter { it.value!=0 } val unitsWhoCanMoveThere = HashMap(unitToTurnsToTile.filter { it.value!=0 })
if (unitsWhoCanMoveThere.isEmpty()){ // give the regular tile overlays with no unit movement if (unitsWhoCanMoveThere.isEmpty()){ // give the regular tile overlays with no unit movement
addTileOverlays(tileInfo) addTileOverlays(tileInfo)
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
return@postRunnable return@postRunnable
} }
val turnsToGetThere = unitsWhoCanMoveThere.values.first() val turnsToGetThere = unitsWhoCanMoveThere.values.max()!!
val selectedUnit = unitsWhoCanMoveThere.keys.first() // val selectedUnit = unitsWhoCanMoveThere.keys.first()
if (UncivGame.Current.settings.singleTapMove && turnsToGetThere == 1) { if (UncivGame.Current.settings.singleTapMove && turnsToGetThere == 1) {
// single turn instant move // single turn instant move
selectedUnit.movement.headTowards(tileInfo) for(unit in unitsWhoCanMoveThere.keys) {
worldScreen.bottomUnitTable.selectUnits(selectedUnit) // keep moved unit selected unit.movement.headTowards(tileInfo)
}
// 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 = if (turnsToGetThere != 0) MoveHereButtonDto(hashMapOf(selectedUnit to turnsToGetThere), tileInfo) val moveHereButtonDto = MoveHereButtonDto(unitsWhoCanMoveThere, tileInfo)
else null
addTileOverlays(tileInfo, moveHereButtonDto) addTileOverlays(tileInfo, moveHereButtonDto)
} }
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
@ -211,7 +211,7 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap
if (unit.currentMovement == 0f) unitGroup.color.a = 0.5f if (unit.currentMovement == 0f) unitGroup.color.a = 0.5f
unitGroup.touchable = Touchable.enabled unitGroup.touchable = Touchable.enabled
unitGroup.onClick { unitGroup.onClick {
worldScreen.bottomUnitTable.selectUnits(unit) worldScreen.bottomUnitTable.selectUnit(unit)
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
unitActionOverlay?.remove() unitActionOverlay?.remove()
} }
@ -227,27 +227,30 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap
val moveHereButton = Group().apply { width = size;height = size; } val moveHereButton = Group().apply { width = size;height = size; }
moveHereButton.addActor(ImageGetter.getCircle().apply { width = size; height = size }) moveHereButton.addActor(ImageGetter.getCircle().apply { width = size; height = size })
moveHereButton.addActor(ImageGetter.getStatIcon("Movement") moveHereButton.addActor(ImageGetter.getStatIcon("Movement")
.apply { color= Color.BLACK; width = size / 2; height = size / 2; center(moveHereButton) }) .apply { color = Color.BLACK; width = size / 2; height = size / 2; center(moveHereButton) })
val numberCircle = ImageGetter.getCircle().apply { width = size / 2; height = size / 2;color = Color.BLUE } val numberCircle = ImageGetter.getCircle().apply { width = size / 2; height = size / 2;color = Color.BLUE }
moveHereButton.addActor(numberCircle) moveHereButton.addActor(numberCircle)
moveHereButton.addActor(dto.unitToTurnsToDestination.values.first().toString().toLabel().apply { center(numberCircle) }) moveHereButton.addActor(dto.unitToTurnsToDestination.values.max()!!.toLabel().apply { center(numberCircle) })
val unit = dto.unitToTurnsToDestination.keys.first() val firstUnit = dto.unitToTurnsToDestination.keys.first()
val unitIcon = UnitGroup(unit, size / 2) val unitIcon = if (dto.unitToTurnsToDestination.size == 1) UnitGroup(firstUnit, size / 2)
else dto.unitToTurnsToDestination.size.toString().toLabel(fontColor = firstUnit.civInfo.nation.getInnerColor()).apply { setAlignment(Align.center) }
.surroundWithCircle(size / 2).apply { circle.color = firstUnit.civInfo.nation.getOuterColor() }
unitIcon.y = size - unitIcon.height unitIcon.y = size - unitIcon.height
moveHereButton.addActor(unitIcon) moveHereButton.addActor(unitIcon)
if (unit.currentMovement > 0) for (unit in dto.unitToTurnsToDestination.keys) {
moveHereButton.onClick(UncivSound.Silent) { if (unit.currentMovement > 0)
UncivGame.Current.settings.addCompletedTutorialTask("Move unit") moveHereButton.onClick(UncivSound.Silent) {
if(unit.type.isAirUnit()) UncivGame.Current.settings.addCompletedTutorialTask("Move unit")
UncivGame.Current.settings.addCompletedTutorialTask("Move an air unit") if (unit.type.isAirUnit())
moveUnitToTargetTile(unit, dto.tileInfo) UncivGame.Current.settings.addCompletedTutorialTask("Move an air unit")
} moveUnitToTargetTile(unit, dto.tileInfo)
}
else moveHereButton.color.a = 0.5f else moveHereButton.color.a = 0.5f
}
return moveHereButton return moveHereButton
} }

View File

@ -593,7 +593,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
val nextDueUnit = viewingCiv.getNextDueUnit() val nextDueUnit = viewingCiv.getNextDueUnit()
if (nextDueUnit != null) { if (nextDueUnit != null) {
mapHolder.setCenterPosition(nextDueUnit.currentTile.position, false, false) mapHolder.setCenterPosition(nextDueUnit.currentTile.position, false, false)
bottomUnitTable.selectUnits(nextDueUnit) bottomUnitTable.selectUnit(nextDueUnit)
shouldUpdate = true shouldUpdate = true
} }
} }
@ -686,7 +686,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
// Deselect Unit // Deselect Unit
if (bottomUnitTable.selectedUnit != null) { if (bottomUnitTable.selectedUnit != null) {
bottomUnitTable.selectUnits() bottomUnitTable.selectUnit()
bottomUnitTable.isVisible = false bottomUnitTable.isVisible = false
shouldUpdate = true shouldUpdate = true
return return

View File

@ -46,7 +46,7 @@ class IdleUnitButton (
unitToSelect.due = false unitToSelect.due = false
tileMapHolder.setCenterPosition(unitToSelect.currentTile.position) tileMapHolder.setCenterPosition(unitToSelect.currentTile.position)
unitTable.selectUnits(unitToSelect) unitTable.selectUnit(unitToSelect)
unitTable.worldScreen.shouldUpdate = true unitTable.worldScreen.shouldUpdate = true
} }
} }

View File

@ -285,7 +285,7 @@ object UnitActions {
type = UnitActionType.ConstructImprovement, type = UnitActionType.ConstructImprovement,
isCurrentAction = unit.currentTile.hasImprovementInProgress(), isCurrentAction = unit.currentTile.hasImprovementInProgress(),
action = { action = {
worldScreen.game.setScreen(ImprovementPickerScreen(tile) { unitTable.selectUnits() }) worldScreen.game.setScreen(ImprovementPickerScreen(tile) { unitTable.selectUnit() })
}.takeIf { canConstruct }) }.takeIf { canConstruct })
} }
@ -443,7 +443,7 @@ object UnitActions {
uncivSound = UncivSound.Fortify, uncivSound = UncivSound.Fortify,
action = { action = {
unit.fortify() unit.fortify()
unitTable.selectUnits() unitTable.selectUnit()
}.takeIf { unit.currentMovement > 0 }) }.takeIf { unit.currentMovement > 0 })
if (unit.health < 100) { if (unit.health < 100) {
@ -452,7 +452,7 @@ object UnitActions {
title = UnitActionType.FortifyUntilHealed.value, title = UnitActionType.FortifyUntilHealed.value,
action = { action = {
unit.fortifyUntilHealed() unit.fortifyUntilHealed()
unitTable.selectUnits() unitTable.selectUnit()
}.takeIf { unit.currentMovement > 0 }) }.takeIf { unit.currentMovement > 0 })
actionList += actionForWounded actionList += actionForWounded
} }
@ -469,7 +469,7 @@ object UnitActions {
isCurrentAction = isSleeping, isCurrentAction = isSleeping,
action = { action = {
unit.action = Constants.unitActionSleep unit.action = Constants.unitActionSleep
unitTable.selectUnits() unitTable.selectUnit()
}.takeIf { !isSleeping }) }.takeIf { !isSleeping })
if (unit.health < 100 && !isSleeping) { if (unit.health < 100 && !isSleeping) {
@ -478,7 +478,7 @@ object UnitActions {
title = UnitActionType.SleepUntilHealed.value, title = UnitActionType.SleepUntilHealed.value,
action = { action = {
unit.action = Constants.unitActionSleepUntilHealed unit.action = Constants.unitActionSleepUntilHealed
unitTable.selectUnits() unitTable.selectUnit()
}) })
actionList += actionForWounded actionList += actionForWounded
} }

View File

@ -1,5 +1,7 @@
package com.unciv.ui.worldscreen.unit package com.unciv.ui.worldscreen.unit
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.Image
@ -28,11 +30,12 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
/** This is in preparation for multi-select and multi-move */ /** This is in preparation for multi-select and multi-move */
val selectedUnits = ArrayList<MapUnit>() val selectedUnits = ArrayList<MapUnit>()
/** Sending no units clears the selected units entirely */
fun selectUnits(vararg units:MapUnit) { /** Sending no unit clears the selected units entirely */
selectedUnits.clear() fun selectUnit(unit:MapUnit?=null, append:Boolean=false) {
if (!append) selectedUnits.clear()
selectedCity = null selectedCity = null
for (unit in units) selectedUnits.add(unit) if (unit != null) selectedUnits.add(unit)
} }
var selectedCity : CityInfo? = null var selectedCity : CityInfo? = null
@ -56,7 +59,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
deselectUnitButton.add(ImageGetter.getImage("OtherIcons/Close")).size(20f).pad(10f) deselectUnitButton.add(ImageGetter.getImage("OtherIcons/Close")).size(20f).pad(10f)
deselectUnitButton.pack() deselectUnitButton.pack()
deselectUnitButton.touchable = Touchable.enabled deselectUnitButton.touchable = Touchable.enabled
deselectUnitButton.onClick { selectUnits(); worldScreen.shouldUpdate=true; this@UnitTable.isVisible=false } deselectUnitButton.onClick { selectUnit(); worldScreen.shouldUpdate=true; this@UnitTable.isVisible=false }
addActor(deselectUnitButton) addActor(deselectUnitButton)
}).left() }).left()
@ -86,10 +89,10 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
if(selectedUnit!=null) { if(selectedUnit!=null) {
isVisible=true isVisible=true
if (selectedUnit!!.civInfo != worldScreen.viewingCiv && !worldScreen.viewingCiv.isSpectator()) { // The unit that was selected, was captured. It exists but is no longer ours. if (selectedUnit!!.civInfo != worldScreen.viewingCiv && !worldScreen.viewingCiv.isSpectator()) { // The unit that was selected, was captured. It exists but is no longer ours.
selectUnits() selectUnit()
selectedUnitHasChanged = true selectedUnitHasChanged = true
} else if (selectedUnit!! !in selectedUnit!!.getTile().getUnits()) { // The unit that was there no longer exists} } else if (selectedUnit!! !in selectedUnit!!.getTile().getUnits()) { // The unit that was there no longer exists}
selectUnits() selectUnit()
selectedUnitHasChanged = true selectedUnitHasChanged = true
} }
} }
@ -192,7 +195,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
} }
fun citySelected(cityInfo: CityInfo) : Boolean { fun citySelected(cityInfo: CityInfo) : Boolean {
selectUnits() selectUnit()
if (cityInfo == selectedCity) return false if (cityInfo == selectedCity) return false
selectedCity = cityInfo selectedCity = cityInfo
selectedUnitHasChanged = true selectedUnitHasChanged = true
@ -204,28 +207,28 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
val previouslySelectedUnit = selectedUnit val previouslySelectedUnit = selectedUnit
if(selectedTile.isCityCenter()
&& (selectedTile.getOwner()==worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator())){ if (selectedTile.isCityCenter()
&& (selectedTile.getOwner() == worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator())) {
citySelected(selectedTile.getCity()!!) citySelected(selectedTile.getCity()!!)
} } else if (selectedTile.militaryUnit != null
else if(selectedTile.militaryUnit!=null
&& (selectedTile.militaryUnit!!.civInfo == worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator()) && (selectedTile.militaryUnit!!.civInfo == worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator())
&& selectedUnit!=selectedTile.militaryUnit && selectedTile.militaryUnit!! !in selectedUnits
&& (selectedTile.civilianUnit==null || selectedUnit!=selectedTile.civilianUnit)) { && (selectedTile.civilianUnit == null || selectedUnit != selectedTile.civilianUnit)) {
selectUnits(selectedTile.militaryUnit!!) if (Gdx.input.isKeyPressed(Input.Keys.SHIFT_LEFT)) selectUnit(selectedTile.militaryUnit!!, true)
} else selectUnit(selectedTile.militaryUnit!!)
else if (selectedTile.civilianUnit!=null } else if (selectedTile.civilianUnit != null
&& (selectedTile.civilianUnit!!.civInfo == worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator()) && (selectedTile.civilianUnit!!.civInfo == worldScreen.viewingCiv || worldScreen.viewingCiv.isSpectator())
&& selectedUnit!=selectedTile.civilianUnit) { && selectedUnit != selectedTile.civilianUnit) {
selectUnits(selectedTile.civilianUnit!!) selectUnit(selectedTile.civilianUnit!!)
} else if(selectedTile == previouslySelectedUnit?.currentTile) { } else if (selectedTile == previouslySelectedUnit?.currentTile) {
// tapping the same tile again will deselect a unit. // tapping the same tile again will deselect a unit.
// important for single-tap-move to abort moving easily // important for single-tap-move to abort moving easily
selectUnits() selectUnit()
isVisible = false isVisible = false
} }
if(selectedUnit != previouslySelectedUnit) if (selectedUnit != previouslySelectedUnit)
selectedUnitHasChanged = true selectedUnitHasChanged = true
} }