From fb30a76e85bbe296ff8518b1b20bb4bafbd24a04 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Wed, 29 Sep 2021 16:39:02 +0200 Subject: [PATCH] Civilopedia category icons and keyboard navigation (#5341) * Civilopedia category icons and keyboard navigation * Civilopedia category icons - white alternative --- android/Images/OtherIcons/Improvements.png | Bin 0 -> 2024 bytes android/Images/OtherIcons/Nations.png | Bin 0 -> 2037 bytes android/Images/OtherIcons/Resources.png | Bin 0 -> 1594 bytes android/Images/OtherIcons/Terrains.png | Bin 0 -> 1613 bytes .../ui/civilopedia/CivilopediaCategories.kt | 97 +++++++++++++++--- .../unciv/ui/civilopedia/CivilopediaScreen.kt | 74 ++++++++++--- docs/Credits.md | 4 +- 7 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 android/Images/OtherIcons/Improvements.png create mode 100644 android/Images/OtherIcons/Nations.png create mode 100644 android/Images/OtherIcons/Resources.png create mode 100644 android/Images/OtherIcons/Terrains.png diff --git a/android/Images/OtherIcons/Improvements.png b/android/Images/OtherIcons/Improvements.png new file mode 100644 index 0000000000000000000000000000000000000000..1778976ab803edafdb39ed52f404eb5f86774457 GIT binary patch literal 2024 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 T=cb5{00000NkvXXu0mjfiOcNR literal 0 HcmV?d00001 diff --git a/android/Images/OtherIcons/Resources.png b/android/Images/OtherIcons/Resources.png new file mode 100644 index 0000000000000000000000000000000000000000..47da740e7df7f6e6fa2e321411240da92a91a956 GIT binary patch literal 1594 zcmV-A2F3Y_P)Y%~!yB-ln0wA$7LDnx}! zszkBY8$|^XMG#97yz$O^QM_reqC%~Ar9YyzV2d$DsYOe*RTP`}Q&6*AH^+;aV34-? zX1>|%_j6wOE;iYmnVqxeyk}MRL$kBfEv1jGrXgAq8Ln7y>TMi9@D={lEdB z8e|XyrmQ~TJ>aUGWtlU;1Hirz#uf$a*gy`Q0niHE5z1Idhm>oPQ&WOU5*@M^_yYJR zM~TzJeGs#n6i;E9n$C`6mjMt z!RK4*kc2@U5^o|bX>mv%%HLF_tb#^}rYwyRg_63aEG2a%b&U{(lDa}2qNJ`VOG#ZL zL`hv8qNJ`+QrDEFq^_i{5pq5>qpsYKcwQU*=}-{1V)Z?*8YAO z&(lLMq5z$rmyX`51C!da>XwD z_~IVmEud7V_A}*>N#L~@q2Go%u{8iZ=ehbYZTm2p)x|}Zj_$EbA-;U|EO4_Opof7C zp0>tqUox4pqIR@wmmhp5eRl#6&1vs48!fG#lgAx%7Ai9pAyIMCu1)!1Iq)KI`Tu_2 z4?N=e?LBP!lv`3Ccg)*!@gQ*fd49eacoMk5lh4NMIUx0R$RW=qmp0(3ix7Al@U#cP z&)7cYlGH1h{R|&|+8SXZw+XW!;))XyIW2RfUcqcGxuU~XQ}eaa3OwNvB~uX{k~vZ@ z^WRRN3q~+EMnu6zpv%$z*@%^v3gs|+4!a+O&_qH4r#>ffxDmwxZd$^HUdi> z-oK1!d+?bf^&&=);DTF$B_5o!!r}eRL{qI~j?{}7b%=}2D?IwL)Y0*)B040KGxdIl zJ_zue=aR_Z4&%|E=b3shZql41xUYMi!dw{@wP@(A=YZ7PA?+C5R8)M5*~50>vUh=B zBffu)?Ncsi>a&&BDAA>#zW}cQzejxk$H40jMaC%6RgRfezYjX5iCw_+z|Zpx)<>8{ z#-AM0=b+{GM9bU9HX6{+xiS$B<&{0&ojPfV?Hphn__ekF@cC3PirjSz*Bx{|s=NnKNxlDd+*Mu<8@NnJ@@NnKNx zlDd+*Mu<}Z?E@T>sz-O7{Lfe&Z!#72JoRz4=7HF){yIp$?}>D&&)FEu)X8<8KTJJWy-Ynz z9rs?4I9gq4Is7uOr20|y9(9-6ufC!FL7frj?Oh=;O1-7Po$6tadhLLM>M82#I zh7z)`t23+6c~qUGcO@`!h-;n-91q-ALUsc11$9*AM1V=aXNR$7D{wh*FHj~?UI-j_ zFo>K3oIK2R&jEUYbtPm!2%J|bkudQkv8%(u(ZET-%91*KMjc(HMJ55WDmZ&Bz$bw} z0c8ryj{`?lNn|=uRoyfL*c2{S#=WLgLL{QqY+y`9L{13HY%C!=4*0IRDC)5`wI!}p z)&&O826R=JjyfU?uZZ(DsgwXx2#DW!eQlHgQzyVc?m^-Jmn z>J92M4P7 zXqV)|?pAeE=KCMjF}de1RQJYpS*G>Aqd=F3)Hc*s_5PAQ`D*p+>gnnsO~Uyk^*ico znKgCj7MVw=&;f0{#XtYQcg9 z#8iEKMqmZ7rGzzFfQ7&@B?xaR=oU9O>6PZHH>wlWPXLQDrIf&3z@|BK=FqZy`Ep`s zZUufE1>QeWN@a$#ezfp3K*RKA(WD@<6dP0m-$HwP{C0mD=BEk*epX!Xoix)F<=FCFH+SH$^ zPh=xZlaRYmeY=D*eUa4{L~ZwCPPwvpN}bi+-A!j_XG7)2so#s8{#G{9)R8|lGWeS% z6?s%$I)vJ8UnI||^XAPP^!#^egyt`+9Svk#)z7JaE@_>?;(7I}>iCY1jv)=RlltkX zhyJR5Up=|rWFtzLD`Nw;46}8vh5L1@A89sCNo5HE9|Nw7@V5haIP%ZNl+xb3g<_uD z1)LwxOa|IZw9|b+4{&#MmmA7N&@==qwMVCSaSYXJz>D$n9^eJwwMc#gd80juOpOhh z9-k*h;@cKo;fk0}_5g1dgzM^v};{v%Nf|NWM(hsv*;BFv8o>xgPyzk})JA=D=TJ5a00000 LNkvXXu0mjf;))JN literal 0 HcmV?d00001 diff --git a/core/src/com/unciv/ui/civilopedia/CivilopediaCategories.kt b/core/src/com/unciv/ui/civilopedia/CivilopediaCategories.kt index 2c3675531c..71e8b3537e 100644 --- a/core/src/com/unciv/ui/civilopedia/CivilopediaCategories.kt +++ b/core/src/com/unciv/ui/civilopedia/CivilopediaCategories.kt @@ -1,5 +1,6 @@ package com.unciv.ui.civilopedia +import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.ui.Container @@ -11,6 +12,7 @@ import com.unciv.models.ruleset.tile.TerrainType import com.unciv.ui.tilegroups.TileGroup import com.unciv.ui.tilegroups.TileSetStrings import com.unciv.ui.utils.ImageGetter +import com.unciv.ui.utils.KeyCharAndCode import com.unciv.ui.utils.surroundWithCircle import java.io.File @@ -113,24 +115,89 @@ object CivilopediaImageGetters { enum class CivilopediaCategories ( val label: String, 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 headerIcon: String ) { - Building ("Buildings", false, CivilopediaImageGetters.construction ), - Wonder ("Wonders", false, CivilopediaImageGetters.construction ), - Resource ("Resources", false, CivilopediaImageGetters.resource ), - Terrain ("Terrains", false, CivilopediaImageGetters.terrain ), - Improvement ("Tile Improvements", false, CivilopediaImageGetters.improvement ), - Unit ("Units", false, CivilopediaImageGetters.construction ), - Nation ("Nations", false, CivilopediaImageGetters.nation ), - Technology ("Technologies", false, CivilopediaImageGetters.technology ), - Promotion ("Promotions", false, CivilopediaImageGetters.promotion ), - Policy ("Policies", false, CivilopediaImageGetters.policy ), - Belief("Religions and Beliefs", false, CivilopediaImageGetters.belief ), - Tutorial ("Tutorials", false, null ), - Difficulty ("Difficulty levels", false, null ), - ; + Building ("Buildings", false, + CivilopediaImageGetters.construction, + KeyCharAndCode('B'), + "OtherIcons/Cities" + ), + Wonder ("Wonders", false, + CivilopediaImageGetters.construction, + KeyCharAndCode('W'), + "OtherIcons/Wonders" + ), + Resource ("Resources", false, + CivilopediaImageGetters.resource, + KeyCharAndCode('R'), + "OtherIcons/Resources" + ), + Terrain ("Terrains", false, + CivilopediaImageGetters.terrain, + KeyCharAndCode('T'), + "OtherIcons/Terrains" + ), + Improvement ("Tile Improvements", false, + CivilopediaImageGetters.improvement, + KeyCharAndCode('T'), + "OtherIcons/Improvements" + ), + Unit ("Units", false, + CivilopediaImageGetters.construction, + KeyCharAndCode('U'), + "OtherIcons/Shield" + ), + Nation ("Nations", false, + CivilopediaImageGetters.nation, + KeyCharAndCode('N'), + "OtherIcons/Nations" + ), + Technology ("Technologies", false, + CivilopediaImageGetters.technology, + KeyCharAndCode('T'), + "TechIcons/Philosophy" + ), + Promotion ("Promotions", false, + CivilopediaImageGetters.promotion, + KeyCharAndCode('P'), + "UnitPromotionIcons/Mobility" + ), + Policy ("Policies", false, + CivilopediaImageGetters.policy, + KeyCharAndCode('P'), + "PolicyIcons/Constitution" + ), + Belief("Religions and Beliefs", false, + CivilopediaImageGetters.belief, + KeyCharAndCode('R'), + "ReligionIcons/Religion" + ), + Tutorial ("Tutorials", false, + getImage = null, + KeyCharAndCode(Input.Keys.F1), + "OtherIcons/ExclamationMark" + ), + Difficulty ("Difficulty levels", false, + getImage = null, + KeyCharAndCode('D'), + "OtherIcons/Quickstart" + ); + + 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 { + private val count = values().size + fun fromLink(name: String): CivilopediaCategories? = values().firstOrNull { it.name == name } ?: values().firstOrNull { it.label == name } diff --git a/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt b/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt index 73d09af070..6425a53d96 100644 --- a/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt +++ b/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt @@ -1,5 +1,6 @@ package com.unciv.ui.civilopedia +import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Touchable @@ -11,6 +12,7 @@ import com.unciv.models.ruleset.unique.Unique import com.unciv.models.stats.INamed import com.unciv.models.translations.tr import com.unciv.ui.utils.* +import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.AutoScrollPane as ScrollPane /** Screen displaying the Civilopedia @@ -44,15 +46,19 @@ class CivilopediaScreen( } private val categoryToEntries = LinkedHashMap>() - private val categoryToButtons = LinkedHashMap() + private class CategoryButtonInfo(val button: Button, val x: Float, val width: Float) + private val categoryToButtons = LinkedHashMap() private val entryIndex = LinkedHashMap() + private val buttonTableScroll: ScrollPane + private val entrySelectTable = Table().apply { defaults().pad(6f).left() } private val entrySelectScroll: ScrollPane private val flavourTable = Table() private var currentCategory: CivilopediaCategories = CivilopediaCategories.Tutorial private var currentEntry: String = "" + private val currentEntryPerCategory = HashMap() /** Jump to a "link" selecting both category and entry * @@ -87,9 +93,11 @@ class CivilopediaScreen( entryIndex.clear() flavourTable.clear() - for (button in categoryToButtons.values) button.color = Color.WHITE - if (category !in categoryToButtons) return // defense against being passed a bad selector - categoryToButtons[category]!!.color = Color.BLUE + for (button in categoryToButtons.values) button.button.color = Color.WHITE + val buttonInfo = categoryToButtons[category] + ?: return // defense against being passed a bad selector + buttonInfo.button.color = Color.BLUE + buttonTableScroll.scrollX = buttonInfo.x + (buttonInfo.width - buttonTableScroll.width) / 2 if (category !in categoryToEntries) return // defense, allowing buggy panes to remain empty while others work var entries = categoryToEntries[category]!! @@ -123,6 +131,9 @@ class CivilopediaScreen( } entrySelectScroll.layout() // necessary for positioning in selectRow to work + + val entry = currentEntryPerCategory[category] + if (entry != null) selectEntry(entry) } /** Select a specified entry within the current category. Unknown strings are ignored! @@ -132,15 +143,14 @@ class CivilopediaScreen( fun selectEntry(name: String, noScrollAnimation: Boolean = false) { val entry = entryIndex[name] ?: return // fails: entrySelectScroll.scrollTo(0f, entry.y, 0f, entry.h, false, true) - entrySelectScroll.let { - it.scrollY = (entry.y + (entry.height - it.height) / 2).coerceIn(0f, it.maxY) - } + entrySelectScroll.scrollY = (entry.y + (entry.height - entrySelectScroll.height) / 2) if (noScrollAnimation) entrySelectScroll.updateVisualScroll() // snap without animation on fresh pedia open selectEntry(entry) } private fun selectEntry(entry: CivilopediaEntry) { currentEntry = entry.name + currentEntryPerCategory[currentCategory] = entry.name flavourTable.clear() if (entry.flavour != null) { flavourTable.isVisible = true @@ -207,17 +217,22 @@ class CivilopediaScreen( buttonTable.pad(15f) buttonTable.defaults().pad(10f) + var currentX = 10f // = padLeft for (categoryKey in categoryToEntries.keys) { - val button = categoryKey.label.toTextButton() - button.style = TextButton.TextButtonStyle(button.style) - categoryToButtons[categoryKey] = button + val button = Button(skin) + if (categoryKey.headerIcon.isNotEmpty()) + button.add(ImageGetter.getImage(categoryKey.headerIcon)).size(20f).padRight(5f) + button.add(categoryKey.label.toLabel()) + button.addTooltip(categoryKey.key) +// button.style = ImageButton.ImageButtonStyle(button.style) button.onClick { selectCategory(categoryKey) } - buttonTable.add(button) + val cell = buttonTable.add(button) + categoryToButtons[categoryKey] = CategoryButtonInfo(button, currentX, cell.prefWidth) + currentX += cell.prefWidth + 20f } buttonTable.pack() - buttonTable.width = stage.width - val buttonTableScroll = ScrollPane(buttonTable) + buttonTableScroll = ScrollPane(buttonTable) buttonTableScroll.setScrollingDisabled(false, true) val goToGameButton = Constants.close.toTextButton() @@ -228,8 +243,9 @@ class CivilopediaScreen( val topTable = Table() topTable.add(goToGameButton).pad(10f) - topTable.add(buttonTableScroll) - topTable.pack() + topTable.add(buttonTableScroll).growX() + topTable.width = stage.width + topTable.layout() val entryTable = Table() val splitPane = SplitPane(topTable, entryTable, true, skin) @@ -257,6 +273,34 @@ class CivilopediaScreen( selectLink(link) else selectEntry(link, noScrollAnimation = true) + + for (categoryKey in CivilopediaCategories.values()) { + keyPressDispatcher[categoryKey.key] = { navigateCategories(categoryKey.key) } + } + keyPressDispatcher[Input.Keys.LEFT] = { selectCategory(currentCategory.getByOffset(-1)) } + keyPressDispatcher[Input.Keys.RIGHT] = { selectCategory(currentCategory.getByOffset(1)) } + keyPressDispatcher[Input.Keys.UP] = { navigateEntries(-1) } + keyPressDispatcher[Input.Keys.DOWN] = { navigateEntries(1) } + keyPressDispatcher[Input.Keys.PAGE_UP] = { navigateEntries(-10) } + keyPressDispatcher[Input.Keys.PAGE_DOWN] = { navigateEntries(10) } + keyPressDispatcher[Input.Keys.HOME] = { navigateEntries(Int.MIN_VALUE) } + keyPressDispatcher[Input.Keys.END] = { navigateEntries(Int.MAX_VALUE) } + } + + private fun navigateCategories(key: KeyCharAndCode) { + selectCategory(currentCategory.nextForKey(key)) + } + + private fun navigateEntries(direction: Int) { + //todo this is abusing a Map as Array - there must be a collection allowing both easy positional and associative access + val index = entryIndex.keys.indexOf(currentEntry) + if (index < 0) return selectEntry(entryIndex.keys.first(), true) + val newIndex = when (direction) { + Int.MIN_VALUE -> 0 + Int.MAX_VALUE -> entryIndex.size - 1 + else -> (index + entryIndex.size + direction) % entryIndex.size + } + selectEntry(entryIndex.keys.drop(newIndex).first()) } override fun resize(width: Int, height: Int) { diff --git a/docs/Credits.md b/docs/Credits.md index 97dd2fba9f..13193a25ec 100644 --- a/docs/Credits.md +++ b/docs/Credits.md @@ -158,7 +158,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https: * [Anvil](https://thenounproject.com/term/anvil/166414/) By Jason Dilworth for Iron * [Deer](https://thenounproject.com/term/deer/338013/) By Richard Nixon * [Banana](https://thenounproject.com/term/banana/1262865/) By Adrian Coquet -* [Oil](https://thenounproject.com/term/oil/88649/) By Tiago Maricate +* [Oil](https://thenounproject.com/term/oil/88649/) By Tiago Maricate (also as Civilopedia category icon) * [Statue](https://thenounproject.com/term/statue/5221/) By Joris Hoogendoorn for Marble * [Ribbon](https://thenounproject.com/term/ribbon/418996) By Anton for Silk * [Stone](https://thenounproject.com/term/stone/1373902/) By AFY Studio @@ -648,6 +648,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https: * [ship helm](https://thenounproject.com/term/ship-helm/2170591/) by Vectors Market for Maritime City-States * [Magnifying Glass](https://thenounproject.com/term/magnifying-glass/1311/) by John Caserta for Mod filter * [tick](https://thenounproject.com/term/tick/3968142/) by Adrien Coquet on Nation picker +* [people](https://thenounproject.com/term/people/458671) by Wilson Joseph as base for Civilopedia category Nations +* [Mountains ](https://thenounproject.com/term/mountains/15616/) by Andrew J. Young as base for Civilopedia category Terrains ## Main menu