From 71f13f70bf32b4af55f91bed2cb2c6ea9a16d08f Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 12 Jan 2024 20:57:12 +0700 Subject: [PATCH] Scissor stack fix --- .../mc/otm/client/render/RenderHelper.kt | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt index 84d7d1da4..806da8d41 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt @@ -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() -@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()