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
import com.mojang.blaze3d.vertex.*
import com.mojang.blaze3d.vertex.VertexConsumer
import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.Colors
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)
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> {

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.Category
import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil.colorShader
import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import fr.username404.snowygui.utils.RenderingUtil.renderBufferWithPipeline
import fr.username404.snowygui.utils.RenderingUtil
import io.github.config4k.extract
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.renderer.RenderPipelines
import net.minecraft.network.chat.Component
import net.minecraft.util.ARGB
import org.jetbrains.annotations.ApiStatus
@ -44,13 +40,13 @@ class ClickBox(
) {
override val color: Int get() = this@ClickBox.color
override fun render(guiGraphics: GuiGraphics?) {
prepareDraw()
colorShader(); defaultRectFunc();
endDraw()
defaultRectFunc(guiGraphics)
}
init { height = 8 }
}
var barStage: Int = 1; private set
fun scroll(d: Double, e: Double, supplied: Double) {
if (isWithinBounds(d, e, offsetHeight = clickboxHeightOffset.toDouble())) {
with(buttonsProgressBar) {
@ -75,33 +71,39 @@ class ClickBox(
const val clickboxHeightOffset: Int = 80
private const val inclination: Float = 2.5F
}
override fun render(guiGraphics: GuiGraphics?) {
val x = x.toFloat()
val y = y.toFloat()
val currentHeight = y + (height + clickboxHeightOffset)
prepareDraw()
renderBufferWithPipeline(renderPipeline = RenderPipelines.DEBUG_TRIANGLE_FAN) {
// Render the header:
addVertex(x, y + height, 0.0F).colorEnd()
addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
addVertex(x + width, y, 0.0F).colorEnd()
addVertex(x + inclination, y, 0.0F).colorEnd()
}
// Header
RenderingUtil.drawRectangle(
guiGraphics = guiGraphics,
x = x,
y = y,
height = height,
width = width,
color = color,
opacity = opacity
)
renderBufferWithPipeline(renderPipeline = RenderPipelines.DEBUG_TRIANGLE_FAN) {
// Render the box:
addVertex(x, currentHeight, 0.0F).colorEnd()
addVertex(x + width + inclination, currentHeight, 0.0F).colorEnd()
addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
addVertex(x, y + height, 0.0F).colorEnd()
}
// Body
RenderingUtil.drawRectangle(
guiGraphics = guiGraphics,
x = x,
y = (y + height),
height = clickboxHeightOffset,
width = width,
color = color,
opacity = opacity
)
renderBufferWithPipeline(renderPipeline = RenderPipelines.LINES_TRANSLUCENT) {
colorShader()
addVertex(x + inclination, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
addVertex(x + width, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
}
endDraw()
// Separator line
RenderingUtil.hLine(
guiGraphics = guiGraphics,
x1 = (x + 0).toInt(),
x2 = (x + width).toInt(),
y = (y + height).toInt(),
rgb = Colors.WHITE_LINES.hexValue,
opacity = 1f
)
if (buttons.isNotEmpty()) {
buttonsProgressBar.apply {
@ -117,15 +119,15 @@ class ClickBox(
}.display(guiGraphics)
}
}
guiGraphics?.run {
with(Minecraft.getInstance().font) {
drawString(
this,
Component.nullToEmpty(name.string),
(x + 5).toInt(), (y + 2).toInt(),
ARGB.opaque(Colors.TRANSPARENT.hexValue), false
)
}
with(Minecraft.getInstance().font) {
guiGraphics?.drawString(
this,
Component.nullToEmpty(name.string),
(x + 5).toInt(), (y + 2).toInt(),
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.feature.ButtonInfo.Companion.Type
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.input.MouseButtonEvent
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()
)
}
var isDisabled: Boolean = false; set(value) {
field = value
hidden = value
}
@JvmField
val info = this::class.findAnnotation<ButtonInfo>() ?: throw Exception("Missing @ButtonInfo annotaton")
final override var color = info.parent.categoryColor; get() {
return info.parent.box.color.let {
if (field == it) field else it
}
}
open val title: String = this@ButtonImpl::class.simpleName.toString()
protected open fun execAction() = Unit
private var wasWithinBounds: Boolean = false
var toggled: Boolean = false; private set(value) {
if (field xor value) {
if (value) lightUp() else lightDown()
@ -67,8 +70,10 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
execAction()
} else field = value
}
private fun lightUp() { opacity += ButtonInfo.lightningFactor }
private fun lightDown() { opacity -= ButtonInfo.lightningFactor }
final override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
wasWithinBounds = isWithinBounds(event.x, event.y).also {
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)) {
execAction()
lightDown()
}; return false
}
return false
}
final override fun render(guiGraphics: GuiGraphics?) {
prepareDraw()
colorShader(); defaultRectFunc();
endDraw()
defaultRectFunc(guiGraphics)
if (guiGraphics != null) {
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?) {
RenderingUtil.prepareDraw()
RenderingUtil.drawRectangle(
x, y, height / 2, height / 2,
guiGraphics, x, y, height / 2, height / 2,
color = color, opacity = getDynamicOpacity(key).toFloat()
)
RenderingUtil.endDraw()
@ -68,7 +68,7 @@ object Keystrokes: ButtonImplWithHud() {
hud.display(it)
}
init {
if (!Position.values().map { it.value }.contains(currentPosition)) {
if (!Position.entries.map { it.value }.contains(currentPosition)) {
currentPosition = Position.LEFT.value
}
}

View File

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