From 4522ab4c6b1296103a4afdf5ca9e4be5ec9ae8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonard=20G=C3=BCnther?= Date: Sun, 6 Nov 2022 21:53:55 +0100 Subject: [PATCH] Added "How to create a UI skin for Unciv" to wiki (#7976) * Replaced all occurrences of deprecated NinePatch function calls This makes a lot of UI elements already moddable but documentation is still missing * Added "How to create a UI skin for Unciv" to wiki * Added image * Fixed two typos and updated directory image Old image was missing a folder --- core/src/com/unciv/MainMenuScreen.kt | 12 +- .../ui/cityscreen/CitizenManagementTable.kt | 15 +- .../ui/cityscreen/CityConstructionsTable.kt | 34 +++- .../com/unciv/ui/cityscreen/CityInfoTable.kt | 7 +- .../cityscreen/CityScreenCityPickerTable.kt | 3 +- .../ui/cityscreen/CityScreenTileTable.kt | 8 +- .../com/unciv/ui/cityscreen/CityStatsTable.kt | 10 +- .../ui/cityscreen/ConstructionInfoTable.kt | 10 +- .../unciv/ui/civilopedia/CivilopediaScreen.kt | 5 +- core/src/com/unciv/ui/images/ImageGetter.kt | 2 +- .../ui/mapeditor/MapEditorToolsDrawer.kt | 7 +- .../com/unciv/ui/newgamescreen/NationTable.kt | 24 ++- .../ui/newgamescreen/PlayerPickerTable.kt | 5 +- .../com/unciv/ui/options/MultiplayerTab.kt | 2 +- .../GlobalPoliticsOverviewTable.kt | 5 +- .../NotificationsOverviewTable.kt | 3 +- .../overviewscreen/ReligionOverviewTable.kt | 5 +- .../overviewscreen/ResourcesOverviewTable.kt | 3 +- .../ui/overviewscreen/TradesOverviewTable.kt | 7 +- .../ui/overviewscreen/UnitOverviewTable.kt | 6 +- .../ui/pickerscreens/ModManagementOptions.kt | 5 +- .../com/unciv/ui/pickerscreens/TechButton.kt | 4 +- core/src/com/unciv/ui/popup/Popup.kt | 9 +- .../src/com/unciv/ui/tilegroups/CityButton.kt | 9 +- .../com/unciv/ui/tilegroups/TileGroupIcons.kt | 6 +- core/src/com/unciv/ui/utils/BaseScreen.kt | 12 +- core/src/com/unciv/ui/utils/ExpanderTab.kt | 7 +- core/src/com/unciv/ui/utils/LanguageTable.kt | 9 +- core/src/com/unciv/ui/utils/TabbedPager.kt | 5 +- core/src/com/unciv/ui/utils/UncivTooltip.kt | 4 +- .../ui/utils/extensions/Scene2dExtensions.kt | 2 +- .../unciv/ui/victoryscreen/VictoryScreen.kt | 3 +- .../ui/worldscreen/NotificationsScroll.kt | 4 +- .../unciv/ui/worldscreen/PlayerReadyScreen.kt | 5 +- .../worldscreen/TechPolicyDiplomacyButtons.kt | 2 +- .../unciv/ui/worldscreen/WorldMapHolder.kt | 3 +- .../com/unciv/ui/worldscreen/WorldScreen.kt | 6 +- .../unciv/ui/worldscreen/WorldScreenTopBar.kt | 11 +- .../ui/worldscreen/bottombar/BattleTable.kt | 5 +- .../ui/worldscreen/bottombar/TileInfoTable.kt | 5 +- .../ui/worldscreen/minimap/MinimapHolder.kt | 11 +- .../ui/worldscreen/unit/UnitActionsTable.kt | 3 - .../unciv/ui/worldscreen/unit/UnitTable.kt | 6 +- docs/Modders/Creating-a-UI-skin.md | 150 ++++++++++++++++++ .../src/com/unciv/dev/FasterUIDevelopment.kt | 4 +- 45 files changed, 370 insertions(+), 93 deletions(-) create mode 100644 docs/Modders/Creating-a-UI-skin.md diff --git a/core/src/com/unciv/MainMenuScreen.kt b/core/src/com/unciv/MainMenuScreen.kt index e0ec61a33a..bcfe7e0d32 100644 --- a/core/src/com/unciv/MainMenuScreen.kt +++ b/core/src/com/unciv/MainMenuScreen.kt @@ -53,7 +53,9 @@ import kotlin.math.min class MainMenuScreen: BaseScreen(), RecreateOnResize { - private val backgroundTable = Table().apply { background= ImageGetter.getBackground(Color.WHITE) } + private val backgroundTable = Table().apply { + background = skinStrings.getUiBackground("MainMenuScreen/Background", tintColor = Color.WHITE) + } private val singleColumn = isCrampedPortrait() private var easterEggRuleset: Ruleset? = null // Cache it so the next 'egg' can be found in Civilopedia @@ -71,7 +73,11 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize { function: () -> Unit ): Table { val table = Table().pad(15f, 30f, 15f, 30f) - table.background = ImageGetter.getRoundedEdgeRectangle(ImageGetter.getBlue()) + table.background = skinStrings.getUiBackground( + "MainMenuScreen/MenuButton", + skinStrings.roundedEdgeRectangle, + skinStrings.skinConfig.baseColor + ) table.add(ImageGetter.getImage(icon)).size(50f).padRight(30f) table.add(text.toLabel().setFontSize(30)).minWidth(200f) @@ -197,7 +203,7 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize { val helpButton = "?".toLabel(fontSize = 48) .apply { setAlignment(Align.center) } - .surroundWithCircle(60f, color = ImageGetter.getBlue()) + .surroundWithCircle(60f, color = skinStrings.skinConfig.baseColor) .apply { actor.y -= 2.5f } // compensate font baseline (empirical) .surroundWithCircle(64f, resizeActor = false) helpButton.touchable = Touchable.enabled diff --git a/core/src/com/unciv/ui/cityscreen/CitizenManagementTable.kt b/core/src/com/unciv/ui/cityscreen/CitizenManagementTable.kt index 1aeacaef28..beb2a0aff5 100644 --- a/core/src/com/unciv/ui/cityscreen/CitizenManagementTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CitizenManagementTable.kt @@ -31,7 +31,10 @@ class CitizenManagementTable(val cityScreen: CityScreen) : Table(BaseScreen.skin cityScreen.update() } } - resetCell.background = ImageGetter.getBackground(colorButton) + resetCell.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CitizenManagementTable/ResetCell", + tintColor = colorButton + ) add(resetCell).colspan(2).growX().pad(3f) row() @@ -46,7 +49,10 @@ class CitizenManagementTable(val cityScreen: CityScreen) : Table(BaseScreen.skin cityScreen.update() } } - avoidCell.background = ImageGetter.getBackground(if (city.avoidGrowth) colorSelected else colorButton) + avoidCell.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CitizenManagementTable/AvoidCell", + tintColor = if (city.avoidGrowth) colorSelected else colorButton + ) add(avoidCell).colspan(2).growX().pad(3f) row() @@ -65,7 +71,10 @@ class CitizenManagementTable(val cityScreen: CityScreen) : Table(BaseScreen.skin cityScreen.update() } } - cell.background = ImageGetter.getBackground(if (city.cityAIFocus == focus) colorSelected else colorButton) + cell.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CitizenManagementTable/FocusCell", + tintColor = if (city.cityAIFocus == focus) colorSelected else colorButton + ) add(cell).growX().pad(3f) if (newRow) // every 2 make new row row() diff --git a/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt index 22a7d8ad13..276fd92e20 100644 --- a/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityConstructionsTable.kt @@ -91,7 +91,10 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { constructionsQueueScrollPane = ScrollPane(constructionsQueueTable.addBorder(2f, Color.WHITE)) constructionsQueueScrollPane.setOverscroll(false, false) - constructionsQueueTable.background = ImageGetter.getBackground(Color.BLACK) + constructionsQueueTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/ConstructionsQueueTable", + tintColor = Color.BLACK + ) upperTable.defaults().left().top() upperTable.add(showCityInfoTableButton).padLeft(pad).padBottom(pad).row() @@ -102,7 +105,10 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { availableConstructionsScrollPane = ScrollPane(availableConstructionsTable.addBorder(2f, Color.WHITE)) availableConstructionsScrollPane.setOverscroll(false, false) - availableConstructionsTable.background = ImageGetter.getBackground(Color.BLACK) + availableConstructionsTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/AvailableConstructionsTable", + tintColor = Color.BLACK + ) lowerTableScrollCell = lowerTable.add(availableConstructionsScrollPane).bottom() lowerTable.row() } @@ -282,10 +288,13 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { val table = Table() table.align(Align.left).pad(5f) - table.background = ImageGetter.getBackground(Color.BLACK) + table.background = BaseScreen.skinStrings.getUiBackground("CityScreen/CityConstructionTable/QueueEntry", tintColor = Color.BLACK) if (constructionQueueIndex == selectedQueueEntry) - table.background = ImageGetter.getBackground(Color.GREEN.darken(0.5f)) + table.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/QueueEntry", + tintColor = Color.GREEN.darken(0.5f) + ) val isFirstConstructionOfItsKind = cityConstructions.isFirstConstructionOfItsKind(constructionQueueIndex, constructionName) @@ -339,11 +348,17 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { val pickConstructionButton = Table() pickConstructionButton.align(Align.left).pad(5f) - pickConstructionButton.background = ImageGetter.getBackground(Color.BLACK) + pickConstructionButton.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/PickConstructionButton", + tintColor = Color.BLACK + ) pickConstructionButton.touchable = Touchable.enabled if (!isSelectedQueueEntry() && cityScreen.selectedConstruction == construction) { - pickConstructionButton.background = ImageGetter.getBackground(Color.GREEN.darken(0.5f)) + pickConstructionButton.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/PickConstructionButton", + tintColor = Color.GREEN.darken(0.5f) + ) } pickConstructionButton.add(getProgressBar(construction.name)).padRight(5f) @@ -631,7 +646,12 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { private fun getHeader(title: String): Table { return Table() - .background(ImageGetter.getBackground(ImageGetter.getBlue())) + .background( + BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityConstructionTable/Header", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor + ) + ) .addCell(title.toLabel(fontSize = Constants.headingFontSize)) .pad(4f) } diff --git a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt b/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt index b70e8c6373..876ef6246a 100644 --- a/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityInfoTable.kt @@ -52,7 +52,10 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin) } innerTable.width = cityScreen.stage.width / 4 - innerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityInfoTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) scrollPane = ScrollPane(innerTable.addBorder(2f, Color.WHITE)) scrollPane.setOverscroll(false, false) @@ -322,7 +325,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(BaseScreen.skin) val label = (if (showDetails) "-" else "+").toLabel() label.setAlignment(Align.center) return label - .surroundWithCircle(25f, color = ImageGetter.getBlue()) + .surroundWithCircle(25f, color = BaseScreen.skinStrings.skinConfig.baseColor) .surroundWithCircle(27f, false) } diff --git a/core/src/com/unciv/ui/cityscreen/CityScreenCityPickerTable.kt b/core/src/com/unciv/ui/cityscreen/CityScreenCityPickerTable.kt index 8604c62dee..9f8ce075e4 100644 --- a/core/src/com/unciv/ui/cityscreen/CityScreenCityPickerTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityScreenCityPickerTable.kt @@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.ui.images.ImageGetter import com.unciv.ui.popup.AskTextPopup +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.extensions.onClick import com.unciv.ui.utils.extensions.toLabel @@ -16,7 +17,7 @@ class CityScreenCityPickerTable(private val cityScreen: CityScreen) : Table() { fun update() { val city = cityScreen.city val civInfo = city.civInfo - background = ImageGetter.getRoundedEdgeRectangle(civInfo.nation.getOuterColor()) + background = BaseScreen.skinStrings.getUiBackground("CityScreen/CityPickerTable", BaseScreen.skinStrings.roundedEdgeRectangle, civInfo.nation.getOuterColor()) clear() if (civInfo.cities.size > 1) { diff --git a/core/src/com/unciv/ui/cityscreen/CityScreenTileTable.kt b/core/src/com/unciv/ui/cityscreen/CityScreenTileTable.kt index 1fcf92c80a..4e782faf93 100644 --- a/core/src/com/unciv/ui/cityscreen/CityScreenTileTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityScreenTileTable.kt @@ -15,6 +15,7 @@ import com.unciv.ui.civilopedia.MarkupRenderer import com.unciv.ui.images.ImageGetter import com.unciv.ui.popup.ConfirmPopup import com.unciv.ui.popup.closeAllPopups +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.extensions.darken import com.unciv.ui.utils.extensions.disable @@ -31,9 +32,12 @@ class CityScreenTileTable(private val cityScreen: CityScreen): Table() { val city = cityScreen.city init { - innerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityScreenTileTable/InnerTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) add(innerTable).pad(2f).fill() - background = ImageGetter.getBackground(Color.WHITE) + background = BaseScreen.skinStrings.getUiBackground("CityScreen/CityScreenTileTable/Background", tintColor = Color.WHITE) } fun update(selectedTile: TileInfo?) { diff --git a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt index 0b2ce5cf6a..8a5ae1ac02 100644 --- a/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/CityStatsTable.kt @@ -35,10 +35,16 @@ class CityStatsTable(val cityScreen: CityScreen): Table() { init { pad(2f) - background = ImageGetter.getBackground(colorFromRGB(194, 180, 131)) + background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityStatsTable/Background", + tintColor = colorFromRGB(194, 180, 131) + ) innerTable.pad(5f) - innerTable.background = ImageGetter.getBackground(Color.BLACK.cpy().apply { a = 0.8f }) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/CityStatsTable/InnerTable", + tintColor = Color.BLACK.cpy().apply { a = 0.8f } + ) innerTable.add(upperTable).row() upperTable.defaults().pad(2f) diff --git a/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt b/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt index 32250dad96..4a7791c3de 100644 --- a/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt +++ b/core/src/com/unciv/ui/cityscreen/ConstructionInfoTable.kt @@ -23,9 +23,15 @@ class ConstructionInfoTable(val cityScreen: CityScreen): Table() { private val selectedConstructionTable = Table() init { - selectedConstructionTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + selectedConstructionTable.background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/ConstructionInfoTable/SelectedConstructionTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) add(selectedConstructionTable).pad(2f).fill() - background = ImageGetter.getBackground(Color.WHITE) + background = BaseScreen.skinStrings.getUiBackground( + "CityScreen/ConstructionInfoTable/Background", + tintColor = Color.WHITE + ) } fun update(selectedConstruction: IConstruction?) { diff --git a/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt b/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt index 52022a04ea..c81ab91b89 100644 --- a/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt +++ b/core/src/com/unciv/ui/civilopedia/CivilopediaScreen.kt @@ -126,7 +126,10 @@ class CivilopediaScreen( for (entry in entries) { val entryButton = Table().apply { - background = ImageGetter.getBackground(colorFromRGB(50, 75, 125)) + background = skinStrings.getUiBackground( + "CivilopediaScreen/EntryButton", + tintColor = colorFromRGB(50, 75, 125) + ) touchable = Touchable.enabled } if (entry.image != null) diff --git a/core/src/com/unciv/ui/images/ImageGetter.kt b/core/src/com/unciv/ui/images/ImageGetter.kt index 4968118a19..62f43ccaf8 100644 --- a/core/src/com/unciv/ui/images/ImageGetter.kt +++ b/core/src/com/unciv/ui/images/ImageGetter.kt @@ -443,7 +443,7 @@ object ImageGetter { healthBar.pad(1f) healthBar.pack() - healthBar.background = getBackground(Color.BLACK) + healthBar.background = BaseScreen.skinStrings.getUiBackground("General/HealthBar", tintColor = Color.BLACK) return healthBar } diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorToolsDrawer.kt b/core/src/com/unciv/ui/mapeditor/MapEditorToolsDrawer.kt index 6f56d0c53b..48ed9cdc62 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorToolsDrawer.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorToolsDrawer.kt @@ -47,7 +47,10 @@ class MapEditorToolsDrawer( arrowWrapper.setSize(arrowSize, arrowSize) arrowWrapper.setOrigin(Align.center) add(arrowWrapper).align(Align.center).width(handleWidth).fillY().apply { // the "handle" - background = ImageGetter.getBackground(BaseScreen.skin.get("color", Color::class.java)) + background = BaseScreen.skinStrings.getUiBackground( + "MapEditor/MapEditorToolsDrawer/Handle", + tintColor = BaseScreen.skin.get("color", Color::class.java) + ) } add(tabs) @@ -104,7 +107,7 @@ class MapEditorToolsDrawer( } } - // single-use helpers placed together for readability. One should be the exact inverse of the other except for the clamping. + // single-use helpers placed together for readability. One should be the exact inverse of the other except for the clamping. private fun splitAmountToX() = stage.width - width + (1f - splitAmount) * (width - handleWidth) private fun xToSplitAmount(x: Float) = diff --git a/core/src/com/unciv/ui/newgamescreen/NationTable.kt b/core/src/com/unciv/ui/newgamescreen/NationTable.kt index 27cd506759..79b73544f0 100644 --- a/core/src/com/unciv/ui/newgamescreen/NationTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/NationTable.kt @@ -29,7 +29,9 @@ class NationTable(val nation: Nation, width: Float, minHeight: Float, ruleset: R val internalWidth = width - totalPadding val titleTable = Table() - titleTable.background = ImageGetter.getBackground(outerColor) + titleTable.background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/NationTable/Title", tintColor = outerColor + ) val nationIndicator: Actor = if (nation.name == Constants.random) ImageGetter.getRandomNationIndicator(50f) else ImageGetter.getNationIndicator(nation, 50f) @@ -50,21 +52,33 @@ class NationTable(val nation: Nation, width: Float, minHeight: Float, ruleset: R if (ruleset != null) { titleTable.padBottom(borderWidth) // visual centering including upper border - innerTable.background = ImageGetter.getBackground(textBackgroundColor) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/NationTable/InnerTable", + tintColor = textBackgroundColor + ) val lines = nation.getCivilopediaTextLines(ruleset) .filter { it.header != 3 } innerTable.add(MarkupRenderer.render(lines, internalWidth, iconDisplay = IconDisplay.NoLink)).pad(10f) val borderTable = Table() - borderTable.background = ImageGetter.getBackground(outerColor) + borderTable.background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/NationTable/BorderTable", + tintColor = outerColor + ) borderTable.add(innerTable).pad(borderWidth).grow() add(borderTable).pad(borderWidth).width(width).minHeight(minHeight - totalPadding) } else { - innerTable.background = ImageGetter.getBackground(outerColor) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/NationTable/InnerTable", + tintColor = outerColor + ) add(innerTable).width(width).minHeight(minHeight - totalPadding) } touchable = Touchable.enabled - background = ImageGetter.getBackground(innerColor) + background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/NationTable/Background", + tintColor = innerColor + ) } } diff --git a/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt b/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt index bae37bdd3e..3243363bc5 100644 --- a/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt @@ -138,7 +138,10 @@ class PlayerPickerTable( private fun getPlayerTable(player: Player): Table { val playerTable = Table() playerTable.pad(5f) - playerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.8f)) + playerTable.background = BaseScreen.skinStrings.getUiBackground( + "NewGameScreen/PlayerPickerTable/PlayerTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.8f) + ) val nationTable = getNationTable(player) playerTable.add(nationTable).left() diff --git a/core/src/com/unciv/ui/options/MultiplayerTab.kt b/core/src/com/unciv/ui/options/MultiplayerTab.kt index 7eeff1c773..eb48b66da8 100644 --- a/core/src/com/unciv/ui/options/MultiplayerTab.kt +++ b/core/src/com/unciv/ui/options/MultiplayerTab.kt @@ -280,5 +280,5 @@ private fun addSelectAsSeparateTable(tab: Table, settingsSelect: SettingsSelect< } private fun addSeparator(tab: Table) { - tab.addSeparator(ImageGetter.getBlue().brighten(0.1f)) + tab.addSeparator(BaseScreen.skinStrings.skinConfig.baseColor.brighten(0.1f)) } diff --git a/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt index efc91d0edc..acd439ee54 100644 --- a/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/GlobalPoliticsOverviewTable.kt @@ -47,7 +47,10 @@ class GlobalPoliticsOverviewTable ( private val fixedContent = Table() private val civTable = Table().apply { defaults().pad(5f) - background = ImageGetter.getBackground(Color.BLACK) + background = BaseScreen.skinStrings.getUiBackground( + "OverviewScreen/DiplomacyOverviewTab/CivTable", + tintColor = Color.BLACK + ) } // Reusable sequences for the Civilizations to display diff --git a/core/src/com/unciv/ui/overviewscreen/NotificationsOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/NotificationsOverviewTable.kt index 2e5522c60f..472ac30191 100644 --- a/core/src/com/unciv/ui/overviewscreen/NotificationsOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/NotificationsOverviewTable.kt @@ -6,7 +6,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.unciv.UncivGame import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.Notification -import com.unciv.ui.images.ImageGetter import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.WrappableLabel import com.unciv.ui.utils.TabbedPager @@ -80,7 +79,7 @@ class NotificationsOverviewTable( val label = WrappableLabel(notification.text, labelWidth, Color.BLACK, 20) notificationTable.add(label) - notificationTable.background = ImageGetter.getRoundedEdgeRectangle() + notificationTable.background = BaseScreen.skinStrings.getUiBackground("OverviewScreen/NotificationOverviewTable/Notification", BaseScreen.skinStrings.roundedEdgeRectangle) notificationTable.touchable = Touchable.enabled notificationTable.onClick { UncivGame.Current.resetToWorldScreen() diff --git a/core/src/com/unciv/ui/overviewscreen/ReligionOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/ReligionOverviewTable.kt index adbe13d0b7..d6b91a2710 100644 --- a/core/src/com/unciv/ui/overviewscreen/ReligionOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/ReligionOverviewTable.kt @@ -179,6 +179,9 @@ class ReligionOverviewTab( ) { UncivGame.Current.pushScreen(CivilopediaScreen(gameInfo.ruleSet, link = it)) }.apply { - background = ImageGetter.getBackground(ImageGetter.getBlue()) + background = BaseScreen.skinStrings.getUiBackground( + "OverviewScreen/ReligionOverviewTab/BeliefDescription", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor + ) } } diff --git a/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt index f0f37d2597..fdae8f5119 100644 --- a/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/ResourcesOverviewTable.kt @@ -13,6 +13,7 @@ import com.unciv.models.translations.tr import com.unciv.ui.civilopedia.CivilopediaCategories import com.unciv.ui.civilopedia.CivilopediaScreen import com.unciv.ui.images.ImageGetter +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.extensions.addSeparator import com.unciv.ui.utils.extensions.addSeparatorVertical @@ -43,7 +44,7 @@ class ResourcesOverviewTab( private fun getTurnImage(vertical: Boolean) = ImageGetter.getImage("OtherIcons/Turn right") .apply { - color = ImageGetter.getBlue() + color = BaseScreen.skinStrings.skinConfig.baseColor if (vertical) rotateBy(90f) } diff --git a/core/src/com/unciv/ui/overviewscreen/TradesOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/TradesOverviewTable.kt index 0e04cc36e9..aaa2fc8f5b 100644 --- a/core/src/com/unciv/ui/overviewscreen/TradesOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/TradesOverviewTable.kt @@ -4,7 +4,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.trade.Trade import com.unciv.logic.trade.TradeOffersList -import com.unciv.ui.images.ImageGetter +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.extensions.addSeparator import com.unciv.ui.utils.extensions.toLabel @@ -43,7 +43,10 @@ class TradesOverviewTab( private fun createOffersTable(civ: CivilizationInfo, offersList: TradeOffersList, numberOfOtherSidesOffers: Int): Table { val table = Table() table.defaults().pad(10f) - table.background = ImageGetter.getBackground(civ.nation.getOuterColor()) + table.background = BaseScreen.skinStrings.getUiBackground( + "OverviewScreen/TradesOverviewTab/OffersTable", + tintColor = civ.nation.getOuterColor() + ) table.add(civ.civName.toLabel(civ.nation.getInnerColor())).row() table.addSeparator() for (offer in offersList) { diff --git a/core/src/com/unciv/ui/overviewscreen/UnitOverviewTable.kt b/core/src/com/unciv/ui/overviewscreen/UnitOverviewTable.kt index 6de3c138b2..b0b73d38c1 100644 --- a/core/src/com/unciv/ui/overviewscreen/UnitOverviewTable.kt +++ b/core/src/com/unciv/ui/overviewscreen/UnitOverviewTable.kt @@ -14,6 +14,7 @@ import com.unciv.ui.images.IconTextButton import com.unciv.ui.images.ImageGetter import com.unciv.ui.pickerscreens.PromotionPickerScreen import com.unciv.ui.pickerscreens.UnitRenamePopup +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.ExpanderTab import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.TabbedPager @@ -110,7 +111,10 @@ class UnitOverviewTab( } ) { it.defaults().pad(5f).fill(false) - it.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.6f)) + it.background = BaseScreen.skinStrings.getUiBackground( + "OverviewScreen/UnitOverviewTab/UnitSupplyTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.6f) + ) it.addLabeledValue("Base Supply", stats.getBaseUnitSupply()) it.addLabeledValue("Cities", stats.getUnitSupplyFromCities()) it.addLabeledValue("Population", stats.getUnitSupplyFromPop()) diff --git a/core/src/com/unciv/ui/pickerscreens/ModManagementOptions.kt b/core/src/com/unciv/ui/pickerscreens/ModManagementOptions.kt index a1710bd97c..e47e89ddf0 100644 --- a/core/src/com/unciv/ui/pickerscreens/ModManagementOptions.kt +++ b/core/src/com/unciv/ui/pickerscreens/ModManagementOptions.kt @@ -160,7 +160,10 @@ class ModManagementOptions(private val modManagementScreen: ModManagementScreen) expanderWidth = 360f, onChange = { expanderChangeEvent?.invoke() } ) { - it.background = ImageGetter.getBackground(Color(0x203050ff)) + it.background = BaseScreen.skinStrings.getUiBackground( + "ModManagementOptions/ExpanderTab", + tintColor = Color(0x203050ff) + ) it.pad(7.5f) it.add(Table().apply { add("Filter:".toLabel()).left() diff --git a/core/src/com/unciv/ui/pickerscreens/TechButton.kt b/core/src/com/unciv/ui/pickerscreens/TechButton.kt index eda3e050a4..c38dee0114 100644 --- a/core/src/com/unciv/ui/pickerscreens/TechButton.kt +++ b/core/src/com/unciv/ui/pickerscreens/TechButton.kt @@ -24,7 +24,7 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS init { touchable = Touchable.enabled - background = ImageGetter.getRoundedEdgeRectangle() + background = BaseScreen.skinStrings.getUiBackground("TechPickerScreen/TechButton", BaseScreen.skinStrings.roundedEdgeRectangle) pad(10f) if (ImageGetter.techIconExists(techName)) @@ -112,7 +112,7 @@ class TechButton(techName:String, private val techManager: TechManager, isWorldS fun addOrderIndicator(number:Int){ orderIndicator = number.toString().toLabel(fontSize = 18) .apply { setAlignment(Align.center) } - .surroundWithCircle(28f, color = ImageGetter.getBlue()) + .surroundWithCircle(28f, color = BaseScreen.skinStrings.skinConfig.baseColor) .surroundWithCircle(30f,false) orderIndicator!!.setPosition(0f, height, Align.topLeft) addActor(orderIndicator) diff --git a/core/src/com/unciv/ui/popup/Popup.kt b/core/src/com/unciv/ui/popup/Popup.kt index 4025e09566..ac4b3ef941 100644 --- a/core/src/com/unciv/ui/popup/Popup.kt +++ b/core/src/com/unciv/ui/popup/Popup.kt @@ -52,8 +52,13 @@ open class Popup( // Set actor name for debugging name = javaClass.simpleName - background = ImageGetter.getBackground(Color.GRAY.cpy().apply { a=.5f }) - innerTable.background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + background = BaseScreen.skinStrings.getUiBackground( + "General/Popup/Background", + tintColor = Color.GRAY.cpy().apply { a=.5f }) + innerTable.background = BaseScreen.skinStrings.getUiBackground( + "General/Popup/InnerTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) innerTable.pad(20f) innerTable.defaults().pad(5f) diff --git a/core/src/com/unciv/ui/tilegroups/CityButton.kt b/core/src/com/unciv/ui/tilegroups/CityButton.kt index 11cd8fe4cc..611c5f06de 100644 --- a/core/src/com/unciv/ui/tilegroups/CityButton.kt +++ b/core/src/com/unciv/ui/tilegroups/CityButton.kt @@ -140,7 +140,7 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab if (!showAdditionalInfoTags || tileGroup.tileInfo.airUnits.isEmpty()) return val secondaryColor = city.civInfo.nation.getInnerColor() val airUnitTable = Table() - airUnitTable.background = ImageGetter.getRoundedEdgeRectangle(city.civInfo.nation.getOuterColor()).apply { setMinSize(0f,0f) } + airUnitTable.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/CityButton/AirUnitTable", BaseScreen.skinStrings.roundedEdgeRectangle, city.civInfo.nation.getOuterColor()).apply { setMinSize(0f,0f) } val aircraftImage = ImageGetter.getImage("OtherIcons/Aircraft") aircraftImage.color = secondaryColor airUnitTable.add(aircraftImage).size(15f) @@ -194,7 +194,7 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab } val iconTable = IconTable().apply { isTransform = false } iconTable.touchable = Touchable.enabled - iconTable.background = ImageGetter.getRoundedEdgeRectangle(city.civInfo.nation.getOuterColor()) + iconTable.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/CityButton/IconTable", BaseScreen.skinStrings.roundedEdgeRectangle, city.civInfo.nation.getOuterColor()) if (city.isInResistance()) { val resistanceImage = ImageGetter.getImage("StatIcons/Resistance") @@ -495,7 +495,10 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab val influenceBar = InfluenceTable().apply { defaults().pad(1f) setSize(width, height) - background = ImageGetter.getBackground(Color.BLACK) + background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/CityButton/InfluenceBar", + tintColor = Color.BLACK + ) } for (i in 0..3) diff --git a/core/src/com/unciv/ui/tilegroups/TileGroupIcons.kt b/core/src/com/unciv/ui/tilegroups/TileGroupIcons.kt index 43f7e737c8..da0ce50563 100644 --- a/core/src/com/unciv/ui/tilegroups/TileGroupIcons.kt +++ b/core/src/com/unciv/ui/tilegroups/TileGroupIcons.kt @@ -9,6 +9,7 @@ import com.unciv.UncivGame import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.map.MapUnit import com.unciv.ui.images.ImageGetter +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.UnitGroup import com.unciv.ui.utils.extensions.center import com.unciv.ui.utils.extensions.centerX @@ -86,7 +87,10 @@ class TileGroupIcons(val tileGroup: TileGroup) { val holder = Table() val secondaryColor = unit.civInfo.nation.getInnerColor() val airUnitTable = Table().apply { defaults().pad(3f) } - airUnitTable.background = ImageGetter.getBackground(unit.civInfo.nation.getOuterColor()) + airUnitTable.background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/AirUnitTable", + tintColor = unit.civInfo.nation.getOuterColor() + ) val aircraftImage = ImageGetter.getImage("OtherIcons/Aircraft") aircraftImage.color = secondaryColor airUnitTable.add(aircraftImage).size(10f) diff --git a/core/src/com/unciv/ui/utils/BaseScreen.kt b/core/src/com/unciv/ui/utils/BaseScreen.kt index 51aff77f29..e7d635509f 100644 --- a/core/src/com/unciv/ui/utils/BaseScreen.kt +++ b/core/src/com/unciv/ui/utils/BaseScreen.kt @@ -117,15 +117,15 @@ abstract class BaseScreen : Screen { skinStrings = SkinStrings() skin = Skin().apply { add("Nativefont", Fonts.font, BitmapFont::class.java) - add("RoundedEdgeRectangle", ImageGetter.getRoundedEdgeRectangle(), Drawable::class.java) + add("RoundedEdgeRectangle", skinStrings.getUiBackground("", skinStrings.roundedEdgeRectangle), Drawable::class.java) add("Rectangle", ImageGetter.getDrawable(""), Drawable::class.java) add("Circle", ImageGetter.getDrawable("OtherIcons/Circle").apply { setMinSize(20f, 20f) }, Drawable::class.java) add("Scrollbar", ImageGetter.getDrawable("").apply { setMinSize(10f, 10f) }, Drawable::class.java) - add("RectangleWithOutline", ImageGetter.getRectangleWithOutline(), Drawable::class.java) - add("Select-box", ImageGetter.getSelectBox(), Drawable::class.java) - add("Select-box-pressed", ImageGetter.getSelectBoxPressed(), Drawable::class.java) - add("Checkbox", ImageGetter.getCheckBox(), Drawable::class.java) - add("Checkbox-pressed", ImageGetter.getCheckBoxPressed(), Drawable::class.java) + add("RectangleWithOutline",skinStrings.getUiBackground("", skinStrings.rectangleWithOutline), Drawable::class.java) + add("Select-box", skinStrings.getUiBackground("", skinStrings.selectBox), Drawable::class.java) + add("Select-box-pressed", skinStrings.getUiBackground("", skinStrings.selectBoxPressed), Drawable::class.java) + add("Checkbox", skinStrings.getUiBackground("", skinStrings.checkbox), Drawable::class.java) + add("Checkbox-pressed", skinStrings.getUiBackground("", skinStrings.checkboxPressed), Drawable::class.java) load(Gdx.files.internal("Skin.json")) } skin.get(TextButton.TextButtonStyle::class.java).font = Fonts.font diff --git a/core/src/com/unciv/ui/utils/ExpanderTab.kt b/core/src/com/unciv/ui/utils/ExpanderTab.kt index cc28fd8d1f..196553339e 100644 --- a/core/src/com/unciv/ui/utils/ExpanderTab.kt +++ b/core/src/com/unciv/ui/utils/ExpanderTab.kt @@ -70,7 +70,12 @@ class ExpanderTab( headerIcon.setOrigin(Align.center) headerIcon.rotation = 180f headerIcon.color = arrowColor - header.background(ImageGetter.getBackground(ImageGetter.getBlue())) + header.background( + BaseScreen.skinStrings.getUiBackground( + "General/ExpanderTab", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor + ) + ) if (icon != null) header.add(icon) header.add(headerLabel) header.add(headerIcon).size(arrowSize).align(Align.center) diff --git a/core/src/com/unciv/ui/utils/LanguageTable.kt b/core/src/com/unciv/ui/utils/LanguageTable.kt index b0578d909e..272ebb0cda 100644 --- a/core/src/com/unciv/ui/utils/LanguageTable.kt +++ b/core/src/com/unciv/ui/utils/LanguageTable.kt @@ -11,8 +11,8 @@ import com.unciv.ui.utils.extensions.toLabel /** Represents a row in the Language picker, used both in OptionsPopup and in LanguagePickerScreen */ internal class LanguageTable(val language:String, val percentComplete: Int): Table(){ - private val blue = ImageGetter.getBlue() - private val darkBlue = blue.darken(0.5f) + private val baseColor = BaseScreen.skinStrings.skinConfig.baseColor + private val darkBaseColor = baseColor.darken(0.5f) init{ pad(10f) @@ -30,7 +30,10 @@ internal class LanguageTable(val language:String, val percentComplete: Int): Tab } fun update(chosenLanguage:String){ - background = ImageGetter.getBackground(if (chosenLanguage == language) blue else darkBlue) + background = BaseScreen.skinStrings.getUiBackground( + "LanguagePickerScreen/LanguageTable", + tintColor = if (chosenLanguage == language) baseColor else darkBaseColor + ) } companion object { diff --git a/core/src/com/unciv/ui/utils/TabbedPager.kt b/core/src/com/unciv/ui/utils/TabbedPager.kt index 15663b628a..caa087f124 100644 --- a/core/src/com/unciv/ui/utils/TabbedPager.kt +++ b/core/src/com/unciv/ui/utils/TabbedPager.kt @@ -17,7 +17,6 @@ import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame import com.unciv.ui.images.IconTextButton -import com.unciv.ui.images.ImageGetter import com.unciv.ui.popup.Popup import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.extensions.addSeparator @@ -61,7 +60,7 @@ open class TabbedPager( private val headerFontSize: Int = Constants.defaultFontSize, private val headerFontColor: Color = Color.WHITE, private val highlightColor: Color = Color.BLUE, - backgroundColor: Color = ImageGetter.getBlue().darken(0.5f), + backgroundColor: Color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f), private val headerPadding: Float = 10f, separatorColor: Color = Color.CLEAR, private val shorcutScreen: BaseScreen? = null, @@ -296,7 +295,7 @@ open class TabbedPager( dimW = DimensionMeasurement.from(minimumWidth, maximumWidth, screenWidth) dimH = DimensionMeasurement.from(minimumHeight, maximumHeight, screenHeight) - background = ImageGetter.getBackground(backgroundColor) + background = BaseScreen.skinStrings.getUiBackground("General/TabbedPager", tintColor = backgroundColor) header.defaults().pad(headerPadding, headerPadding * 0.5f) // Measure header height, most likely its final value diff --git a/core/src/com/unciv/ui/utils/UncivTooltip.kt b/core/src/com/unciv/ui/utils/UncivTooltip.kt index 4adc40844d..5c8d2a3062 100644 --- a/core/src/com/unciv/ui/utils/UncivTooltip.kt +++ b/core/src/com/unciv/ui/utils/UncivTooltip.kt @@ -183,10 +183,10 @@ class UncivTooltip ( ) { if (!(always || KeyCharAndCode.keyboardAvailable) || text.isEmpty()) return - val label = text.toLabel(ImageGetter.getBlue(), 38) + val label = text.toLabel(BaseScreen.skinStrings.skinConfig.baseColor, 38) label.setAlignment(Align.center) - val background = ImageGetter.getRoundedEdgeRectangle(Color.LIGHT_GRAY) + val background = BaseScreen.skinStrings.getUiBackground("General/Tooltip", BaseScreen.skinStrings.roundedEdgeRectangle, Color.LIGHT_GRAY) // This controls text positioning relative to the background. // The minute fiddling makes both single caps and longer text look centered. @Suppress("SpellCheckingInspection") diff --git a/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt b/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt index 85371e80bf..f7d96e563f 100644 --- a/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt +++ b/core/src/com/unciv/ui/utils/extensions/Scene2dExtensions.kt @@ -317,7 +317,7 @@ fun Actor.surroundWithCircle(size: Float, resizeActor: Boolean = true, color: Co fun Actor.addBorder(size:Float, color: Color, expandCell:Boolean = false): Table { val table = Table() table.pad(size) - table.background = ImageGetter.getBackground(color) + table.background = BaseScreen.skinStrings.getUiBackground("General/Border", tintColor = color) val cell = table.add(this) if (expandCell) cell.expand() cell.fill() diff --git a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt index ebe2dac719..80ced6a3d0 100644 --- a/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt +++ b/core/src/com/unciv/ui/victoryscreen/VictoryScreen.kt @@ -12,7 +12,6 @@ import com.unciv.models.translations.tr import com.unciv.ui.images.ImageGetter import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.pickerscreens.PickerScreen -import com.unciv.ui.utils.KeyCharAndCode import com.unciv.ui.utils.extensions.addSeparator import com.unciv.ui.utils.extensions.enable import com.unciv.ui.utils.extensions.onClick @@ -284,7 +283,7 @@ class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() { labelText = Constants.unknownNationName } - civGroup.background = ImageGetter.getRoundedEdgeRectangle(backgroundColor) + civGroup.background = skinStrings.getUiBackground("VictoryScreen/CivGroup", skinStrings.roundedEdgeRectangle, backgroundColor) val label = labelText.toLabel(labelColor) label.setAlignment(Align.center) diff --git a/core/src/com/unciv/ui/worldscreen/NotificationsScroll.kt b/core/src/com/unciv/ui/worldscreen/NotificationsScroll.kt index c31dc4a3b4..5c9b737e2c 100644 --- a/core/src/com/unciv/ui/worldscreen/NotificationsScroll.kt +++ b/core/src/com/unciv/ui/worldscreen/NotificationsScroll.kt @@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Cell import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.logic.civilization.Notification -import com.unciv.ui.images.ImageGetter +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.WrappableLabel import com.unciv.ui.utils.extensions.onClick import kotlin.math.min @@ -71,7 +71,7 @@ class NotificationsScroll( for (notification in notifications.asReversed().toList()) { // toList to avoid concurrency problems val listItem = Table() - listItem.background = ImageGetter.getRoundedEdgeRectangle() + listItem.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/Notification", BaseScreen.skinStrings.roundedEdgeRectangle) val labelWidth = maxEntryWidth - iconSize * notification.icons.size - 10f val label = WrappableLabel(notification.text, labelWidth, Color.BLACK, 30) diff --git a/core/src/com/unciv/ui/worldscreen/PlayerReadyScreen.kt b/core/src/com/unciv/ui/worldscreen/PlayerReadyScreen.kt index bceb242e39..155b403189 100644 --- a/core/src/com/unciv/ui/worldscreen/PlayerReadyScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/PlayerReadyScreen.kt @@ -14,7 +14,10 @@ class PlayerReadyScreen(worldScreen: WorldScreen) : BaseScreen() { val table = Table() table.touchable = Touchable.enabled val curCiv = worldScreen.viewingCiv - table.background = ImageGetter.getBackground(curCiv.nation.getOuterColor()) + table.background = skinStrings.getUiBackground( + "PlayerReadyScreen", + tintColor = curCiv.nation.getOuterColor() + ) table.add("[$curCiv] ready?".toLabel(curCiv.nation.getInnerColor(), Constants.headingFontSize)) diff --git a/core/src/com/unciv/ui/worldscreen/TechPolicyDiplomacyButtons.kt b/core/src/com/unciv/ui/worldscreen/TechPolicyDiplomacyButtons.kt index aa10fee1c4..663bdb2501 100644 --- a/core/src/com/unciv/ui/worldscreen/TechPolicyDiplomacyButtons.kt +++ b/core/src/com/unciv/ui/worldscreen/TechPolicyDiplomacyButtons.kt @@ -44,7 +44,7 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree add(espionageButtonHolder).padTop(10f) add().growX() // Allows Policy and Diplo buttons to keep to the left - pickTechButton.background = ImageGetter.getRoundedEdgeRectangle(colorFromRGB(7, 46, 43)) + pickTechButton.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/PickTechButton", BaseScreen.skinStrings.roundedEdgeRectangle, colorFromRGB(7, 46, 43)) pickTechButton.defaults().pad(20f) pickTechButton.add(pickTechLabel) techButtonHolder.onClick(UncivSound.Paper) { diff --git a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt index 8388c89520..9aed1b4554 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt @@ -38,6 +38,7 @@ import com.unciv.ui.map.TileGroupMap import com.unciv.ui.tilegroups.TileGroup import com.unciv.ui.tilegroups.TileSetStrings import com.unciv.ui.tilegroups.WorldTileGroup +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.utils.KeyCharAndCode import com.unciv.ui.utils.UnitGroup import com.unciv.ui.utils.ZoomableScrollPane @@ -443,7 +444,7 @@ class WorldMapHolder( val numberCircle = dto.unitToTurnsToDestination.values.maxOrNull()!!.toString().toLabel(fontSize = 14) .apply { setAlignment(Align.center) } - .surroundWithCircle(smallerCircleSizes-2, color = ImageGetter.getBlue().darken(0.3f)) + .surroundWithCircle(smallerCircleSizes-2, color = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.3f)) .surroundWithCircle(smallerCircleSizes,false) moveHereButton.addActor(numberCircle) diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index bda4966896..7bc4662c3f 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -31,7 +31,6 @@ import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.unique.UniqueType import com.unciv.ui.cityscreen.CityScreen import com.unciv.ui.civilopedia.CivilopediaScreen -import com.unciv.ui.images.ImageGetter import com.unciv.ui.overviewscreen.EmpireOverviewScreen import com.unciv.ui.pickerscreens.DiplomaticVotePickerScreen import com.unciv.ui.pickerscreens.DiplomaticVoteResultScreen @@ -126,8 +125,9 @@ class WorldScreen( private val notificationsScroll = NotificationsScroll(this) private val nextTurnButton = NextTurnButton() private val statusButtons = StatusButtons(nextTurnButton) - private val tutorialTaskTable = Table().apply { background = ImageGetter.getBackground( - ImageGetter.getBlue().darken(0.5f)) } + private val tutorialTaskTable = Table().apply { + background = skinStrings.getUiBackground("WorldScreen/TutorialTaskTable", tintColor = skinStrings.skinConfig.baseColor.darken(0.5f)) + } private var nextTurnUpdateJob: Job? = null diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt index 9c652abf6b..a1b1012dd0 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreenTopBar.kt @@ -75,16 +75,15 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() { init { // Not the Table, the Cells (all except one) have the background. To avoid gaps, _no_ // padding except inside the cell actors, and all actors need to _fill_ their cell. - val backColor = ImageGetter.getBlue().darken(0.5f) - val backgroundDrawable = ImageGetter.getBackground(backColor) - statsTable.background = backgroundDrawable - resourceTable.background = backgroundDrawable + val backColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + statsTable.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/TopBar/StatsTable", tintColor = backColor) + resourceTable.background = BaseScreen.skinStrings.getUiBackground("WorldScreen/TopBar/ResourceTable", tintColor = backColor) add(statsTable).colspan(3).growX().row() add(resourceTable).colspan(3).growX().row() - val leftFillerBG = ImageGetter.getRoundedEdgeRectangle(backColor) + val leftFillerBG = BaseScreen.skinStrings.getUiBackground("WorldScreen/TopBar/LeftAttachment", BaseScreen.skinStrings.roundedEdgeRectangle, backColor) leftFillerCell = add(BackgroundActor(leftFillerBG, Align.topLeft)) add().growX() - val rightFillerBG = ImageGetter.getRoundedEdgeRectangle(backColor) + val rightFillerBG = BaseScreen.skinStrings.getUiBackground("WorldScreen/TopBar/RightAttachment", BaseScreen.skinStrings.roundedEdgeRectangle, backColor) rightFillerCell = add(BackgroundActor(rightFillerBG, Align.topRight)) pack() } diff --git a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt index 6ffe01d851..79e4ba1dac 100644 --- a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt +++ b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt @@ -38,7 +38,10 @@ class BattleTable(val worldScreen: WorldScreen): Table() { init { isVisible = false skin = BaseScreen.skin - background = ImageGetter.getBackground(ImageGetter.getBlue().apply { a = 0.8f }) + background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/BattleTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.apply { a = 0.8f } + ) defaults().pad(5f) pad(5f) diff --git a/core/src/com/unciv/ui/worldscreen/bottombar/TileInfoTable.kt b/core/src/com/unciv/ui/worldscreen/bottombar/TileInfoTable.kt index f94eeff497..9b2d7602c2 100644 --- a/core/src/com/unciv/ui/worldscreen/bottombar/TileInfoTable.kt +++ b/core/src/com/unciv/ui/worldscreen/bottombar/TileInfoTable.kt @@ -17,7 +17,10 @@ import com.unciv.ui.utils.extensions.toLabel class TileInfoTable(private val viewingCiv :CivilizationInfo) : Table(BaseScreen.skin) { init { - background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/TileInfoTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) } internal fun updateTileTable(tile: TileInfo?) { diff --git a/core/src/com/unciv/ui/worldscreen/minimap/MinimapHolder.kt b/core/src/com/unciv/ui/worldscreen/minimap/MinimapHolder.kt index ef8d9a0aa0..53caf2b821 100644 --- a/core/src/com/unciv/ui/worldscreen/minimap/MinimapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/minimap/MinimapHolder.kt @@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.Align import com.unciv.UncivGame import com.unciv.logic.civilization.CivilizationInfo import com.unciv.ui.images.ImageGetter +import com.unciv.ui.utils.BaseScreen import com.unciv.ui.worldscreen.WorldMapHolder class MinimapHolder(val mapHolder: WorldMapHolder) : Table() { @@ -62,12 +63,18 @@ class MinimapHolder(val mapHolder: WorldMapHolder) : Table() { val internalMinimapWrapper = Table() internalMinimapWrapper.add(minimap) - internalMinimapWrapper.background = ImageGetter.getBackground(Color.GRAY) + internalMinimapWrapper.background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/Minimap/Background", + tintColor = Color.GRAY + ) internalMinimapWrapper.pack() val externalMinimapWrapper = Table() externalMinimapWrapper.add(internalMinimapWrapper).pad(5f) - externalMinimapWrapper.background = ImageGetter.getBackground(Color.WHITE) + externalMinimapWrapper.background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/Minimap/Border", + tintColor = Color.WHITE + ) externalMinimapWrapper.pack() return externalMinimapWrapper diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt index 881776ad6a..47cf53aa9a 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt @@ -6,16 +6,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.unciv.UncivGame import com.unciv.logic.map.MapUnit import com.unciv.models.UnitAction -import com.unciv.ui.audio.SoundPlayer import com.unciv.ui.images.IconTextButton import com.unciv.ui.utils.KeyCharAndCode import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip import com.unciv.ui.utils.extensions.disable import com.unciv.ui.utils.extensions.keyShortcuts import com.unciv.ui.utils.extensions.onActivation -import com.unciv.ui.utils.extensions.onClick import com.unciv.ui.worldscreen.WorldScreen -import com.unciv.utils.concurrency.Concurrency class UnitActionsTable(val worldScreen: WorldScreen) : Table() { diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt index dda8589b36..4965afdfc9 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitTable.kt @@ -7,7 +7,6 @@ import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup import com.unciv.Constants -import com.unciv.UncivGame import com.unciv.logic.battle.CityCombatant import com.unciv.logic.city.CityInfo import com.unciv.logic.map.MapUnit @@ -65,7 +64,10 @@ class UnitTable(val worldScreen: WorldScreen) : Table() { init { pad(5f) touchable = Touchable.enabled - background = ImageGetter.getBackground(ImageGetter.getBlue().darken(0.5f)) + background = BaseScreen.skinStrings.getUiBackground( + "WorldScreen/UnitTable", + tintColor = BaseScreen.skinStrings.skinConfig.baseColor.darken(0.5f) + ) promotionsTable.touchable = Touchable.enabled diff --git a/docs/Modders/Creating-a-UI-skin.md b/docs/Modders/Creating-a-UI-skin.md new file mode 100644 index 0000000000..cfb39db640 --- /dev/null +++ b/docs/Modders/Creating-a-UI-skin.md @@ -0,0 +1,150 @@ +# How to create a UI skin for Unciv + +**You should read the [Mods](Mods.md) page first before proceeding** + +In order to add a UI skin mod (yes, UI skins are just another type of mod), all you need to do is add your images under `Images/Skins/MyCoolSkinExample` and enable the mod as a permanent visual mod - the game will recognize the skin, and allow you to pick it in the options menu. + +Just like [tilesets](Creating-a-custom-tileset.md), UI skins can be used to alter the appearance of Unciv. Please note that UI skins do not support custom icons and fonts and not every UI element can be customized yet too. + +We use so called 9.png (or Ninepatch) files for every skin image because UI elements need a way to be resized based on game window size and resolution. Ninepatch files can be created manually by adding black pixels around your custom images in a specific manner or by using [Android Studio's Draw 9-patch tool](https://developer.android.com/studio/write/draw9patch) or [this tool by romannurik](https://romannurik.github.io/AndroidAssetStudio/nine-patches.html) for example. You may also check if your favorite image creation tool supports nine patches itself to generate them more easily. + +Every skin image needs to be **gray scale** since colors are applied later in game. The color for the image can be modified using the [skinConfig](Creating-a-UI-skin.md#tint). Please note that tileable ninepatches and ninepatches with multiple stretch areas are not supported because of technical restrictions by libgdx. + +There are 6 basic shapes which can be placed inside the `Images/Skins/MyCoolSkinExample` folder: + - checkbox + - checkbox-pressed + - rectangleWithOutline + - roundedEdgeRectangle + - select-box + - select-box-pressed + +These shapes are used all over Unciv and can be replaced to make a lot of UI elements change appearance at once. To change just one specific element use the [table](Creating-a-UI-skin.md#Available-UI-elements) below to create an image at the specified directory using the specified name inside `Images/Skins/MyCoolSkinExample`. See the image below for an example file structure. ![skinExample](https://user-images.githubusercontent.com/24532072/198904598-0d298035-5b02-431b-bfb4-7da4b9c821c9.png) + +## Available UI elements + + + +| Directory | Name | Default shape | Image | +|---|:---:|:---:|---| +| CivilopediaScreen/ | EntryButton | null | | +| CityScreen/CityConstructionTable/ | AvailableConstructionsTable | null | | +| CityScreen/CityConstructionTable/ | ConstructionsQueueTable | null | | +| CityScreen/CityConstructionTable/ | Header | null | | +| CityScreen/CityConstructionTable/ | PickConstructionButton | null | | +| CityScreen/CityConstructionTable/ | QueueEntry | null | | +| CityScreen/ | CityInfoTable | null | | +| CityScreen/CitizenManagementTable/ | AvoidCell | null | | +| CityScreen/CitizenManagementTable/ | FocusCell | null | | +| CityScreen/CitizenManagementTable/ | ResetCell | null | | +| CityScreen/ | CityPickerTable | roundedEdgeRectangle | | +| CityScreen/CityScreenTileTable/ | Background | null | | +| CityScreen/CityScreenTileTable/ | InnerTable | null | | +| CityScreen/CityStatsTable/ | Background | null | | +| CityScreen/CityStatsTable/ | InnerTable | null | | +| CityScreen/ConstructionInfoTable/ | Background | null | | +| CityScreen/ConstructionInfoTable/ | SelectedConstructionTable | null | | +| General/ | Border | null | | +| General/ | ExpanderTab | null | | +| General/ | HealthBar | null | | +| General/ | TabbedPager | null | | +| General/ | Tooltip | roundedEdgeRectangle | | +| General/Popup/ | Background | null | | +| General/Popup/ | InnerTable | null | | +| LanguagePickerScreen/ | LanguageTable | null | | +| MainMenuScreen/ | MenuButton | roundedEdgeRectangle | | +| MapEditor/MapEditorToolsDrawer/ | Handle | null | | +| ModManagementOptions/ | ExpanderTab | null | | +| NewGameScreen/NationTable/ | Background | null | | +| NewGameScreen/NationTable/ | BorderTable | null | | +| NewGameScreen/NationTable/ | InnerTable | null | | +| NewGameScreen/NationTable/ | Title | null | | +| NewGameScreen/PlayerPickerTable/ | PlayerTable | null | | +| OverviewScreen/DiplomacyOverviewTab/ | CivTable | null | | +| OverviewScreen/NotificationOverviewTable/ | Notification | roundedEdgeRectangle | | +| OverviewScreen/ReligionOverviewTab/ | BeliefDescription | null | | +| OverviewScreen/TradesOverviewTab/ | OffersTable | null | | +| OverviewScreen/UnitOverviewTab/ | UnitSupplyTable | null | | +| TechPickerScreen/ | TechButton | roundedEdgeRectangle | | +| VictoryScreen/ | CivGroup | roundedEdgeRectangle | | +| WorldScreen/ | AirUnitTable | null | | +| WorldScreen/CityButton/ | AirUnitTable | roundedEdgeRectangle | | +| WorldScreen/CityButton/ | IconTable | roundedEdgeRectangle | | +| WorldScreen/CityButton/ | InfluenceBar | null | | +| WorldScreen/ | Notification | null | | +| WorldScreen/ | PickTechButton | roundedEdgeRectangle | | +| WorldScreen/ | TutorialTaskTable | null | | +| WorldScreen/TopBar/ | ResourceTable | null | | +| WorldScreen/TopBar/ | StatsTable | null | | +| WorldScreen/TopBar/ | LeftAttachment | roundedEdgeRectangle | | +| WorldScreen/TopBar/ | RightAttachment | roundedEdgeRectangle | | +| WorldScreen/ | BattleTable | null | | +| WorldScreen/ | TileInfoTable | null | | +| WorldScreen/Minimap/ | Background | null | | +| WorldScreen/Minimap/ | Border | null | | +| WorldScreen/ | UnitTable | null | | + +## SkinConfig + +The skinConfig is similar to the [tilesetConfig](Creating-a-custom-tileset.md#tileset-config) and can be used to define different colors and shapes for unciv to use. + +To create a config for your skin you just need to create a new .json file under `Jsons/Skins/`. Just create a .txt file and rename it to MyCoolSkinExample.json. You only have to add things if you want to change them. Else the default values will be used. + +This is an example of such a config file that will be explain below: + +```json + "baseColor": {"r":1,"g":0,"b":0,"a":1}, + "skinVariants": { + "MainMenuScreen/MenuButton": { + "image": "MyCoolNewDesign", + }, + "TechPickerScreen/TechButton": { + "image": "MyCoolNewDesign", + "alpha": 0.7 + }, + "WorldScreen/TopBar/ResourceTable": { + "alpha": 0.8 + }, + "WorldScreen/UnitTable": { + "tint": {"r": 1, "g": 0, "b": 0}, + "image": "WorldScreen/TopBar/ResourceTable", + "alpha": 0.4 + }, + "WorldScreen/Minimap/Background": { + "tint": {"r": 0.2, "g": 0.4, "b": 0.45, "a": 1} + }, + } +``` + +### baseColor + +A color defined with normalized RGBA values. Default value: "{"r": 0, "g": 0.251, "b": 0.522, "a": 0.749}" + +Defines the color unciv uses in most ui elements as default + +### skinVariants + +A dictionary mapping string to a SkinElement. Default value: empty + +These variants can be used to define a different image, tint and/or alpha for a specified UI element. The string used to identify the UI element can be taken from the [table](Creating-a-UI-skin.md#Available-UI-elements) above by appending the name to the directory. +``` +| Directory | Name | +|-----------------------|---------------| +| WorldScreen/ | Notification | -> WorldScreen/Notification +| WorldScreen/TopBar/ | StatsTable | -> WorldScreen/TopBar/StatsTable +``` + +#### image + +A path to an image. The file is expected to be located alongside the 6 basic shapes inside the `Images/Skins/MyCoolSkinExample` folder if just a name like `MyCoolNewDesign` is given. The image path can also be another ui element like `WorldScreen/TopBar/ResourceTable` so images can be reused by other elements. + +#### tint + +A color defined with normalized RGBA values. Default value: null + +The color this UI element should have. + +#### alpha + +A float value. Default value: null + +The alpha this UI element should have. Overwrites the alpha value of tint if specified. diff --git a/tests/src/com/unciv/dev/FasterUIDevelopment.kt b/tests/src/com/unciv/dev/FasterUIDevelopment.kt index 5b026911ee..494f2f5884 100644 --- a/tests/src/com/unciv/dev/FasterUIDevelopment.kt +++ b/tests/src/com/unciv/dev/FasterUIDevelopment.kt @@ -105,7 +105,7 @@ object FasterUIDevelopment { } private var curBorderZ = 0 fun addBorder(actor: Actor, color: Color) { - val border = ImageWithCustomSize(ImageGetter.getBackground(color)) + val border = ImageWithCustomSize(skinStrings.getUiBackground("", tintColor = color)) border.zIndex = curBorderZ++ val stageCoords = actor.localToStageCoordinates(Vector2(0f, 0f)) border.x = stageCoords.x - 1 @@ -114,7 +114,7 @@ object FasterUIDevelopment { border.height = actor.height + 2 stage.addActor(border) - val background = ImageWithCustomSize(ImageGetter.getBackground(clearColor)) + val background = ImageWithCustomSize(skinStrings.getUiBackground("", tintColor = clearColor)) background.zIndex = curBorderZ++ background.x = stageCoords.x background.y = stageCoords.y