mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-27 08:09:21 +07:00
Civilopedia key bindings (#10723)
* Move CivilopediaImageGetters object to own file * Keyboard bindings for Civilopedia * Better default key choices * Change default Key Binding Tab visibility to ON
This commit is contained in:
@ -286,7 +286,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "AutoPlay",
|
"name": "AutoPlay",
|
||||||
"steps": ["When at later stages of the game, you might have a lot of units but only a little to do. To help you we have implemented an AutoPlay feature that lets you use the AI to play part or all of your turn.",
|
"steps": ["When at later stages of the game, you might have a lot of units but only a little to do. To help you we have implemented an AutoPlay feature that lets you use the AI to play part or all of your turn.",
|
||||||
"To enable AutoPlay, go to options and open the AutoPlay tab and press \"Show AutoPlay button\".",
|
"To enable AutoPlay, go to options and open the AutoPlay tab and press \"Show AutoPlay button\".",
|
||||||
"Clicking on the AutoPlay button opens a popup menue for choosing to AutoPlay parts or all of your turn.",
|
"Clicking on the AutoPlay button opens a popup menue for choosing to AutoPlay parts or all of your turn.",
|
||||||
"Clicking Start AutoPlay in the pop-up menue or long pressing the AutoPlay button begins the multi-turn AutoPlay. This will play your next turns as if you were an AI.",
|
"Clicking Start AutoPlay in the pop-up menue or long pressing the AutoPlay button begins the multi-turn AutoPlay. This will play your next turns as if you were an AI.",
|
||||||
@ -435,7 +435,6 @@
|
|||||||
{},
|
{},
|
||||||
{"text":"For discussion about missing entries, see the linked github issue.","link":"https://github.com/yairm210/Unciv/issues/8862"}
|
{"text":"For discussion about missing entries, see the linked github issue.","link":"https://github.com/yairm210/Unciv/issues/8862"}
|
||||||
]
|
]
|
||||||
// "uniques": ["Will not be displayed in Civilopedia"] // would prevent use for help link
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Civilopedia",
|
"name": "Civilopedia",
|
||||||
|
@ -165,10 +165,29 @@ enum class KeyboardBinding(
|
|||||||
AddConstructionAllTop(Category.CityScreenConstructionMenu, "Add or move to the top in all cities", KeyCharAndCode.ctrl('t')),
|
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')),
|
RemoveConstructionAll(Category.CityScreenConstructionMenu, "Remove from the queue in all cities", KeyCharAndCode.ctrl('r')),
|
||||||
|
|
||||||
|
// Civilopedia
|
||||||
|
PediaBuildings(Category.Civilopedia, "Buildings", 'b'),
|
||||||
|
PediaWonders(Category.Civilopedia, "Wonders", 'w'),
|
||||||
|
PediaResources(Category.Civilopedia, "Resources", 'r'),
|
||||||
|
PediaTerrains(Category.Civilopedia, "Terrains", 't'),
|
||||||
|
PediaImprovements(Category.Civilopedia, "Tile Improvements", 'i'),
|
||||||
|
PediaUnits(Category.Civilopedia, "Units", 'u'),
|
||||||
|
PediaUnitTypes(Category.Civilopedia, "Unit types", 'y'),
|
||||||
|
PediaNations(Category.Civilopedia, "Nations", 'n'),
|
||||||
|
PediaTechnologies(Category.Civilopedia, "Technologies", KeyCharAndCode.ctrl('t')),
|
||||||
|
PediaPromotions(Category.Civilopedia, "Promotions", 'p'),
|
||||||
|
PediaPolicies(Category.Civilopedia, "Policies", 'o'),
|
||||||
|
PediaBeliefs(Category.Civilopedia, "Religions and Beliefs", 'f'),
|
||||||
|
PediaTutorials(Category.Civilopedia, "Tutorials", Input.Keys.F1),
|
||||||
|
PediaDifficulties(Category.Civilopedia, "Difficulty levels", 'd'),
|
||||||
|
PediaEras(Category.Civilopedia, "Eras", 'e'),
|
||||||
|
PediaSpeeds(Category.Civilopedia, "Speeds", 's'),
|
||||||
|
PediaSearch(Category.Civilopedia, "Open the Search Dialog", KeyCharAndCode.ctrl('f')),
|
||||||
|
|
||||||
// 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'),
|
||||||
UpgradeAll(Category.Popups, KeyCharAndCode.ctrl('a')),
|
UpgradeAll(Category.Popups, KeyCharAndCode.ctrl('a')), // rethink? No UnitUpgradeMenu category, but CityScreenConstructionMenu gets one?
|
||||||
;
|
;
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
@ -188,6 +207,7 @@ enum class KeyboardBinding(
|
|||||||
},
|
},
|
||||||
CityScreen,
|
CityScreen,
|
||||||
CityScreenConstructionMenu, // Maybe someday a category hierarchy?
|
CityScreenConstructionMenu, // Maybe someday a category hierarchy?
|
||||||
|
Civilopedia,
|
||||||
Popups
|
Popups
|
||||||
;
|
;
|
||||||
val label = unCamelCase(name)
|
val label = unCamelCase(name)
|
||||||
|
@ -43,7 +43,7 @@ class OptionsPopup(
|
|||||||
|
|
||||||
private var keyBindingsTab: KeyBindingsTab? = null
|
private var keyBindingsTab: KeyBindingsTab? = null
|
||||||
/** Enable the still experimental Keyboard Bindings page in OptionsPopup */
|
/** Enable the still experimental Keyboard Bindings page in OptionsPopup */
|
||||||
var enableKeyBindingsTab: Boolean = false
|
var enableKeyBindingsTab: Boolean = true
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
@ -209,7 +209,8 @@ class OptionsPopup(
|
|||||||
internal fun showOrHideKeyBindings() {
|
internal fun showOrHideKeyBindings() {
|
||||||
// At the moment, the Key bindings Tab exists only on-demand. To refactor it back to permanent,
|
// At the moment, the Key bindings Tab exists only on-demand. To refactor it back to permanent,
|
||||||
// move the `keyBindingsTab =` line and addPage call to before the Advanced Tab creation,
|
// move the `keyBindingsTab =` line and addPage call to before the Advanced Tab creation,
|
||||||
// then delete this function, delete the enableKeyBindingsTab flag and clean up what is flagged by the compiler as missing or unused.
|
// then delete this function, delete the enableKeyBindingsTab flag and clean up what is flagged
|
||||||
|
// by the compiler as missing or unused - like the `add("Show keyboard bindings".toCheckBox` option on DebugTab.
|
||||||
val existingIndex = tabs.getPageIndex(keysTabCaption)
|
val existingIndex = tabs.getPageIndex(keysTabCaption)
|
||||||
if (enableKeyBindingsTab && existingIndex < 0) {
|
if (enableKeyBindingsTab && existingIndex < 0) {
|
||||||
if (keyBindingsTab == null)
|
if (keyBindingsTab == null)
|
||||||
|
@ -1,111 +1,12 @@
|
|||||||
package com.unciv.ui.screens.civilopediascreen
|
package com.unciv.ui.screens.civilopediascreen
|
||||||
|
|
||||||
import com.badlogic.gdx.Input
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Container
|
|
||||||
import com.unciv.Constants
|
|
||||||
import com.unciv.logic.map.tile.Tile
|
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.tile.Terrain
|
import com.unciv.ui.components.input.KeyboardBinding
|
||||||
import com.unciv.models.ruleset.tile.TerrainType
|
|
||||||
import com.unciv.models.ruleset.unit.UnitMovementType
|
|
||||||
import com.unciv.ui.components.extensions.setSize
|
|
||||||
import com.unciv.ui.components.extensions.surroundWithCircle
|
|
||||||
import com.unciv.ui.components.input.KeyCharAndCode
|
|
||||||
import com.unciv.ui.components.tilegroups.TileGroup
|
|
||||||
import com.unciv.ui.components.tilegroups.TileSetStrings
|
|
||||||
import com.unciv.ui.images.IconCircleGroup
|
|
||||||
import com.unciv.ui.images.ImageGetter
|
|
||||||
import com.unciv.ui.screens.basescreen.TutorialController
|
import com.unciv.ui.screens.basescreen.TutorialController
|
||||||
import com.unciv.models.ruleset.Belief as BaseBelief
|
import com.unciv.models.ruleset.Belief as BaseBelief
|
||||||
import com.unciv.models.ruleset.unit.UnitType as BaseUnitType
|
import com.unciv.models.ruleset.unit.UnitType as BaseUnitType
|
||||||
|
|
||||||
|
|
||||||
/** Encapsulates the knowledge on how to get an icon for each of the Civilopedia categories */
|
|
||||||
object CivilopediaImageGetters {
|
|
||||||
private const val policyIconFolder = "PolicyIcons"
|
|
||||||
private const val policyBranchIconFolder = "PolicyBranchIcons"
|
|
||||||
private const val policyInnerSize = 0.25f
|
|
||||||
|
|
||||||
// Todo: potential synergy with map editor
|
|
||||||
fun terrainImage(terrain: Terrain, ruleset: Ruleset, imageSize: Float): Actor {
|
|
||||||
val tile = Tile()
|
|
||||||
tile.ruleset = ruleset
|
|
||||||
when (terrain.type) {
|
|
||||||
TerrainType.NaturalWonder -> {
|
|
||||||
tile.naturalWonder = terrain.name
|
|
||||||
tile.baseTerrain = terrain.turnsInto ?: terrain.occursOn.firstOrNull() ?: Constants.grassland
|
|
||||||
}
|
|
||||||
TerrainType.TerrainFeature -> {
|
|
||||||
tile.baseTerrain =
|
|
||||||
if (terrain.occursOn.isEmpty() || terrain.occursOn.contains(Constants.grassland))
|
|
||||||
Constants.grassland
|
|
||||||
else
|
|
||||||
terrain.occursOn.lastOrNull()!!
|
|
||||||
tile.setTerrainTransients()
|
|
||||||
tile.addTerrainFeature(terrain.name)
|
|
||||||
}
|
|
||||||
else ->
|
|
||||||
tile.baseTerrain = terrain.name
|
|
||||||
}
|
|
||||||
tile.setTerrainTransients()
|
|
||||||
val group = TileGroup(tile, TileSetStrings(), imageSize * 36f/54f) // TileGroup normally spills out of its bounding box
|
|
||||||
group.isForceVisible = true
|
|
||||||
group.isForMapEditorIcon = true
|
|
||||||
group.update()
|
|
||||||
return Container(group)
|
|
||||||
}
|
|
||||||
|
|
||||||
val construction = { name: String, size: Float ->
|
|
||||||
ImageGetter.getConstructionPortrait(name, size)
|
|
||||||
}
|
|
||||||
val improvement = { name: String, size: Float ->
|
|
||||||
ImageGetter.getImprovementPortrait(name, size)
|
|
||||||
}
|
|
||||||
val nation = { name: String, size: Float ->
|
|
||||||
val nation = ImageGetter.ruleset.nations[name]
|
|
||||||
if (nation == null) null
|
|
||||||
else ImageGetter.getNationPortrait(nation, size)
|
|
||||||
}
|
|
||||||
val policy = fun(name: String, size: Float): IconCircleGroup? {
|
|
||||||
// result is nullable: policy branch complete have no icons but are linked -> nonexistence must be passed down
|
|
||||||
fun tryImage(path: String, color: Color): IconCircleGroup? {
|
|
||||||
if (ImageGetter.imageExists(path)) return ImageGetter.getImage(path).apply {
|
|
||||||
setSize(size * policyInnerSize,size * policyInnerSize)
|
|
||||||
this.color = color
|
|
||||||
}.surroundWithCircle(size)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return tryImage("$policyBranchIconFolder/$name", Color.BLACK)
|
|
||||||
?: tryImage("$policyIconFolder/$name", Color.BROWN)
|
|
||||||
}
|
|
||||||
val resource = { name: String, size: Float ->
|
|
||||||
ImageGetter.getResourcePortrait(name, size)
|
|
||||||
}
|
|
||||||
val technology = { name: String, size: Float ->
|
|
||||||
ImageGetter.getTechIconPortrait(name, size)
|
|
||||||
}
|
|
||||||
val promotion = { name: String, size: Float ->
|
|
||||||
ImageGetter.getPromotionPortrait(name, size)
|
|
||||||
}
|
|
||||||
val terrain = { name: String, size: Float ->
|
|
||||||
val terrain = ImageGetter.ruleset.terrains[name]
|
|
||||||
if (terrain == null) null
|
|
||||||
else terrainImage(terrain, ImageGetter.ruleset, size)
|
|
||||||
}
|
|
||||||
val belief = { name: String, size: Float ->
|
|
||||||
ImageGetter.getReligionPortrait(name, size)
|
|
||||||
}
|
|
||||||
val unitType = { name: String, size: Float ->
|
|
||||||
val path = UnitMovementType.values().firstOrNull { "Domain: [${it.name}]" == name }
|
|
||||||
?.let {"UnitTypeIcons/Domain${it.name}" }
|
|
||||||
?: "UnitTypeIcons/$name"
|
|
||||||
if (ImageGetter.imageExists(path)) ImageGetter.getImage(path).apply { setSize(size) }
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Enum used as keys for Civilopedia "pages" (categories).
|
/** Enum used as keys for Civilopedia "pages" (categories).
|
||||||
*
|
*
|
||||||
* Note names are singular on purpose - a "link" allows both key and label
|
* Note names are singular on purpose - a "link" allows both key and label
|
||||||
@ -117,121 +18,110 @@ enum class CivilopediaCategories (
|
|||||||
val label: String,
|
val label: String,
|
||||||
val hide: Boolean, // Omitted on CivilopediaScreen
|
val hide: Boolean, // Omitted on CivilopediaScreen
|
||||||
val getImage: ((name: String, size: Float) -> Actor?)?,
|
val getImage: ((name: String, size: Float) -> Actor?)?,
|
||||||
val key: KeyCharAndCode = KeyCharAndCode.UNKNOWN,
|
val binding: KeyboardBinding,
|
||||||
val headerIcon: String,
|
val headerIcon: String,
|
||||||
val getCategoryIterator: (ruleset: Ruleset, tutorialController: TutorialController) -> Collection<ICivilopediaText>
|
val getCategoryIterator: (ruleset: Ruleset, tutorialController: TutorialController) -> Collection<ICivilopediaText>
|
||||||
) {
|
) {
|
||||||
Building ("Buildings", false,
|
Building ("Buildings", false,
|
||||||
CivilopediaImageGetters.construction,
|
CivilopediaImageGetters.construction,
|
||||||
KeyCharAndCode('B'),
|
KeyboardBinding.PediaBuildings,
|
||||||
"OtherIcons/Cities",
|
"OtherIcons/Cities",
|
||||||
{ ruleset, _ -> ruleset.buildings.values.filter { !it.isAnyWonder() } }
|
{ ruleset, _ -> ruleset.buildings.values.filter { !it.isAnyWonder() } }
|
||||||
),
|
),
|
||||||
Wonder ("Wonders", false,
|
Wonder ("Wonders", false,
|
||||||
CivilopediaImageGetters.construction,
|
CivilopediaImageGetters.construction,
|
||||||
KeyCharAndCode('W'),
|
KeyboardBinding.PediaWonders,
|
||||||
"OtherIcons/Wonders",
|
"OtherIcons/Wonders",
|
||||||
{ ruleset, _ -> ruleset.buildings.values.filter { it.isAnyWonder() } }
|
{ ruleset, _ -> ruleset.buildings.values.filter { it.isAnyWonder() } }
|
||||||
),
|
),
|
||||||
Resource ("Resources", false,
|
Resource ("Resources", false,
|
||||||
CivilopediaImageGetters.resource,
|
CivilopediaImageGetters.resource,
|
||||||
KeyCharAndCode('R'),
|
KeyboardBinding.PediaResources,
|
||||||
"OtherIcons/Resources",
|
"OtherIcons/Resources",
|
||||||
{ ruleset, _ -> ruleset.tileResources.values }
|
{ ruleset, _ -> ruleset.tileResources.values }
|
||||||
),
|
),
|
||||||
Terrain ("Terrains", false,
|
Terrain ("Terrains", false,
|
||||||
CivilopediaImageGetters.terrain,
|
CivilopediaImageGetters.terrain,
|
||||||
KeyCharAndCode('T'),
|
KeyboardBinding.PediaTerrains,
|
||||||
"OtherIcons/Terrains",
|
"OtherIcons/Terrains",
|
||||||
{ ruleset, _ -> ruleset.terrains.values }
|
{ ruleset, _ -> ruleset.terrains.values }
|
||||||
),
|
),
|
||||||
Improvement ("Tile Improvements", false,
|
Improvement ("Tile Improvements", false,
|
||||||
CivilopediaImageGetters.improvement,
|
CivilopediaImageGetters.improvement,
|
||||||
KeyCharAndCode('T'),
|
KeyboardBinding.PediaImprovements,
|
||||||
"OtherIcons/Improvements",
|
"OtherIcons/Improvements",
|
||||||
{ ruleset, _ -> ruleset.tileImprovements.values }
|
{ ruleset, _ -> ruleset.tileImprovements.values }
|
||||||
),
|
),
|
||||||
Unit ("Units", false,
|
Unit ("Units", false,
|
||||||
CivilopediaImageGetters.construction,
|
CivilopediaImageGetters.construction,
|
||||||
KeyCharAndCode('U'),
|
KeyboardBinding.PediaUnits,
|
||||||
"OtherIcons/Shield",
|
"OtherIcons/Shield",
|
||||||
{ ruleset, _ -> ruleset.units.values }
|
{ ruleset, _ -> ruleset.units.values }
|
||||||
),
|
),
|
||||||
UnitType ("Unit types", false,
|
UnitType ("Unit types", false,
|
||||||
CivilopediaImageGetters.unitType,
|
CivilopediaImageGetters.unitType,
|
||||||
KeyCharAndCode('U'),
|
KeyboardBinding.PediaUnitTypes,
|
||||||
"UnitTypeIcons/UnitTypes",
|
"UnitTypeIcons/UnitTypes",
|
||||||
{ ruleset, _ -> BaseUnitType.getCivilopediaIterator(ruleset) }
|
{ ruleset, _ -> BaseUnitType.getCivilopediaIterator(ruleset) }
|
||||||
),
|
),
|
||||||
Nation ("Nations", false,
|
Nation ("Nations", false,
|
||||||
CivilopediaImageGetters.nation,
|
CivilopediaImageGetters.nation,
|
||||||
KeyCharAndCode('N'),
|
KeyboardBinding.PediaNations,
|
||||||
"OtherIcons/Nations",
|
"OtherIcons/Nations",
|
||||||
{ ruleset, _ -> ruleset.nations.values.filter { !it.isSpectator } }
|
{ ruleset, _ -> ruleset.nations.values.filter { !it.isSpectator } }
|
||||||
),
|
),
|
||||||
Technology ("Technologies", false,
|
Technology ("Technologies", false,
|
||||||
CivilopediaImageGetters.technology,
|
CivilopediaImageGetters.technology,
|
||||||
KeyCharAndCode('T'),
|
KeyboardBinding.PediaTechnologies,
|
||||||
"TechIcons/Philosophy",
|
"TechIcons/Philosophy",
|
||||||
{ ruleset, _ -> ruleset.technologies.values }
|
{ ruleset, _ -> ruleset.technologies.values }
|
||||||
),
|
),
|
||||||
Promotion ("Promotions", false,
|
Promotion ("Promotions", false,
|
||||||
CivilopediaImageGetters.promotion,
|
CivilopediaImageGetters.promotion,
|
||||||
KeyCharAndCode('P'),
|
KeyboardBinding.PediaPromotions,
|
||||||
"UnitPromotionIcons/Mobility",
|
"UnitPromotionIcons/Mobility",
|
||||||
{ ruleset, _ -> ruleset.unitPromotions.values }
|
{ ruleset, _ -> ruleset.unitPromotions.values }
|
||||||
),
|
),
|
||||||
Policy ("Policies", false,
|
Policy ("Policies", false,
|
||||||
CivilopediaImageGetters.policy,
|
CivilopediaImageGetters.policy,
|
||||||
KeyCharAndCode('P'),
|
KeyboardBinding.PediaPolicies,
|
||||||
"PolicyIcons/Constitution",
|
"PolicyIcons/Constitution",
|
||||||
{ ruleset, _ -> ruleset.policies.values }
|
{ ruleset, _ -> ruleset.policies.values }
|
||||||
),
|
),
|
||||||
Belief("Religions and Beliefs", false,
|
Belief("Religions and Beliefs",
|
||||||
|
hide = false, // Skipping this page when showReligionInCivilopedia returns false is hardcoded
|
||||||
CivilopediaImageGetters.belief,
|
CivilopediaImageGetters.belief,
|
||||||
KeyCharAndCode('R'),
|
KeyboardBinding.PediaBeliefs,
|
||||||
"ReligionIcons/Religion",
|
"ReligionIcons/Religion",
|
||||||
{ ruleset, _ -> (ruleset.beliefs.values.asSequence() +
|
{ ruleset, _ -> (ruleset.beliefs.values.asSequence() +
|
||||||
BaseBelief.getCivilopediaReligionEntry(ruleset)).toList() }
|
BaseBelief.getCivilopediaReligionEntry(ruleset)).toList() }
|
||||||
),
|
),
|
||||||
Tutorial ("Tutorials", false,
|
Tutorial ("Tutorials", false,
|
||||||
getImage = null,
|
getImage = null,
|
||||||
KeyCharAndCode(Input.Keys.F1),
|
KeyboardBinding.PediaTutorials,
|
||||||
"OtherIcons/ExclamationMark",
|
"OtherIcons/ExclamationMark",
|
||||||
{ _, tutorialController -> tutorialController.getCivilopediaTutorials() }
|
{ _, tutorialController -> tutorialController.getCivilopediaTutorials() }
|
||||||
),
|
),
|
||||||
Difficulty ("Difficulty levels", false,
|
Difficulty ("Difficulty levels", false,
|
||||||
getImage = null,
|
getImage = null,
|
||||||
KeyCharAndCode('D'),
|
KeyboardBinding.PediaDifficulties,
|
||||||
"OtherIcons/Quickstart",
|
"OtherIcons/Quickstart",
|
||||||
{ ruleset, _ -> ruleset.difficulties.values }
|
{ ruleset, _ -> ruleset.difficulties.values }
|
||||||
),
|
),
|
||||||
Era ("Eras", false,
|
Era ("Eras", false,
|
||||||
getImage = null,
|
getImage = null,
|
||||||
KeyCharAndCode('D'),
|
KeyboardBinding.PediaEras,
|
||||||
"OtherIcons/Tyrannosaurus",
|
"OtherIcons/Tyrannosaurus",
|
||||||
{ ruleset, _ -> ruleset.eras.values }
|
{ ruleset, _ -> ruleset.eras.values }
|
||||||
),
|
),
|
||||||
Speed ("Speeds", false,
|
Speed ("Speeds", false,
|
||||||
getImage = null,
|
getImage = null,
|
||||||
KeyCharAndCode('S'),
|
KeyboardBinding.PediaSpeeds,
|
||||||
"OtherIcons/Timer",
|
"OtherIcons/Timer",
|
||||||
{ ruleset, _ -> ruleset.speeds.values }
|
{ ruleset, _ -> ruleset.speeds.values }
|
||||||
);
|
);
|
||||||
|
|
||||||
private fun getByOffset(offset: Int) = values()[(ordinal + count + offset) % count]
|
|
||||||
|
|
||||||
fun nextForKey(key: KeyCharAndCode): CivilopediaCategories {
|
|
||||||
for (i in 1..count) {
|
|
||||||
val next = getByOffset(i)
|
|
||||||
if (next.key == key) return next
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val count = values().size
|
|
||||||
|
|
||||||
fun fromLink(name: String): CivilopediaCategories? =
|
fun fromLink(name: String): CivilopediaCategories? =
|
||||||
values().firstOrNull { it.name == name }
|
values().firstOrNull { it.name == name }
|
||||||
?: values().firstOrNull { it.label == name }
|
?: values().firstOrNull { it.label == name }
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.unciv.ui.screens.civilopediascreen
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Container
|
||||||
|
import com.unciv.Constants
|
||||||
|
import com.unciv.logic.map.tile.Tile
|
||||||
|
import com.unciv.models.ruleset.Ruleset
|
||||||
|
import com.unciv.models.ruleset.tile.Terrain
|
||||||
|
import com.unciv.models.ruleset.tile.TerrainType
|
||||||
|
import com.unciv.models.ruleset.unit.UnitMovementType
|
||||||
|
import com.unciv.ui.components.extensions.setSize
|
||||||
|
import com.unciv.ui.components.extensions.surroundWithCircle
|
||||||
|
import com.unciv.ui.components.tilegroups.TileGroup
|
||||||
|
import com.unciv.ui.components.tilegroups.TileSetStrings
|
||||||
|
import com.unciv.ui.images.IconCircleGroup
|
||||||
|
import com.unciv.ui.images.ImageGetter
|
||||||
|
|
||||||
|
/** Encapsulates the knowledge on how to get an icon for each of the Civilopedia categories */
|
||||||
|
internal object CivilopediaImageGetters {
|
||||||
|
private const val policyIconFolder = "PolicyIcons"
|
||||||
|
private const val policyBranchIconFolder = "PolicyBranchIcons"
|
||||||
|
private const val policyInnerSize = 0.25f
|
||||||
|
|
||||||
|
// Todo: potential synergy with map editor
|
||||||
|
private fun terrainImage(terrain: Terrain, ruleset: Ruleset, imageSize: Float): Actor {
|
||||||
|
val tile = Tile()
|
||||||
|
tile.ruleset = ruleset
|
||||||
|
when (terrain.type) {
|
||||||
|
TerrainType.NaturalWonder -> {
|
||||||
|
tile.naturalWonder = terrain.name
|
||||||
|
tile.baseTerrain = terrain.turnsInto ?: terrain.occursOn.firstOrNull() ?: Constants.grassland
|
||||||
|
}
|
||||||
|
TerrainType.TerrainFeature -> {
|
||||||
|
tile.baseTerrain =
|
||||||
|
if (terrain.occursOn.isEmpty() || terrain.occursOn.contains(Constants.grassland))
|
||||||
|
Constants.grassland
|
||||||
|
else
|
||||||
|
terrain.occursOn.lastOrNull()!!
|
||||||
|
tile.setTerrainTransients()
|
||||||
|
tile.addTerrainFeature(terrain.name)
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
tile.baseTerrain = terrain.name
|
||||||
|
}
|
||||||
|
tile.setTerrainTransients()
|
||||||
|
val group = TileGroup(tile, TileSetStrings(), imageSize * 36f / 54f) // TileGroup normally spills out of its bounding box
|
||||||
|
group.isForceVisible = true
|
||||||
|
group.isForMapEditorIcon = true
|
||||||
|
group.update()
|
||||||
|
return Container(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
val construction = { name: String, size: Float ->
|
||||||
|
ImageGetter.getConstructionPortrait(name, size)
|
||||||
|
}
|
||||||
|
val improvement = { name: String, size: Float ->
|
||||||
|
ImageGetter.getImprovementPortrait(name, size)
|
||||||
|
}
|
||||||
|
val nation = { name: String, size: Float ->
|
||||||
|
val nation = ImageGetter.ruleset.nations[name]
|
||||||
|
if (nation == null) null
|
||||||
|
else ImageGetter.getNationPortrait(nation, size)
|
||||||
|
}
|
||||||
|
val policy = fun(name: String, size: Float): IconCircleGroup? {
|
||||||
|
// result is nullable: policy branch complete have no icons but are linked -> nonexistence must be passed down
|
||||||
|
fun tryImage(path: String, color: Color): IconCircleGroup? {
|
||||||
|
if (ImageGetter.imageExists(path)) return ImageGetter.getImage(path).apply {
|
||||||
|
setSize(size * policyInnerSize,size * policyInnerSize)
|
||||||
|
this.color = color
|
||||||
|
}.surroundWithCircle(size)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return tryImage("$policyBranchIconFolder/$name", Color.BLACK)
|
||||||
|
?: tryImage("$policyIconFolder/$name", Color.BROWN)
|
||||||
|
}
|
||||||
|
val resource = { name: String, size: Float ->
|
||||||
|
ImageGetter.getResourcePortrait(name, size)
|
||||||
|
}
|
||||||
|
val technology = { name: String, size: Float ->
|
||||||
|
ImageGetter.getTechIconPortrait(name, size)
|
||||||
|
}
|
||||||
|
val promotion = { name: String, size: Float ->
|
||||||
|
ImageGetter.getPromotionPortrait(name, size)
|
||||||
|
}
|
||||||
|
val terrain = { name: String, size: Float ->
|
||||||
|
val terrain = ImageGetter.ruleset.terrains[name]
|
||||||
|
if (terrain == null) null
|
||||||
|
else terrainImage(terrain, ImageGetter.ruleset, size)
|
||||||
|
}
|
||||||
|
val belief = { name: String, size: Float ->
|
||||||
|
ImageGetter.getReligionPortrait(name, size)
|
||||||
|
}
|
||||||
|
val unitType = { name: String, size: Float ->
|
||||||
|
val path = UnitMovementType.values().firstOrNull { "Domain: [${it.name}]" == name }
|
||||||
|
?.let {"UnitTypeIcons/Domain${it.name}" }
|
||||||
|
?: "UnitTypeIcons/$name"
|
||||||
|
if (ImageGetter.imageExists(path)) ImageGetter.getImage(path).apply { setSize(size) }
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ import com.unciv.models.ruleset.unique.IHasUniques
|
|||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.stats.INamed
|
import com.unciv.models.stats.INamed
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
|
|
||||||
import com.unciv.ui.components.extensions.colorFromRGB
|
import com.unciv.ui.components.extensions.colorFromRGB
|
||||||
import com.unciv.ui.components.extensions.toImageButton
|
import com.unciv.ui.components.extensions.toImageButton
|
||||||
import com.unciv.ui.components.extensions.toLabel
|
import com.unciv.ui.components.extensions.toLabel
|
||||||
@ -236,8 +235,7 @@ class CivilopediaScreen(
|
|||||||
if (entries.isEmpty()) continue
|
if (entries.isEmpty()) continue
|
||||||
val icon = if (categoryKey.headerIcon.isNotEmpty()) ImageGetter.getImage(categoryKey.headerIcon) else null
|
val icon = if (categoryKey.headerIcon.isNotEmpty()) ImageGetter.getImage(categoryKey.headerIcon) else null
|
||||||
val button = IconTextButton(categoryKey.label, icon)
|
val button = IconTextButton(categoryKey.label, icon)
|
||||||
button.addTooltip(categoryKey.key)
|
button.onActivation(binding = categoryKey.binding) { selectCategory(categoryKey) }
|
||||||
button.onClick { selectCategory(categoryKey) }
|
|
||||||
val cell = buttonTable.add(button)
|
val cell = buttonTable.add(button)
|
||||||
categoryToButtons[categoryKey] = CategoryButtonInfo(button, currentX, cell.prefWidth)
|
categoryToButtons[categoryKey] = CategoryButtonInfo(button, currentX, cell.prefWidth)
|
||||||
currentX += cell.prefWidth + 20f
|
currentX += cell.prefWidth + 20f
|
||||||
@ -245,11 +243,10 @@ class CivilopediaScreen(
|
|||||||
|
|
||||||
buttonTable.pack()
|
buttonTable.pack()
|
||||||
buttonTableScroll = ScrollPane(buttonTable)
|
buttonTableScroll = ScrollPane(buttonTable)
|
||||||
buttonTableScroll.setScrollingDisabled(false, true)
|
buttonTableScroll.setScrollingDisabled(x = false, y = true)
|
||||||
|
|
||||||
val searchButton = "OtherIcons/Search".toImageButton(imageSize - 16f, imageSize, skinStrings.skinConfig.baseColor, Color.GOLD)
|
val searchButton = "OtherIcons/Search".toImageButton(imageSize - 16f, imageSize, skinStrings.skinConfig.baseColor, Color.GOLD)
|
||||||
searchButton.onActivation { searchPopup.open(true) }
|
searchButton.onActivation(binding = KeyboardBinding.PediaSearch) { searchPopup.open(true) }
|
||||||
searchButton.keyShortcuts.add(KeyboardBinding.Civilopedia) // "hit twice to search"
|
|
||||||
|
|
||||||
val closeButton = "OtherIcons/Close".toImageButton(imageSize - 20f, imageSize, skinStrings.skinConfig.baseColor, Color.RED)
|
val closeButton = "OtherIcons/Close".toImageButton(imageSize - 20f, imageSize, skinStrings.skinConfig.baseColor, Color.RED)
|
||||||
closeButton.onActivation { game.popScreen() }
|
closeButton.onActivation { game.popScreen() }
|
||||||
@ -292,26 +289,8 @@ class CivilopediaScreen(
|
|||||||
else
|
else
|
||||||
selectEntry(link, noScrollAnimation = true)
|
selectEntry(link, noScrollAnimation = true)
|
||||||
|
|
||||||
for (categoryKey in categoryToEntries.keys) {
|
globalShortcuts.add(Input.Keys.LEFT) { navigateCategories(-1) }
|
||||||
globalShortcuts.add(categoryKey.key) { navigateCategories(categoryKey.key) }
|
globalShortcuts.add(Input.Keys.RIGHT) { navigateCategories(1) }
|
||||||
}
|
|
||||||
globalShortcuts.add(Input.Keys.LEFT) {
|
|
||||||
val categoryKey = categoryToEntries.keys
|
|
||||||
val currentIndex = categoryKey.indexOf(currentCategory)
|
|
||||||
val targetCategory = categoryKey.elementAt(
|
|
||||||
(currentIndex + categoryKey.size - 1) % categoryKey.size
|
|
||||||
)
|
|
||||||
selectCategory(targetCategory)
|
|
||||||
}
|
|
||||||
globalShortcuts.add(Input.Keys.RIGHT) {
|
|
||||||
val categoryKey = categoryToEntries.keys
|
|
||||||
val currentIndex = categoryKey.indexOf(currentCategory)
|
|
||||||
val targetCategory = categoryKey.elementAt(
|
|
||||||
(currentIndex + categoryKey.size + 1) % categoryKey.size
|
|
||||||
)
|
|
||||||
selectCategory(targetCategory)
|
|
||||||
|
|
||||||
}
|
|
||||||
globalShortcuts.add(Input.Keys.UP) { navigateEntries(-1) }
|
globalShortcuts.add(Input.Keys.UP) { navigateEntries(-1) }
|
||||||
globalShortcuts.add(Input.Keys.DOWN) { navigateEntries(1) }
|
globalShortcuts.add(Input.Keys.DOWN) { navigateEntries(1) }
|
||||||
globalShortcuts.add(Input.Keys.PAGE_UP) { navigateEntries(-10) }
|
globalShortcuts.add(Input.Keys.PAGE_UP) { navigateEntries(-10) }
|
||||||
@ -320,8 +299,11 @@ class CivilopediaScreen(
|
|||||||
globalShortcuts.add(Input.Keys.END) { navigateEntries(Int.MAX_VALUE) }
|
globalShortcuts.add(Input.Keys.END) { navigateEntries(Int.MAX_VALUE) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateCategories(key: KeyCharAndCode) {
|
private fun navigateCategories(direction: Int) {
|
||||||
selectCategory(currentCategory.nextForKey(key))
|
val categoryKeys = categoryToEntries.keys
|
||||||
|
val currentIndex = categoryKeys.indexOf(currentCategory)
|
||||||
|
val newIndex = (currentIndex + categoryKeys.size + direction) % categoryKeys.size
|
||||||
|
selectCategory(categoryKeys.elementAt(newIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateEntries(direction: Int) {
|
private fun navigateEntries(direction: Int) {
|
||||||
|
Reference in New Issue
Block a user