
net.peanuuutz.fork.ui.scene.screen.NativeCanvasHelperImpl.kt Maven / Gradle / Ivy
package net.peanuuutz.fork.ui.scene.screen
import net.minecraft.client.gl.ShaderProgram
import net.peanuuutz.fork.render.gl.GLContext.blendFunctionSeparate
import net.peanuuutz.fork.render.gl.GLContext.colorLogic
import net.peanuuutz.fork.render.gl.GLContext.disableBlend
import net.peanuuutz.fork.render.gl.GLContext.disableColorLogic
import net.peanuuutz.fork.render.gl.GLContext.enableBlend
import net.peanuuutz.fork.render.gl.GLContext.enableColorLogic
import net.peanuuutz.fork.render.gl.GLContext.setShaderTexture
import net.peanuuutz.fork.render.gl.GLContext.shaderAlpha
import net.peanuuutz.fork.render.gl.GLContext.shaderProgram
import net.peanuuutz.fork.render.gl.context.BlendFunction
import net.peanuuutz.fork.render.gl.context.ColorLogic
import net.peanuuutz.fork.render.screen.clip.StencilClip
import net.peanuuutz.fork.render.screen.draw.Drawer
import net.peanuuutz.fork.render.vertex.bufferPosColor
import net.peanuuutz.fork.render.vertex.bufferPosColorTex
import net.peanuuutz.fork.render.vertex.bufferPosTex
import net.peanuuutz.fork.render.vertex.draw
import net.peanuuutz.fork.render.vertex.tessellator
import net.peanuuutz.fork.ui.scene.base.MatrixStackCanvas
import net.peanuuutz.fork.ui.scene.base.currentTransformation
import net.peanuuutz.fork.ui.scene.base.toNative
import net.peanuuutz.fork.ui.ui.draw.canvas.BlendMode
import net.peanuuutz.fork.ui.ui.draw.canvas.BlockClipSave
import net.peanuuutz.fork.ui.ui.draw.canvas.Canvas
import net.peanuuutz.fork.ui.ui.draw.canvas.ClipSave
import net.peanuuutz.fork.ui.ui.draw.canvas.OutlineClipSave
import net.peanuuutz.fork.ui.ui.draw.canvas.PosColorTexVertices
import net.peanuuutz.fork.ui.ui.draw.canvas.PosColorVertices
import net.peanuuutz.fork.ui.ui.draw.canvas.PosTexVertices
import net.peanuuutz.fork.ui.ui.draw.shape.Outline
import net.peanuuutz.fork.util.common.Color
// We use a global stack to track shader alpha in order to avoid problems caused by zero alpha
private val shaderAlphaCache: ArrayDeque = ArrayDeque(4)
private val BlendFunctions: List = listOf(
BlendFunction.Default,
BlendFunction.Clear,
BlendFunction.Src,
BlendFunction.Dst,
BlendFunction.SrcOver,
BlendFunction.DstOver,
BlendFunction.SrcIn,
BlendFunction.DstIn,
BlendFunction.SrcOut,
BlendFunction.DstOut,
BlendFunction.SrcAtop,
BlendFunction.DstAtop
)
private val ColorLogics: List = listOf(
ColorLogic.InvertedSrc,
ColorLogic.InvertedDst,
ColorLogic.And,
ColorLogic.Nand,
ColorLogic.Or,
ColorLogic.Nor,
ColorLogic.Xor,
ColorLogic.Equivalent,
ColorLogic.SrcAndInvertedDst,
ColorLogic.DstAndInvertedSrc,
ColorLogic.SrcOrInvertedDst,
ColorLogic.DstOrInvertedSrc
)
context(MatrixStackCanvas)
internal fun nSaveClipImpl(clip: ClipSave) {
when (clip) {
is OutlineClipSave -> {
StencilClip.save(
op = clip.op
) {
drawClip(clip.outline)
}
}
is BlockClipSave -> {
StencilClip.save(
op = clip.op,
clip = clip.block
)
}
}
}
context(MatrixStackCanvas)
internal fun nRestoreClipImpl(clip: ClipSave) {
when (clip) {
is OutlineClipSave -> {
StencilClip.restore {
drawClip(clip.outline)
}
}
is BlockClipSave -> {
StencilClip.restore(clip.block)
}
}
}
context(MatrixStackCanvas)
private fun drawClip(outline: Outline) {
when (outline) {
is Outline.Regular -> {
with(outline.rect) {
Drawer.fillRect(
matrices = matrices,
color = Color.White,
leftX = leftX,
topY = topY,
rightX = rightX,
bottomY = bottomY
)
}
}
is Outline.Rounded -> {
with(outline.roundedRect) {
Drawer.fillRoundedRect(
matrices = matrices,
color = Color.White,
leftX = leftX,
topY = topY,
rightX = rightX,
bottomY = bottomY,
topLeftRadius = topLeftRadius,
bottomLeftRadius = bottomLeftRadius,
bottomRightRadius = topRightRadius,
topRightRadius = topRightRadius
)
}
}
}
}
context(Canvas)
internal fun nSaveAlphaImpl(alpha: Float) {
if (alpha > 0.0f) {
shaderAlpha *= alpha
} else {
shaderAlphaCache.add(shaderAlpha)
shaderAlpha = 0.0f
}
}
context(Canvas)
internal fun nRestoreAlphaImpl(alpha: Float) {
if (alpha > 0.0f) {
shaderAlpha /= alpha
} else {
shaderAlpha = shaderAlphaCache.removeLast()
}
}
context(Canvas)
internal fun nSaveBlendModeImpl(blendMode: BlendMode) {
val value = blendMode.value
if (value < 12) {
enableBlend()
blendFunctionSeparate(BlendFunctions[value])
} else {
enableColorLogic()
colorLogic(ColorLogics[value - 12])
}
}
context(Canvas)
internal fun nRestoreBlendModeImpl(blendMode: BlendMode) {
val value = blendMode.value
if (value < 12) {
disableBlend()
} else {
disableColorLogic()
}
}
context(MatrixStackCanvas)
internal fun nDrawVerticesImpl(
vertices: PosColorVertices,
program: ShaderProgram
) {
val vertexMode = vertices.mode
val positions = vertices.positions
val colors = vertices.colors
val transformation = currentTransformation
shaderProgram = program
tessellator.draw(vertexMode.toNative(), program.format) { buffer ->
for (i in positions.indices) {
val (x, y) = positions[i]
val (r, g, b, a) = colors[i]
buffer.bufferPosColor(
transformation = transformation,
x = x,
y = y,
z = 0.0f,
r = r,
g = g,
b = b,
a = a
)
}
}
}
context(MatrixStackCanvas)
internal fun nDrawVerticesImpl(
vertices: PosTexVertices,
program: ShaderProgram
) {
val vertexMode = vertices.mode
val positions = vertices.positions
val texturePositions = vertices.texturePositions
val texture = vertices.texture
val transformation = currentTransformation
shaderProgram = program
setShaderTexture(0, texture)
tessellator.draw(vertexMode.toNative(), program.format) { buffer ->
for (i in positions.indices) {
val (x, y) = positions[i]
val (u, v) = texturePositions[i]
buffer.bufferPosTex(
transformation = transformation,
x = x,
y = y,
z = 0.0f,
u = u,
v = v
)
}
}
}
context(MatrixStackCanvas)
internal fun nDrawVerticesImpl(
vertices: PosColorTexVertices,
program: ShaderProgram
) {
val vertexMode = vertices.mode
val positions = vertices.positions
val colors = vertices.colors
val texturePositions = vertices.texturePositions
val texture = vertices.texture
val transformation = currentTransformation
shaderProgram = program
setShaderTexture(0, texture)
tessellator.draw(vertexMode.toNative(), program.format) { buffer ->
for (i in positions.indices) {
val (x, y) = positions[i]
val (r, g, b, a) = colors[i]
val (u, v) = texturePositions[i]
buffer.bufferPosColorTex(
transformation = transformation,
x = x,
y = y,
z = 0.0f,
r = r,
g = g,
b = b,
a = a,
u = u,
v = v
)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy