Huge update of Technology Picker screen UI (Civ 5), new original icons + misc changes (#8188)

* Huge update of Technology Picker screen UI, new original icons + misc changes

* Fix possible memory leak

* Fix lines Z-Depth, shifted era boundary lines, thicker queue-path lines

* Fix lines Z-Depth more correctly

* Size checks replaced by truncation

* Icons credits

Co-authored-by: tunerzinc@gmail.com <vfylfhby>
This commit is contained in:
vegeta1k95
2022-12-21 10:25:10 +01:00
committed by GitHub
parent 0b10bf1d14
commit 1346eea4ca
17 changed files with 361 additions and 72 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -263,6 +263,48 @@ ImprovementIcons/Railroad
orig: 100, 100 orig: 100, 100
offset: 0, 0 offset: 0, 0
index: -1 index: -1
ImprovementIcons/Remove Fallout
rotate: false
xy: 250, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Remove Forest
rotate: false
xy: 350, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Remove Jungle
rotate: false
xy: 350, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Remove Marsh
rotate: false
xy: 450, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Remove Railroad
rotate: false
xy: 550, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Remove Road
rotate: false
xy: 650, 0
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
ImprovementIcons/Repair ImprovementIcons/Repair
rotate: false rotate: false
xy: 1270, 1720 xy: 1270, 1720
@ -361,6 +403,13 @@ StatIcons/Science
orig: 100, 100 orig: 100, 100
offset: 0, 0 offset: 0, 0
index: -1 index: -1
OtherIcons/ConvertScience
rotate: false
xy: 622, 886
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
OtherIcons/AirSweep OtherIcons/AirSweep
rotate: false rotate: false
xy: 4, 369 xy: 4, 369
@ -543,6 +592,13 @@ OtherIcons/Improvements
orig: 50, 50 orig: 50, 50
offset: 0, 0 offset: 0, 0
index: -1 index: -1
OtherIcons/Unique
rotate: false
xy: 1921, 1655
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
OtherIcons/Link OtherIcons/Link
rotate: false rotate: false
xy: 1004, 906 xy: 1004, 906
@ -1194,6 +1250,20 @@ StatIcons/Gold
orig: 100, 100 orig: 100, 100
offset: 0, 0 offset: 0, 0
index: -1 index: -1
OtherIcons/ConvertGold
rotate: false
xy: 298, 1426
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
OtherIcons/ConvertNothing
rotate: false
xy: 1923, 1545
size: 100, 100
orig: 100, 100
offset: 0, 0
index: -1
StatIcons/Happiness StatIcons/Happiness
rotate: false rotate: false
xy: 514, 1642 xy: 514, 1642

Binary file not shown.

Before

Width:  |  Height:  |  Size: 523 KiB

After

Width:  |  Height:  |  Size: 520 KiB

View File

@ -18,6 +18,7 @@ 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.json.json import com.unciv.json.json
import com.unciv.logic.city.PerpetualConstruction
import com.unciv.models.ruleset.Nation import com.unciv.models.ruleset.Nation
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.ResourceType
@ -238,17 +239,19 @@ object ImageGetter {
} }
fun getImprovementIcon(improvementName: String, size: Float = 20f): Group { fun getImprovementIcon(improvementName: String, size: Float = 20f, withCircle: Boolean = true): Group {
if (improvementName.startsWith(Constants.remove) || improvementName == Constants.cancelImprovementOrder) if (improvementName == Constants.cancelImprovementOrder)
return getImage("OtherIcons/Stop").surroundWithCircle(size) return getImage("OtherIcons/Stop").surroundWithCircle(size)
val iconGroup = getImage("ImprovementIcons/$improvementName").surroundWithCircle(size) val icon = getImage("ImprovementIcons/$improvementName")
if (!withCircle) return icon.toGroup(size)
val group = icon.surroundWithCircle(size)
val improvement = ruleset.tileImprovements[improvementName] val improvement = ruleset.tileImprovements[improvementName]
if (improvement != null) if (improvement != null)
iconGroup.circle.color = getColorFromStats(improvement) group.circle.color = getColorFromStats(improvement)
return group.surroundWithThinCircle()
return iconGroup.surroundWithThinCircle()
} }
fun getPortraitImage(construction: String, size: Float): Group { fun getPortraitImage(construction: String, size: Float): Group {
@ -269,8 +272,8 @@ object ImageGetter {
} else } else
getUnitIcon(construction).surroundWithCircle(size).surroundWithThinCircle() getUnitIcon(construction).surroundWithCircle(size).surroundWithThinCircle()
} }
if (construction == "Nothing") if (construction in PerpetualConstruction.perpetualConstructionsMap)
return getImage("OtherIcons/Sleep").surroundWithCircle(size).surroundWithThinCircle() return getImage("OtherIcons/Convert$construction").toGroup(size)
return getStatIcon(construction).surroundWithCircle(size).surroundWithThinCircle() return getStatIcon(construction).surroundWithCircle(size).surroundWithThinCircle()
} }

