fix leaf block & leaf particle colors
This commit is contained in:
@@ -70,6 +70,8 @@ data class Color(val alpha: Int, val red: Int, val green: Int, val blue: Int) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val asInt get() = (alpha shl 24) or (red shl 16) or (green shl 8) or blue
|
val asInt get() = (alpha shl 24) or (red shl 16) or (green shl 8) or blue
|
||||||
|
val asHSB get() = HSB.fromColor(this)
|
||||||
|
|
||||||
operator fun times(f: Float) = Color(
|
operator fun times(f: Float) = Color(
|
||||||
alpha,
|
alpha,
|
||||||
(f * red.toFloat()).toInt().coerceIn(0 until 256),
|
(f * red.toFloat()).toInt().coerceIn(0 until 256),
|
||||||
@@ -93,6 +95,10 @@ data class HSB(var hue: Float, var saturation: Float, var brightness: Float) {
|
|||||||
val hsbVals = java.awt.Color.RGBtoHSB((color shr 16) and 255, (color shr 8) and 255, color and 255, null)
|
val hsbVals = java.awt.Color.RGBtoHSB((color shr 16) and 255, (color shr 8) and 255, color and 255, null)
|
||||||
return HSB(hsbVals[0], hsbVals[1], hsbVals[2])
|
return HSB(hsbVals[0], hsbVals[1], hsbVals[2])
|
||||||
}
|
}
|
||||||
|
fun fromColor(color: Color): HSB {
|
||||||
|
val hsbVals = java.awt.Color.RGBtoHSB(color.red, color.green, color.blue, null)
|
||||||
|
return HSB(hsbVals[0], hsbVals[1], hsbVals[2])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val asInt: Int get() = java.awt.Color.HSBtoRGB(hue, saturation, brightness)
|
val asInt: Int get() = java.awt.Color.HSBtoRGB(hue, saturation, brightness)
|
||||||
val asColor: Color get() = Color(asInt)
|
val asColor: Color get() = Color(asInt)
|
||||||
|
|||||||
@@ -84,20 +84,20 @@ fun crossModelsRaw(num: Int, size: Double, hOffset: Double, vOffset: Double): Li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun crossModelSingle(base: List<Quad>, sprite: TextureAtlasSprite, tintIndex: Int,scrambleUV: Boolean) =
|
fun crossModelSingle(base: List<Quad>, sprite: TextureAtlasSprite, color: Color, tint: Int, scrambleUV: Boolean) =
|
||||||
base.map { if (scrambleUV) it.scrambleUV(random, canFlipU = true, canFlipV = true, canRotate = true) else it }
|
base.map { if (scrambleUV) it.scrambleUV(random, canFlipU = true, canFlipV = true, canRotate = true) else it }
|
||||||
.map { it.colorIndex(tintIndex) }
|
.map { it.color(color).colorIndex(tint) }
|
||||||
.mapIndexed { idx, quad -> quad.sprite(sprite) }
|
.mapIndexed { idx, quad -> quad.sprite(sprite) }
|
||||||
.withOpposites()
|
.withOpposites()
|
||||||
.bake(false)
|
.bake(false)
|
||||||
|
|
||||||
fun crossModelsTextured(
|
fun crossModelsTextured(
|
||||||
leafBase: Iterable<List<Quad>>,
|
leafBase: Iterable<List<Quad>>,
|
||||||
tintIndex: Int,
|
color: Color, tint: Int,
|
||||||
scrambleUV: Boolean,
|
scrambleUV: Boolean,
|
||||||
spriteGetter: (Int) -> ResourceLocation
|
spriteGetter: (Int) -> ResourceLocation
|
||||||
) = leafBase.mapIndexed { idx, leaf ->
|
) = leafBase.mapIndexed { idx, leaf ->
|
||||||
crossModelSingle(leaf, Atlas.BLOCKS[spriteGetter(idx)], tintIndex, scrambleUV)
|
crossModelSingle(leaf, Atlas.BLOCKS[spriteGetter(idx)], color, tint, scrambleUV)
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
fun Iterable<Quad>.withOpposites() = flatMap { listOf(it, it.flipped) }
|
fun Iterable<Quad>.withOpposites() = flatMap { listOf(it, it.flipped) }
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class StandardCactusModel(
|
|||||||
crossModelsRaw(64, config.size, 0.0, 0.0)
|
crossModelsRaw(64, config.size, 0.0, 0.0)
|
||||||
.transform { rotateZ(randomD(-config.sizeVariation, config.sizeVariation)) }
|
.transform { rotateZ(randomD(-config.sizeVariation, config.sizeVariation)) }
|
||||||
}
|
}
|
||||||
crossModelsTextured(models, -1, true) { cactusCrossSprite }
|
crossModelsTextured(models, Color.white, -1, true) { cactusCrossSprite }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,19 +28,24 @@ import mods.betterfoliage.util.averageHSB
|
|||||||
import mods.betterfoliage.util.idxOrNull
|
import mods.betterfoliage.util.idxOrNull
|
||||||
import mods.betterfoliage.util.lazy
|
import mods.betterfoliage.util.lazy
|
||||||
import mods.betterfoliage.util.lazyMap
|
import mods.betterfoliage.util.lazyMap
|
||||||
import mods.betterfoliage.util.lighten
|
import mods.betterfoliage.util.brighten
|
||||||
|
import mods.betterfoliage.util.logTextureColor
|
||||||
import mods.betterfoliage.util.randomI
|
import mods.betterfoliage.util.randomI
|
||||||
import net.minecraft.client.renderer.RenderType
|
import net.minecraft.client.renderer.RenderType
|
||||||
import net.minecraft.util.Direction.DOWN
|
import net.minecraft.util.Direction.DOWN
|
||||||
import net.minecraft.util.Direction.UP
|
import net.minecraft.util.Direction.UP
|
||||||
import net.minecraft.util.ResourceLocation
|
import net.minecraft.util.ResourceLocation
|
||||||
|
import org.apache.logging.log4j.Level.INFO
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
object StandardGrassDiscovery : ParametrizedModelDiscovery() {
|
object StandardGrassDiscovery : ParametrizedModelDiscovery() {
|
||||||
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
||||||
val texture = params.location("texture") ?: return
|
val texture = params.location("texture") ?: return
|
||||||
val tint = params.int("tint") ?: -1
|
val tint = params.int("tint") ?: -1
|
||||||
val color = Atlas.BLOCKS.file(texture).averageHSB.lighten()
|
val color = Atlas.BLOCKS.file(texture).averageHSB.let {
|
||||||
|
detailLogger.logTextureColor(INFO, "grass texture \"$texture\"", it)
|
||||||
|
it.brighten().asColor
|
||||||
|
}
|
||||||
ctx.addReplacement(StandardGrassKey(texture, tint, color))
|
ctx.addReplacement(StandardGrassKey(texture, tint, color))
|
||||||
BetterFoliage.blockTypes.grass.add(ctx.blockState)
|
BetterFoliage.blockTypes.grass.add(ctx.blockState)
|
||||||
ctx.blockState.block.extendLayers()
|
ctx.blockState.block.extendLayers()
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
|
|||||||
import mods.betterfoliage.resource.discovery.ParametrizedModelDiscovery
|
import mods.betterfoliage.resource.discovery.ParametrizedModelDiscovery
|
||||||
import mods.betterfoliage.resource.generated.GeneratedLeafSprite
|
import mods.betterfoliage.resource.generated.GeneratedLeafSprite
|
||||||
import mods.betterfoliage.util.Atlas
|
import mods.betterfoliage.util.Atlas
|
||||||
|
import mods.betterfoliage.util.averageHSB
|
||||||
|
import mods.betterfoliage.util.lazy
|
||||||
import mods.betterfoliage.util.lazyMap
|
import mods.betterfoliage.util.lazyMap
|
||||||
import mods.betterfoliage.util.logColorOverride
|
import mods.betterfoliage.util.brighten
|
||||||
|
import mods.betterfoliage.util.logTextureColor
|
||||||
|
import mods.betterfoliage.util.saturate
|
||||||
import net.minecraft.client.renderer.RenderType
|
import net.minecraft.client.renderer.RenderType
|
||||||
import net.minecraft.util.Direction.UP
|
import net.minecraft.util.Direction.UP
|
||||||
import net.minecraft.util.ResourceLocation
|
import net.minecraft.util.ResourceLocation
|
||||||
@@ -31,14 +35,19 @@ import org.apache.logging.log4j.Level.INFO
|
|||||||
|
|
||||||
object StandardLeafDiscovery : ParametrizedModelDiscovery() {
|
object StandardLeafDiscovery : ParametrizedModelDiscovery() {
|
||||||
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
||||||
val leafSprite = params.location("texture-leaf") ?: return
|
val texture = params.location("texture") ?: return
|
||||||
val leafType = LeafParticleRegistry.typeMappings.getType(leafSprite) ?: "default"
|
val tint = params.int("tint") ?: -1
|
||||||
val generated = GeneratedLeafSprite(leafSprite, leafType)
|
val color = Atlas.BLOCKS.file(texture).averageHSB.let {
|
||||||
|
detailLogger.logTextureColor(INFO, "leaf texture \"$texture\"", it)
|
||||||
|
it.brighten().asColor
|
||||||
|
}
|
||||||
|
val leafType = LeafParticleRegistry.typeMappings.getType(texture) ?: "default"
|
||||||
|
val generated = GeneratedLeafSprite(texture, leafType)
|
||||||
.register(BetterFoliage.generatedPack)
|
.register(BetterFoliage.generatedPack)
|
||||||
.apply { ctx.sprites.add(this) }
|
.apply { ctx.sprites.add(this) }
|
||||||
|
|
||||||
detailLogger.log(INFO, " particle $leafType")
|
detailLogger.log(INFO, " particle $leafType")
|
||||||
ctx.addReplacement(StandardLeafKey(generated, leafType, null))
|
ctx.addReplacement(StandardLeafKey(generated, leafType, tint, color))
|
||||||
BetterFoliage.blockTypes.leaf.add(ctx.blockState)
|
BetterFoliage.blockTypes.leaf.add(ctx.blockState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,10 +55,9 @@ object StandardLeafDiscovery : ParametrizedModelDiscovery() {
|
|||||||
data class StandardLeafKey(
|
data class StandardLeafKey(
|
||||||
val roundLeafTexture: ResourceLocation,
|
val roundLeafTexture: ResourceLocation,
|
||||||
override val leafType: String,
|
override val leafType: String,
|
||||||
override val overrideColor: Color?
|
override val tintIndex: Int,
|
||||||
|
override val avgColor: Color
|
||||||
) : HalfBakedWrapperKey(), LeafParticleKey {
|
) : HalfBakedWrapperKey(), LeafParticleKey {
|
||||||
val tintIndex: Int get() = if (overrideColor == null) 0 else -1
|
|
||||||
|
|
||||||
override fun bake(ctx: ModelBakingContext, wrapped: SpecialRenderModel): SpecialRenderModel {
|
override fun bake(ctx: ModelBakingContext, wrapped: SpecialRenderModel): SpecialRenderModel {
|
||||||
return StandardLeafModel(wrapped, this)
|
return StandardLeafModel(wrapped, this)
|
||||||
}
|
}
|
||||||
@@ -78,14 +86,16 @@ class StandardLeafModel(
|
|||||||
val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
|
val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
|
||||||
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_leaves_snowed_$idx")
|
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_leaves_snowed_$idx")
|
||||||
}
|
}
|
||||||
val leafModelsBase = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
|
val leafModelsBase by BetterFoliage.modelManager.lazy {
|
||||||
Config.leaves.let { crossModelsRaw(64, it.size, it.hOffset, it.vOffset) }
|
Config.leaves.let { crossModelsRaw(64, it.size, it.hOffset, it.vOffset) }
|
||||||
}
|
}
|
||||||
val leafModelsNormal = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
|
val leafModelsNormal = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
|
||||||
crossModelsTextured(leafModelsBase[key], key.tintIndex, true) { key.roundLeafTexture }
|
// generated leaf textures naturally carry the color of their source textures
|
||||||
|
// no need to color the quad a second time
|
||||||
|
crossModelsTextured(leafModelsBase, Color.white, key.tintIndex, true) { key.roundLeafTexture }
|
||||||
}
|
}
|
||||||
val leafModelsSnowed = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
|
val leafModelsSnowed = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
|
||||||
crossModelsTextured(leafModelsBase[key], -1, false) { leafSpritesSnowed[it].name }
|
crossModelsTextured(leafModelsBase, Color.white, -1, false) { leafSpritesSnowed[it].name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ import mods.betterfoliage.util.averageHSB
|
|||||||
import mods.betterfoliage.util.idxOrNull
|
import mods.betterfoliage.util.idxOrNull
|
||||||
import mods.betterfoliage.util.lazy
|
import mods.betterfoliage.util.lazy
|
||||||
import mods.betterfoliage.util.lazyMap
|
import mods.betterfoliage.util.lazyMap
|
||||||
import mods.betterfoliage.util.lighten
|
import mods.betterfoliage.util.brighten
|
||||||
import mods.betterfoliage.util.randomI
|
import mods.betterfoliage.util.randomI
|
||||||
import net.minecraft.client.renderer.RenderType
|
import net.minecraft.client.renderer.RenderType
|
||||||
import net.minecraft.util.Direction
|
import net.minecraft.util.Direction
|
||||||
@@ -36,7 +36,7 @@ object StandardMyceliumDiscovery : ParametrizedModelDiscovery() {
|
|||||||
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
|
||||||
val texture = params.location("texture") ?: return
|
val texture = params.location("texture") ?: return
|
||||||
val tint = params.int("tint") ?: -1
|
val tint = params.int("tint") ?: -1
|
||||||
val color = Atlas.BLOCKS.file(texture).averageHSB.lighten(multiplier = 1.5f)
|
val color = Atlas.BLOCKS.file(texture).averageHSB.brighten(multiplier = 1.5f).asColor
|
||||||
ctx.addReplacement(StandardMyceliumKey(texture, tint, color))
|
ctx.addReplacement(StandardMyceliumKey(texture, tint, color))
|
||||||
ctx.blockState.block.extendLayers()
|
ctx.blockState.block.extendLayers()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package mods.betterfoliage.render.particle
|
package mods.betterfoliage.render.particle
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.IVertexBuilder
|
import com.mojang.blaze3d.vertex.IVertexBuilder
|
||||||
|
import mods.betterfoliage.model.Color
|
||||||
|
import mods.betterfoliage.model.HSB
|
||||||
import mods.betterfoliage.util.Double3
|
import mods.betterfoliage.util.Double3
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.particle.SpriteTexturedParticle
|
import net.minecraft.client.particle.SpriteTexturedParticle
|
||||||
@@ -92,10 +94,16 @@ abstract class AbstractParticle(world: ClientWorld, x: Double, y: Double, z: Dou
|
|||||||
renderVertex(coords[3], sprite.u0, sprite.v1)
|
renderVertex(coords[3], sprite.u0, sprite.v1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setColor(color: Int) {
|
fun setColor(color: Color) {
|
||||||
bCol = (color and 255) / 256.0f
|
rCol = color.red / 256.0f
|
||||||
gCol = ((color shr 8) and 255) / 256.0f
|
gCol = color.green / 256.0f
|
||||||
rCol = ((color shr 16) and 255) / 256.0f
|
bCol = color.blue / 256.0f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set particle color to the "stronger" of the given colors, determined by higher color saturation
|
||||||
|
*/
|
||||||
|
fun setColor(color1: Color, color2: Color) =
|
||||||
|
setColor(if (color1.asHSB.saturation > color2.asHSB.saturation) color1 else color2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mods.betterfoliage.render.particle
|
package mods.betterfoliage.render.particle
|
||||||
|
|
||||||
import mods.betterfoliage.config.Config
|
import mods.betterfoliage.config.Config
|
||||||
|
import mods.betterfoliage.model.Color
|
||||||
import mods.betterfoliage.util.Double3
|
import mods.betterfoliage.util.Double3
|
||||||
import mods.betterfoliage.util.PI2
|
import mods.betterfoliage.util.PI2
|
||||||
import mods.betterfoliage.util.minmax
|
import mods.betterfoliage.util.minmax
|
||||||
@@ -44,7 +45,7 @@ class FallingLeafParticle(
|
|||||||
yd = -Config.fallingLeaves.speed
|
yd = -Config.fallingLeaves.speed
|
||||||
|
|
||||||
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
|
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
|
||||||
setColor(leaf.overrideColor?.asInt ?: blockColor)
|
if (leaf.tintIndex == -1) setColor(leaf.avgColor) else setColor(leaf.avgColor, Color(blockColor))
|
||||||
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
|
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ interface LeafBlockModel {
|
|||||||
|
|
||||||
interface LeafParticleKey {
|
interface LeafParticleKey {
|
||||||
val leafType: String
|
val leafType: String
|
||||||
val overrideColor: Color?
|
val tintIndex: Int
|
||||||
|
val avgColor: Color
|
||||||
}
|
}
|
||||||
|
|
||||||
object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package mods.betterfoliage.util
|
package mods.betterfoliage.util
|
||||||
|
|
||||||
import mods.betterfoliage.BetterFoliageMod
|
import mods.betterfoliage.BetterFoliageMod
|
||||||
|
import mods.betterfoliage.model.HSB
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.util.ResourceLocation
|
import net.minecraft.util.ResourceLocation
|
||||||
@@ -65,6 +66,11 @@ abstract class HasLogger {
|
|||||||
val detailLogger = BetterFoliageMod.detailLogger(this)
|
val detailLogger = BetterFoliageMod.detailLogger(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Logger.logTextureColor(level: Level, description: String, avgColor: HSB) {
|
||||||
|
val rgb = avgColor.asColor
|
||||||
|
log(level, "$description average color RGB[${rgb.red},${rgb.green},${rgb.blue}], HSB[${avgColor.hue},${avgColor.saturation},${avgColor.brightness}]")
|
||||||
|
}
|
||||||
|
|
||||||
fun getBlockModel(state: BlockState) = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state)
|
fun getBlockModel(state: BlockState) = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state)
|
||||||
/**
|
/**
|
||||||
* Check if the Chunk containing the given [BlockPos] is loaded.
|
* Check if the Chunk containing the given [BlockPos] is loaded.
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import java.io.IOException
|
|||||||
import javax.imageio.ImageIO
|
import javax.imageio.ImageIO
|
||||||
import kotlin.math.atan2
|
import kotlin.math.atan2
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
enum class Atlas(val resourceId: ResourceLocation) {
|
enum class Atlas(val resourceId: ResourceLocation) {
|
||||||
@@ -107,8 +109,10 @@ val ResourceLocation.averageHSB: HSB get() = resourceManager.loadSprite(this).le
|
|||||||
return HSB(avgHue, sumSaturation / numOpaque.toFloat(), sumBrightness / numOpaque.toFloat())
|
return HSB(avgHue, sumSaturation / numOpaque.toFloat(), sumBrightness / numOpaque.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun HSB.lighten(multiplier: Float = 2.0f, ceiling: Float = 0.9f) =
|
fun HSB.brighten(multiplier: Float = 1.5f, floor: Float = 0.1f, ceiling: Float = 0.9f) =
|
||||||
copy(brightness = (brightness * multiplier).coerceAtMost(ceiling)).asColor
|
copy(brightness = (brightness * multiplier).coerceAtMost(max(ceiling, brightness)).coerceAtLeast(min(floor, brightness)))
|
||||||
|
fun HSB.saturate(multiplier: Float = 1.5f, floor: Float = 0.1f, ceiling: Float = 0.9f) =
|
||||||
|
copy(saturation = (saturation * multiplier).coerceAtMost(max(ceiling, saturation)).coerceAtLeast(min(floor, saturation)))
|
||||||
|
|
||||||
/** Weighted blend of 2 packed RGB colors */
|
/** Weighted blend of 2 packed RGB colors */
|
||||||
fun blendRGB(rgb1: Int, rgb2: Int, weight1: Int, weight2: Int): Int {
|
fun blendRGB(rgb1: Int, rgb2: Int, weight1: Int, weight2: Int): Int {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ match block.class.extends(classOf("minecraft:oak_leaves")) setParam("type", "lea
|
|||||||
|
|
||||||
match isParam("type", "leaf")
|
match isParam("type", "leaf")
|
||||||
model.extends("minecraft:block/leaves", "minecraft:block/cube_all")
|
model.extends("minecraft:block/leaves", "minecraft:block/cube_all")
|
||||||
setParam("texture-leaf", model.texture("all"))
|
setParam("texture", model.texture("all"))
|
||||||
setParam("tint-leaf", model.tint("all"))
|
setParam("tint", model.tint("all"))
|
||||||
end
|
end
|
||||||
|
|
||||||
// Podzol
|
// Podzol
|
||||||
|
|||||||
Reference in New Issue
Block a user