mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-05 21:11:35 +07:00
City construct menu (#9961)
* Some preparation refactoring * Some preparation API extension * Initial constructions context menu * More CityConstructions API clarification * Templates and KeyBindings * Fix quirks and prettify highlighting issues
This commit is contained in:
parent
dcb50bbbf5
commit
ca160b56fa
@ -1236,6 +1236,12 @@ Default Focus =
|
|||||||
[stat] Focus =
|
[stat] Focus =
|
||||||
Please enter a new name for your city =
|
Please enter a new name for your city =
|
||||||
Please select a tile for this building's [improvement] =
|
Please select a tile for this building's [improvement] =
|
||||||
|
Move to the top of the queue =
|
||||||
|
Move to the end of the queue =
|
||||||
|
Add to the top of the queue =
|
||||||
|
Add to the queue in all cities =
|
||||||
|
Add or move to the top in all cities =
|
||||||
|
Remove from the queue in all cities =
|
||||||
|
|
||||||
# Specialized Popups - Ask for text or numbers, file picker
|
# Specialized Popups - Ask for text or numbers, file picker
|
||||||
|
|
||||||
|
@ -142,13 +142,16 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @constructionName needs to be a non-perpetual construction, else an empty string is returned */
|
/** @param constructionName needs to be a non-perpetual construction, else an empty string is returned */
|
||||||
internal fun getTurnsToConstructionString(constructionName: String, useStoredProduction:Boolean = true): String {
|
internal fun getTurnsToConstructionString(constructionName: String, useStoredProduction:Boolean = true) =
|
||||||
val construction = getConstruction(constructionName)
|
getTurnsToConstructionString(getConstruction(constructionName), useStoredProduction)
|
||||||
|
|
||||||
|
/** @param construction needs to be a non-perpetual construction, else an empty string is returned */
|
||||||
|
internal fun getTurnsToConstructionString(construction: IConstruction, useStoredProduction:Boolean = true): String {
|
||||||
if (construction !is INonPerpetualConstruction) return "" // shouldn't happen
|
if (construction !is INonPerpetualConstruction) return "" // shouldn't happen
|
||||||
val cost = construction.getProductionCost(city.civ)
|
val cost = construction.getProductionCost(city.civ)
|
||||||
val turnsToConstruction = turnsToConstruction(constructionName, useStoredProduction)
|
val turnsToConstruction = turnsToConstruction(construction.name, useStoredProduction)
|
||||||
val currentProgress = if (useStoredProduction) getWorkDone(constructionName) else 0
|
val currentProgress = if (useStoredProduction) getWorkDone(construction.name) else 0
|
||||||
val lines = ArrayList<String>()
|
val lines = ArrayList<String>()
|
||||||
val buildable = !construction.getMatchingUniques(UniqueType.Unbuildable)
|
val buildable = !construction.getMatchingUniques(UniqueType.Unbuildable)
|
||||||
.any { it.conditionalsApply(StateForConditionals(city.civ, city)) }
|
.any { it.conditionalsApply(StateForConditionals(city.civ, city)) }
|
||||||
@ -189,12 +192,23 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
|||||||
fun isAllBuilt(buildingList: List<String>): Boolean = buildingList.all { isBuilt(it) }
|
fun isAllBuilt(buildingList: List<String>): Boolean = buildingList.all { isBuilt(it) }
|
||||||
|
|
||||||
fun isBuilt(buildingName: String): Boolean = builtBuildingObjects.any { it.name == buildingName }
|
fun isBuilt(buildingName: String): Boolean = builtBuildingObjects.any { it.name == buildingName }
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
fun isBeingConstructed(constructionName: String): Boolean = currentConstructionFromQueue == constructionName
|
|
||||||
fun isEnqueued(constructionName: String): Boolean = constructionQueue.contains(constructionName)
|
|
||||||
fun isBeingConstructedOrEnqueued(constructionName: String): Boolean = isBeingConstructed(constructionName) || isEnqueued(constructionName)
|
|
||||||
|
|
||||||
fun isQueueFull(): Boolean = constructionQueue.size == queueMaxSize
|
// Note: There was a isEnqueued here functionally identical to isBeingConstructedOrEnqueued,
|
||||||
|
// which was calling both isEnqueued and isBeingConstructed - BUT: currentConstructionFromQueue is just a
|
||||||
|
// a wrapper for constructionQueue[0], so that was redundant. Also, isEnqueued was used nowhere,
|
||||||
|
// and isBeingConstructed _only_ redundantly as described above.
|
||||||
|
// `isEnqueuedForLater` is not optimal code as it can iterate the whole list where checking size
|
||||||
|
// and first() would suffice, but the one current use in CityScreenConstructionMenu isn't critical.
|
||||||
|
|
||||||
|
@Suppress("unused", "MemberVisibilityCanBePrivate") // kept for illustration
|
||||||
|
/** @return `true` if [constructionName] is the top queue entry, the one receiving production points */
|
||||||
|
fun isBeingConstructed(constructionName: String) = currentConstructionFromQueue == constructionName
|
||||||
|
/** @return `true` if [constructionName] is queued but not the top queue entry */
|
||||||
|
fun isEnqueuedForLater(constructionName: String) = constructionQueue.indexOf(constructionName) > 0
|
||||||
|
/** @return `true` if [constructionName] is anywhere in the construction queue - [isBeingConstructed] **or** [isEnqueuedForLater] */
|
||||||
|
fun isBeingConstructedOrEnqueued(constructionName: String) = constructionQueue.contains(constructionName)
|
||||||
|
|
||||||
|
fun isQueueFull(): Boolean = constructionQueue.size >= queueMaxSize
|
||||||
|
|
||||||
fun isBuildingWonder(): Boolean {
|
fun isBuildingWonder(): Boolean {
|
||||||
val currentConstruction = getCurrentConstruction()
|
val currentConstruction = getCurrentConstruction()
|
||||||
@ -208,8 +222,8 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
/** If the city is constructing multiple units of the same type, subsequent units will require the full cost */
|
/** If the city is constructing multiple units of the same type, subsequent units will require the full cost */
|
||||||
fun isFirstConstructionOfItsKind(constructionQueueIndex: Int, name: String): Boolean {
|
fun isFirstConstructionOfItsKind(constructionQueueIndex: Int, name: String): Boolean {
|
||||||
// if the construction name is the same as the current construction, it isn't the first
|
// Simply compare index of first found [name] with given index
|
||||||
return constructionQueueIndex == constructionQueue.indexOfFirst { it == name }
|
return constructionQueueIndex == constructionQueue.indexOf(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -745,25 +759,53 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
|||||||
newTile.improvementFunctions.markForCreatesOneImprovement(improvement.name)
|
newTile.improvementFunctions.markForCreatesOneImprovement(improvement.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addToQueue(constructionName: String) {
|
fun canAddToQueue(construction: IConstruction) =
|
||||||
if (isQueueFull()) return
|
!isQueueFull() &&
|
||||||
val construction = getConstruction(constructionName)
|
construction.isBuildable(this) &&
|
||||||
if (!construction.isBuildable(this)) return
|
!(construction is Building && isBeingConstructedOrEnqueued(construction.name))
|
||||||
if (construction is Building && isBeingConstructedOrEnqueued(constructionName)) return
|
|
||||||
if (currentConstructionFromQueue == "" || currentConstructionFromQueue == "Nothing") {
|
private fun isLastConstructionPerpetual() = constructionQueue.isNotEmpty() &&
|
||||||
currentConstructionFromQueue = constructionName
|
PerpetualConstruction.isNamePerpetual(constructionQueue.last())
|
||||||
} else if (getConstruction(constructionQueue.last()) is PerpetualConstruction) {
|
// `getConstruction(constructionQueue.last()) is PerpetualConstruction` is clear but more expensive
|
||||||
if (construction is PerpetualConstruction) { // perpetual constructions will replace each other
|
|
||||||
constructionQueue.removeAt(constructionQueue.size - 1)
|
/** Add [construction] to the end or top (controlled by [addToTop]) of the queue with all checks (does nothing if not possible)
|
||||||
|
*
|
||||||
|
* Note: Overload with string parameter `constructionName` exists as well.
|
||||||
|
*/
|
||||||
|
fun addToQueue(construction: IConstruction, addToTop: Boolean = false) {
|
||||||
|
if (!canAddToQueue(construction)) return
|
||||||
|
val constructionName = construction.name
|
||||||
|
when {
|
||||||
|
currentConstructionFromQueue.isEmpty() || currentConstructionFromQueue == "Nothing" ->
|
||||||
|
currentConstructionFromQueue = constructionName
|
||||||
|
addToTop && construction is PerpetualConstruction && PerpetualConstruction.isNamePerpetual(currentConstructionFromQueue) ->
|
||||||
|
currentConstructionFromQueue = constructionName // perpetual constructions will replace each other
|
||||||
|
addToTop ->
|
||||||
|
constructionQueue.add(0, constructionName)
|
||||||
|
isLastConstructionPerpetual() -> {
|
||||||
|
// Note this also works if currentConstructionFromQueue is perpetual and the only entry - that var is delegated to the first queue position
|
||||||
|
if (construction is PerpetualConstruction) {
|
||||||
|
// perpetual constructions will replace each other
|
||||||
|
constructionQueue.removeLast()
|
||||||
|
constructionQueue.add(constructionName)
|
||||||
|
} else
|
||||||
|
constructionQueue.add(constructionQueue.size - 1, constructionName) // insert new construction before perpetual one
|
||||||
|
}
|
||||||
|
else ->
|
||||||
constructionQueue.add(constructionName)
|
constructionQueue.add(constructionName)
|
||||||
} else
|
}
|
||||||
constructionQueue.add(constructionQueue.size - 1, constructionName) // insert new construction before perpetual one
|
|
||||||
} else
|
|
||||||
constructionQueue.add(constructionName)
|
|
||||||
currentConstructionIsUserSet = true
|
currentConstructionIsUserSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If this was done automatically, we should automatically try to choose a new construction and treat it as such */
|
/** Add a construction named [constructionName] to the end of the queue with all checks
|
||||||
|
*
|
||||||
|
* Note: Delegates to overload with `construction` parameter.
|
||||||
|
*/
|
||||||
|
fun addToQueue(constructionName: String) = addToQueue(getConstruction(constructionName))
|
||||||
|
|
||||||
|
/** Remove one entry from the queue by index.
|
||||||
|
* @param automatic If this was done automatically, we should automatically try to choose a new construction and treat it as such
|
||||||
|
*/
|
||||||
fun removeFromQueue(constructionQueueIndex: Int, automatic: Boolean) {
|
fun removeFromQueue(constructionQueueIndex: Int, automatic: Boolean) {
|
||||||
val constructionName = constructionQueue.removeAt(constructionQueueIndex)
|
val constructionName = constructionQueue.removeAt(constructionQueueIndex)
|
||||||
|
|
||||||
@ -783,6 +825,38 @@ class CityConstructions : IsPartOfGameInfoSerialization {
|
|||||||
} else true // we're just continuing the regular queue
|
} else true // we're just continuing the regular queue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Remove all queue entries for [constructionName].
|
||||||
|
*
|
||||||
|
* Does nothing if there's no entry of that name in the queue.
|
||||||
|
* If the queue is emptied, no automatic: getSettings().autoAssignCityProduction is ignored! (parameter to be added when needed)
|
||||||
|
*/
|
||||||
|
fun removeAllByName(constructionName: String) {
|
||||||
|
while (true) {
|
||||||
|
val index = constructionQueue.indexOf(constructionName)
|
||||||
|
if (index < 0) return
|
||||||
|
removeFromQueue(index, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Moves an entry to the queue top by index.
|
||||||
|
* No-op when index invalid. Must not be called for PerpetualConstruction entries - unchecked! */
|
||||||
|
fun moveEntryToTop(constructionQueueIndex: Int) {
|
||||||
|
if (constructionQueueIndex == 0 || constructionQueueIndex >= constructionQueue.size) return
|
||||||
|
val constructionName = constructionQueue.removeAt(constructionQueueIndex)
|
||||||
|
constructionQueue.add(0, constructionName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Moves an entry by index to the end of the queue, or just before a PerpetualConstruction
|
||||||
|
* (or replacing a PerpetualConstruction if it itself is one and the queue is by happenstance invalid having more than one of those)
|
||||||
|
*/
|
||||||
|
fun moveEntryToEnd(constructionQueueIndex: Int) {
|
||||||
|
if (constructionQueueIndex >= constructionQueue.size) return
|
||||||
|
val constructionName = constructionQueue.removeAt(constructionQueueIndex)
|
||||||
|
// Some of the overhead of addToQueue is redundant here, but if the complex "needs to replace or go before a perpetual" logic is needed, then use it anyway
|
||||||
|
if (isLastConstructionPerpetual()) return addToQueue(constructionName)
|
||||||
|
constructionQueue.add(constructionName)
|
||||||
|
}
|
||||||
|
|
||||||
fun raisePriority(constructionQueueIndex: Int): Int {
|
fun raisePriority(constructionQueueIndex: Int): Int {
|
||||||
constructionQueue.swap(constructionQueueIndex - 1, constructionQueueIndex)
|
constructionQueue.swap(constructionQueueIndex - 1, constructionQueueIndex)
|
||||||
return constructionQueueIndex - 1
|
return constructionQueueIndex - 1
|
||||||
|
@ -224,6 +224,9 @@ open class PerpetualConstruction(override var name: String, val description: Str
|
|||||||
|
|
||||||
val perpetualConstructionsMap: Map<String, PerpetualConstruction>
|
val perpetualConstructionsMap: Map<String, PerpetualConstruction>
|
||||||
= mapOf(science.name to science, gold.name to gold, culture.name to culture, faith.name to faith, idle.name to idle)
|
= mapOf(science.name to science, gold.name to gold, culture.name to culture, faith.name to faith, idle.name to idle)
|
||||||
|
|
||||||
|
/** @return whether [name] represents a PerpetualConstruction - note "" is translated to Nothing in the queue so `isNamePerpetual("")==true` */
|
||||||
|
fun isNamePerpetual(name: String) = name.isEmpty() || name in perpetualConstructionsMap
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean =
|
override fun isBuildable(cityConstructions: CityConstructions): Boolean =
|
||||||
|
@ -157,6 +157,12 @@ enum class KeyboardBinding(
|
|||||||
CultureFocus(Category.CityScreen, "[${Stat.Culture.name}] Focus", KeyCharAndCode.ctrl('c')),
|
CultureFocus(Category.CityScreen, "[${Stat.Culture.name}] Focus", KeyCharAndCode.ctrl('c')),
|
||||||
FaithFocus(Category.CityScreen, "[${Stat.Faith.name}] Focus", KeyCharAndCode.UNKNOWN),
|
FaithFocus(Category.CityScreen, "[${Stat.Faith.name}] Focus", KeyCharAndCode.UNKNOWN),
|
||||||
|
|
||||||
|
// CityScreenConstructionMenu (not quite cleanly) reuses RaisePriority/LowerPriority, plus:
|
||||||
|
AddConstructionTop(Category.CityScreenConstructionMenu, "Add to the top of the queue", 't'),
|
||||||
|
AddConstructionAll(Category.CityScreenConstructionMenu, "Add to the queue in all cities", KeyCharAndCode.ctrl('a')),
|
||||||
|
AddConstructionAllTop(Category.CityScreenConstructionMenu, "Add or move to the top in all cities", KeyCharAndCode.ctrl('t')),
|
||||||
|
RemoveConstructionAll(Category.CityScreenConstructionMenu, "Remove from the queue in all cities", KeyCharAndCode.ctrl('r')),
|
||||||
|
|
||||||
// Popups
|
// Popups
|
||||||
Confirm(Category.Popups, "Confirm Dialog", 'y'),
|
Confirm(Category.Popups, "Confirm Dialog", 'y'),
|
||||||
Cancel(Category.Popups, "Cancel Dialog", 'n'),
|
Cancel(Category.Popups, "Cancel Dialog", 'n'),
|
||||||
@ -179,6 +185,7 @@ enum class KeyboardBinding(
|
|||||||
override fun checkConflictsIn() = sequenceOf(WorldScreen)
|
override fun checkConflictsIn() = sequenceOf(WorldScreen)
|
||||||
},
|
},
|
||||||
CityScreen,
|
CityScreen,
|
||||||
|
CityScreenConstructionMenu, // Maybe someday a category hierarchy?
|
||||||
Popups
|
Popups
|
||||||
;
|
;
|
||||||
val label = unCamelCase(name)
|
val label = unCamelCase(name)
|
||||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.NinePatch
|
import com.badlogic.gdx.graphics.g2d.NinePatch
|
||||||
import com.badlogic.gdx.math.Interpolation
|
import com.badlogic.gdx.math.Interpolation
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||||
@ -54,6 +55,13 @@ open class AnimatedMenuPopup(
|
|||||||
var anyButtonWasClicked = false
|
var anyButtonWasClicked = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** Get stage coords of an [actor]'s right edge center, to help position an [AnimatedMenuPopup].
|
||||||
|
* Note the Popup will center over this point.
|
||||||
|
*/
|
||||||
|
fun getActorTopRight(actor: Actor): Vector2 = actor.localToStageCoordinates(Vector2(actor.width, actor.height / 2))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Popup content.
|
* Provides the Popup content.
|
||||||
*
|
*
|
||||||
@ -61,8 +69,11 @@ open class AnimatedMenuPopup(
|
|||||||
* You can use [getButton], which produces TextButtons slightly smaller than Unciv's default ones.
|
* You can use [getButton], which produces TextButtons slightly smaller than Unciv's default ones.
|
||||||
* The content adding functions offered by [Popup] or [Table] won't work.
|
* The content adding functions offered by [Popup] or [Table] won't work.
|
||||||
* The content needs to be complete when the method finishes, it will be `pack()`ed and measured immediately.
|
* The content needs to be complete when the method finishes, it will be `pack()`ed and measured immediately.
|
||||||
|
*
|
||||||
|
* Return `null` to abort the menu creation - nothing will be shown and the instance should be discarded.
|
||||||
|
* Useful if you need full context first to determine if any entry makes sense.
|
||||||
*/
|
*/
|
||||||
open fun createContentTable() = Table().apply {
|
open fun createContentTable(): Table? = Table().apply {
|
||||||
defaults().pad(5f, 15f, 5f, 15f).growX()
|
defaults().pad(5f, 15f, 5f, 15f).growX()
|
||||||
background = BaseScreen.skinStrings.getUiBackground("General/AnimatedMenu", BaseScreen.skinStrings.roundedEdgeRectangleShape, Color.DARK_GRAY)
|
background = BaseScreen.skinStrings.getUiBackground("General/AnimatedMenu", BaseScreen.skinStrings.roundedEdgeRectangleShape, Color.DARK_GRAY)
|
||||||
}
|
}
|
||||||
@ -79,6 +90,7 @@ open class AnimatedMenuPopup(
|
|||||||
|
|
||||||
private fun createAndShow(position: Vector2) {
|
private fun createAndShow(position: Vector2) {
|
||||||
val newInnerTable = createContentTable()
|
val newInnerTable = createContentTable()
|
||||||
|
?: return // Special case - we don't want the context menu after all. If cleanup should become necessary in that case, add here.
|
||||||
newInnerTable.pack()
|
newInnerTable.pack()
|
||||||
container.actor = newInnerTable
|
container.actor = newInnerTable
|
||||||
container.touchable = Touchable.childrenOnly
|
container.touchable = Touchable.childrenOnly
|
||||||
|
105
core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt
Normal file
105
core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package com.unciv.ui.popups
|
||||||
|
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
|
import com.unciv.logic.city.City
|
||||||
|
import com.unciv.logic.city.CityConstructions
|
||||||
|
import com.unciv.models.ruleset.Building
|
||||||
|
import com.unciv.models.ruleset.IConstruction
|
||||||
|
import com.unciv.models.ruleset.PerpetualConstruction
|
||||||
|
import com.unciv.ui.components.input.KeyboardBinding
|
||||||
|
|
||||||
|
//todo Check move/top/end for "place one improvement" buildings
|
||||||
|
//todo Check add/remove-all for "place one improvement" buildings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Context menu" for City constructions - available by right-clicking (or long-press) in
|
||||||
|
* City Screen, left side, available constructions or queue entries.
|
||||||
|
*
|
||||||
|
* @param city The [City] calling us - we need only `cityConstructions`, but future expansion may be easier having the parent
|
||||||
|
* @param construction The construction that was right-clicked
|
||||||
|
* @param onButtonClicked Callback if closed due to any action having been chosen - to update CityScreen
|
||||||
|
*/
|
||||||
|
class CityScreenConstructionMenu(
|
||||||
|
stage: Stage,
|
||||||
|
positionNextTo: Actor,
|
||||||
|
private val city: City,
|
||||||
|
private val construction: IConstruction,
|
||||||
|
private val onButtonClicked: () -> Unit
|
||||||
|
) : AnimatedMenuPopup(stage, getActorTopRight(positionNextTo)) {
|
||||||
|
|
||||||
|
// These are only readability shorteners
|
||||||
|
private val cityConstructions = city.cityConstructions
|
||||||
|
private val constructionName = construction.name
|
||||||
|
private val queueSizeWithoutPerpetual get() = // simply remove get() should this be needed more than once
|
||||||
|
cityConstructions.constructionQueue
|
||||||
|
.count { it !in PerpetualConstruction.perpetualConstructionsMap }
|
||||||
|
private val myIndex = cityConstructions.constructionQueue.indexOf(constructionName)
|
||||||
|
private fun anyCity(predicate: (CityConstructions) -> Boolean) =
|
||||||
|
(construction as? Building)?.isAnyWonder() != true &&
|
||||||
|
city.civ.cities.map { it.cityConstructions }.any(predicate)
|
||||||
|
private fun forAllCities(action: (CityConstructions) -> Unit) =
|
||||||
|
city.civ.cities.map { it.cityConstructions }.forEach(action)
|
||||||
|
|
||||||
|
init {
|
||||||
|
closeListeners.add {
|
||||||
|
if (anyButtonWasClicked) onButtonClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createContentTable(): Table? {
|
||||||
|
val table = super.createContentTable()!!
|
||||||
|
if (canMoveQueueTop())
|
||||||
|
table.add(getButton("Move to the top of the queue", KeyboardBinding.RaisePriority, ::moveQueueTop)).row()
|
||||||
|
if (canMoveQueueEnd())
|
||||||
|
table.add(getButton("Move to the end of the queue", KeyboardBinding.LowerPriority, ::moveQueueEnd)).row()
|
||||||
|
if (canAddQueueTop())
|
||||||
|
table.add(getButton("Add to the top of the queue", KeyboardBinding.AddConstructionTop, ::addQueueTop)).row()
|
||||||
|
if (canAddAllQueues())
|
||||||
|
table.add(getButton("Add to the queue in all cities", KeyboardBinding.AddConstructionAll, ::addAllQueues)).row()
|
||||||
|
if (canAddAllQueuesTop())
|
||||||
|
table.add(getButton("Add or move to the top in all cities", KeyboardBinding.AddConstructionAllTop, ::addAllQueuesTop)).row()
|
||||||
|
if (canRemoveAllQueues())
|
||||||
|
table.add(getButton("Remove from the queue in all cities", KeyboardBinding.RemoveConstructionAll, ::removeAllQueues)).row()
|
||||||
|
return table.takeUnless { it.cells.isEmpty }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canMoveQueueTop(): Boolean {
|
||||||
|
if (construction is PerpetualConstruction)
|
||||||
|
return false
|
||||||
|
return myIndex > 0
|
||||||
|
}
|
||||||
|
private fun moveQueueTop() = cityConstructions.moveEntryToTop(myIndex)
|
||||||
|
|
||||||
|
private fun canMoveQueueEnd(): Boolean {
|
||||||
|
if (construction is PerpetualConstruction)
|
||||||
|
return false
|
||||||
|
return myIndex in 0 until queueSizeWithoutPerpetual - 1
|
||||||
|
}
|
||||||
|
private fun moveQueueEnd() = cityConstructions.moveEntryToEnd(myIndex)
|
||||||
|
|
||||||
|
private fun canAddQueueTop() = construction !is PerpetualConstruction &&
|
||||||
|
cityConstructions.canAddToQueue(construction)
|
||||||
|
private fun addQueueTop() = cityConstructions.addToQueue(construction, addToTop = true)
|
||||||
|
|
||||||
|
private fun canAddAllQueues() = anyCity {
|
||||||
|
it.canAddToQueue(construction) &&
|
||||||
|
// A Perpetual that is already queued can still be added says canAddToQueue, but here we don't want to count that
|
||||||
|
!(construction is PerpetualConstruction && it.isBeingConstructedOrEnqueued(constructionName))
|
||||||
|
}
|
||||||
|
private fun addAllQueues() = forAllCities { it.addToQueue(construction) }
|
||||||
|
|
||||||
|
private fun canAddAllQueuesTop() = construction !is PerpetualConstruction &&
|
||||||
|
anyCity { it.canAddToQueue(construction) || it.isEnqueuedForLater(constructionName) }
|
||||||
|
private fun addAllQueuesTop() = forAllCities {
|
||||||
|
val index = it.constructionQueue.indexOf(constructionName)
|
||||||
|
if (index > 0)
|
||||||
|
it.moveEntryToTop(index)
|
||||||
|
else
|
||||||
|
it.addToQueue(construction, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canRemoveAllQueues() = anyCity { it.isBeingConstructedOrEnqueued(constructionName) }
|
||||||
|
private fun removeAllQueues() = forAllCities { it.removeAllByName(constructionName) }
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.unciv.ui.popups
|
package com.unciv.ui.popups
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Stage
|
import com.badlogic.gdx.scenes.scene2d.Stage
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.unciv.logic.map.mapunit.MapUnit
|
import com.unciv.logic.map.mapunit.MapUnit
|
||||||
@ -30,12 +31,12 @@ import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade
|
|||||||
*/
|
*/
|
||||||
class UnitUpgradeMenu(
|
class UnitUpgradeMenu(
|
||||||
stage: Stage,
|
stage: Stage,
|
||||||
position: Vector2,
|
positionNextTo: Actor,
|
||||||
private val unit: MapUnit,
|
private val unit: MapUnit,
|
||||||
private val unitAction: UpgradeUnitAction,
|
private val unitAction: UpgradeUnitAction,
|
||||||
private val callbackAfterAnimation: Boolean = false,
|
private val callbackAfterAnimation: Boolean = false,
|
||||||
private val onButtonClicked: () -> Unit
|
private val onButtonClicked: () -> Unit
|
||||||
) : AnimatedMenuPopup(stage, position) {
|
) : AnimatedMenuPopup(stage, getActorTopRight(positionNextTo)) {
|
||||||
|
|
||||||
private val allUpgradableUnits: Sequence<MapUnit> by lazy {
|
private val allUpgradableUnits: Sequence<MapUnit> by lazy {
|
||||||
unit.civ.units.getCivUnits()
|
unit.civ.units.getCivUnits()
|
||||||
|
@ -10,14 +10,14 @@ import com.badlogic.gdx.utils.Align
|
|||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.logic.city.City
|
import com.unciv.logic.city.City
|
||||||
import com.unciv.logic.city.CityConstructions
|
import com.unciv.logic.city.CityConstructions
|
||||||
|
import com.unciv.logic.map.tile.Tile
|
||||||
|
import com.unciv.models.UncivSound
|
||||||
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.IConstruction
|
import com.unciv.models.ruleset.IConstruction
|
||||||
import com.unciv.models.ruleset.INonPerpetualConstruction
|
import com.unciv.models.ruleset.INonPerpetualConstruction
|
||||||
import com.unciv.models.ruleset.PerpetualConstruction
|
import com.unciv.models.ruleset.PerpetualConstruction
|
||||||
import com.unciv.models.ruleset.RejectionReason
|
import com.unciv.models.ruleset.RejectionReason
|
||||||
import com.unciv.models.ruleset.RejectionReasonType
|
import com.unciv.models.ruleset.RejectionReasonType
|
||||||
import com.unciv.logic.map.tile.Tile
|
|
||||||
import com.unciv.models.UncivSound
|
|
||||||
import com.unciv.models.ruleset.Building
|
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.ruleset.unit.BaseUnit
|
import com.unciv.models.ruleset.unit.BaseUnit
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
@ -34,15 +34,17 @@ import com.unciv.ui.components.extensions.darken
|
|||||||
import com.unciv.ui.components.extensions.disable
|
import com.unciv.ui.components.extensions.disable
|
||||||
import com.unciv.ui.components.extensions.getConsumesAmountString
|
import com.unciv.ui.components.extensions.getConsumesAmountString
|
||||||
import com.unciv.ui.components.extensions.isEnabled
|
import com.unciv.ui.components.extensions.isEnabled
|
||||||
import com.unciv.ui.components.input.onActivation
|
|
||||||
import com.unciv.ui.components.input.onClick
|
|
||||||
import com.unciv.ui.components.extensions.packIfNeeded
|
import com.unciv.ui.components.extensions.packIfNeeded
|
||||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
import com.unciv.ui.components.extensions.toTextButton
|
import com.unciv.ui.components.extensions.toTextButton
|
||||||
import com.unciv.ui.components.input.KeyboardBinding
|
import com.unciv.ui.components.input.KeyboardBinding
|
||||||
import com.unciv.ui.components.input.keyShortcuts
|
import com.unciv.ui.components.input.keyShortcuts
|
||||||
|
import com.unciv.ui.components.input.onActivation
|
||||||
|
import com.unciv.ui.components.input.onClick
|
||||||
|
import com.unciv.ui.components.input.onRightClick
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
|
import com.unciv.ui.popups.CityScreenConstructionMenu
|
||||||
import com.unciv.ui.popups.ConfirmPopup
|
import com.unciv.ui.popups.ConfirmPopup
|
||||||
import com.unciv.ui.popups.Popup
|
import com.unciv.ui.popups.Popup
|
||||||
import com.unciv.ui.popups.closeAllPopups
|
import com.unciv.ui.popups.closeAllPopups
|
||||||
@ -206,7 +208,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
|||||||
for (entry in constructionsSequence.filter { it.shouldBeDisplayed(cityConstructions) }) {
|
for (entry in constructionsSequence.filter { it.shouldBeDisplayed(cityConstructions) }) {
|
||||||
|
|
||||||
val useStoredProduction = entry is Building || !cityConstructions.isBeingConstructedOrEnqueued(entry.name)
|
val useStoredProduction = entry is Building || !cityConstructions.isBeingConstructedOrEnqueued(entry.name)
|
||||||
val buttonText = cityConstructions.getTurnsToConstructionString(entry.name, useStoredProduction).trim()
|
val buttonText = cityConstructions.getTurnsToConstructionString(entry, useStoredProduction).trim()
|
||||||
val resourcesRequired = entry.getResourceRequirementsPerTurn()
|
val resourcesRequired = entry.getResourceRequirementsPerTurn()
|
||||||
val mostImportantRejection =
|
val mostImportantRejection =
|
||||||
entry.getRejectionReasons(cityConstructions)
|
entry.getRejectionReasons(cityConstructions)
|
||||||
@ -308,21 +310,16 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
|||||||
|
|
||||||
val table = Table()
|
val table = Table()
|
||||||
table.align(Align.left).pad(5f)
|
table.align(Align.left).pad(5f)
|
||||||
table.background = BaseScreen.skinStrings.getUiBackground("CityScreen/CityConstructionTable/QueueEntry", tintColor = Color.BLACK)
|
highlightQueueEntry(table, constructionQueueIndex == selectedQueueEntry)
|
||||||
|
|
||||||
if (constructionQueueIndex == selectedQueueEntry)
|
|
||||||
table.background = BaseScreen.skinStrings.getUiBackground(
|
|
||||||
"CityScreen/CityConstructionTable/QueueEntrySelected",
|
|
||||||
tintColor = Color.GREEN.darken(0.5f)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
val construction = cityConstructions.getConstruction(constructionName)
|
||||||
val isFirstConstructionOfItsKind = cityConstructions.isFirstConstructionOfItsKind(constructionQueueIndex, constructionName)
|
val isFirstConstructionOfItsKind = cityConstructions.isFirstConstructionOfItsKind(constructionQueueIndex, constructionName)
|
||||||
|
|
||||||
var text = constructionName.tr(true) +
|
var text = constructionName.tr(true) +
|
||||||
if (constructionName in PerpetualConstruction.perpetualConstructionsMap) "\n∞"
|
if (constructionName in PerpetualConstruction.perpetualConstructionsMap) "\n∞"
|
||||||
else cityConstructions.getTurnsToConstructionString(constructionName, isFirstConstructionOfItsKind)
|
else cityConstructions.getTurnsToConstructionString(construction, isFirstConstructionOfItsKind)
|
||||||
|
|
||||||
val constructionResource = cityConstructions.getConstruction(constructionName).getResourceRequirementsPerTurn()
|
val constructionResource = construction.getResourceRequirementsPerTurn()
|
||||||
for ((resourceName, amount) in constructionResource) {
|
for ((resourceName, amount) in constructionResource) {
|
||||||
val resource = cityConstructions.city.getRuleset().tileResources[resourceName] ?: continue
|
val resource = cityConstructions.city.getRuleset().tileResources[resourceName] ?: continue
|
||||||
text += "\n" + resourceName.getConsumesAmountString(amount, resource.isStockpiled()).tr()
|
text += "\n" + resourceName.getConsumesAmountString(amount, resource.isStockpiled()).tr()
|
||||||
@ -345,15 +342,40 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
|||||||
else table.add().right()
|
else table.add().right()
|
||||||
|
|
||||||
table.touchable = Touchable.enabled
|
table.touchable = Touchable.enabled
|
||||||
table.onClick {
|
|
||||||
|
fun selectQueueEntry(onBeforeUpdate: () -> Unit) {
|
||||||
cityScreen.selectConstruction(constructionName)
|
cityScreen.selectConstruction(constructionName)
|
||||||
selectedQueueEntry = constructionQueueIndex
|
selectedQueueEntry = constructionQueueIndex
|
||||||
cityScreen.update()
|
onBeforeUpdate()
|
||||||
|
cityScreen.update() // Not before CityScreenConstructionMenu or table will have no parent to get stage coords
|
||||||
ensureQueueEntryVisible()
|
ensureQueueEntryVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.onClick { selectQueueEntry {} }
|
||||||
|
if (cityScreen.canCityBeChanged())
|
||||||
|
table.onRightClick { selectQueueEntry {
|
||||||
|
CityScreenConstructionMenu(cityScreen.stage, table, cityScreen.city, construction) {
|
||||||
|
cityScreen.update()
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun highlightQueueEntry(queueEntry: Table, highlight: Boolean) {
|
||||||
|
queueEntry.background =
|
||||||
|
if (highlight)
|
||||||
|
BaseScreen.skinStrings.getUiBackground(
|
||||||
|
"CityScreen/CityConstructionTable/QueueEntrySelected",
|
||||||
|
tintColor = Color.GREEN.darken(0.5f)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
BaseScreen.skinStrings.getUiBackground(
|
||||||
|
"CityScreen/CityConstructionTable/QueueEntry",
|
||||||
|
tintColor = Color.BLACK
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getProgressBar(constructionName: String): Group {
|
private fun getProgressBar(constructionName: String): Group {
|
||||||
val cityConstructions = cityScreen.city.cityConstructions
|
val cityConstructions = cityScreen.city.cityConstructions
|
||||||
val construction = cityConstructions.getConstruction(constructionName)
|
val construction = cityConstructions.getConstruction(constructionName)
|
||||||
@ -368,22 +390,14 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
|||||||
|
|
||||||
private fun getConstructionButton(constructionButtonDTO: ConstructionButtonDTO): Table {
|
private fun getConstructionButton(constructionButtonDTO: ConstructionButtonDTO): Table {
|
||||||
val construction = constructionButtonDTO.construction
|
val construction = constructionButtonDTO.construction
|
||||||
val pickConstructionButton = Table().apply { isTransform = false }
|
val pickConstructionButton = Table().apply {
|
||||||
|
isTransform = false
|
||||||
pickConstructionButton.align(Align.left).pad(5f)
|
align(Align.left).pad(5f)
|
||||||
pickConstructionButton.background = BaseScreen.skinStrings.getUiBackground(
|
touchable = Touchable.enabled
|
||||||
"CityScreen/CityConstructionTable/PickConstructionButton",
|
|
||||||
tintColor = Color.BLACK
|
|
||||||
)
|
|
||||||
pickConstructionButton.touchable = Touchable.enabled
|
|
||||||
|
|
||||||
if (!isSelectedQueueEntry() && cityScreen.selectedConstruction == construction) {
|
|
||||||
pickConstructionButton.background = BaseScreen.skinStrings.getUiBackground(
|
|
||||||
"CityScreen/CityConstructionTable/PickConstructionButtonSelected",
|
|
||||||
tintColor = Color.GREEN.darken(0.5f)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
highlightConstructionButton(pickConstructionButton, !isSelectedQueueEntry() && cityScreen.selectedConstruction == construction)
|
||||||
|
|
||||||
val icon = ImageGetter.getConstructionPortrait(construction.name, 40f)
|
val icon = ImageGetter.getConstructionPortrait(construction.name, 40f)
|
||||||
pickConstructionButton.add(getProgressBar(construction.name)).padRight(5f)
|
pickConstructionButton.add(getProgressBar(construction.name)).padRight(5f)
|
||||||
pickConstructionButton.add(icon).padRight(10f)
|
pickConstructionButton.add(icon).padRight(10f)
|
||||||
@ -444,14 +458,68 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
|
|||||||
addConstructionToQueue(construction, cityScreen.city.cityConstructions)
|
addConstructionToQueue(construction, cityScreen.city.cityConstructions)
|
||||||
} else {
|
} else {
|
||||||
cityScreen.selectConstruction(construction)
|
cityScreen.selectConstruction(construction)
|
||||||
|
highlightConstructionButton(pickConstructionButton, true, true) // without, will highlight but with visible delay
|
||||||
}
|
}
|
||||||
selectedQueueEntry = -1
|
selectedQueueEntry = -1
|
||||||
cityScreen.update()
|
cityScreen.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cityScreen.canCityBeChanged()) return pickConstructionButton
|
||||||
|
|
||||||
|
pickConstructionButton.onRightClick {
|
||||||
|
if (cityScreen.selectedConstruction != construction) {
|
||||||
|
// Ensure context is visible
|
||||||
|
cityScreen.selectConstruction(construction)
|
||||||
|
highlightConstructionButton(pickConstructionButton, true, true)
|
||||||
|
cityScreen.updateWithoutConstructionAndMap()
|
||||||
|
}
|
||||||
|
CityScreenConstructionMenu(cityScreen.stage, pickConstructionButton, cityScreen.city, construction) {
|
||||||
|
cityScreen.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
return pickConstructionButton
|
return pickConstructionButton
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun highlightConstructionButton(
|
||||||
|
pickConstructionButton: Table,
|
||||||
|
highlight: Boolean,
|
||||||
|
clearOthers: Boolean = false
|
||||||
|
) {
|
||||||
|
val unselected by lazy {
|
||||||
|
// Lazy because possibly not needed (highlight true, clearOthers false) and slightly costly
|
||||||
|
BaseScreen.skinStrings.getUiBackground(
|
||||||
|
"CityScreen/CityConstructionTable/PickConstructionButton",
|
||||||
|
tintColor = Color.BLACK
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pickConstructionButton.background =
|
||||||
|
if (highlight)
|
||||||
|
BaseScreen.skinStrings.getUiBackground(
|
||||||
|
"CityScreen/CityConstructionTable/PickConstructionButtonSelected",
|
||||||
|
tintColor = Color.GREEN.darken(0.5f)
|
||||||
|
)
|
||||||
|
else unselected
|
||||||
|
|
||||||
|
if (!clearOthers) return
|
||||||
|
// Using knowledge about Widget hierarchy - Making the Buttons their own class might be a better design.
|
||||||
|
for (categoryExpander in availableConstructionsTable.children.filterIsInstance<ExpanderTab>()) {
|
||||||
|
if (!categoryExpander.isOpen) continue
|
||||||
|
for (button in categoryExpander.innerTable.children.filterIsInstance<Table>()) {
|
||||||
|
if (button == pickConstructionButton) continue
|
||||||
|
button.background = unselected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSelectedQueueEntry()) return
|
||||||
|
// Same as above but worse - both buttons and headers are typed `Table`
|
||||||
|
for (button in constructionsQueueTable.children.filterIsInstance<Table>()) {
|
||||||
|
if (button.children.size == 1) continue // Skip headers, they only have 1 Label
|
||||||
|
highlightQueueEntry(button, false)
|
||||||
|
}
|
||||||
|
selectedQueueEntry = -1
|
||||||
|
}
|
||||||
|
|
||||||
private fun isSelectedQueueEntry(): Boolean = selectedQueueEntry >= 0
|
private fun isSelectedQueueEntry(): Boolean = selectedQueueEntry >= 0
|
||||||
|
|
||||||
private fun cannotAddConstructionToQueue(construction: IConstruction, city: City, cityConstructions: CityConstructions): Boolean {
|
private fun cannotAddConstructionToQueue(construction: IConstruction, city: City, cityConstructions: CityConstructions): Boolean {
|
||||||
|
@ -5,19 +5,19 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.models.ruleset.IConstruction
|
|
||||||
import com.unciv.models.ruleset.PerpetualConstruction
|
|
||||||
import com.unciv.models.ruleset.PerpetualStatConversion
|
|
||||||
import com.unciv.models.UncivSound
|
import com.unciv.models.UncivSound
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
|
import com.unciv.models.ruleset.IConstruction
|
||||||
import com.unciv.models.ruleset.IRulesetObject
|
import com.unciv.models.ruleset.IRulesetObject
|
||||||
|
import com.unciv.models.ruleset.PerpetualConstruction
|
||||||
|
import com.unciv.models.ruleset.PerpetualStatConversion
|
||||||
import com.unciv.models.ruleset.unit.BaseUnit
|
import com.unciv.models.ruleset.unit.BaseUnit
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.components.Fonts
|
import com.unciv.ui.components.Fonts
|
||||||
import com.unciv.ui.components.extensions.darken
|
import com.unciv.ui.components.extensions.darken
|
||||||
import com.unciv.ui.components.extensions.disable
|
import com.unciv.ui.components.extensions.disable
|
||||||
import com.unciv.ui.components.input.onClick
|
|
||||||
import com.unciv.ui.components.extensions.toTextButton
|
import com.unciv.ui.components.extensions.toTextButton
|
||||||
|
import com.unciv.ui.components.input.onClick
|
||||||
import com.unciv.ui.images.ImageGetter
|
import com.unciv.ui.images.ImageGetter
|
||||||
import com.unciv.ui.popups.ConfirmPopup
|
import com.unciv.ui.popups.ConfirmPopup
|
||||||
import com.unciv.ui.popups.closeAllPopups
|
import com.unciv.ui.popups.closeAllPopups
|
||||||
@ -74,7 +74,7 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() {
|
|||||||
val specialConstruction = PerpetualConstruction.perpetualConstructionsMap[construction.name]
|
val specialConstruction = PerpetualConstruction.perpetualConstructionsMap[construction.name]
|
||||||
|
|
||||||
buildingText += specialConstruction?.getProductionTooltip(city)
|
buildingText += specialConstruction?.getProductionTooltip(city)
|
||||||
?: cityConstructions.getTurnsToConstructionString(construction.name)
|
?: cityConstructions.getTurnsToConstructionString(construction)
|
||||||
|
|
||||||
add(Label(buildingText, BaseScreen.skin)).row() // already translated
|
add(Label(buildingText, BaseScreen.skin)).row() // already translated
|
||||||
|
|
||||||
|
@ -6,8 +6,6 @@ import com.badlogic.gdx.scenes.scene2d.Action
|
|||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.Group
|
import com.badlogic.gdx.scenes.scene2d.Group
|
||||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
|
||||||
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.Constants
|
import com.unciv.Constants
|
||||||
@ -267,8 +265,7 @@ class UnitOverviewTab(
|
|||||||
val upgradeIcon = ImageGetter.getUnitIcon(unitToUpgradeTo.name,
|
val upgradeIcon = ImageGetter.getUnitIcon(unitToUpgradeTo.name,
|
||||||
if (enable) Color.GREEN else Color.GREEN.darken(0.5f))
|
if (enable) Color.GREEN else Color.GREEN.darken(0.5f))
|
||||||
if (enable) upgradeIcon.onClick {
|
if (enable) upgradeIcon.onClick {
|
||||||
val pos = upgradeIcon.localToStageCoordinates(Vector2(upgradeIcon.width/2, upgradeIcon.height/2))
|
UnitUpgradeMenu(overviewScreen.stage, upgradeIcon, unit, unitAction) {
|
||||||
UnitUpgradeMenu(overviewScreen.stage, pos, unit, unitAction) {
|
|
||||||
unitListTable.updateUnitListTable()
|
unitListTable.updateUnitListTable()
|
||||||
select(selectKey)
|
select(selectKey)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.unciv.ui.screens.worldscreen.unit.actions
|
package com.unciv.ui.screens.worldscreen.unit.actions
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.math.Vector2
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.unciv.GUI
|
import com.unciv.GUI
|
||||||
@ -10,9 +9,7 @@ import com.unciv.logic.map.mapunit.MapUnit
|
|||||||
import com.unciv.models.UnitAction
|
import com.unciv.models.UnitAction
|
||||||
import com.unciv.models.UnitActionType
|
import com.unciv.models.UnitActionType
|
||||||
import com.unciv.models.UpgradeUnitAction
|
import com.unciv.models.UpgradeUnitAction
|
||||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
|
||||||
import com.unciv.ui.components.extensions.disable
|
import com.unciv.ui.components.extensions.disable
|
||||||
import com.unciv.ui.components.input.keyShortcuts
|
|
||||||
import com.unciv.ui.components.input.onActivation
|
import com.unciv.ui.components.input.onActivation
|
||||||
import com.unciv.ui.components.input.onRightClick
|
import com.unciv.ui.components.input.onRightClick
|
||||||
import com.unciv.ui.images.IconTextButton
|
import com.unciv.ui.images.IconTextButton
|
||||||
@ -29,8 +26,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
|||||||
val button = getUnitActionButton(unit, unitAction)
|
val button = getUnitActionButton(unit, unitAction)
|
||||||
if (unitAction is UpgradeUnitAction) {
|
if (unitAction is UpgradeUnitAction) {
|
||||||
button.onRightClick {
|
button.onRightClick {
|
||||||
val pos = button.localToStageCoordinates(Vector2(button.width, button.height))
|
UnitUpgradeMenu(worldScreen.stage, button, unit, unitAction, callbackAfterAnimation = true) {
|
||||||
UnitUpgradeMenu(worldScreen.stage, pos, unit, unitAction, callbackAfterAnimation = true) {
|
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user