View File

@ -1,35 +1,57 @@
package com.unciv.ui.pickerscreens package com.unciv.ui.pickerscreens
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
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.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.civilization.TechManager import com.unciv.logic.civilization.TechManager
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.images.IconCircleGroup import com.unciv.ui.images.IconCircleGroup
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.extensions.addBorder import com.unciv.ui.utils.extensions.addBorder
import com.unciv.ui.utils.extensions.brighten import com.unciv.ui.utils.extensions.brighten
import com.unciv.ui.utils.extensions.center import com.unciv.ui.utils.extensions.center
import com.unciv.ui.utils.extensions.centerY
import com.unciv.ui.utils.extensions.darken import com.unciv.ui.utils.extensions.darken
import com.unciv.ui.utils.extensions.setFontSize
import com.unciv.ui.utils.extensions.setSize
import com.unciv.ui.utils.extensions.surroundWithCircle import com.unciv.ui.utils.extensions.surroundWithCircle
import com.unciv.ui.utils.extensions.surroundWithThinCircle import com.unciv.ui.utils.extensions.surroundWithThinCircle
import com.unciv.ui.utils.extensions.toGroup
import com.unciv.ui.utils.extensions.toLabel import com.unciv.ui.utils.extensions.toLabel
class TechButton(techName:String, private val techManager: TechManager, isWorldScreen: Boolean = true) : Table(BaseScreen.skin) { class TechButton(techName:String, private val techManager: TechManager, isWorldScreen: Boolean = true) : Table(BaseScreen.skin) {
val text = "".toLabel().apply { setAlignment(Align.center) } val text = "".toLabel().apply {
wrap = false
setFontSize(14)
setAlignment(Align.left)
setEllipsis(true)
}
val turns = "".toLabel().apply {
setFontSize(14)
setAlignment(Align.right)
}
var orderIndicator: IconCircleGroup? = null var orderIndicator: IconCircleGroup? = null
var bg = Image(BaseScreen.skinStrings.getUiBackground("TechPickerScreen/TechButton", BaseScreen.skinStrings.roundedEdgeRectangleShape))
init { init {
touchable = Touchable.enabled touchable = Touchable.enabled
background = BaseScreen.skinStrings.getUiBackground("TechPickerScreen/TechButton", BaseScreen.skinStrings.roundedEdgeRectangleShape) background = BaseScreen.skinStrings.getUiBackground("TechPickerScreen/TechButton", BaseScreen.skinStrings.roundedEdgeRectangleShape,
pad(10f) tintColor = Color.WHITE.darken(0.3f))
bg.toBack()
addActor(bg)
pad(0f).padBottom(5f).padTop(5f).padLeft(5f).padRight(5f)
if (ImageGetter.techIconExists(techName)) if (ImageGetter.techIconExists(techName))
add(ImageGetter.getTechIconGroup(techName, 60f)).left() add(ImageGetter.getTechIconGroup(techName, 45f)).padRight(5f).left()
val rightSide = Table() val rightSide = Table()
@ -45,18 +67,37 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
.addColor(Color.BLUE.brighten(0.3f), percentWillBeComplete) .addColor(Color.BLUE.brighten(0.3f), percentWillBeComplete)
.addColor(Color.BLUE.darken(0.5f), percentComplete) .addColor(Color.BLUE.darken(0.5f), percentComplete)
add(progressBar.addBorder(1f, Color.GRAY)).pad(10f) add(progressBar.addBorder(1f, Color.GRAY)).pad(10f)
rightSide.add(text).padBottom(5f).row() }
} else rightSide.add(text).height(25f).padBottom(5f).row() rightSide.add(text).width(145f).top().left().padRight(15f)
rightSide.add(turns).width(40f).top().right().padRight(10f).row()
addTechEnabledIcons(techName, isWorldScreen, rightSide) addTechEnabledIcons(techName, isWorldScreen, rightSide)
add(rightSide) rightSide.centerY(this)
add(rightSide).expandX().left()
pack()
bg.setSize(width-3f, height-3f)
bg.align = Align.center
bg.center(this)
pack()
}
fun setButtonColor(color: Color) {
bg.color = color
pack() pack()
} }
private fun addTechEnabledIcons(techName: String, isWorldScreen: Boolean, rightSide: Table) { private fun addTechEnabledIcons(techName: String, isWorldScreen: Boolean, rightSide: Table) {
val techEnabledIcons = Table() val techEnabledIcons = Table().align(Align.left)
techEnabledIcons.defaults().pad(5f) techEnabledIcons.background = BaseScreen.skinStrings.getUiBackground(
"TechPickerScreen/TechButtonIconsOutline",
BaseScreen.skinStrings.rectangleWithOutlineShape,
tintColor = Color.BLACK.cpy().apply { a = 0.7f }
)
techEnabledIcons.pad(0f).padLeft(10f).padTop(2f).padBottom(2f)
techEnabledIcons.defaults().padRight(5f)
val techIconSize = 30f val techIconSize = 30f
val civName = techManager.civInfo.civName val civName = techManager.civInfo.civName
@ -64,11 +105,15 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
val tech = ruleset.technologies[techName]!! val tech = ruleset.technologies[techName]!!
for (unit in tech.getEnabledUnits(ruleset, techManager.civInfo)) val icons = ArrayList<Group>()
techEnabledIcons.add(ImageGetter.getPortraitImage(unit.name, techIconSize))
for (building in tech.getEnabledBuildings(ruleset, techManager.civInfo)) for (unit in tech.getEnabledUnits(ruleset, techManager.civInfo)) {
techEnabledIcons.add(ImageGetter.getPortraitImage(building.name, techIconSize)) icons.add(ImageGetter.getPortraitImage(unit.name, techIconSize))
}
for (building in tech.getEnabledBuildings(ruleset, techManager.civInfo)) {
icons.add(ImageGetter.getPortraitImage(building.name, techIconSize))
}
for (obj in tech.getObsoletedObjects(ruleset, techManager.civInfo)) { for (obj in tech.getObsoletedObjects(ruleset, techManager.civInfo)) {
val obsoletedIcon = when (obj) { val obsoletedIcon = when (obj) {
@ -81,34 +126,56 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
closeImage.center(it) closeImage.center(it)
it.addActor(closeImage) it.addActor(closeImage)
} }
techEnabledIcons.add(obsoletedIcon) icons.add(obsoletedIcon)
} }
for (resource in ruleset.tileResources.values.filter { it.revealedBy == techName }) {
icons.add(ImageGetter.getResourceImage(resource.name, techIconSize))
}
for (improvement in ruleset.tileImprovements.values.asSequence() for (improvement in ruleset.tileImprovements.values.asSequence()
.filter { .filter { it.techRequired == techName }
it.techRequired == techName
|| it.uniqueObjects.any { u -> u.allParams.contains(techName) }
}
.filter { it.uniqueTo == null || it.uniqueTo == civName } .filter { it.uniqueTo == null || it.uniqueTo == civName }
) { ) {
techEnabledIcons.add(ImageGetter.getImprovementIcon(improvement.name, techIconSize)) icons.add(ImageGetter.getImprovementIcon(improvement.name, techIconSize, true))
} }
for (improvement in ruleset.tileImprovements.values.asSequence()
for (resource in ruleset.tileResources.values.filter { it.revealedBy == techName }) .filter { it.uniqueObjects.any { u -> u.allParams.contains(techName) } }
techEnabledIcons.add(ImageGetter.getResourceImage(resource.name, techIconSize)) .filter { it.uniqueTo == null || it.uniqueTo == civName }
) {
for (unique in tech.uniques) icons.add(
techEnabledIcons.add( ImageGetter.getImage("OtherIcons/Unique")
ImageGetter.getImage("OtherIcons/Star")
.apply { color = Color.BLACK }
.surroundWithCircle(techIconSize) .surroundWithCircle(techIconSize)
.surroundWithThinCircle()) .surroundWithThinCircle())
}
if (isWorldScreen) rightSide.add(techEnabledIcons) for (unique in tech.uniques) {
else rightSide.add(techEnabledIcons) icons.add(
.minWidth(225f) when (unique) {
UniqueType.EnablesCivWideStatProduction.text.replace("civWideStat", "Gold" )
-> ImageGetter.getImage("OtherIcons/ConvertGold").toGroup(techIconSize)
UniqueType.EnablesCivWideStatProduction.text.replace("civWideStat", "Science" )
-> ImageGetter.getImage("OtherIcons/ConvertScience").toGroup(techIconSize)
else -> ImageGetter.getImage("OtherIcons/Unique")
.surroundWithCircle(techIconSize)
.surroundWithThinCircle()
}
)
}
for (i in 0..4) {
val icon = icons.getOrNull(i)
if (icon != null)
techEnabledIcons.add(icon)
}
rightSide.add(techEnabledIcons)
.colspan(2)
.minWidth(195f)
.prefWidth(195f)
.maxWidth(195f)
.expandX().left().row()
} }
fun addOrderIndicator(number:Int){ fun addOrderIndicator(number:Int){
@ -119,4 +186,5 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS
orderIndicator!!.setPosition(0f, height, Align.topLeft) orderIndicator!!.setPosition(0f, height, Align.topLeft)
addActor(orderIndicator) addActor(orderIndicator)
} }
} }

