Skip to content

Commit

Permalink
feat: hue slider now follows value on non clickgui value changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
opZywl committed Jan 11, 2025
1 parent 492fa8d commit 01985fe
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@
*/
package net.ccbluex.liquidbounce.ui.client.clickgui.style

import net.ccbluex.liquidbounce.config.ColorValue
import net.ccbluex.liquidbounce.config.Value
import net.ccbluex.liquidbounce.file.FileManager.saveConfig
import net.ccbluex.liquidbounce.file.FileManager.valuesConfig
import net.ccbluex.liquidbounce.ui.client.clickgui.Panel
import net.ccbluex.liquidbounce.ui.client.clickgui.elements.ButtonElement
import net.ccbluex.liquidbounce.ui.client.clickgui.elements.ModuleElement
import net.ccbluex.liquidbounce.utils.client.MinecraftInstance
import net.ccbluex.liquidbounce.config.Value
import net.ccbluex.liquidbounce.utils.client.asResourceLocation
import net.ccbluex.liquidbounce.utils.client.playSound
import net.ccbluex.liquidbounce.utils.timing.WaitTickUtils
import org.lwjgl.input.Mouse
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE
import java.awt.Color
import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.math.BigDecimal
import java.nio.ByteBuffer
import kotlin.math.max

abstract class Style : MinecraftInstance {
Expand All @@ -29,13 +38,107 @@ abstract class Style : MinecraftInstance {
abstract fun drawButtonElement(mouseX: Int, mouseY: Int, buttonElement: ButtonElement)
abstract fun drawModuleElementAndClick(mouseX: Int, mouseY: Int, moduleElement: ModuleElement, mouseButton: Int?): Boolean

data class ColorValueCache(val lastHue: Float, val cachedTextureID: Int)

private val colorValueCache: MutableMap<ColorValue, MutableMap<Int, ColorValueCache>> = mutableMapOf()

fun ColorValue.updateTextureCache(
id: Int, hue: Float, width: Int, height: Int, generateImage: (BufferedImage, Graphics2D) -> Unit,
drawAt: (Int) -> Unit
) {
val cached = colorValueCache[this]?.get(id)
val lastHue = cached?.lastHue

if (lastHue == null || lastHue != hue) {
val image = createRGBImageDrawing(width, height) { img, graphics -> generateImage(img, graphics) }
val texture = convertImageToTexture(image)
colorValueCache.getOrPut(this, ::mutableMapOf)[id] = ColorValueCache(hue, texture)
}

colorValueCache[this]?.get(id)?.cachedTextureID?.let(drawAt)
}

private fun createRGBImageDrawing(width: Int, height: Int, f: (BufferedImage, Graphics2D) -> Unit): BufferedImage {
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
val g = image.createGraphics()

f(image, g)

g.dispose()
return image
}

private fun convertImageToTexture(image: BufferedImage): Int {
val width = image.width
val height = image.height

val pixels = IntArray(width * height)

image.getRGB(0, 0, width, height, pixels, 0, width)

val buffer = ByteBuffer.allocateDirect(width * height * 4)

for (i in pixels.indices) {
val pixel = pixels[i]
buffer.put(((pixel shr 16) and 0xFF).toByte())
buffer.put(((pixel shr 8) and 0xFF).toByte())
buffer.put(((pixel shr 0) and 0xFF).toByte())
buffer.put(((pixel shr 24) and 0xFF).toByte())
}

buffer.flip()

val textureID = glGenTextures()

glPushAttrib(GL_ALL_ATTRIB_BITS)
glPushMatrix()

glBindTexture(GL_TEXTURE_2D, textureID)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer)

glPopMatrix()
glPopAttrib()

return textureID
}

fun drawTexture(textureID: Int, x: Int, y: Int, width: Int, height: Int) {
glPushAttrib(GL_ALL_ATTRIB_BITS)
glPushMatrix()

glEnable(GL_TEXTURE_2D)

glBindTexture(GL_TEXTURE_2D, textureID)

glTranslatef(x.toFloat(), y.toFloat(), 0.0f)

glBegin(GL_QUADS)
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f) // Bottom-left corner
glTexCoord2f(1.0f, 0.0f); glVertex2f(width.toFloat(), 0.0f) // Bottom-right corner
glTexCoord2f(1.0f, 1.0f); glVertex2f(width.toFloat(), height.toFloat()) // Top-right corner
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height.toFloat()) // Top-left corner
glEnd()

glDisable(GL_TEXTURE_2D)

glPopMatrix()
glPopAttrib()
}

fun clickSound() {
mc.playSound("gui.button.press".asResourceLocation())
}

fun showSettingsSound() {
mc.playSound("random.bow".asResourceLocation())
}

protected fun round(v: Float): Float {
var bigDecimal = BigDecimal(v.toString())
bigDecimal = bigDecimal.setScale(2, 4)
Expand All @@ -50,4 +153,16 @@ abstract class Style : MinecraftInstance {

return Color(max(r, 0), max(g, 0), max(b, 0), alpha).rgb
}

fun <T> Value<T>.setAndSaveValueOnButtonRelease(new: T) {
set(new, false)

with(WaitTickUtils) {
if (!hasScheduled(this)) {
conditionalSchedule(this, 10) {
(sliderValueHeld == null).also { if (it) saveConfig(valuesConfig) }
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import kotlin.math.min
* Each panel can be dragged and displays modules. Now includes a small outline
* around the category's top bar if enabled in [ClickGUIModule].
*/
class MainScreen(private val category: Category) : Screen {
class DropdownCategory(private val category: Category) : Screen {

private val rectWidth = 110f
private val categoryRectHeight = 18f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ class FDPDropdownClickGUI : GuiScreen() {

private val hudIcon = ResourceLocation("${CLIENT_NAME.lowercase()}/custom_hud_icon.png")

private var categoryPanels: MutableList<MainScreen>? = null
private var categoryPanels: MutableList<DropdownCategory>? = null

override fun initGui() {
if (categoryPanels == null || Main.reloadModules) {
categoryPanels = mutableListOf<MainScreen>().apply {
categoryPanels = mutableListOf<DropdownCategory>().apply {
Category.entries.forEach { category ->
add(MainScreen(category))
add(DropdownCategory(category))
}
}
Main.reloadModules = false
Expand Down

0 comments on commit 01985fe

Please sign in to comment.