mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-14 18:05:51 -04:00
color tests, some fixes
This commit is contained in:
parent
59ddd7fe5e
commit
6fd062d19d
@ -100,7 +100,7 @@ open class TextComponent(
|
||||
override val legacy: String
|
||||
get() {
|
||||
val builder = StringBuilder()
|
||||
ChatColors.getChar(color?.rgb())?.let { builder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX).append(it) }
|
||||
ChatColors.getChar(color)?.let { builder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX).append(it) }
|
||||
for (formattingCode in this.formatting) {
|
||||
builder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX)
|
||||
builder.append(formattingCode.char)
|
||||
|
@ -49,10 +49,8 @@ object ChatColors {
|
||||
|
||||
var index = 0
|
||||
for (field in this::class.java.declaredFields) {
|
||||
val color = field.get(null)
|
||||
if (color !is RGBAColor) {
|
||||
continue
|
||||
}
|
||||
if (field.type != Int::class.java) continue // inlined datatype
|
||||
val color = RGBAColor(field.getInt(null))
|
||||
VALUES[index] = color
|
||||
CHAR_MAP[color] = index
|
||||
nameMap[field.name.lowercase()] = color
|
||||
@ -60,6 +58,7 @@ object ChatColors {
|
||||
}
|
||||
|
||||
NAME_MAP = nameMap
|
||||
if (NAME_MAP.size != 16) throw IllegalStateException("No colors found?")
|
||||
|
||||
CHAR_MAP.defaultReturnValue(-1)
|
||||
}
|
||||
@ -72,14 +71,12 @@ object ChatColors {
|
||||
return VALUES.getOrNull(id)
|
||||
}
|
||||
|
||||
operator fun get(name: String): RGBAColor? {
|
||||
return when (name) {
|
||||
"dark_grey" -> DARK_GRAY
|
||||
else -> NAME_MAP[name]
|
||||
}
|
||||
operator fun get(name: String) = when (name) {
|
||||
"dark_grey" -> DARK_GRAY
|
||||
else -> NAME_MAP[name]
|
||||
}
|
||||
|
||||
fun getChar(color: RGBColor?): String? {
|
||||
fun getChar(color: RGBAColor?): String? {
|
||||
if (color == null) return null
|
||||
val char = CHAR_MAP.getInt(color)
|
||||
if (char < 0) return null
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.data.text.formatting.color
|
||||
|
||||
import de.bixilon.kotlinglm.func.common.clamp
|
||||
import de.bixilon.kutil.ansi.ANSI
|
||||
|
||||
interface Color {
|
||||
@ -40,6 +41,8 @@ interface Color {
|
||||
const val TIMES = VALUES * VALUES
|
||||
|
||||
|
||||
fun Int.clamp() = this.clamp(MIN, MAX)
|
||||
|
||||
fun toFloat(value: Int) = value * (1.0f / MAX)
|
||||
fun fromFloat(value: Float) = (value * MAX).toInt()
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.text.formatting.color
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kotlinglm.vec4.Vec4
|
||||
import de.bixilon.kutil.primitive.IntUtil.toHex
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.data.text.formatting.TextFormattable
|
||||
@ -22,13 +23,14 @@ import de.bixilon.minosoft.data.text.formatting.color.Color.Companion.BITS
|
||||
import de.bixilon.minosoft.data.text.formatting.color.Color.Companion.MASK
|
||||
import de.bixilon.minosoft.data.text.formatting.color.Color.Companion.MAX
|
||||
import de.bixilon.minosoft.data.text.formatting.color.Color.Companion.TIMES
|
||||
import de.bixilon.minosoft.data.text.formatting.color.Color.Companion.clamp
|
||||
|
||||
|
||||
@JvmInline
|
||||
value class RGBAColor(val argb: Int) : Color, TextFormattable {
|
||||
|
||||
constructor(red: Int, green: Int, blue: Int) : this(red, green, blue, MAX)
|
||||
constructor(red: Int, green: Int, blue: Int, alpha: Int) : this(((alpha and MASK) shl ALPHA_SHIFT) or ((red and MASK) shl RED_SHIFT) or ((green and MASK) shl GREEN_SHIFT) or ((blue and MASK) shl BLUE_SHIFT))
|
||||
constructor(red: Int, green: Int, blue: Int, alpha: Int) : this(((alpha.clamp() and MASK) shl ALPHA_SHIFT) or ((red.clamp() and MASK) shl RED_SHIFT) or ((green.clamp() and MASK) shl GREEN_SHIFT) or ((blue.clamp() and MASK) shl BLUE_SHIFT))
|
||||
|
||||
constructor(red: Float, green: Float, blue: Float) : this(Color.fromFloat(red), Color.fromFloat(green), Color.fromFloat(blue))
|
||||
constructor(red: Float, green: Float, blue: Float, alpha: Float) : this(Color.fromFloat(red), Color.fromFloat(green), Color.fromFloat(blue), Color.fromFloat(alpha))
|
||||
@ -73,11 +75,15 @@ value class RGBAColor(val argb: Int) : Color, TextFormattable {
|
||||
fun toVec4() = Vec4(redf, greenf, bluef, alphaf)
|
||||
|
||||
override fun toString(): String {
|
||||
return if (alpha != MAX) {
|
||||
String.format("#%08X", rgba)
|
||||
} else {
|
||||
String.format("#%06X", rgb)
|
||||
val builder = StringBuilder(9)
|
||||
builder.append('#')
|
||||
builder.append(red.toHex(2))
|
||||
builder.append(green.toHex(2))
|
||||
builder.append(blue.toHex(2))
|
||||
if (alpha != MAX) {
|
||||
builder.append(alpha.toHex(2))
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
override fun toText(): ChatComponent {
|
||||
@ -93,7 +99,7 @@ value class RGBAColor(val argb: Int) : Color, TextFormattable {
|
||||
|
||||
fun Vec4.color() = RGBAColor(r, g, b, a)
|
||||
|
||||
inline fun Int.rgba() = RGBAColor(this shl BITS or (this ushr (BITS * 3)))
|
||||
inline fun Int.rgba() = RGBAColor(this shr BITS or (this and BITS shl (BITS * 3)))
|
||||
inline fun Int.argb() = RGBColor(this)
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ class RGB8Buffer(
|
||||
}
|
||||
|
||||
override fun setRGB(x: Int, y: Int, value: RGBColor) = setRGB(x, y, value.red, value.green, value.blue)
|
||||
override fun setRGBA(x: Int, y: Int, value: RGBAColor) = setRGBA(x, y, value.red, value.green, value.blue, value.alpha)
|
||||
override fun setRGBA(x: Int, y: Int, value: RGBAColor) = setRGB(x, y, value.red, value.green, value.blue)
|
||||
|
||||
override fun copy() = RGB8Buffer(Vec2i(size), data.duplicate())
|
||||
|
||||
|
@ -54,7 +54,7 @@ class RGBA8Buffer(
|
||||
|
||||
override fun getRGBA(x: Int, y: Int): RGBAColor {
|
||||
val stride = stride(x, y)
|
||||
return RGBAColor(this[stride + 0], this[stride + 1], this[stride + 2], this[stride + 3] shl 0)
|
||||
return RGBAColor(this[stride + 0], this[stride + 1], this[stride + 2], this[stride + 3])
|
||||
}
|
||||
|
||||
override fun getRGB(x: Int, y: Int): RGBColor {
|
||||
|
@ -111,7 +111,7 @@ object TextureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
mkdirParent()
|
||||
file.mkdirParent()
|
||||
|
||||
ImageIO.write(bufferedImage, "png", file)
|
||||
}
|
||||
|
@ -334,9 +334,9 @@ internal class ChatComponentTest {
|
||||
private fun assertEquals(expected: ChatComponent, actual: ChatComponent) {
|
||||
when (expected) {
|
||||
is BaseComponent -> {
|
||||
if (actual !is BaseComponent) throw AssertionFailedError("Type mismatch", "BaseComponent", actual::class.java.name)
|
||||
if (actual !is BaseComponent) assert("Type mismatch", "BaseComponent", actual::class.java.name)
|
||||
|
||||
if (expected.parts.size != actual.parts.size) throw AssertionFailedError("Count of parts does not match", expected.parts, actual.parts)
|
||||
if (expected.parts.size != actual.parts.size) assert("Count of parts does not match", expected.parts, actual.parts)
|
||||
|
||||
for (index in expected.parts.indices) {
|
||||
val first = expected.parts[index]
|
||||
@ -347,20 +347,20 @@ internal class ChatComponentTest {
|
||||
}
|
||||
|
||||
is TextComponent -> {
|
||||
if (actual !is TextComponent) throw AssertionFailedError("Type mismatch", "TextComponent", actual::class.java.name)
|
||||
if (expected.message != actual.message) {
|
||||
throw AssertionFailedError("Message mismatch", expected.message, actual.message)
|
||||
}
|
||||
if (expected.clickEvent != actual.clickEvent) {
|
||||
throw AssertionFailedError("Click event mismatch: $expected", expected.clickEvent, actual.clickEvent)
|
||||
}
|
||||
if (expected.hoverEvent != actual.hoverEvent) {
|
||||
throw AssertionFailedError("Click event mismatch: $expected", expected.hoverEvent, actual.hoverEvent)
|
||||
}
|
||||
if (actual !is TextComponent) assert("Type mismatch", "TextComponent", actual::class.java.name)
|
||||
if (expected.message != actual.message) assert("Message mismatch", expected.message, actual.message)
|
||||
if (expected.clickEvent != actual.clickEvent) assert("Click event mismatch: $expected", expected.clickEvent, actual.clickEvent)
|
||||
if (expected.hoverEvent != actual.hoverEvent) assert("Click event mismatch: $expected", expected.hoverEvent, actual.hoverEvent)
|
||||
if (expected.color != actual.color) assert("Color mismatch", expected.color, actual.color)
|
||||
if (expected.font != actual.font) assert("Font mismatch: $expected", expected.font, actual.font)
|
||||
if (expected.formatting != actual.formatting) assert("Formatting mismatch: $expected", expected.formatting, actual.formatting)
|
||||
|
||||
assertEquals(expected as Any, actual)
|
||||
}
|
||||
|
||||
else -> assertEquals(expected as Any, actual)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assert(message: String, expected: Any?, actual: Any?): Nothing = throw AssertionFailedError("$message: expected=$expected, actual=$actual", expected, actual)
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.text.formatting.color
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class RGBAColorTest {
|
||||
|
||||
@Test
|
||||
fun `color int components`() {
|
||||
val color = RGBAColor(0x12, 0x34, 0x56, 0x78)
|
||||
assertEquals(color.red, 0x12)
|
||||
assertEquals(color.green, 0x34)
|
||||
assertEquals(color.blue, 0x56)
|
||||
assertEquals(color.alpha, 0x78)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `color float components`() {
|
||||
val color = RGBAColor(0x12, 0x34, 0x56, 0x78)
|
||||
assertEquals(color.redf, 0x12 / 255.0f, 0.01f)
|
||||
assertEquals(color.greenf, 0x34 / 255.0f, 0.01f)
|
||||
assertEquals(color.bluef, 0x56 / 255.0f, 0.01f)
|
||||
assertEquals(color.alphaf, 0x78 / 255.0f, 0.01f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `color swizzles`() {
|
||||
val color = RGBAColor(0x12, 0x34, 0x56, 0x78)
|
||||
assertEquals(color.rgba, 0x12345678)
|
||||
assertEquals(color.rgb, 0x123456)
|
||||
assertEquals(color.argb, 0x78123456)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `default alpha`() {
|
||||
val color = RGBAColor(0x12, 0x34, 0x56)
|
||||
assertEquals(color.alpha, 0xFF)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of bounds clamping positive`() {
|
||||
val color = RGBAColor(0x145, 0x145, 0x145, 0x145)
|
||||
assertEquals(color.red, 0xFF)
|
||||
assertEquals(color.green, 0xFF)
|
||||
assertEquals(color.blue, 0xFF)
|
||||
assertEquals(color.alpha, 0xFF)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of bounds clamping negative`() {
|
||||
val color = RGBAColor(-123, -123, -123, -123)
|
||||
assertEquals(color.red, 0)
|
||||
assertEquals(color.green, 0)
|
||||
assertEquals(color.blue, 0)
|
||||
assertEquals(color.alpha, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `operations minus`() {
|
||||
val a = RGBAColor(0x12, 0x34, 0x56, 0x78)
|
||||
val b = RGBAColor(0x05, 0x06, 0x07, 0x08)
|
||||
|
||||
assertEquals(a - b, RGBAColor(0x0D, 0x2e, 0x4F, 0x70))
|
||||
assertEquals(a - 3, RGBAColor(0x0F, 0x31, 0x53, 0x75))
|
||||
assertEquals(a - 0.1f, RGBAColor(0x00, 0x1b, 0x3d, 0x5f))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `conversion rgb`() {
|
||||
val color = RGBAColor(0x12, 0x34, 0x56, 0x78)
|
||||
|
||||
assertEquals(color.rgb(), RGBColor(0x12, 0x34, 0x56))
|
||||
}
|
||||
|
||||
// TODO: operations (plus, times), conversion, toString, Int::rgb, Int::rgba, mix
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2025 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.data.text.formatting.color
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class RGBColorTest {
|
||||
|
||||
@Test
|
||||
fun `color int components`() {
|
||||
val color = RGBColor(0x12, 0x34, 0x56)
|
||||
assertEquals(color.red, 0x12)
|
||||
assertEquals(color.green, 0x34)
|
||||
assertEquals(color.blue, 0x56)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `color float components`() {
|
||||
val color = RGBColor(0x12, 0x34, 0x56)
|
||||
assertEquals(color.redf, 0x12 / 255.0f, 0.01f)
|
||||
assertEquals(color.greenf, 0x34 / 255.0f, 0.01f)
|
||||
assertEquals(color.bluef, 0x56 / 255.0f, 0.01f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `color swizzles`() {
|
||||
val color = RGBColor(0x12, 0x34, 0x56)
|
||||
assertEquals(color.rgb, 0x123456)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of bounds clamping positive`() {
|
||||
val color = RGBColor(0x145, 0x145, 0x145)
|
||||
assertEquals(color.red, 0xFF)
|
||||
assertEquals(color.green, 0xFF)
|
||||
assertEquals(color.blue, 0xFF)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of bounds clamping negative`() {
|
||||
val color = RGBColor(-123, -123, -123)
|
||||
assertEquals(color.red, 0)
|
||||
assertEquals(color.green, 0)
|
||||
assertEquals(color.blue, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `operations minus`() {
|
||||
val a = RGBColor(0x12, 0x34, 0x56)
|
||||
val b = RGBColor(0x05, 0x06, 0x07)
|
||||
|
||||
assertEquals(a - b, RGBColor(0x0D, 0x2e, 0x4F))
|
||||
assertEquals(a - 3, RGBColor(0x0F, 0x31, 0x53))
|
||||
assertEquals(a - 0.1f, RGBColor(0x00, 0x1b, 0x3d))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `conversion rgba`() {
|
||||
val color = RGBColor(0x12, 0x34, 0x56)
|
||||
|
||||
assertEquals(color.rgba(), RGBAColor(0x12, 0x34, 0x56, 0xFF))
|
||||
}
|
||||
|
||||
// TODO: operations (plus, times), conversion, toString, Int::rgb, Int::rgba, mix
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user