View File

@ -3,7 +3,9 @@ package com.unciv.ui.pickerscreens
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.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
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.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
@ -16,14 +18,17 @@ import com.unciv.ui.civilopedia.CivilopediaCategories
import com.unciv.ui.civilopedia.CivilopediaScreen import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.images.ImageGetter import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popup.ToastPopup import com.unciv.ui.popup.ToastPopup
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.extensions.addBorder import com.unciv.ui.utils.extensions.addBorder
import com.unciv.ui.utils.extensions.brighten
import com.unciv.ui.utils.extensions.colorFromRGB import com.unciv.ui.utils.extensions.colorFromRGB
import com.unciv.ui.utils.extensions.darken import com.unciv.ui.utils.extensions.darken
import com.unciv.ui.utils.extensions.disable import com.unciv.ui.utils.extensions.disable
import com.unciv.ui.utils.extensions.onClick import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.utils.extensions.toLabel import com.unciv.ui.utils.extensions.toLabel
import com.unciv.utils.concurrency.Concurrency import com.unciv.utils.concurrency.Concurrency
import kotlin.math.abs
class TechPickerScreen( class TechPickerScreen(
@ -37,6 +42,7 @@ class TechPickerScreen(
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>()
private var eraLabels = ArrayList<Label>()
/** We need this to be a separate table, and NOT the topTable, because *inhales* /** 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 * When call setConnectingLines we need to pack() the table so that the lines will align correctly, BUT
@ -51,10 +57,10 @@ class TechPickerScreen(
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(72, 147, 175)
private val researchedTechColor = colorFromRGB(133, 112, 39) private val researchedTechColor = colorFromRGB(255, 215, 0)
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(7*2, 46*2, 43*2)
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) })
@ -110,6 +116,10 @@ class TechPickerScreen(
} }
private fun createTechTable() { private fun createTechTable() {
for (label in eraLabels) label.remove()
eraLabels.clear()
val allTechs = civInfo.gameInfo.ruleSet.technologies.values val allTechs = civInfo.gameInfo.ruleSet.technologies.values
if (allTechs.isEmpty()) return if (allTechs.isEmpty()) return
val columns = allTechs.maxOf { it.column!!.columnNumber } + 1 val columns = allTechs.maxOf { it.column!!.columnNumber } + 1
@ -127,28 +137,55 @@ class TechPickerScreen(
val columnNumber = tech.column!!.columnNumber val columnNumber = tech.column!!.columnNumber
if (!erasNamesToColumns[era]!!.contains(columnNumber)) erasNamesToColumns[era]!!.add(columnNumber) if (!erasNamesToColumns[era]!!.contains(columnNumber)) erasNamesToColumns[era]!!.add(columnNumber)
} }
var i = 0
for ((era, eraColumns) in erasNamesToColumns) { for ((era, eraColumns) in erasNamesToColumns) {
val columnSpan = eraColumns.size val columnSpan = eraColumns.size
val color = if (i % 2 == 0) Color.BLUE else Color.FIREBRICK val color = when {
i++ civTech.era.name == era -> queuedTechColor
techTable.add(era.toLabel().addBorder(2f, color)).fill().colspan(columnSpan) civInfo.gameInfo.ruleSet.eras[era]!!.eraNumber < civTech.era.eraNumber -> colorFromRGB(255, 175, 0)
else -> Color.BLACK
}
val table1 = Table().pad(1f)
val table2 = Table()
table1.background = skinStrings.getUiBackground("General/Border", tintColor = Color.WHITE)
table2.background = skinStrings.getUiBackground("General/Border", tintColor = color)
val label = era.toLabel().apply {
setAlignment(Align.center)
if (civInfo.gameInfo.ruleSet.eras[era]!!.eraNumber < civTech.era.eraNumber)
this.color = colorFromRGB(120, 46, 16) }
eraLabels.add(label)
table2.add(label).growX()
table1.add(table2).growX()
techTable.add(table1).fill().colspan(columnSpan)
} }
for (rowIndex in 0 until rows) { for (rowIndex in 0 until rows) {
techTable.row().pad(5f).padRight(40f)
techTable.row()
for (columnIndex in techMatrix.indices) { for (columnIndex in techMatrix.indices) {
val tech = techMatrix[columnIndex][rowIndex] val tech = techMatrix[columnIndex][rowIndex]
if (tech == null)
techTable.add() // empty cell
else { val table = Table().pad(2f).padRight(60f).padLeft(20f)
if (rowIndex == 0)
table.padTop(7f)
if (erasNamesToColumns[civTech.era.name]!!.contains(columnIndex))
table.background = skinStrings.getUiBackground("TechPickerScreen/Background", tintColor = queuedTechColor.darken(0.5f))
if (tech == null) {
techTable.add(table).fill()
} else {
val techButton = TechButton(tech.name, civTech, false) val techButton = TechButton(tech.name, civTech, false)
table.add(techButton)
techNameToButton[tech.name] = techButton techNameToButton[tech.name] = techButton
techButton.onClick { selectTechnology(tech, false) } techButton.onClick { selectTechnology(tech, false) }
techTable.add(techButton).fillX() techTable.add(table).fillX()
} }
} }
} }
@ -157,19 +194,22 @@ class TechPickerScreen(
private fun setButtonsInfo() { private fun setButtonsInfo() {
for (techName in techNameToButton.keys) { for (techName in techNameToButton.keys) {
val techButton = techNameToButton[techName]!! val techButton = techNameToButton[techName]!!
techButton.color = when { techButton.setButtonColor(when {
civTech.isResearched(techName) && techName != Constants.futureTech -> researchedTechColor civTech.isResearched(techName) && techName != Constants.futureTech -> researchedTechColor
// if we're here to pick a free tech, show the current tech like the rest of the researchables so it'll be obvious what we can pick // if we're here to pick a free tech, show the current tech like the rest of the researchables so it'll be obvious what we can pick
tempTechsToResearch.firstOrNull() == techName && !freeTechPick -> currentTechColor tempTechsToResearch.firstOrNull() == techName && !freeTechPick -> currentTechColor
researchableTechs.contains(techName) -> researchableTechColor researchableTechs.contains(techName) -> researchableTechColor
tempTechsToResearch.contains(techName) -> queuedTechColor tempTechsToResearch.contains(techName) -> queuedTechColor
else -> Color.GRAY else -> Color.BLACK
})
if (civTech.isResearched(techName) && techName != Constants.futureTech) {
techButton.text.color = colorFromRGB(154, 98, 16)
techButton.color = researchedTechColor.cpy().darken(0.5f)
} }
var text = techName.tr() if (techName == selectedTech?.name && civTech.isResearched(techName)) {
techButton.setButtonColor(colorFromRGB(230, 220, 114))
if (techName == selectedTech?.name && techButton.color != currentTechColor) {
techButton.color = techButton.color.darken(0.5f)
} }
techButton.orderIndicator?.remove() techButton.orderIndicator?.remove()
@ -177,10 +217,11 @@ class TechPickerScreen(
techButton.addOrderIndicator(tempTechsToResearch.indexOf(techName) + 1) techButton.addOrderIndicator(tempTechsToResearch.indexOf(techName) + 1)
} }
if (!civTech.isResearched(techName) || techName == Constants.futureTech) if (!civTech.isResearched(techName) || techName == Constants.futureTech) {
text += "\r\n" + turnsToTech[techName] + "${Fonts.turn}".tr() techButton.turns.setText(turnsToTech[techName] + "${Fonts.turn}".tr())
}
techButton.text.setText(text) techButton.text.setText(techName.tr())
} }
addConnectingLines() addConnectingLines()
@ -193,6 +234,17 @@ class TechPickerScreen(
for (line in lines) line.remove() for (line in lines) line.remove()
lines.clear() lines.clear()
for (eraLabel in eraLabels) {
val coords = Vector2(0f, 0f)
eraLabel.localToStageCoordinates(coords)
techTable.stageToLocalCoordinates(coords)
val line = ImageGetter.getLine(coords.x-1f, coords.y, coords.x-1f, coords.y - 1000f, 1f)
line.color = Color.GRAY.apply { a = 0.6f }
line.toBack()
techTable.addActor(line)
lines.add(line)
}
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)) {
ToastPopup("Tech ${tech.name} appears to be missing - perhaps two techs have the same row & column", this) ToastPopup("Tech ${tech.name} appears to be missing - perhaps two techs have the same row & column", this)
@ -213,22 +265,110 @@ class TechPickerScreen(
prerequisiteButton.localToStageCoordinates(prerequisiteCoords) prerequisiteButton.localToStageCoordinates(prerequisiteCoords)
techTable.stageToLocalCoordinates(prerequisiteCoords) techTable.stageToLocalCoordinates(prerequisiteCoords)
val line = ImageGetter.getLine(techButtonCoords.x, techButtonCoords.y,
prerequisiteCoords.x, prerequisiteCoords.y, 2f)
val lineColor = when { val lineColor = when {
civTech.isResearched(tech.name) && !tech.isContinuallyResearchable() -> researchedTechColor civTech.isResearched(tech.name) && !tech.isContinuallyResearchable() -> Color.WHITE
civTech.isResearched(prerequisite) -> researchableTechColor civTech.isResearched(prerequisite) -> researchableTechColor
tempTechsToResearch.contains(tech.name) -> queuedTechColor tempTechsToResearch.contains(tech.name) -> currentTechColor
else -> Color.GRAY else -> Color.WHITE
} }
line.color = lineColor
techTable.addActor(line) val lineSize = when {
line.toBack() tempTechsToResearch.contains(tech.name) && !civTech.isResearched(prerequisite) -> 4f
lines.add(line) else -> 2f
}
if (techButtonCoords.y != prerequisiteCoords.y) {
val r = 6f
val deltaX = techButtonCoords.x - prerequisiteCoords.x
val deltaY = techButtonCoords.y - prerequisiteCoords.y
val halfLength = deltaX / 2f
val line = ImageGetter.getWhiteDot().apply {
width = halfLength - r
height = lineSize
x = prerequisiteCoords.x
y = prerequisiteCoords.y - height / 2
}
val line1 = ImageGetter.getWhiteDot().apply {
width = halfLength - r
height = lineSize
x = techButtonCoords.x - halfLength + r
y = techButtonCoords.y - height / 2
}
val line2 = ImageGetter.getWhiteDot().apply {
width = lineSize
height = abs(deltaY) - 2*r
x = techButtonCoords.x - halfLength - width / 2
y = techButtonCoords.y + (if (deltaY > 0f) -height - r else r + width / 2)
}
var line3: Image?
var line4: Image?
if (deltaY < 0) {
line3 = ImageGetter.getLine(line2.x, line2.y + line2.height,
line.x + line.width, line.y+lineSize/2, lineSize)
line4 = ImageGetter.getLine(line2.x, line2.y, line1.x, line1.y+lineSize/2, lineSize)
} else {
line3 = ImageGetter.getLine(line2.x+lineSize/2, line2.y,
line.x + line.width, line.y, lineSize)
line4 = ImageGetter.getLine(line2.x, line2.y + line2.height-lineSize/2,
line1.x, line1.y+lineSize/2, lineSize)
}
line.color = lineColor
line1.color = lineColor
line2.color = lineColor
line3.color = lineColor
line4.color = lineColor
techTable.addActor(line)
techTable.addActor(line1)
techTable.addActor(line2)
techTable.addActor(line3)
techTable.addActor(line4)
line.toFront()
line1.toFront()
line2.toFront()
line3.toFront()
line4.toFront()
lines.add(line)
lines.add(line1)
lines.add(line2)
lines.add(line3)
lines.add(line4)
} else {
val line = ImageGetter.getWhiteDot().apply {
width = techButtonCoords.x - prerequisiteCoords.x
height = lineSize
x = prerequisiteCoords.x
y = prerequisiteCoords.y - height / 2
}
line.color = lineColor
techTable.addActor(line)
if (tempTechsToResearch.contains(tech.name))
line.zIndex = 200000
else
line.zIndex = 500
lines.add(line)
}
} }
} }
for (line in lines) {
if (line.color == currentTechColor)
line.toFront()
}
} }
private fun selectTechnology(tech: Technology?, center: Boolean = false, switchFromWorldScreen: Boolean = true) { private fun selectTechnology(tech: Technology?, center: Boolean = false, switchFromWorldScreen: Boolean = true) {

View File

@ -88,10 +88,11 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
if (viewingCiv.tech.currentTechnology() != null) { if (viewingCiv.tech.currentTechnology() != null) {
val currentTech = viewingCiv.tech.currentTechnologyName()!! val currentTech = viewingCiv.tech.currentTechnologyName()!!
val innerButton = TechButton(currentTech, viewingCiv.tech) val innerButton = TechButton(currentTech, viewingCiv.tech)
innerButton.color = colorFromRGB(7, 46, 43) innerButton.setButtonColor(colorFromRGB(7, 46, 43))
techButtonHolder.actor = innerButton techButtonHolder.actor = innerButton
val turnsToTech = viewingCiv.tech.turnsToTech(currentTech) val turnsToTech = viewingCiv.tech.turnsToTech(currentTech)
innerButton.text.setText(currentTech.tr() + "\r\n" + turnsToTech + Fonts.turn) innerButton.text.setText(currentTech.tr())
innerButton.turns.setText(turnsToTech + Fonts.turn)
} else { } else {
val canResearch = viewingCiv.tech.canResearchTech() val canResearch = viewingCiv.tech.canResearchTech()
if (canResearch || viewingCiv.tech.researchedTechnologies.size != 0) { if (canResearch || viewingCiv.tech.researchedTechnologies.size != 0) {

View File

@ -213,6 +213,11 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
- [Village](https://thenounproject.com/search/?q=city+center&i=476338) by Andrey Vasiliev - [Village](https://thenounproject.com/search/?q=city+center&i=476338) by Andrey Vasiliev
- [pumping station](https://thenounproject.com/search/?q=dike&i=555172) by Peter van Driel for Polder - [pumping station](https://thenounproject.com/search/?q=dike&i=555172) by Peter van Driel for Polder
- [Oil Platform](https://thenounproject.com/icon/oil-platform-1364795/) by Georgiana Ionescu for Offshore Platform - [Oil Platform](https://thenounproject.com/icon/oil-platform-1364795/) by Georgiana Ionescu for Offshore Platform
- [Broom](https://thenounproject.com/icon/broom-1642644/) by Rakhmat Setiawan for Remove Fallout
- [Axe](https://www.flaticon.com/ru/free-icon/axe_803805) by Those Icons for Remove Forest and Remove Jungle
- [Machete](https://thenounproject.com/icon/machete-36067/) by Robert A. Di Ieso for Remove Marsh
- Icon for Remove Railroad by [vegeta1k95](https://github.com/vegeta1k95)
- Icon for Remove Road by [vegeta1k95](https://github.com/vegeta1k95)
### Buildings ### Buildings
@ -756,6 +761,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
- [Political Science](https://www.flaticon.com/premium-icon/political-science_5403775) created by Hilmy Abiyyu A. - Flaticon - [Political Science](https://www.flaticon.com/premium-icon/political-science_5403775) created by Hilmy Abiyyu A. - Flaticon
- [Question](https://thenounproject.com/icon/question-1157126/) created by Aneeque Ahmed for Question Icon - [Question](https://thenounproject.com/icon/question-1157126/) created by Aneeque Ahmed for Question Icon
- [Trade](https://www.flaticon.com/free-icon/trade_4257019) created by Smashicons for Conduct Trade Mission - [Trade](https://www.flaticon.com/free-icon/trade_4257019) created by Smashicons for Conduct Trade Mission
- [Nothing](https://www.flaticon.com/free-icon/nothing_5084125) created by Freepik for Nothing construction process
- Icon for Unique created by [vegeta1k95](https://github.com/vegeta1k95)
### Main menu ### Main menu