TechPickerScreen centers small tech trees nicely

This commit is contained in:
Yair Morgenstern 2020-08-20 10:44:22 +03:00
parent cd72926a60
commit 67ce953c62

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
@ -22,19 +23,28 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
private var selectedTech: Technology? = null private var selectedTech: Technology? = null
private var civTech: TechManager = civInfo.tech private var civTech: TechManager = civInfo.tech
private var tempTechsToResearch: ArrayList<String> private var tempTechsToResearch: ArrayList<String>
private var lines=ArrayList<Image>() private var lines = ArrayList<Image>()
/** We need this to be a separate table, and NOT the topTable, because *inhales*
* When call setConnectingLines we need to pack() the table so that the lines will align correctly, BUT
* this causes the table to be SMALLER THAN THE SCREEN for small tech trees e.g. scenarios,
* meaning the tech tree is in a crumpled heap at the lower-left corner of the screen
* Having this be a separate table allows us to leave the TopTable as is (that is: auto-width to fit the scrollPane)
* leaving us the juicy small tech tree right in the center.
*/
private val techTable = Table()
// All these are to counter performance problems when updating buttons for all techs. // All these are to counter performance problems when updating buttons for all techs.
private var researchableTechs = civInfo.gameInfo.ruleSet.technologies.keys private var researchableTechs = civInfo.gameInfo.ruleSet.technologies.keys
.filter { civTech.canBeResearched(it) }.toHashSet() .filter { civTech.canBeResearched(it) }.toHashSet()
private val currentTechColor = colorFromRGB(7,46,43) private val currentTechColor = colorFromRGB(7, 46, 43)
private val researchedTechColor = colorFromRGB(133,112,39) private val researchedTechColor = colorFromRGB(133, 112, 39)
private val researchableTechColor = colorFromRGB(28,170,0) private val researchableTechColor = colorFromRGB(28, 170, 0)
private val queuedTechColor = colorFromRGB(39,114,154) private val queuedTechColor = colorFromRGB(39, 114, 154)
private val turnsToTech = civInfo.gameInfo.ruleSet.technologies.values.associateBy ({ it.name },{civTech.turnsToTech(it.name)}) private val turnsToTech = civInfo.gameInfo.ruleSet.technologies.values.associateBy({ it.name }, { civTech.turnsToTech(it.name) })
constructor(freeTechPick: Boolean, civInfo: CivilizationInfo) : this(civInfo) { constructor(freeTechPick: Boolean, civInfo: CivilizationInfo) : this(civInfo) {
isFreeTechPick = freeTechPick isFreeTechPick = freeTechPick
@ -44,12 +54,13 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
init { init {
setDefaultCloseAction() setDefaultCloseAction()
onBackButtonClicked { UncivGame.Current.setWorldScreen() } onBackButtonClicked { UncivGame.Current.setWorldScreen() }
scrollPane.setOverscroll(false,false) scrollPane.setOverscroll(false, false)
tempTechsToResearch = ArrayList(civTech.techsToResearch) tempTechsToResearch = ArrayList(civTech.techsToResearch)
createTechTable() createTechTable()
setButtonsInfo() setButtonsInfo()
topTable.add(techTable)
rightSideButton.setText("Pick a tech".tr()) rightSideButton.setText("Pick a tech".tr())
rightSideButton.onClick(UncivSound.Paper) { rightSideButton.onClick(UncivSound.Paper) {
game.settings.addCompletedTutorialTask("Pick technology") game.settings.addCompletedTutorialTask("Pick technology")
@ -77,12 +88,11 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
if (firstAvailableTech != null) if (firstAvailableTech != null)
centerOnTechnology(firstAvailableTech) centerOnTechnology(firstAvailableTech)
} }
} }
private fun createTechTable() { private fun createTechTable() {
val allTechs = civInfo.gameInfo.ruleSet.technologies.values val allTechs = civInfo.gameInfo.ruleSet.technologies.values
val columns = allTechs.map { it.column!!.columnNumber}.max()!! +1 val columns = allTechs.map { it.column!!.columnNumber }.max()!! + 1
val techMatrix = Array<Array<Technology?>>(columns) { arrayOfNulls(10) } // Divided into columns, then rows val techMatrix = Array<Array<Technology?>>(columns) { arrayOfNulls(10) } // Divided into columns, then rows
for (technology in allTechs) { for (technology in allTechs) {
@ -90,26 +100,26 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
} }
val erasName = allTechs.map { it.era() }.distinct() val erasName = allTechs.map { it.era() }.distinct()
for ((i,eraName) in erasName.withIndex()) { for ((i, eraName) in erasName.withIndex()) {
val columnSpan = if (eraName != Constants.ancientEra && eraName != Constants.futureEra) 2 else 3 val columnSpan = if (eraName != Constants.ancientEra && eraName != Constants.futureEra) 2 else 3
val color = if (i % 2 == 0) Color.BLUE else Color.FIREBRICK val color = if (i % 2 == 0) Color.BLUE else Color.FIREBRICK
topTable.add(eraName.toLabel().addBorder(2f, color)).fill().colspan(columnSpan) techTable.add(eraName.toLabel().addBorder(2f, color)).fill().colspan(columnSpan)
} }
for (i in 0..9) { for (i in 0..9) {
topTable.row().pad(5f).padRight(40f) techTable.row().pad(5f).padRight(40f)
for (j in techMatrix.indices) { for (j in techMatrix.indices) {
val tech = techMatrix[j][i] val tech = techMatrix[j][i]
if (tech == null) if (tech == null)
topTable.add() // empty cell techTable.add() // empty cell
else { else {
val techButton = TechButton(tech.name, civTech, false) val techButton = TechButton(tech.name, civTech, false)
techNameToButton[tech.name] = techButton techNameToButton[tech.name] = techButton
techButton.onClick { selectTechnology(tech, false) } techButton.onClick { selectTechnology(tech, false) }
topTable.add(techButton) techTable.add(techButton)
} }
} }
} }
@ -137,34 +147,35 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
text += " (" + tempTechsToResearch.indexOf(techName) + ")" text += " (" + tempTechsToResearch.indexOf(techName) + ")"
} }
if (!civTech.isResearched(techName) || techName== Constants.futureTech) if (!civTech.isResearched(techName) || techName == Constants.futureTech)
text += "\r\n" + turnsToTech[techName] + " {turns}".tr() text += "\r\n" + turnsToTech[techName] + " {turns}".tr()
techButton.text.setText(text) techButton.text.setText(text)
} }
addConnectingLines() addConnectingLines()
} }
private fun addConnectingLines() { private fun addConnectingLines() {
topTable.pack() // Needed for the lines to work! techTable.pack() // required for the table to have the button positions set, so topTable.stageToLocalCoordinates will be correct
scrollPane.updateVisualScroll()
for (line in lines) line.remove() for (line in lines) line.remove()
lines.clear() lines.clear()
for (tech in civInfo.gameInfo.ruleSet.technologies.values) { for (tech in civInfo.gameInfo.ruleSet.technologies.values) {
if(!techNameToButton.containsKey(tech.name)) if (!techNameToButton.containsKey(tech.name))
throw Exception("tech ${tech.name} not found!") throw Exception("tech ${tech.name} not found!")
val techButton = techNameToButton[tech.name]!! val techButton = techNameToButton[tech.name]!!
for (prerequisite in tech.prerequisites) { for (prerequisite in tech.prerequisites) {
val prerequisiteButton = techNameToButton[prerequisite]!! val prerequisiteButton = techNameToButton[prerequisite]!!
val techButtonCoords = Vector2(0f, techButton.height / 2) val techButtonCoords = Vector2(0f, techButton.height / 2)
techButton.localToStageCoordinates(techButtonCoords) techButton.localToStageCoordinates(techButtonCoords)
topTable.stageToLocalCoordinates(techButtonCoords) techTable.stageToLocalCoordinates(techButtonCoords)
val prerequisiteCoords = Vector2(prerequisiteButton.width, prerequisiteButton.height / 2) val prerequisiteCoords = Vector2(prerequisiteButton.width, prerequisiteButton.height / 2)
prerequisiteButton.localToStageCoordinates(prerequisiteCoords) prerequisiteButton.localToStageCoordinates(prerequisiteCoords)
topTable.stageToLocalCoordinates(prerequisiteCoords) techTable.stageToLocalCoordinates(prerequisiteCoords)
val line = ImageGetter.getLine(techButtonCoords.x, techButtonCoords.y, val line = ImageGetter.getLine(techButtonCoords.x, techButtonCoords.y,
prerequisiteCoords.x, prerequisiteCoords.y, 2f) prerequisiteCoords.x, prerequisiteCoords.y, 2f)
@ -176,7 +187,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
} }
line.color = lineColor line.color = lineColor
topTable.addActor(line) techTable.addActor(line)
lines.add(line) lines.add(line)
} }
} }
@ -191,13 +202,11 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
if (!switchfromWorldScreen) if (!switchfromWorldScreen)
return return
if(tech==null) if (tech == null)
return return
// center on technology // center on technology
if (center) { if (center) centerOnTechnology(tech)
centerOnTechnology(tech)
}
if (isFreeTechPick) { if (isFreeTechPick) {
selectTechnologyForFreeTech(tech) selectTechnologyForFreeTech(tech)
@ -206,7 +215,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec
} }
if (civInfo.gameInfo.gameParameters.godMode && !civInfo.tech.isResearched(tech.name) if (civInfo.gameInfo.gameParameters.godMode && !civInfo.tech.isResearched(tech.name)
&& selectedTech == previousSelectedTech){ && selectedTech == previousSelectedTech) {
civInfo.tech.addTechnology(tech.name) civInfo.tech.addTechnology(tech.name)
} }