All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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