City-stationed unit icons get a circular touchable area (#10866)

* Linting

* Move ClickableCircle to allow reuse

* Make the Unit list icons clickable only within their circle
This commit is contained in:
SomeTroglodyte
2024-01-04 08:03:37 +01:00
committed by GitHub
parent 8573aaf8d1
commit 42188f160c
5 changed files with 45 additions and 25 deletions

View File

@ -0,0 +1,30 @@
package com.unciv.ui.components.input
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
/**
* Invisible Widget that supports detecting clicks in a circular area.
*
* (An Image Actor does not respect alpha for its hit area, it's always square, but we want a clickable _circle_)
*
* Usage: instantiate, position and overlay on something with [addActor], add listener using [onActivation].
* Does not implement Layout at the moment - usage e.g. in a Table Cell may need that.
*
* Note this is a [Group] that is supposed to have no [children] - as a simple [Actor] the Scene2D framework won't know to call our [hit] method.
*/
class ClickableCircle(size: Float) : Group() {
private val center = Vector2(size / 2, size / 2)
private val maxDst2 = size * size / 4 // squared radius
init {
touchable = Touchable.enabled
setSize(size, size)
}
override fun hit(x: Float, y: Float, touchable: Boolean): Actor? {
return if (center.dst2(x, y) < maxDst2) this else null
}
}

View File

@ -28,6 +28,7 @@ import com.unciv.ui.components.extensions.equalizeColumns
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.components.fonts.Fonts
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.widgets.AutoScrollPane
@ -536,18 +537,5 @@ class GlobalPoliticsOverviewTable(
}
}
/** An Image Actor does not respect alpha for its hit area, it's always square, but we want a clickable _circle_ */
private class ClickableCircle(size: Float) : Group() {
val center = Vector2(size / 2, size / 2)
val maxDst2 = size * size / 4 // squared radius
init {
touchable = Touchable.enabled
setSize(size, size)
}
override fun hit(x: Float, y: Float, touchable: Boolean): Actor? {
return if (center.dst2(x, y) < maxDst2) this else null
}
}
//endregion
}

View File

@ -41,6 +41,7 @@ import com.unciv.ui.components.extensions.isShiftKeyPressed
import com.unciv.ui.components.extensions.surroundWithCircle
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.input.ActivationTypes
import com.unciv.ui.components.input.ClickableCircle
import com.unciv.ui.components.input.KeyCharAndCode
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.keyShortcuts
@ -480,12 +481,14 @@ class WorldMapHolder(
val unitGroup = UnitGroup(unit, 48f).surroundWithCircle(68f, resizeActor = false)
unitGroup.circle.color = Color.GRAY.cpy().apply { a = 0.5f }
if (unit.currentMovement == 0f) unitGroup.color.a = 0.66f
unitGroup.touchable = Touchable.enabled
unitGroup.onClick {
val clickableCircle = ClickableCircle(68f)
clickableCircle.touchable = Touchable.enabled
clickableCircle.onClick {
worldScreen.bottomUnitTable.selectUnit(unit, Gdx.input.isShiftKeyPressed())
worldScreen.shouldUpdate = true
removeUnitActionOverlay()
}
unitGroup.addActor(clickableCircle)
table.add(unitGroup)
}
@ -655,7 +658,7 @@ class WorldMapHolder(
val city = unitTable.selectedCity!!
updateBombardableTilesForSelectedCity(city)
// We still want to show road paths to the selected city if they are present
if (unitTable.selectedUnitIsConnectingRoad){
if (unitTable.selectedUnitIsConnectingRoad) {
updateTilesForSelectedUnit(unitTable.selectedUnits[0])
}
}
@ -715,11 +718,10 @@ class WorldMapHolder(
// Z-Layer: 0
// Highlight suitable tiles in road connecting mode
if (worldScreen.bottomUnitTable.selectedUnitIsConnectingRoad){
if (worldScreen.bottomUnitTable.selectedUnitIsConnectingRoad) {
val validTiles = unit.civ.gameInfo.tileMap.tileList.filter {
MapPathing.isValidRoadPathTile(unit, it)
}
unit.civ.gameInfo.civilizations
val connectRoadTileOverlayColor = Color.RED
for (tile in validTiles) {
tileGroups[tile]!!.layerOverlay.showHighlight(connectRoadTileOverlayColor, 0.3f)
@ -796,10 +798,10 @@ class WorldMapHolder(
if (currTileIndex != -1) {
val futureTiles = unit.automatedRoadConnectionPath!!.filterIndexed { index, _ ->
index > currTileIndex
}.map{tilePos ->
}.map { tilePos ->
tileMap[tilePos]
}
for (tile in futureTiles){
for (tile in futureTiles) {
tileGroups[tile]!!.layerOverlay.showHighlight(Color.ORANGE, if (UncivGame.Current.settings.singleTapMove) 0.7f else 0.3f)
}
}

View File

@ -214,7 +214,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table() {
separator.isVisible = true
val city = selectedCity!!
var nameLabelText = city.name.tr()
if(city.health<city.getMaxHealth()) nameLabelText+=" ("+city.health+")"
if (city.health < city.getMaxHealth()) nameLabelText += " ("+city.health+")"
unitNameLabel.setText(nameLabelText)
unitNameLabel.clearListeners()
@ -286,10 +286,10 @@ class UnitTable(val worldScreen: WorldScreen) : Table() {
fun citySelected(city: City) : Boolean {
// If the last selected unit connecting a road, keep it selected. Otherwise, clear.
if(selectedUnitIsConnectingRoad){
if (selectedUnitIsConnectingRoad) {
selectUnit(selectedUnits[0])
selectedUnitIsConnectingRoad = true // selectUnit resets this
}else{
} else {
selectUnit()
}
if (city == selectedCity) return false