Start remaking UI rendering

Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
This commit is contained in:
Username404-59 2026-02-05 23:44:41 +01:00
parent b51e0ec2e0
commit 1c43549b8f
Signed by: Username404-59
GPG Key ID: 7AB361FBB257A5D1
5 changed files with 96 additions and 136 deletions

View File

@ -1,6 +1,6 @@
package fr.username404.snowygui.gui package fr.username404.snowygui.gui
import com.mojang.blaze3d.vertex.* import com.mojang.blaze3d.vertex.VertexConsumer
import fr.username404.snowygui.Snowy import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil import fr.username404.snowygui.utils.RenderingUtil
@ -58,8 +58,12 @@ abstract class ColoredElement(
} }
} }
} }
internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color) = colorIt(color, opacity) internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color) = colorIt(color, opacity)
protected fun defaultRectFunc() = RenderingUtil.drawRectangle(x, y, height, width, color, opacity)
protected fun defaultRectFunc(guiGraphics: GuiGraphics?) = guiGraphics?.let {
RenderingUtil.drawRectangle(it, x, y, height, width, color, opacity)
}
} }
fun hextoRGB(hex: Int): MutableList<Float> { fun hextoRGB(hex: Int): MutableList<Float> {

View File

@ -6,14 +6,10 @@ import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.feature.ButtonImpl import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.gui.feature.Category import fr.username404.snowygui.gui.feature.Category
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil.colorShader import fr.username404.snowygui.utils.RenderingUtil
import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import fr.username404.snowygui.utils.RenderingUtil.renderBufferWithPipeline
import io.github.config4k.extract import io.github.config4k.extract
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.renderer.RenderPipelines
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.util.ARGB import net.minecraft.util.ARGB
import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.ApiStatus
@ -44,13 +40,13 @@ class ClickBox(
) { ) {
override val color: Int get() = this@ClickBox.color override val color: Int get() = this@ClickBox.color
override fun render(guiGraphics: GuiGraphics?) { override fun render(guiGraphics: GuiGraphics?) {
prepareDraw() defaultRectFunc(guiGraphics)
colorShader(); defaultRectFunc();
endDraw()
} }
init { height = 8 } init { height = 8 }
} }
var barStage: Int = 1; private set var barStage: Int = 1; private set
fun scroll(d: Double, e: Double, supplied: Double) { fun scroll(d: Double, e: Double, supplied: Double) {
if (isWithinBounds(d, e, offsetHeight = clickboxHeightOffset.toDouble())) { if (isWithinBounds(d, e, offsetHeight = clickboxHeightOffset.toDouble())) {
with(buttonsProgressBar) { with(buttonsProgressBar) {
@ -75,33 +71,39 @@ class ClickBox(
const val clickboxHeightOffset: Int = 80 const val clickboxHeightOffset: Int = 80
private const val inclination: Float = 2.5F private const val inclination: Float = 2.5F
} }
override fun render(guiGraphics: GuiGraphics?) { override fun render(guiGraphics: GuiGraphics?) {
val x = x.toFloat() // Header
val y = y.toFloat() RenderingUtil.drawRectangle(
val currentHeight = y + (height + clickboxHeightOffset) guiGraphics = guiGraphics,
prepareDraw() x = x,
renderBufferWithPipeline(renderPipeline = RenderPipelines.DEBUG_TRIANGLE_FAN) { y = y,
// Render the header: height = height,
addVertex(x, y + height, 0.0F).colorEnd() width = width,
addVertex(x + width + inclination, y + height, 0.0F).colorEnd() color = color,
addVertex(x + width, y, 0.0F).colorEnd() opacity = opacity
addVertex(x + inclination, y, 0.0F).colorEnd() )
}
renderBufferWithPipeline(renderPipeline = RenderPipelines.DEBUG_TRIANGLE_FAN) { // Body
// Render the box: RenderingUtil.drawRectangle(
addVertex(x, currentHeight, 0.0F).colorEnd() guiGraphics = guiGraphics,
addVertex(x + width + inclination, currentHeight, 0.0F).colorEnd() x = x,
addVertex(x + width + inclination, y + height, 0.0F).colorEnd() y = (y + height),
addVertex(x, y + height, 0.0F).colorEnd() height = clickboxHeightOffset,
} width = width,
color = color,
opacity = opacity
)
renderBufferWithPipeline(renderPipeline = RenderPipelines.LINES_TRANSLUCENT) { // Separator line
colorShader() RenderingUtil.hLine(
addVertex(x + inclination, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue) guiGraphics = guiGraphics,
addVertex(x + width, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue) x1 = (x + 0).toInt(),
} x2 = (x + width).toInt(),
endDraw() y = (y + height).toInt(),
rgb = Colors.WHITE_LINES.hexValue,
opacity = 1f
)
if (buttons.isNotEmpty()) { if (buttons.isNotEmpty()) {
buttonsProgressBar.apply { buttonsProgressBar.apply {
@ -117,15 +119,15 @@ class ClickBox(
}.display(guiGraphics) }.display(guiGraphics)
} }
} }
guiGraphics?.run {
with(Minecraft.getInstance().font) { with(Minecraft.getInstance().font) {
drawString( guiGraphics?.drawString(
this, this,
Component.nullToEmpty(name.string), Component.nullToEmpty(name.string),
(x + 5).toInt(), (y + 2).toInt(), (x + 5).toInt(), (y + 2).toInt(),
ARGB.opaque(Colors.TRANSPARENT.hexValue), false ARGB.opaque(Colors.TRANSPARENT.hexValue),
) false
} )
} }
} }
} }

View File

@ -6,9 +6,6 @@ import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.ColoredElement import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type
import fr.username404.snowygui.utils.FontUtil import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.utils.RenderingUtil.colorShader
import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.input.MouseButtonEvent import net.minecraft.client.input.MouseButtonEvent
import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.findAnnotation
@ -46,20 +43,26 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
}.plus(Configuration.foundMacros).toTypedArray() }.plus(Configuration.foundMacros).toTypedArray()
) )
} }
var isDisabled: Boolean = false; set(value) { var isDisabled: Boolean = false; set(value) {
field = value field = value
hidden = value hidden = value
} }
@JvmField @JvmField
val info = this::class.findAnnotation<ButtonInfo>() ?: throw Exception("Missing @ButtonInfo annotaton") val info = this::class.findAnnotation<ButtonInfo>() ?: throw Exception("Missing @ButtonInfo annotaton")
final override var color = info.parent.categoryColor; get() { final override var color = info.parent.categoryColor; get() {
return info.parent.box.color.let { return info.parent.box.color.let {
if (field == it) field else it if (field == it) field else it
} }
} }
open val title: String = this@ButtonImpl::class.simpleName.toString() open val title: String = this@ButtonImpl::class.simpleName.toString()
protected open fun execAction() = Unit protected open fun execAction() = Unit
private var wasWithinBounds: Boolean = false private var wasWithinBounds: Boolean = false
var toggled: Boolean = false; private set(value) { var toggled: Boolean = false; private set(value) {
if (field xor value) { if (field xor value) {
if (value) lightUp() else lightDown() if (value) lightUp() else lightDown()
@ -67,8 +70,10 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
execAction() execAction()
} else field = value } else field = value
} }
private fun lightUp() { opacity += ButtonInfo.lightningFactor } private fun lightUp() { opacity += ButtonInfo.lightningFactor }
private fun lightDown() { opacity -= ButtonInfo.lightningFactor } private fun lightDown() { opacity -= ButtonInfo.lightningFactor }
final override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean { final override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
wasWithinBounds = isWithinBounds(event.x, event.y).also { wasWithinBounds = isWithinBounds(event.x, event.y).also {
if (it) { if (it) {
@ -84,12 +89,12 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
if (wasWithinBounds && (info.kind == Type.CLICK)) { if (wasWithinBounds && (info.kind == Type.CLICK)) {
execAction() execAction()
lightDown() lightDown()
}; return false }
return false
} }
final override fun render(guiGraphics: GuiGraphics?) { final override fun render(guiGraphics: GuiGraphics?) {
prepareDraw() defaultRectFunc(guiGraphics)
colorShader(); defaultRectFunc();
endDraw()
if (guiGraphics != null) { if (guiGraphics != null) {
FontUtil.drawScaled(guiGraphics, title, x + 1, y + 1, 0.75F) FontUtil.drawScaled(guiGraphics, title, x + 1, y + 1, 0.75F)
} }

View File

@ -44,7 +44,7 @@ object Keystrokes: ButtonImplWithHud() {
private fun drawKey(x: Double, y: Double, key: Int, guiGraphics: GuiGraphics?) { private fun drawKey(x: Double, y: Double, key: Int, guiGraphics: GuiGraphics?) {
RenderingUtil.prepareDraw() RenderingUtil.prepareDraw()
RenderingUtil.drawRectangle( RenderingUtil.drawRectangle(
x, y, height / 2, height / 2, guiGraphics, x, y, height / 2, height / 2,
color = color, opacity = getDynamicOpacity(key).toFloat() color = color, opacity = getDynamicOpacity(key).toFloat()
) )
RenderingUtil.endDraw() RenderingUtil.endDraw()
@ -68,7 +68,7 @@ object Keystrokes: ButtonImplWithHud() {
hud.display(it) hud.display(it)
} }
init { init {
if (!Position.values().map { it.value }.contains(currentPosition)) { if (!Position.entries.map { it.value }.contains(currentPosition)) {
currentPosition = Position.LEFT.value currentPosition = Position.LEFT.value
} }
} }

View File

@ -1,95 +1,44 @@
package fr.username404.snowygui.utils package fr.username404.snowygui.utils
import com.mojang.blaze3d.opengl.GlCommandEncoder
import com.mojang.blaze3d.opengl.GlStateManager import com.mojang.blaze3d.opengl.GlStateManager
import com.mojang.blaze3d.pipeline.RenderPipeline
import com.mojang.blaze3d.pipeline.RenderTarget
import com.mojang.blaze3d.systems.RenderPass
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.BufferBuilder
import com.mojang.blaze3d.vertex.Tesselator
import com.mojang.blaze3d.vertex.VertexConsumer
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.gui.hextoRGB import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.Minecraft import net.minecraft.util.ARGB
import net.minecraft.client.renderer.RenderPipelines
import org.joml.Matrix4f
import org.joml.Vector3f
import org.joml.Vector4f
import java.util.OptionalDouble
import java.util.OptionalInt
object RenderingUtil { object RenderingUtil {
@JvmStatic fun prepareDraw() = GlStateManager._enableBlend()
fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer = hextoRGB(color).run { fun endDraw() = GlStateManager._disableBlend()
setColor(get(0), get(1), get(2), opacity)
} private fun argbFromRgb(rgb: Int, opacity: Float = 1f): Int {
fun colorShader() {} return ARGB.color(
fun prepareDraw() { (opacity.coerceIn(0f, 1f) * 255f).toInt().coerceIn(0, 255),
colorShader() (rgb shr 16) and 0xFF,
GlStateManager._enableBlend() (rgb shr 8) and 0xFF,
} rgb and 0xFF
fun endDraw() { )
GlStateManager._disableBlend()
}
fun drawRectangle(
x: Double, y: Double, height: Int, width: Int,
color: Int = Colors.TRANSPARENT(), opacity: Float = 1F
): Unit = renderBufferWithPipeline(renderPipeline = RenderPipelines.DEBUG_QUADS) {
fun VertexConsumer.colorIt() = colorIt(color, opacity)
val x = x.toFloat() ; val y = y.toFloat()
addVertex(x, y + height, 0.0F).colorIt()
addVertex(x + width, y + height, 0.0F).colorIt()
addVertex(x + width, y, 0.0F).colorIt()
addVertex(x, y, 0.0F).colorIt()
} }
val gpuSlice = RenderSystem.getDynamicUniforms().writeTransform( fun drawRectangle(
RenderSystem.getModelViewMatrix(), guiGraphics: GuiGraphics?,
Vector4f(1F, 1F, 1F, 1F), // Alternative to old setShaderColor x: Double,
Vector3f(), y: Double,
Matrix4f() height: Int,
) width: Int,
fun renderBufferWithPipeline( color: Int = Colors.TRANSPARENT(),
name: String = "Dynamic vertex buffer", opacity: Float = 1F
renderPipeline: RenderPipeline,
renderTarget: RenderTarget = Minecraft.getInstance().mainRenderTarget,
uniformAndSamplerConsumer: ((RenderPass) -> Unit)? = null,
bufferBuilderConsumer: BufferBuilder.() -> Unit,
) { ) {
val mode = renderPipeline.vertexFormatMode prepareDraw()
val builder = Tesselator.getInstance().begin(mode, renderPipeline.vertexFormat) guiGraphics?.fill(
bufferBuilderConsumer(builder) x.toInt(), y.toInt(),
builder.buildOrThrow().use { meshData -> (x + width).toInt(), (y + height).toInt(),
val encoder = RenderSystem.getDevice().createCommandEncoder() as GlCommandEncoder argbFromRgb(color, opacity)
encoder.createRenderPass( )
{ name }, endDraw()
renderTarget.colorTextureView!!, }
OptionalInt.empty(),
renderTarget.depthTextureView!!, fun hLine(guiGraphics: GuiGraphics?, x1: Int, x2: Int, y: Int, rgb: Int, opacity: Float = 1f) {
OptionalDouble.empty() prepareDraw()
).use { renderPass -> guiGraphics?.hLine(x1, x2, y, argbFromRgb(rgb, opacity))
encoder.inRenderPass = false; endDraw()
RenderSystem.getDevice().createBuffer(
{ name }, 40, meshData.vertexBuffer()
).use { buffer ->
val autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(mode)
renderPass.setPipeline(renderPipeline)
renderPass.setVertexBuffer(0, buffer)
renderPass.setIndexBuffer(
autoStorageIndexBuffer.getBuffer(meshData.drawState().indexCount()),
autoStorageIndexBuffer.type()
)
// RenderSystem.bindDefaultUniforms(renderPass)
renderPass.setUniform(
"DynamicTransforms",
gpuSlice
)
uniformAndSamplerConsumer?.invoke(renderPass)
renderPass.drawIndexed(0, 0, meshData.drawState().indexCount(), 1)
}
encoder.inRenderPass = false;
}
}
} }
} }