Skip to content

Commit

Permalink
feat: ColorValue for RGBColors
Browse files Browse the repository at this point in the history
  • Loading branch information
opZywl committed Jan 7, 2025
1 parent 375ef98 commit b1be475
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 23 deletions.
59 changes: 47 additions & 12 deletions src/main/java/net/ccbluex/liquidbounce/config/Value.kt
Original file line number Diff line number Diff line change
Expand Up @@ -420,42 +420,77 @@ open class NumberValue(
}

class ColorValue(
val nameVal: String,
initialColor: Color,
val module: Any?
) {
name: String,
defaultColor: Color,
var rainbow: Boolean = false,
var showPicker: Boolean = false
) : Value<Color>(name, defaultColor) {

var hue = 0f
var saturation = 1f
var brightness = 1f
var alpha = 1f
var rainbow = false

init {
set(initialColor)
changeValue(defaultColor)
}

fun get(): Color {
fun getColor(): Color {
val base = Color.getHSBColor(hue, saturation, brightness)
val finalAlpha = (alpha * 255).toInt().coerceIn(0, 255)
return Color(base.red, base.green, base.blue, finalAlpha)
}

fun set(color: Color) {
val hsb = Color.RGBtoHSB(color.red, color.green, color.blue, null)
fun setColor(color: Color) {
set(color)
}

override fun onInit(value: Color) {
val r = value.red
val g = value.green
val b = value.blue
val a = value.alpha
val hsb = Color.RGBtoHSB(r, g, b, null)
hue = hsb[0]
saturation = hsb[1]
brightness = hsb[2]
alpha = a / 255f
}

override fun onChange(oldValue: Color, newValue: Color): Color {
val r = newValue.red
val g = newValue.green
val b = newValue.blue
val a = newValue.alpha
val hsb = Color.RGBtoHSB(r, g, b, null)
hue = hsb[0]
saturation = hsb[1]
brightness = hsb[2]
alpha = color.alpha / 255f
alpha = a / 255f
return newValue
}

override fun toJsonF(): JsonElement? {
val argbHex = "#%08X".format(value.rgb)
return JsonPrimitive(argbHex)
}

override fun fromJsonF(element: JsonElement): Color? {
if (element.isJsonPrimitive) {
val raw = element.asString.removePrefix("#")
val argb = raw.toLongOrNull(16)?.toInt()
if (argb != null) return Color(argb, true)
}
return null
}
}

val customBgColorValue = ColorValue(
"CustomBG",
Color(32, 32, 64),
null
false
)


fun int(
name: String,
value: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import net.ccbluex.liquidbounce.utils.block.BlockUtils.getBlockName
import net.ccbluex.liquidbounce.utils.extensions.component1
import net.ccbluex.liquidbounce.utils.extensions.component2
import net.ccbluex.liquidbounce.utils.extensions.lerpWith
import net.ccbluex.liquidbounce.utils.render.ColorUtils
import net.ccbluex.liquidbounce.utils.render.RenderUtils
import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawBorderedRect
import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawFilledCircle
import net.ccbluex.liquidbounce.utils.render.RenderUtils.drawRect
Expand Down Expand Up @@ -247,10 +249,8 @@ object BlackStyle : Style() {
)
)

// Keep changing this slider until mouse is unpressed.
sliderValueHeld = value

// Stop rendering and interacting only when this event was triggered by a mouse click.
if (mouseButton == 0) return true
}

Expand Down Expand Up @@ -288,10 +288,8 @@ object BlackStyle : Style() {
.coerceIn(value.range)
)

// Keep changing this slider until mouse is unpressed.
sliderValueHeld = value

// Stop rendering and interacting only when this event was triggered by a mouse click.
if (mouseButton == 0) return true
}

Expand Down Expand Up @@ -331,10 +329,8 @@ object BlackStyle : Style() {
value.setFirst(value.lerpWith(percentage).coerceIn(value.minimum, slider2))
} else value.setLast(value.lerpWith(percentage).coerceIn(slider1, value.maximum))

