Add HSVColor, massively overhaul RGBAColor class
This commit is contained in:
parent
d855234808
commit
04f58c01db
388
src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt
Normal file
388
src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.math
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import it.unimi.dsi.fastutil.chars.CharAVLTreeSet
|
||||||
|
import net.minecraft.ChatFormatting
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class HSVColor(hue: Float, saturation: Float, value: Float) : Comparable<HSVColor> {
|
||||||
|
val hue = (hue % 360f).let { if (it < 0f) it + 360f else it }
|
||||||
|
val saturation = saturation.coerceIn(0f, 1f)
|
||||||
|
val value = value.coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other === this || other is HSVColor && other.hue == hue && other.saturation == saturation && other.value == value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return hue.hashCode() + saturation.hashCode() * 31 + value.hashCode() * 31 * 31
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copy(hue: Float = this.hue, saturation: Float = this.saturation, value: Float = this.value): HSVColor {
|
||||||
|
return HSVColor(hue, saturation, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun component1() = hue
|
||||||
|
operator fun component2() = saturation
|
||||||
|
operator fun component3() = value
|
||||||
|
|
||||||
|
fun toRGBA(alpha: Float = 1f): RGBAColor {
|
||||||
|
val valueMin = (1f - saturation) * value
|
||||||
|
val delta = (value - valueMin) * (hue % 60f) / 60f
|
||||||
|
val valueInc = valueMin + delta
|
||||||
|
val valueDec = value - delta
|
||||||
|
|
||||||
|
return when ((hue / 60f).toInt()) {
|
||||||
|
0 -> RGBAColor(value, valueInc, valueMin, alpha)
|
||||||
|
1 -> RGBAColor(valueDec, value, valueMin, alpha)
|
||||||
|
2 -> RGBAColor(valueMin, value, valueInc, alpha)
|
||||||
|
3 -> RGBAColor(valueMin, valueDec, value, alpha)
|
||||||
|
4 -> RGBAColor(valueInc, valueMin, value, alpha)
|
||||||
|
5 -> RGBAColor(value, valueMin, valueDec, alpha)
|
||||||
|
else -> throw IllegalStateException("whut")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: HSVColor): Int {
|
||||||
|
return comparator.compare(this, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmField val WHITE = HSVColor(0f, 1f, 1f)
|
||||||
|
|
||||||
|
private val comparator = Comparator
|
||||||
|
.comparing(HSVColor::hue)
|
||||||
|
.thenComparing(HSVColor::saturation)
|
||||||
|
.thenComparing(HSVColor::value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hex(value: Int): String {
|
||||||
|
require(value in 0 .. 255)
|
||||||
|
val v = value.toString(16)
|
||||||
|
|
||||||
|
if (v.length == 1)
|
||||||
|
return "0$v"
|
||||||
|
else
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
class RGBAColor(red: Float, green: Float, blue: Float, alpha: Float = 1f) : Comparable<RGBAColor> {
|
||||||
|
constructor(r: Int, g: Int, b: Int) : this((r / 255f), (g / 255f), (b / 255f), 1f)
|
||||||
|
constructor(r: Int, g: Int, b: Int, a: Int) : this((r / 255f), (g / 255f), (b / 255f), (a / 255f))
|
||||||
|
constructor(r: Int, g: Int, b: Int, a: Float) : this((r / 255f), (g / 255f), (b / 255f), a)
|
||||||
|
|
||||||
|
val red = red.coerceIn(0f, 1f)
|
||||||
|
val green = green.coerceIn(0f, 1f)
|
||||||
|
val blue = blue.coerceIn(0f, 1f)
|
||||||
|
val alpha = alpha.coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
val redInt get() = (red * 255f).roundToInt()
|
||||||
|
val greenInt get() = (green * 255f).roundToInt()
|
||||||
|
val blueInt get() = (blue * 255f).roundToInt()
|
||||||
|
val alphaInt get() = (alpha * 255f).roundToInt()
|
||||||
|
|
||||||
|
fun toRGBA(): Int {
|
||||||
|
return (redInt shl 24) or (greenInt shl 16) or (blueInt shl 8) or alphaInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toARGB(): Int {
|
||||||
|
return (alphaInt shl 24) or (redInt shl 16) or (greenInt shl 8) or blueInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toBGRA(): Int {
|
||||||
|
return (blueInt shl 24) or (greenInt shl 16) or (redInt shl 8) or alphaInt
|
||||||
|
}
|
||||||
|
|
||||||
|
val isFullyTransparent get() = alpha <= 0f
|
||||||
|
val isWhite: Boolean get() = red >= 1f && green >= 1f && blue >= 1f && alpha >= 1f
|
||||||
|
|
||||||
|
fun canRepresentHue(): Boolean {
|
||||||
|
val min = red.coerceAtMost(green).coerceAtMost(blue)
|
||||||
|
val max = red.coerceAtLeast(green).coerceAtLeast(blue)
|
||||||
|
return min != max
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hue(ifNoHue: Float = 0f): Float {
|
||||||
|
val min = red.coerceAtMost(green).coerceAtMost(blue)
|
||||||
|
val max = red.coerceAtLeast(green).coerceAtLeast(blue)
|
||||||
|
|
||||||
|
if (min == max) {
|
||||||
|
return ifNoHue
|
||||||
|
}
|
||||||
|
|
||||||
|
val diff = max - min
|
||||||
|
|
||||||
|
return if (max == red && green >= blue) {
|
||||||
|
60f * (green - blue) / diff
|
||||||
|
} else if (max == red) {
|
||||||
|
60f * (green - blue) / diff + 360f
|
||||||
|
} else if (max == green) {
|
||||||
|
60f * (blue - red) / diff + 120f
|
||||||
|
} else if (max == blue) {
|
||||||
|
60f * (red - green) / diff + 240f
|
||||||
|
} else {
|
||||||
|
throw IllegalStateException("Whut $red $green $blue ($min / $max)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toHSV(): HSVColor {
|
||||||
|
val min = red.coerceAtMost(green).coerceAtMost(blue)
|
||||||
|
val max = red.coerceAtLeast(green).coerceAtLeast(blue)
|
||||||
|
|
||||||
|
if (min == max) {
|
||||||
|
return HSVColor(0f, if (max == 0f) 0f else 1f - min / max, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
val diff = max - min
|
||||||
|
|
||||||
|
val hue = if (max == red && green >= blue) {
|
||||||
|
60f * (green - blue) / diff
|
||||||
|
} else if (max == red) {
|
||||||
|
60f * (green - blue) / diff + 360f
|
||||||
|
} else if (max == green) {
|
||||||
|
60f * (blue - red) / diff + 120f
|
||||||
|
} else if (max == blue) {
|
||||||
|
60f * (red - green) / diff + 240f
|
||||||
|
} else {
|
||||||
|
throw IllegalStateException("Whut $red $green $blue ($min / $max)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return HSVColor(hue, 1f - min / max, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toHexStringRGB(): String {
|
||||||
|
return "#${hex(redInt)}${hex(greenInt)}${hex(blueInt)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toHexStringRGBA(): String {
|
||||||
|
return "#${hex(redInt)}${hex(greenInt)}${hex(blueInt)}${hex(alphaInt)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toHexStringARGB(): String {
|
||||||
|
return "#${hex(alphaInt)}${hex(redInt)}${hex(greenInt)}${hex(blueInt)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "RGBAColor[$red $green $blue $alpha]"
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun component1() = red
|
||||||
|
operator fun component2() = green
|
||||||
|
operator fun component3() = blue
|
||||||
|
operator fun component4() = alpha
|
||||||
|
|
||||||
|
fun toIntInv(): Int {
|
||||||
|
return (blueInt shl 16) or (greenInt shl 8) or redInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toRGB(): Int {
|
||||||
|
return (redInt shl 16) or (greenInt shl 8) or blueInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copy(red: Float = this.red, green: Float = this.green, blue: Float = this.blue, alpha: Float = this.alpha): RGBAColor {
|
||||||
|
return RGBAColor(red, green, blue, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: RGBAColor): Int {
|
||||||
|
if (canRepresentHue() && other.canRepresentHue())
|
||||||
|
return hue().compareTo(other.hue()).let {
|
||||||
|
if (it != 0)
|
||||||
|
it
|
||||||
|
else
|
||||||
|
toHSV().compareTo(other.toHSV())
|
||||||
|
}
|
||||||
|
|
||||||
|
return comparator.compare(this, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other === this || other is RGBAColor && comparator.compare(this, other) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return red.hashCode() + green.hashCode() * 31 + blue.hashCode() * 31 * 31 + alpha.hashCode() * 31 * 31 * 31
|
||||||
|
}
|
||||||
|
|
||||||
|
fun linearInterpolation(t: Float, other: RGBAColor, interpolateAlpha: Boolean = true): RGBAColor {
|
||||||
|
return RGBAColor(
|
||||||
|
linearInterpolation(t, red, other.red),
|
||||||
|
linearInterpolation(t, green, other.green),
|
||||||
|
linearInterpolation(t, blue, other.blue),
|
||||||
|
if (interpolateAlpha) linearInterpolation(t, alpha, other.alpha) else alpha,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun times(other: RGBAColor): RGBAColor {
|
||||||
|
if (isWhite)
|
||||||
|
return other
|
||||||
|
else if (other.isWhite)
|
||||||
|
return this
|
||||||
|
|
||||||
|
return RGBAColor(red * other.red, green * other.green, blue * other.blue, alpha * other.alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
companion object {
|
||||||
|
private val comparator = Comparator
|
||||||
|
.comparing(RGBAColor::red)
|
||||||
|
.thenComparing(RGBAColor::green)
|
||||||
|
.thenComparing(RGBAColor::blue)
|
||||||
|
.thenComparing(RGBAColor::alpha)
|
||||||
|
|
||||||
|
@JvmField val TRANSPARENT_BLACK = RGBAColor(0f, 0f, 0f, 0f)
|
||||||
|
@JvmField val TRANSPARENT_WHITE = RGBAColor(1f, 1f, 1f, 0f)
|
||||||
|
|
||||||
|
@JvmField val BLACK = RGBAColor(0f, 0f, 0f)
|
||||||
|
@JvmField val WHITE = RGBAColor(1f, 1f, 1f)
|
||||||
|
@JvmField val RED = RGBAColor(1f, 0f, 0f)
|
||||||
|
@JvmField val GREEN = RGBAColor(0f, 1f, 0f)
|
||||||
|
@JvmField val LIGHT_GREEN = RGBAColor(136, 255, 124)
|
||||||
|
@JvmField val SLATE_GRAY = RGBAColor(64, 64, 64)
|
||||||
|
@JvmField val GRAY = rgb(0x2C2C2CL)
|
||||||
|
|
||||||
|
@JvmField val DARK_BLUE = rgb(ChatFormatting.DARK_BLUE.color!!)
|
||||||
|
@JvmField val DARK_GREEN = rgb(ChatFormatting.DARK_GREEN.color!!)
|
||||||
|
@JvmField val DARK_AQUA = rgb(ChatFormatting.DARK_AQUA.color!!)
|
||||||
|
@JvmField val DARK_RED = rgb(ChatFormatting.DARK_RED.color!!)
|
||||||
|
@JvmField val DARK_PURPLE = rgb(ChatFormatting.DARK_PURPLE.color!!)
|
||||||
|
@JvmField val GOLD = rgb(ChatFormatting.GOLD.color!!)
|
||||||
|
@JvmField val DARK_GRAY = rgb(ChatFormatting.DARK_GRAY.color!!)
|
||||||
|
@JvmField val BLUE = rgb(ChatFormatting.BLUE.color!!)
|
||||||
|
@JvmField val AQUA = rgb(ChatFormatting.AQUA.color!!)
|
||||||
|
@JvmField val LIGHT_PURPLE = rgb(ChatFormatting.LIGHT_PURPLE.color!!)
|
||||||
|
@JvmField val YELLOW = rgb(ChatFormatting.YELLOW.color!!)
|
||||||
|
|
||||||
|
@JvmField val LOW_POWER = RGBAColor(173, 41, 41)
|
||||||
|
@JvmField val FULL_POWER = RGBAColor(255, 242, 40)
|
||||||
|
@JvmField val LOW_MATTER = RGBAColor(0, 24, 148)
|
||||||
|
@JvmField val FULL_MATTER = RGBAColor(72, 90, 255)
|
||||||
|
@JvmField val LOW_PATTERNS = RGBAColor(44, 104, 57)
|
||||||
|
@JvmField val FULL_PATTERNS = RGBAColor(65, 255, 87)
|
||||||
|
|
||||||
|
@JvmField val HALF_TRANSPARENT = RGBAColor(1f, 1f, 1f, 0.5f)
|
||||||
|
@JvmField val REDDISH = RGBAColor(1f, 0.4f, 0.4f)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val CODECRGBA: Codec<RGBAColor> = RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red),
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green),
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue),
|
||||||
|
Codec.floatRange(0f, 1f).optionalFieldOf("alpha", 1f).forGetter(RGBAColor::alpha),
|
||||||
|
).apply(it, ::RGBAColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val CODECRGB: Codec<RGBAColor> = RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red),
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green),
|
||||||
|
Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue),
|
||||||
|
).apply(it, ::RGBAColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rgb(color: Int): RGBAColor {
|
||||||
|
val r = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val g = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val b = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rgb(color: Long): RGBAColor {
|
||||||
|
val r = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val g = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val b = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bgr(color: Int): RGBAColor {
|
||||||
|
val r = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val g = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val b = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(b, g, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bgr(color: Long): RGBAColor {
|
||||||
|
val r = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val g = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val b = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(b, g, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun abgr(color: Int): RGBAColor {
|
||||||
|
val r = (color and -0x1000000 ushr 24) / 255f
|
||||||
|
val g = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val b = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val a = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(a, b, g, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun argb(color: Int): RGBAColor {
|
||||||
|
val a = (color and -0x1000000 ushr 24) / 255f
|
||||||
|
val r = (color and 0xFF0000 ushr 16) / 255f
|
||||||
|
val g = (color and 0xFF00 ushr 8) / 255f
|
||||||
|
val b = (color and 0xFF) / 255f
|
||||||
|
return RGBAColor(r, g, b, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val hexChars = CharAVLTreeSet()
|
||||||
|
|
||||||
|
init {
|
||||||
|
"#0123456789abcdefABCDEF".forEach { hexChars.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isHexCharacter(char: Char): Boolean {
|
||||||
|
return char in hexChars
|
||||||
|
}
|
||||||
|
|
||||||
|
private val shorthandRGBHex = Regex("#?([0-9abcdef])([0-9abcdef])([0-9abcdef])", RegexOption.IGNORE_CASE)
|
||||||
|
private val longhandRGBHex = Regex("#?([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
|
private val shorthandRGBAHex = Regex("#?([0-9abcdef])([0-9abcdef])([0-9abcdef])([0-9abcdef])", RegexOption.IGNORE_CASE)
|
||||||
|
private val longhandRGBAHex = Regex("#?([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
|
fun fromHexStringRGB(value: String): RGBAColor? {
|
||||||
|
if (value.length == 3 || value.length == 4) {
|
||||||
|
val match = shorthandRGBHex.find(value) ?: return null
|
||||||
|
val red = match.groupValues[1].toIntOrNull(16) ?: return null
|
||||||
|
val green = match.groupValues[2].toIntOrNull(16) ?: return null
|
||||||
|
val blue = match.groupValues[3].toIntOrNull(16) ?: return null
|
||||||
|
return RGBAColor(red * 16, green * 16, blue * 16)
|
||||||
|
} else if (value.length == 6 || value.length == 7) {
|
||||||
|
val match = longhandRGBHex.find(value) ?: return null
|
||||||
|
val red = match.groupValues[1].toIntOrNull(16) ?: return null
|
||||||
|
val green = match.groupValues[2].toIntOrNull(16) ?: return null
|
||||||
|
val blue = match.groupValues[3].toIntOrNull(16) ?: return null
|
||||||
|
return RGBAColor(red, green, blue)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromHexStringRGBA(value: String): RGBAColor? {
|
||||||
|
if (value.length == 4 || value.length == 5) {
|
||||||
|
val match = shorthandRGBAHex.find(value) ?: return null
|
||||||
|
val red = match.groupValues[1].toIntOrNull(16) ?: return null
|
||||||
|
val green = match.groupValues[2].toIntOrNull(16) ?: return null
|
||||||
|
val blue = match.groupValues[3].toIntOrNull(16) ?: return null
|
||||||
|
val alpha = match.groupValues[4].toIntOrNull(16) ?: return null
|
||||||
|
return RGBAColor(red * 16, green * 16, blue * 16, alpha * 16)
|
||||||
|
} else if (value.length == 8 || value.length == 9) {
|
||||||
|
val match = longhandRGBAHex.find(value) ?: return null
|
||||||
|
val red = match.groupValues[1].toIntOrNull(16) ?: return null
|
||||||
|
val green = match.groupValues[2].toIntOrNull(16) ?: return null
|
||||||
|
val blue = match.groupValues[3].toIntOrNull(16) ?: return null
|
||||||
|
val alpha = match.groupValues[4].toIntOrNull(16) ?: return null
|
||||||
|
return RGBAColor(red, green, blue, alpha)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun linearInterpolation(t: Float, a: RGBAColor, b: RGBAColor): RGBAColor {
|
||||||
|
return a.linearInterpolation(t, b)
|
||||||
|
}
|
@ -1,127 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.math
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
|
||||||
import net.minecraft.ChatFormatting
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alpha: Float = 1f) {
|
|
||||||
constructor(r: Int, g: Int, b: Int) : this((r / 255f), (g / 255f), (b / 255f), 1f)
|
|
||||||
constructor(r: Int, g: Int, b: Int, a: Int) : this((r / 255f), (g / 255f), (b / 255f), (a / 255f))
|
|
||||||
constructor(r: Int, g: Int, b: Int, a: Float) : this((r / 255f), (g / 255f), (b / 255f), a)
|
|
||||||
|
|
||||||
constructor(color: Long) : this(
|
|
||||||
(((color and -0x1000000) ushr 24) / 255f),
|
|
||||||
(((color and 0xFF0000) ushr 16) / 255f),
|
|
||||||
(((color and 0xFF00) ushr 8) / 255f),
|
|
||||||
(((color and 0xFF)) / 255f)
|
|
||||||
)
|
|
||||||
|
|
||||||
val isWhite = red >= 1f && green >= 1f && blue >= 1f && alpha >= 1f
|
|
||||||
|
|
||||||
val redInt = (red.coerceIn(0f, 1f) * 255f).roundToInt()
|
|
||||||
val greenInt = (green.coerceIn(0f, 1f) * 255f).roundToInt()
|
|
||||||
val blueInt = (blue.coerceIn(0f, 1f) * 255f).roundToInt()
|
|
||||||
val alphaInt = (alpha.coerceIn(0f, 1f) * 255f).roundToInt()
|
|
||||||
|
|
||||||
fun toRGB(): Int {
|
|
||||||
return (redInt shl 16) or (greenInt shl 8) or blueInt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toRGBA(): Int {
|
|
||||||
return (redInt shl 24) or (greenInt shl 16) or (blueInt shl 8) or alphaInt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toARGB(): Int {
|
|
||||||
return (alphaInt shl 24) or (redInt shl 16) or (greenInt shl 8) or blueInt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toBGRA(): Int {
|
|
||||||
return (blueInt shl 24) or (greenInt shl 16) or (redInt shl 8) or alphaInt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toIntInv(): Int {
|
|
||||||
return (blueInt shl 16) or (greenInt shl 8) or redInt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun linearInterpolation(t: Float, other: RGBAColor, interpolateAlpha: Boolean = true): RGBAColor {
|
|
||||||
return RGBAColor(
|
|
||||||
linearInterpolation(t, red, other.red),
|
|
||||||
linearInterpolation(t, green, other.green),
|
|
||||||
linearInterpolation(t, blue, other.blue),
|
|
||||||
if (interpolateAlpha) linearInterpolation(t, alpha, other.alpha) else alpha,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun times(other: RGBAColor): RGBAColor {
|
|
||||||
if (isWhite)
|
|
||||||
return other
|
|
||||||
else if (other.isWhite)
|
|
||||||
return this
|
|
||||||
|
|
||||||
return RGBAColor(red * other.red, green * other.green, blue * other.blue, alpha * other.alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
val isFullyTransparent get() = alpha <= 0f
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@JvmField val TRANSPARENT_BLACK = RGBAColor(0f, 0f, 0f, 0f)
|
|
||||||
@JvmField val TRANSPARENT_WHITE = RGBAColor(1f, 1f, 1f, 0f)
|
|
||||||
|
|
||||||
@JvmField val BLACK = RGBAColor(0f, 0f, 0f, 1f)
|
|
||||||
@JvmField val WHITE = RGBAColor(1f, 1f, 1f, 1f)
|
|
||||||
@JvmField val RED = RGBAColor(1f, 0f, 0f)
|
|
||||||
@JvmField val GREEN = RGBAColor(0f, 1f, 0f, 1f)
|
|
||||||
@JvmField val LIGHT_GREEN = RGBAColor(136, 255, 124)
|
|
||||||
@JvmField val SLATE_GRAY = RGBAColor(64, 64, 64)
|
|
||||||
@JvmField val GRAY = RGBAColor(0x2C2C2CFFL)
|
|
||||||
|
|
||||||
@JvmField val DARK_BLUE = rgb(ChatFormatting.DARK_BLUE.color!!)
|
|
||||||
@JvmField val DARK_GREEN = rgb(ChatFormatting.DARK_GREEN.color!!)
|
|
||||||
@JvmField val DARK_AQUA = rgb(ChatFormatting.DARK_AQUA.color!!)
|
|
||||||
@JvmField val DARK_RED = rgb(ChatFormatting.DARK_RED.color!!)
|
|
||||||
@JvmField val DARK_PURPLE = rgb(ChatFormatting.DARK_PURPLE.color!!)
|
|
||||||
@JvmField val GOLD = rgb(ChatFormatting.GOLD.color!!)
|
|
||||||
@JvmField val DARK_GRAY = rgb(ChatFormatting.DARK_GRAY.color!!)
|
|
||||||
@JvmField val BLUE = rgb(ChatFormatting.BLUE.color!!)
|
|
||||||
@JvmField val AQUA = rgb(ChatFormatting.AQUA.color!!)
|
|
||||||
@JvmField val LIGHT_PURPLE = rgb(ChatFormatting.LIGHT_PURPLE.color!!)
|
|
||||||
@JvmField val YELLOW = rgb(ChatFormatting.YELLOW.color!!)
|
|
||||||
|
|
||||||
@JvmField val LOW_POWER = RGBAColor(173, 41, 41)
|
|
||||||
@JvmField val FULL_POWER = RGBAColor(255, 242, 40)
|
|
||||||
@JvmField val LOW_MATTER = RGBAColor(0, 24, 148)
|
|
||||||
@JvmField val FULL_MATTER = RGBAColor(72, 90, 255)
|
|
||||||
@JvmField val LOW_PATTERNS = RGBAColor(44, 104, 57)
|
|
||||||
@JvmField val FULL_PATTERNS = RGBAColor(65, 255, 87)
|
|
||||||
|
|
||||||
@JvmField val HALF_TRANSPARENT = RGBAColor(1f, 1f, 1f, 0.5f)
|
|
||||||
@JvmField val REDDISH = RGBAColor(1f, 0.4f, 0.4f)
|
|
||||||
|
|
||||||
fun inv(color: Int): RGBAColor {
|
|
||||||
val r = (color and -0x1000000 ushr 24) / 255f
|
|
||||||
val g = (color and 0xFF0000 ushr 16) / 255f
|
|
||||||
val b = (color and 0xFF00 ushr 8) / 255f
|
|
||||||
val a = (color and 0xFF) / 255f
|
|
||||||
return RGBAColor(a, b, g, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun rgb(color: Int): RGBAColor {
|
|
||||||
val r = (color and 0xFF0000 ushr 16) / 255f
|
|
||||||
val g = (color and 0xFF00 ushr 8) / 255f
|
|
||||||
val b = (color and 0xFF) / 255f
|
|
||||||
return RGBAColor(r, g, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun argb(color: Int): RGBAColor {
|
|
||||||
val a = (color and -0x1000000 ushr 24) / 255f
|
|
||||||
val r = (color and 0xFF0000 ushr 16) / 255f
|
|
||||||
val g = (color and 0xFF00 ushr 8) / 255f
|
|
||||||
val b = (color and 0xFF) / 255f
|
|
||||||
return RGBAColor(r, g, b, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun linearInterpolation(t: Float, a: RGBAColor, b: RGBAColor): RGBAColor {
|
|
||||||
return a.linearInterpolation(t, b)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user