Scissor stack fix

This commit is contained in:
DBotThePony 2024-01-12 20:57:12 +07:00
parent 0dffe511fd
commit 71f13f70bf
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -3,13 +3,11 @@ package ru.dbotthepony.mc.otm.client.render
import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.*
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.client.renderer.RenderStateShard
import net.minecraft.client.renderer.RenderStateShard.LineStateShard
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.ShaderInstance
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceProvider
import org.apache.logging.log4j.LogManager
@ -294,9 +292,15 @@ fun drawLine(
tess.end()
}
data class ScissorRect(val x: Int, val y: Int, val width: Int, val height: Int, val lock: Boolean = false) {
data class ScissorRect(val xStart: Int, val yStart: Int, val xEnd: Int, val yEnd: Int, val lock: Boolean = false) {
val width: Int
get() = (xEnd - xStart).coerceAtLeast(0)
val height: Int
get() = (yEnd - yStart).coerceAtLeast(0)
fun withinBounds(x: Int, y: Int): Boolean {
return (x in this.x .. this.x + width) && (y in this.y .. this.y + height)
return (x in this.xStart .. xEnd) && (y in this.yStart .. yEnd)
}
fun cross(x: Int, y: Int, width: Int, height: Int): Boolean {
@ -306,18 +310,18 @@ data class ScissorRect(val x: Int, val y: Int, val width: Int, val height: Int,
}
// crossing at least one line
if (y in this.y .. this.y + height) {
if (x < this.x && x + width > this.x + this.width) {
if (y in this.yStart .. this.yStart + height) {
if (x < this.xStart && x + width > this.xEnd) {
return true
}
} else if (x in this.x .. this.x + width) {
if (y < this.y && y + height > this.y + this.height) {
} else if (x in this.xStart .. this.xStart + width) {
if (y < this.yStart && y + height > this.yEnd) {
return true
}
}
// final test: check if scissor rect is completely inside provided rect
return this.x in x .. x + width && this.y in y .. y + height
return this.xStart in x .. x + width && this.yStart in y .. y + height
}
fun crossScaled(x: Float, y: Float, width: Float, height: Float): Boolean {
@ -329,17 +333,20 @@ data class ScissorRect(val x: Int, val y: Int, val width: Int, val height: Int,
val scale = minecraft.window.guiScale
return cross((x * scale).roundToInt(), (y * scale).roundToInt(), (width * scale).roundToInt(), (height * scale).roundToInt())
}
fun apply() {
RenderSystem.enableScissor(xStart, minecraft.window.height - yStart - height, width, height)
}
}
private val scissorStack = ArrayDeque<ScissorRect>()
@Suppress("NAME_SHADOWING")
@JvmOverloads
fun pushScissorRect(x: Int, y: Int, width: Int, height: Int, lock: Boolean = false) {
var x = x
var y = y
var width = width
var height = height
var xStart = x
var yStart = y
var xEnd = x + width
var yEnd = y + height
val peek = scissorStack.lastOrNull()
@ -349,34 +356,31 @@ fun pushScissorRect(x: Int, y: Int, width: Int, height: Int, lock: Boolean = fal
return
}
x = x.coerceAtLeast(peek.x)
y = y.coerceAtLeast(peek.y)
width = width.coerceAtMost(peek.width)
height = height.coerceAtMost(peek.height)
xStart = xStart.coerceAtLeast(peek.xStart)
yStart = yStart.coerceAtLeast(peek.yStart)
xEnd = xEnd.coerceAtMost(peek.xEnd)
yEnd = yEnd.coerceAtMost(peek.yEnd)
if (peek.x == x && peek.y == y && peek.width == width && peek.height == height) {
if (peek.xStart == xStart && peek.yStart == yStart && peek.xEnd == xEnd && peek.yEnd == yEnd) {
scissorStack.add(peek)
return
}
}
scissorStack.add(ScissorRect(x, y, width, height, lock))
y = minecraft.window.height - y - height
RenderSystem.enableScissor(x, y, width, height)
val new = ScissorRect(xStart, yStart, xEnd, yEnd, lock)
scissorStack.add(new)
new.apply()
}
fun popScissorRect() {
scissorStack.removeLast()
val peek = scissorStack.lastOrNull()
if (peek == null) {
RenderSystem.disableScissor()
return
} else {
peek.apply()
}
val y = minecraft.window.height - peek.y - peek.height
RenderSystem.enableScissor(peek.x, y, peek.width, peek.height)
}
val currentScissorRect get() = scissorStack.lastOrNull()