aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/util/render/RenderCircleProgress.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/util/render/RenderCircleProgress.kt')
-rw-r--r--src/main/kotlin/util/render/RenderCircleProgress.kt118
1 files changed, 67 insertions, 51 deletions
diff --git a/src/main/kotlin/util/render/RenderCircleProgress.kt b/src/main/kotlin/util/render/RenderCircleProgress.kt
index d759033..81dde6f 100644
--- a/src/main/kotlin/util/render/RenderCircleProgress.kt
+++ b/src/main/kotlin/util/render/RenderCircleProgress.kt
@@ -1,85 +1,101 @@
package moe.nea.firmament.util.render
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.vertex.VertexFormat
import io.github.notenoughupdates.moulconfig.platform.next
+import java.util.OptionalInt
import org.joml.Matrix4f
-import org.joml.Vector2f
import util.render.CustomRenderLayers
-import kotlin.math.atan2
-import kotlin.math.tan
import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.render.BufferBuilder
+import net.minecraft.client.render.RenderLayer
+import net.minecraft.client.util.BufferAllocator
import net.minecraft.util.Identifier
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.collections.nonNegligibleSubSectionsAlignedWith
+import moe.nea.firmament.util.math.Projections
object RenderCircleProgress {
- fun renderCircle(
+ fun renderCircularSlice(
drawContext: DrawContext,
- texture: Identifier,
- progress: Float,
+ layer: RenderLayer,
u1: Float,
u2: Float,
v1: Float,
v2: Float,
+ angleRadians: ClosedFloatingPointRange<Float>,
+ color: Int = -1,
+ innerCutoutRadius: Float = 0F
) {
- drawContext.draw {
- val bufferBuilder = it.getBuffer(CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture))
- val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
-
- val corners = listOf(
- Vector2f(0F, -1F),
- Vector2f(1F, -1F),
- Vector2f(1F, 0F),
- Vector2f(1F, 1F),
- Vector2f(0F, 1F),
- Vector2f(-1F, 1F),
- Vector2f(-1F, 0F),
- Vector2f(-1F, -1F),
- )
+ drawContext.draw()
+ val sections = angleRadians.nonNegligibleSubSectionsAlignedWith((τ / 8f).toFloat())
+ .zipWithNext().toList()
+ BufferAllocator(layer.vertexFormat.vertexSize * sections.size * 3).use { allocator ->
- for (i in (0 until 8)) {
- if (progress < i / 8F) {
- break
- }
- val second = corners[(i + 1) % 8]
- val first = corners[i]
- if (progress <= (i + 1) / 8F) {
- val internalProgress = 1 - (progress - i / 8F) * 8F
- val angle = lerpAngle(
- atan2(second.y, second.x),
- atan2(first.y, first.x),
- internalProgress
- )
- if (angle < tau / 8 || angle >= tau * 7 / 8) {
- second.set(1F, tan(angle))
- } else if (angle < tau * 3 / 8) {
- second.set(1 / tan(angle), 1F)
- } else if (angle < tau * 5 / 8) {
- second.set(-1F, -tan(angle))
- } else {
- second.set(-1 / tan(angle), -1F)
- }
- }
+ val bufferBuilder = BufferBuilder(allocator, VertexFormat.DrawMode.TRIANGLES, layer.vertexFormat)
+ val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
+ 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, second.x, second.y, 0F)
- .texture(lerp(u1, u2, ilerp(second.x)), lerp(v1, v2, ilerp(second.y)))
- .color(-1)
+ .vertex(matrix, secondPoint.x, secondPoint.y, 0F)
+ .texture(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y)))
+ .color(color)
.next()
bufferBuilder
- .vertex(matrix, first.x, first.y, 0F)
- .texture(lerp(u1, u2, ilerp(first.x)), lerp(v1, v2, ilerp(first.y)))
- .color(-1)
+ .vertex(matrix, firstPoint.x, firstPoint.y, 0F)
+ .texture(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y)))
+ .color(color)
.next()
bufferBuilder
.vertex(matrix, 0F, 0F, 0F)
.texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
- .color(-1)
+ .color(color)
.next()
}
+
+ bufferBuilder.end().use { buffer ->
+ // TODO: write a better utility to pass uniforms :sob: ill even take a mixin at this point
+ if (innerCutoutRadius <= 0) {
+ layer.draw(buffer)
+ return
+ }
+ val vertexBuffer = layer.vertexFormat.uploadImmediateVertexBuffer(buffer.buffer)
+ val indexBufferConstructor = RenderSystem.getSequentialBuffer(VertexFormat.DrawMode.TRIANGLES)
+ val indexBuffer = indexBufferConstructor.getIndexBuffer(buffer.drawParameters.indexCount)
+ RenderSystem.getDevice().createCommandEncoder().createRenderPass(
+ MC.instance.framebuffer.colorAttachment,
+ OptionalInt.empty(),
+ ).use { renderPass ->
+ renderPass.setPipeline(layer.pipeline)
+ renderPass.setUniform("InnerCutoutRadius", innerCutoutRadius)
+ renderPass.setIndexBuffer(indexBuffer, indexBufferConstructor.indexType)
+ renderPass.setVertexBuffer(0, vertexBuffer)
+ renderPass.drawIndexed(0, buffer.drawParameters.indexCount)
+ }
+ }
}
}
-
+ fun renderCircle(
+ drawContext: DrawContext,
+ texture: Identifier,
+ progress: Float,
+ u1: Float,
+ u2: Float,
+ v1: Float,
+ v2: Float,
+ ) {
+ renderCircularSlice(
+ drawContext,
+ CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture),
+ u1, u2, v1, v2,
+ (-τ / 4).toFloat()..(progress * τ - τ / 4).toFloat()
+ )
+ }
}