// Keep changing this slider until mouse is unpressed.
sliderValueHeld = value

// Stop rendering and interacting only when this event was triggered by a mouse click.
if (mouseButton == 0) return true
}

Expand Down Expand Up @@ -383,10 +379,8 @@ object BlackStyle : Style() {
value.setFirst(value.lerpWith(percentage).coerceIn(value.minimum, slider2))
} else value.setLast(value.lerpWith(percentage).coerceIn(slider1, value.maximum))

// Keep changing this slider until mouse is unpressed.
sliderValueHeld = value

// Stop rendering and interacting only when this event was triggered by a mouse click.
if (mouseButton == 0) return true
}

Expand Down Expand Up @@ -415,16 +409,149 @@ object BlackStyle : Style() {
font35.drawString(displayString, minX + 2, yPos + 2, Color.WHITE.rgb)

if (mouseButton != null && mouseX in minX..maxX && mouseY in yPos..yPos + 12) {
// Cycle to next font when left-clicked, previous when right-clicked.
if (mouseButton == 0) value.next()
else value.previous()
if (mouseButton == 0) value.next() else value.previous()
clickSound()
return true
}

yPos += 11
}

is ColorValue -> {
val colorValue = value

val currentColor = if (colorValue.rainbow) {
ColorUtils.rainbow()
} else {
colorValue.get()
}

val previewSize = 10
val previewX1 = moduleElement.x + moduleElement.width + 4
val previewY1 = yPos + 2
val previewX2 = previewX1 + previewSize
val previewY2 = previewY1 + previewSize

drawRect(previewX1, previewY1, previewX2, previewY2, currentColor.rgb)

if (mouseButton == 0 && mouseX in previewX1..previewX2 && mouseY in previewY1..previewY2) {
colorValue.showPicker = !colorValue.showPicker
clickSound()
return true
}

if (!colorValue.showPicker) {
yPos += (previewSize + 6)
return false
}

if (!colorValue.rainbow) {
val hsb = Color.RGBtoHSB(currentColor.red, currentColor.green, currentColor.blue, null)
var hue = hsb[0]
var saturation = hsb[1]
var brightness = hsb[2]

val colorPickerWidth = 75
val colorPickerHeight = 50
val hueSliderWidth = 7
val hueSliderHeight = 50

val startX = previewX1
val startY = previewY1 + previewSize + 4

font35.drawCenteredStringWithShadow(
"Color",
(startX + 1).toFloat(),
(startY - 10).toFloat(),
0xFFFFFFFF.toInt()
)

for (px in 0 until colorPickerWidth) {
for (py in 0 until colorPickerHeight) {
val localS = px / colorPickerWidth.toFloat()
val localB = 1.0f - (py / colorPickerHeight.toFloat())
val rgb = Color.HSBtoRGB(hue, localS, localB)
drawRect(startX + px, startY + py, startX + px + 1, startY + py + 1, rgb)
}
}

val markerX = startX + (saturation * colorPickerWidth).toInt()
val markerY = startY + ((1.0f - brightness) * colorPickerHeight).toInt()
RenderUtils.drawBorderedRectRGB(
markerX - 2, markerY - 2,
markerX + 3, markerY + 3,
1.0f,
0xFFFFFFFF.toInt(),
0x00000000
)

val hueSliderX = startX + colorPickerWidth + 5
val hueSliderY = startY
for (i in 0 until hueSliderHeight) {
val localHue = i / hueSliderHeight.toFloat()
val rgb = Color.HSBtoRGB(localHue, 1.0f, 1.0f)
drawRect(hueSliderX, hueSliderY + i, hueSliderX + hueSliderWidth, hueSliderY + i + 1, rgb)
}

val hueMarkerY = hueSliderY + (hue * hueSliderHeight).toInt()
RenderUtils.drawBorderedRectRGB(
hueSliderX - 1, hueMarkerY - 1,
hueSliderX + hueSliderWidth + 1, hueMarkerY + 2,
1.0f,
0xFFFFFFFF.toInt(),
0x00000000
)

val inColorPicker =
(mouseX in startX until (startX + colorPickerWidth)) &&
(mouseY in startY until (startY + colorPickerHeight))

val inHueSlider =
(mouseX in hueSliderX until (hueSliderX + hueSliderWidth)) &&
(mouseY in hueSliderY until (hueSliderY + hueSliderHeight))

if ((mouseButton == 0 || sliderValueHeld == colorValue) && (inColorPicker || inHueSlider)) {
if (inColorPicker) {
val newS = ((mouseX - startX) / colorPickerWidth.toFloat()).coerceIn(0f, 1f)
val newB = (1.0f - ((mouseY - startY) / colorPickerHeight.toFloat())).coerceIn(0f, 1f)
saturation = newS
brightness = newB
}
if (inHueSlider) {
val newH = ((mouseY - hueSliderY) / hueSliderHeight.toFloat()).coerceIn(0f, 1f)
hue = newH
}

sliderValueHeld = colorValue

if (mouseButton == 0) {
return true
}
}

val finalRGB = Color.HSBtoRGB(hue, saturation, brightness)
val finalColor = Color(finalRGB)
colorValue.set(finalColor)

val previewSubSize = 6
drawRect(
startX + 75,
startY - 10,
startX + 75 + previewSubSize,
startY - 10 + previewSubSize,
finalColor.rgb
)

yPos += colorPickerHeight + previewSize + 6
} else {
yPos += previewSize + 15
}

if (mouseButton == -1) {
sliderValueHeld = null
}
}

