aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/util/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/util/render')
-rw-r--r--src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt48
-rw-r--r--src/main/kotlin/util/render/RenderCircleProgress.kt170
2 files changed, 166 insertions, 52 deletions
diff --git a/src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt b/src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt
new file mode 100644
index 0000000..ce56df3
--- /dev/null
+++ b/src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt
@@ -0,0 +1,48 @@
+package moe.nea.firmament.util.render
+
+import org.joml.Matrix3x2f
+import net.minecraft.client.gui.ScreenRect
+import net.minecraft.client.gui.render.SpecialGuiElementRenderer
+import net.minecraft.client.gui.render.state.GuiRenderState
+import net.minecraft.client.gui.render.state.special.SpecialGuiElementRenderState
+import net.minecraft.client.render.VertexConsumerProvider
+
+abstract class MultiSpecialGuiRenderState : SpecialGuiElementRenderState {
+ // I wish i had manifolds @Self type here... Maybe i should switch to java after all :(
+ abstract fun createRenderer(vertexConsumers: VertexConsumerProvider.Immediate): MultiSpecialGuiRenderer<out MultiSpecialGuiRenderState>
+ abstract val x1: Int
+ abstract val x2: Int
+ abstract val y1: Int
+ abstract val y2: Int
+ abstract val scale: Float
+ abstract val bounds: ScreenRect?
+ abstract val scissorArea: ScreenRect?
+ override fun x1(): Int = x1
+
+ override fun x2(): Int = x2
+
+ override fun y1(): Int = y1
+
+ override fun y2(): Int = y2
+
+ override fun scale(): Float = scale
+
+ override fun scissorArea(): ScreenRect? = scissorArea
+
+ override fun bounds(): ScreenRect? = bounds
+
+}
+
+abstract class MultiSpecialGuiRenderer<T : MultiSpecialGuiRenderState>(
+ vertexConsumers: VertexConsumerProvider.Immediate
+) : SpecialGuiElementRenderer<T>(vertexConsumers) {
+ var wasUsedThisFrame = false
+ fun consumeRender(): Boolean {
+ return wasUsedThisFrame.also { wasUsedThisFrame = false }
+ }
+
+ override fun renderElement(element: T, state: GuiRenderState) {
+ wasUsedThisFrame = true
+ super.renderElement(element, state)
+ }
+}
diff --git a/src/main/kotlin/util/render/RenderCircleProgress.kt b/src/main/kotlin/util/render/RenderCircleProgress.kt
index efd99fe..bbc4ace 100644
--- a/src/main/kotlin/util/render/RenderCircleProgress.kt
+++ b/src/main/kotlin/util/render/RenderCircleProgress.kt
@@ -4,9 +4,12 @@ import com.mojang.blaze3d.vertex.VertexFormat
import org.joml.Matrix3x2f
import util.render.CustomRenderLayers
import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.gui.ScreenRect
import net.minecraft.client.render.BufferBuilder
import net.minecraft.client.render.RenderLayer
+import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.util.BufferAllocator
+import net.minecraft.client.util.math.MatrixStack
import net.minecraft.util.Identifier
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.collections.nonNegligibleSubSectionsAlignedWith
@@ -15,6 +18,105 @@ import moe.nea.firmament.util.mc.CustomRenderPassHelper
object RenderCircleProgress {
+
+ data class State(
+ override val x1: Int,
+ override val x2: Int,
+ override val y1: Int,
+ override val y2: Int,
+ val layer: RenderLayer.MultiPhase,
+ val u1: Float,
+ val u2: Float,
+ val v1: Float,
+ val v2: Float,
+ val angleRadians: ClosedFloatingPointRange<Float>,
+ val color: Int,
+ val innerCutoutRadius: Float,
+ override val scale: Float,
+ override val bounds: ScreenRect?,
+ override val scissorArea: ScreenRect?,
+ ) : MultiSpecialGuiRenderState() {
+ override fun createRenderer(vertexConsumers: VertexConsumerProvider.Immediate): MultiSpecialGuiRenderer<out MultiSpecialGuiRenderState> {
+ return Renderer(vertexConsumers)
+ }
+ }
+
+ class Renderer(vertexConsumers: VertexConsumerProvider.Immediate) :
+ MultiSpecialGuiRenderer<State>(vertexConsumers) {
+ override fun render(
+ state: State,
+ matrices: MatrixStack
+ ) {
+ matrices.push()
+ matrices.translate(0F, -1F, 0F)
+ val sections = state.angleRadians.nonNegligibleSubSectionsAlignedWith((τ / 8f).toFloat())
+ .zipWithNext().toList()
+ val u1 = state.u1
+ val u2 = state.u2
+ val v1 = state.v1
+ val v2 = state.v2
+ val color = state.color
+ val matrix = matrices.peek().positionMatrix
+ BufferAllocator(state.layer.vertexFormat.vertexSize * sections.size * 3).use { allocator ->
+
+ val bufferBuilder = BufferBuilder(allocator, VertexFormat.DrawMode.TRIANGLES, state.layer.vertexFormat)
+
+ for ((sectionStart, sectionEnd) in sections) {
+ val firstPoint = Projections.Two.projectAngleOntoUnitBox(sectionStart.toDouble())
+ val secondPoint = Projections.Two.projectAngleOntoUnitBox(sectionEnd.toDouble())
+ fun ilerp(f: Float): Float =
+ ilerp(-1f, 1f, f)
+
+ bufferBuilder
+ .vertex(matrix, secondPoint.x, secondPoint.y, 0F)
+ .texture(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y)))
+ .color(color)
+
+ bufferBuilder
+ .vertex(matrix, firstPoint.x, firstPoint.y, 0F)
+ .texture(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y)))
+ .color(color)
+
+ bufferBuilder
+ .vertex(matrix, 0F, 0F, 0F)
+ .texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
+ .color(color)
+
+ }
+
+ bufferBuilder.end().use { buffer ->
+ if (state.innerCutoutRadius <= 0) {
+ state.layer.draw(buffer)
+ return
+ }
+ CustomRenderPassHelper(
+ { "RenderCircleProgress" },
+ VertexFormat.DrawMode.TRIANGLES,
+ state.layer.vertexFormat,
+ MC.instance.framebuffer,
+ false,
+ ).use { renderPass ->
+ renderPass.uploadVertices(buffer)
+ renderPass.setPipeline(state.layer.pipeline)
+ renderPass.setUniform("InnerCutoutRadius", 4) {
+ it.putFloat(state.innerCutoutRadius)
+ }
+ renderPass.draw()
+ }
+ }
+ }
+ matrices.pop()
+ }
+
+ override fun getElementClass(): Class<State> {
+ return State::class.java
+ }
+
+ override fun getName(): String {
+ return "Firmament Circle"
+ }
+ }
+
fun renderCircularSlice(
drawContext: DrawContext,
layer: RenderLayer.MultiPhase,
@@ -25,58 +127,22 @@ object RenderCircleProgress {
angleRadians: ClosedFloatingPointRange<Float>,
color: Int = -1,
innerCutoutRadius: Float = 0F
- ) { // TODO: this is fixed by adding a special gui element renderer
- val sections = angleRadians.nonNegligibleSubSectionsAlignedWith((τ / 8f).toFloat())
- .zipWithNext().toList()
- BufferAllocator(layer.vertexFormat.vertexSize * sections.size * 3).use { allocator ->
-
- val bufferBuilder = BufferBuilder(allocator, VertexFormat.DrawMode.TRIANGLES, layer.vertexFormat)
- val matrix: Matrix3x2f = drawContext.matrices
-
- for ((sectionStart, sectionEnd) in sections) {
- val firstPoint = Projections.Two.projectAngleOntoUnitBox(sectionStart.toDouble())
- val secondPoint = Projections.Two.projectAngleOntoUnitBox(sectionEnd.toDouble())
- fun ilerp(f: Float): Float =
- ilerp(-1f, 1f, f)
-
- bufferBuilder
- .vertex(matrix, secondPoint.x, secondPoint.y, 0F)
- .texture(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y)))
- .color(color)
-
- bufferBuilder
- .vertex(matrix, firstPoint.x, firstPoint.y, 0F)
- .texture(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y)))
- .color(color)
-
- bufferBuilder
- .vertex(matrix, 0F, 0F, 0F)
- .texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
- .color(color)
-
- }
-
- bufferBuilder.end().use { buffer ->
- if (innerCutoutRadius <= 0) {
- layer.draw(buffer)
- return
- }
- CustomRenderPassHelper(
- { "RenderCircleProgress" },
- VertexFormat.DrawMode.TRIANGLES,
- layer.vertexFormat,
- MC.instance.framebuffer,
- false,
- ).use { renderPass ->
- renderPass.uploadVertices(buffer)
- renderPass.setPipeline(layer.pipeline)
- renderPass.setUniform("InnerCutoutRadius", 4) {
- it.putFloat(innerCutoutRadius)
- }
- renderPass.draw()
- }
- }
- }
+ ) {
+ val screenRect = ScreenRect(-1, -1, 2, 2).transform(drawContext.matrices)
+ drawContext.state.addSpecialElement(
+ State(
+ screenRect.left, screenRect.right,
+ screenRect.top, screenRect.bottom,
+ layer,
+ u1, u2, v1, v2,
+ angleRadians,
+ color,
+ innerCutoutRadius,
+ screenRect.width / 2F,
+ screenRect,
+ null
+ )
+ )
}
fun renderCircle(