mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-12 08:49:22 +07:00
Added more options for UI skin mods (#12501)
* Add fallback skin to skin config * Add icon and font color to SkinElement * Use foregroundColor if no icon color is specified + Fix fallbackSkinVariants are not used * Add defaultVariantTint to reduce mod copy pasta * Add docs for new skin variables
This commit is contained in:
@ -107,6 +107,7 @@ object Constants {
|
||||
const val defaultFallbackTileset = "FantasyHex"
|
||||
const val defaultUnitset = "AbsoluteUnits"
|
||||
const val defaultSkin = "Minimal"
|
||||
const val defaultFallbackSkin = "Minimal"
|
||||
|
||||
/**
|
||||
* Use this to determine whether a [MapUnit][com.unciv.logic.map.mapunit.MapUnit]'s movement is exhausted
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.unciv.models.skins
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.Constants
|
||||
|
||||
class SkinConfig(initialCapacity: Int) {
|
||||
var baseColor: Color = Color(0x004085bf)
|
||||
var clearColor: Color = Color(0x000033ff)
|
||||
var defaultVariantTint: Color? = null
|
||||
var fallbackSkin: String? = Constants.defaultFallbackSkin
|
||||
var skinVariants: HashMap<String, SkinElement> = HashMap(initialCapacity)
|
||||
|
||||
constructor() : this(16) // = HashMap.DEFAULT_INITIAL_CAPACITY which is private
|
||||
@ -16,17 +19,22 @@ class SkinConfig(initialCapacity: Int) {
|
||||
val image: String? = null
|
||||
val tint: Color? = null
|
||||
val alpha: Float? = null
|
||||
val foregroundColor: Color? = null
|
||||
val iconColor: Color? = null
|
||||
}
|
||||
|
||||
fun clone() = SkinConfig(skinVariants.size).also { it.updateConfig(this) }
|
||||
|
||||
/** 'Merges' [other] into **`this`**
|
||||
*
|
||||
* [baseColor] and [clearColor] are overwritten with clones from [other].
|
||||
* [baseColor], [clearColor], and [defaultVariantTint] are overwritten with clones from [other].
|
||||
* [fallbackSkin] is overwritten with [other]'s value.
|
||||
* [skinVariants] with the same key are copied and overwritten, new [skinVariants] are added. */
|
||||
fun updateConfig(other: SkinConfig) {
|
||||
baseColor = other.baseColor.cpy()
|
||||
clearColor = other.clearColor.cpy()
|
||||
defaultVariantTint = other.defaultVariantTint?.cpy()
|
||||
fallbackSkin = other.fallbackSkin
|
||||
skinVariants.putAll(other.skinVariants)
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,21 @@ import com.unciv.ui.images.ImageGetter
|
||||
class SkinStrings(skin: String = UncivGame.Current.settings.skin) {
|
||||
private val skinLocation = "Skins/$skin/"
|
||||
val skinConfig = SkinCache[skin] ?: SkinConfig()
|
||||
private val fallbackSkinLocation = if (skinConfig.fallbackSkin != null) "Skins/${skinConfig.fallbackSkin}/" else null
|
||||
private val fallbackSkinConfig = SkinCache[skinConfig.fallbackSkin]
|
||||
|
||||
// Default shapes must always end with "Shape" so the UiElementDocsWriter can identify them
|
||||
val roundedEdgeRectangleSmallShape = skinLocation + "roundedEdgeRectangle-small"
|
||||
val roundedTopEdgeRectangleSmallShape = skinLocation + "roundedTopEdgeRectangle-small"
|
||||
val roundedTopEdgeRectangleSmallBorderShape = skinLocation + "roundedTopEdgeRectangle-small-border"
|
||||
val roundedEdgeRectangleMidShape = skinLocation + "roundedEdgeRectangle-mid"
|
||||
val roundedEdgeRectangleMidBorderShape = skinLocation + "roundedEdgeRectangle-mid-border"
|
||||
val roundedEdgeRectangleShape = skinLocation + "roundedEdgeRectangle"
|
||||
val rectangleWithOutlineShape = skinLocation + "rectangleWithOutline"
|
||||
val selectBoxShape = skinLocation + "select-box"
|
||||
val selectBoxPressedShape = skinLocation + "select-box-pressed"
|
||||
val checkboxShape = skinLocation + "checkbox"
|
||||
val checkboxPressedShape = skinLocation + "checkbox-pressed"
|
||||
val roundedEdgeRectangleSmallShape = "roundedEdgeRectangle-small"
|
||||
val roundedTopEdgeRectangleSmallShape = "roundedTopEdgeRectangle-small"
|
||||
val roundedTopEdgeRectangleSmallBorderShape = "roundedTopEdgeRectangle-small-border"
|
||||
val roundedEdgeRectangleMidShape = "roundedEdgeRectangle-mid"
|
||||
val roundedEdgeRectangleMidBorderShape = "roundedEdgeRectangle-mid-border"
|
||||
val roundedEdgeRectangleShape = "roundedEdgeRectangle"
|
||||
val rectangleWithOutlineShape = "rectangleWithOutline"
|
||||
val selectBoxShape = "select-box"
|
||||
val selectBoxPressedShape = "select-box-pressed"
|
||||
val checkboxShape = "checkbox"
|
||||
val checkboxPressedShape = "checkbox-pressed"
|
||||
|
||||
/**
|
||||
* Gets either a drawable which was defined inside skinConfig for the given path or the drawable
|
||||
@ -46,27 +48,64 @@ class SkinStrings(skin: String = UncivGame.Current.settings.skin) {
|
||||
* separate alpha value, it will be applied to a clone of either color.
|
||||
*/
|
||||
fun getUiBackground(path: String, default: String? = null, tintColor: Color? = null): NinePatchDrawable {
|
||||
val locationForDefault = skinLocation + default
|
||||
val locationByName = skinLocation + path
|
||||
val skinVariant = skinConfig.skinVariants[path]
|
||||
val locationByConfigVariant = if (skinVariant?.image != null) skinLocation + skinVariant.image else null
|
||||
val tint = (skinVariant?.tint ?: tintColor)?.run {
|
||||
val tint = (skinVariant?.tint ?: skinConfig.defaultVariantTint ?: tintColor)?.run {
|
||||
if (skinVariant?.alpha == null) this
|
||||
else cpy().apply { a = skinVariant.alpha }
|
||||
}
|
||||
|
||||
val location = when {
|
||||
locationByConfigVariant != null && ImageGetter.ninePatchImageExists(locationByConfigVariant) ->
|
||||
locationByConfigVariant
|
||||
ImageGetter.ninePatchImageExists(locationByName) ->
|
||||
locationByName
|
||||
default != null && ImageGetter.ninePatchImageExists(locationForDefault) ->
|
||||
locationForDefault
|
||||
else ->
|
||||
default
|
||||
null
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
return ImageGetter.getNinePatch(location, tint)
|
||||
}
|
||||
|
||||
val fallbackLocationForDefault = fallbackSkinLocation + default
|
||||
val fallbackLocationByName = fallbackSkinLocation + path
|
||||
val fallbackSkinVariant = fallbackSkinConfig?.skinVariants?.get(path)
|
||||
val fallbackLocationByConfigVariant = if (fallbackSkinVariant?.image != null)
|
||||
fallbackSkinLocation + fallbackSkinVariant.image
|
||||
else
|
||||
null
|
||||
val fallbackTint = (fallbackSkinVariant?.tint ?: tintColor)?.run {
|
||||
if (fallbackSkinVariant?.alpha == null) this
|
||||
else cpy().apply { a = fallbackSkinVariant.alpha }
|
||||
}
|
||||
|
||||
val fallbackLocation = when {
|
||||
fallbackLocationByConfigVariant != null && ImageGetter.ninePatchImageExists(fallbackLocationByConfigVariant) ->
|
||||
fallbackLocationByConfigVariant
|
||||
ImageGetter.ninePatchImageExists(fallbackLocationByName) ->
|
||||
fallbackLocationByName
|
||||
default != null && ImageGetter.ninePatchImageExists(fallbackLocationForDefault) ->
|
||||
fallbackLocationForDefault
|
||||
else ->
|
||||
null
|
||||
}
|
||||
return ImageGetter.getNinePatch(fallbackLocation, fallbackTint)
|
||||
}
|
||||
|
||||
fun getUIColor(path: String, default: Color? = null) =
|
||||
skinConfig.skinVariants[path]?.tint
|
||||
?: default
|
||||
?: skinConfig.clearColor
|
||||
|
||||
|
||||
fun getUIFontColor(path: String) = skinConfig.skinVariants[path]?.foregroundColor
|
||||
|
||||
fun getUIIconColor(path: String) =
|
||||
skinConfig.skinVariants[path]?.iconColor ?: skinConfig.skinVariants[path]?.foregroundColor
|
||||
|
||||
}
|
||||
|
@ -111,6 +111,8 @@ object ImageGetter {
|
||||
}
|
||||
for (region in tempAtlas.regions) {
|
||||
if (region.name.startsWith("Skins")) {
|
||||
// TODO: give user a mod warning that the image names has to be [name].9.png
|
||||
// if this throws an exception
|
||||
val ninePatch = tempAtlas.createPatch(region.name)
|
||||
ninePatchDrawables[region.name] = NinePatchDrawable(ninePatch)
|
||||
} else {
|
||||
@ -213,7 +215,8 @@ object ImageGetter {
|
||||
fun getExternalImage(fileName: String) =
|
||||
getExternalImage(Gdx.files.internal("ExtraImages/$fileName"))
|
||||
|
||||
fun getImage(fileName: String?): Image = ImageWithCustomSize(getDrawable(fileName))
|
||||
fun getImage(fileName: String?, tintColor: Color? = null): Image =
|
||||
ImageWithCustomSize(getDrawable(fileName)).apply { color = tintColor ?: Color.WHITE }
|
||||
|
||||
fun getDrawable(fileName: String?): TextureRegionDrawable =
|
||||
textureRegionDrawables[fileName] ?: textureRegionDrawables[whiteDotLocation]!!
|
||||
|
@ -169,9 +169,12 @@ This is an example of such a config file that will be explain below:
|
||||
```json
|
||||
{
|
||||
"baseColor": {"r":1,"g":0,"b":0,"a":1},
|
||||
"defaultVariantTint": {"r":1,"g":1,"b":1,"a":1},
|
||||
"skinVariants": {
|
||||
"MainMenuScreen/MenuButton": {
|
||||
"image": "MyCoolNewDesign"
|
||||
"image": "MyCoolNewDesign",
|
||||
"foregroundColor": {"r": 0, "g": 0, "b": 1, "a": 1},
|
||||
"iconColor": {"r": 0, "g": 1, "b": 0, "a": 1}
|
||||
},
|
||||
"TechPickerScreen/TechButton": {
|
||||
"image": "MyCoolNewDesign",
|
||||
@ -198,6 +201,21 @@ A color defined with normalized RGBA values. Default value: `{"r": 0, "g": 0.251
|
||||
|
||||
Defines the color unciv uses in most ui elements as default
|
||||
|
||||
### fallbackSkin
|
||||
|
||||
A string. Default value: "Minimal".
|
||||
|
||||
The name of another skin to use as a fallback if an image is not found or not specified in this skin.
|
||||
Set to null to disable fallback.
|
||||
|
||||
### defaultVariantTint
|
||||
|
||||
A color defined with normalized RGBA values. Default value: null
|
||||
|
||||
The tint all skinVariants should use if not explicitly specified in a skinVariant.
|
||||
If you mostly use colored images set this to white (`{"r": 1, "g": 1, "b": 1, "a": 1}`) to get
|
||||
the correct colors.
|
||||
|
||||
### skinVariants
|
||||
|
||||
A dictionary mapping string to a SkinElement. Default value: empty
|
||||
@ -218,10 +236,24 @@ A path to an image. The file is expected to be located alongside the 6 basic sha
|
||||
|
||||
A color defined with normalized RGBA values. Default value: null
|
||||
|
||||
The color this UI element should have.
|
||||
The tint this UI element should get. Is applied as a tint on top of the image. This means that if the
|
||||
image is colored and the tint is not white the tint color will merge with the image color and not override it.
|
||||
|
||||
#### alpha
|
||||
|
||||
A float value. Default value: null
|
||||
|
||||
The alpha this UI element should have. Overwrites the alpha value of tint if specified.
|
||||
|
||||
### foregroundColor
|
||||
|
||||
A color defined with normalized RGBA values. Default value: null
|
||||
|
||||
The color this UI element should use for its font and icons. To color icon and font differently use
|
||||
the `iconColor` in addition to this.
|
||||
|
||||
### iconColor
|
||||
|
||||
A color defined with normalized RGBA values. Default value: null
|
||||
|
||||
The color this UI element should use for its icons. Overrides the `foregroundColor` for icons if specified.
|
Reference in New Issue
Block a user