else -> {
val text = value.name + "§f: " + value.get()

Expand All @@ -443,6 +570,10 @@ object BlackStyle : Style() {
}
}

if (mouseButton == -1) {
sliderValueHeld = null
}

return false
}
}
25 changes: 25 additions & 0 deletions src/main/java/net/ccbluex/liquidbounce/utils/render/ColorUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package net.ccbluex.liquidbounce.utils.render

import net.ccbluex.liquidbounce.utils.attack.EntityUtils.getHealth
import net.ccbluex.liquidbounce.utils.extensions.lerp
import net.ccbluex.liquidbounce.utils.kotlin.RandomUtils.nextInt
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.entity.EntityLivingBase
Expand Down Expand Up @@ -181,6 +182,30 @@ object ColorUtils {
GlStateManager.color(1f, 1f, 1f, 1f)
}

fun getOverallColorFrom(color1: Int, color2: Int, percentTo2: Float): Int {
return Color(
lerp((color1 shr 16 and 0xFF).toFloat(), (color2 shr 16 and 0xFF).toFloat(), percentTo2),
lerp((color1 shr 8 and 0xFF).toFloat(), (color2 shr 8 and 0xFF).toFloat(), percentTo2),
lerp((color1 and 0xFF).toFloat(), (color2 and 0xFF).toFloat(), percentTo2),
lerp((color1 shr 24 and 0xFF).toFloat(), (color2 shr 24 and 0xFF).toFloat(), percentTo2)
).rgb
}

fun getCustomColor(red: Int, green: Int, blue: Int, alpha: Int): Int {
var color = 0
color = color or (alpha shl 24)
color = color or (red shl 16)
color = color or (green shl 8)
return blue.let { color = color or it; color }
}

fun swapAlpha(color: Int, alpha: Float): Int {
val f = color shr 16 and 0xFF
val f1 = color shr 8 and 0xFF
val f2 = color and 0xFF
return getCustomColor(f, f1, f2, alpha.toInt())
}

fun reAlpha(color: Int, alpha: Float): Color {
val c = Color(color)
val r = 0.003921569f * c.red.toFloat()
Expand Down

0 comments on commit b1be475

Please sign in to comment.