mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-22 20:49:36 +07:00
Improved city button (#771)
* improved CityButton * keep city button out of the way if a unit on the city tile is selected * fixed city button to be clickable always. however this hides units behind it * added click area for city buttons in an own layer, so the units render in front and the city button click area handles the clicks * city button: simplified code
This commit is contained in:
parent
054b3b000d
commit
73e397c2c2
@ -2,9 +2,10 @@ package com.unciv.ui.tilegroups
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Interpolation
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.FloatAction
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.utils.Align
|
||||
@ -24,9 +25,8 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
|
||||
touchable= Touchable.disabled
|
||||
}
|
||||
|
||||
var offset: Float = 0f;
|
||||
var isButtonMoved = false
|
||||
var isLabelClicked = false
|
||||
var buttonDownClickArea: Actor? = null
|
||||
fun isButtonMoved() = buttonDownClickArea != null
|
||||
|
||||
fun update(isCityViewable:Boolean) {
|
||||
val cityButtonText = city.population.population.toString() + " | " + city.name
|
||||
@ -36,61 +36,37 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
|
||||
label.setFontColor(city.civInfo.getNation().getSecondaryColor())
|
||||
|
||||
clear()
|
||||
val unitTable = tileGroup.worldScreen.bottomBar.unitTable
|
||||
if (UnCivGame.Current.viewEntireMapForDebug || city.civInfo.isCurrentPlayer()) {
|
||||
|
||||
// So you can click anywhere on the button to go to the city
|
||||
touchable = Touchable.enabled
|
||||
|
||||
label.touchable = Touchable.enabled
|
||||
label.onClick {
|
||||
isLabelClicked = true
|
||||
// clicking on the label swings that label a little down to allow selection of units there.
|
||||
// second tap on the label will go to the city screen
|
||||
if (tileGroup.selectCity(city)) {
|
||||
val floatAction = object : FloatAction(0f, 1f, 0.4f) {
|
||||
override fun update(percent: Float) {
|
||||
offset = -height*percent
|
||||
update(isCityViewable)
|
||||
}
|
||||
|
||||
override fun end() {
|
||||
isButtonMoved=true
|
||||
}
|
||||
}
|
||||
floatAction.interpolation = Interpolation.swingOut
|
||||
tileGroup.addAction(floatAction)
|
||||
}
|
||||
else {
|
||||
UnCivGame.Current.screen = CityScreen(city)
|
||||
}
|
||||
}
|
||||
|
||||
// clicking anywhere else on the button opens the city screen immediately
|
||||
onClick {
|
||||
// we need to check if the label was just clicked, as onClick will propagate
|
||||
// the click event to its touchable parent.
|
||||
if(!isLabelClicked)
|
||||
UnCivGame.Current.screen = CityScreen(city)
|
||||
isLabelClicked=false
|
||||
onClickEvent { _, x, y ->
|
||||
if (!isButtonMoved()) {
|
||||
if (hit(x, y, true) == label) {
|
||||
// clicking on the label swings that label a little down to allow selection of units there.
|
||||
// this also allows to target selected units to move to the city tile from elsewhere.
|
||||
// second tap on the label will go to the city screen
|
||||
moveButtonDown()
|
||||
if (unitTable.selectedUnit == null || unitTable.selectedUnit!!.currentMovement==0f)
|
||||
tileGroup.selectCity(city)
|
||||
} else {
|
||||
UnCivGame.Current.screen = CityScreen(city)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// when deselected, move city button to its original position
|
||||
val unitTable = tileGroup.worldScreen.bottomBar.unitTable
|
||||
if (isButtonMoved
|
||||
&& unitTable.selectedCity == null
|
||||
if (isButtonMoved()
|
||||
&& unitTable.selectedCity != city
|
||||
&& unitTable.selectedUnit?.currentTile != city.ccenterTile) {
|
||||
|
||||
isButtonMoved = false
|
||||
val floatAction = object : FloatAction(0f, 1f, 0.4f) {
|
||||
override fun update(percent: Float) {
|
||||
offset = -height*(1-percent)
|
||||
update(isCityViewable)
|
||||
}
|
||||
}
|
||||
floatAction.interpolation = Interpolation.sine
|
||||
tileGroup.addAction(floatAction)
|
||||
moveButtonUp()
|
||||
}
|
||||
|
||||
if (isCityViewable && city.health < city.getMaxHealth().toFloat()) {
|
||||
@ -129,12 +105,47 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
|
||||
add(iconTable).row()
|
||||
pack()
|
||||
setOrigin(Align.center)
|
||||
center(tileGroup)
|
||||
y += offset // for animated shifting of City button
|
||||
centerX(tileGroup)
|
||||
touchable = Touchable.enabled
|
||||
updateClickArea()
|
||||
|
||||
}
|
||||
|
||||
private fun moveButtonDown() {
|
||||
val floatAction = Actions.sequence(
|
||||
Actions.moveBy(0f, -height, 0.4f, Interpolation.swingOut),
|
||||
Actions.run {
|
||||
buttonDownClickArea = Actor().onClick {
|
||||
UnCivGame.Current.screen = CityScreen(city)
|
||||
}
|
||||
tileGroup.cityButtonLayerGroup.addActor(buttonDownClickArea)
|
||||
updateClickArea()
|
||||
}
|
||||
)
|
||||
tileGroup.addAction(floatAction)
|
||||
}
|
||||
|
||||
private fun moveButtonUp() {
|
||||
val floatAction = Actions.sequence(
|
||||
Actions.moveBy(0f, height, 0.4f, Interpolation.sine),
|
||||
Actions.run {
|
||||
buttonDownClickArea?.remove()
|
||||
buttonDownClickArea = null
|
||||
}
|
||||
)
|
||||
tileGroup.addAction(floatAction)
|
||||
}
|
||||
|
||||
private fun updateClickArea() {
|
||||
buttonDownClickArea?.let { clickArea ->
|
||||
clickArea.setSize(width, height)
|
||||
clickArea.setScale(scaleX, scaleY)
|
||||
clickArea.setOrigin(Align.center)
|
||||
clickArea.centerX(tileGroup.cityButtonLayerGroup)
|
||||
clickArea.y = y-height
|
||||
clickArea.touchable = Touchable.enabled
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConstructionGroup(cityConstructions: CityConstructions): Group {
|
||||
val group= Group()
|
||||
|
@ -55,6 +55,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
||||
protected var civilianUnitImage: UnitGroup? = null
|
||||
protected var militaryUnitImage: UnitGroup? = null
|
||||
|
||||
val cityButtonLayerGroup = Group().apply { isTransform=true; setSize(groupSize,groupSize);touchable=Touchable.childrenOnly }
|
||||
|
||||
val circleCrosshairFogLayerGroup = Group().apply { isTransform=false; setSize(groupSize,groupSize) }
|
||||
private val circleImage = ImageGetter.getCircle() // for blue and red circles on the tile
|
||||
private val crosshairImage = ImageGetter.getImage("OtherIcons/Crosshair.png") // for when a unit is targete
|
||||
@ -76,6 +78,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
||||
this.addActor(featureLayerGroup)
|
||||
this.addActor(miscLayerGroup)
|
||||
this.addActor(unitLayerGroup)
|
||||
this.addActor(cityButtonLayerGroup)
|
||||
this.addActor(circleCrosshairFogLayerGroup)
|
||||
|
||||
updateTileImage(false)
|
||||
|
@ -122,20 +122,23 @@ fun Label.setFontSize(size:Int): Label {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If there are other buttons that require special clicks then we'll have an onclick that will accept a string parameter, no worries
|
||||
|
||||
fun Actor.onClick(sound:String,function: () -> Unit){
|
||||
/** same as [onClick], but sends the [InputEvent] and coordinates along */
|
||||
fun Actor.onClickEvent(sound: String = "click", function: (event: InputEvent?, x: Float, y: Float) -> Unit) {
|
||||
this.addListener(object : ClickListener() {
|
||||
override fun clicked(event: InputEvent?, x: Float, y: Float) {
|
||||
if(sound!="") Sounds.play(sound)
|
||||
function()
|
||||
if (sound != "") Sounds.play(sound)
|
||||
function(event, x, y)
|
||||
}
|
||||
} )
|
||||
})
|
||||
}
|
||||
|
||||
// If there are other buttons that require special clicks then we'll have an onclick that will accept a string parameter, no worries
|
||||
fun Actor.onClick(sound: String = "click", function: () -> Unit) {
|
||||
onClickEvent(sound) { _, _, _ -> function() }
|
||||
}
|
||||
|
||||
fun Actor.onClick(function: () -> Unit): Actor {
|
||||
onClick("click",function)
|
||||
onClick("click", function)
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): G
|
||||
val featureLayers = ArrayList<Group>()
|
||||
val miscLayers = ArrayList<Group>()
|
||||
val unitLayers = ArrayList<Group>()
|
||||
val cityButtonLayers = ArrayList<Group>()
|
||||
val circleCrosshairFogLayers = ArrayList<Group>()
|
||||
|
||||
for(group in tileGroups.sortedByDescending { it.tileInfo.position.x + it.tileInfo.position.y }){
|
||||
@ -39,6 +40,7 @@ class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): G
|
||||
featureLayers.add(group.featureLayerGroup.apply { setPosition(group.x,group.y) })
|
||||
miscLayers.add(group.miscLayerGroup.apply { setPosition(group.x,group.y) })
|
||||
unitLayers.add(group.unitLayerGroup.apply { setPosition(group.x,group.y) })
|
||||
cityButtonLayers.add(group.cityButtonLayerGroup.apply { setPosition(group.x,group.y) })
|
||||
circleCrosshairFogLayers.add(group.circleCrosshairFogLayerGroup.apply { setPosition(group.x,group.y) })
|
||||
}
|
||||
for(group in baseLayers) addActor(group)
|
||||
@ -46,6 +48,7 @@ class TileGroupMap<T: TileGroup>(val tileGroups:Collection<T>, padding:Float): G
|
||||
for(group in miscLayers) addActor(group)
|
||||
for(group in circleCrosshairFogLayers) addActor(group)
|
||||
for(group in tileGroups) addActor(group) // The above layers are for the visual layers, this is for the clickability
|
||||
for(group in cityButtonLayers) addActor(group) // city buttons clickability
|
||||
for(group in unitLayers) addActor(group) // Aaand units above everything else.
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user