Немного прибераемся в самом низу render pipeline
This commit is contained in:
parent
c7980d9068
commit
0a00595520
@ -59,9 +59,9 @@ fun main() {
|
|||||||
var parse = 0L
|
var parse = 0L
|
||||||
|
|
||||||
//for (chunkX in 17 .. 18) {
|
//for (chunkX in 17 .. 18) {
|
||||||
for (chunkX in 0 .. 60) {
|
for (chunkX in 14 .. 24) {
|
||||||
// for (chunkY in 21 .. 21) {
|
// for (chunkY in 21 .. 21) {
|
||||||
for (chunkY in 0 .. 60) {
|
for (chunkY in 18 .. 24) {
|
||||||
var t = System.currentTimeMillis()
|
var t = System.currentTimeMillis()
|
||||||
val data = db.read(byteArrayOf(1, 0, chunkX.toByte(), 0, chunkY.toByte()))
|
val data = db.read(byteArrayOf(1, 0, chunkX.toByte(), 0, chunkY.toByte()))
|
||||||
find += System.currentTimeMillis() - t
|
find += System.currentTimeMillis() - t
|
||||||
|
@ -22,17 +22,10 @@ class ClientWorld(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun addLayers(
|
||||||
* Отрисовывает этот с обрезкой невидимой геометрии с точки зрения [size] в Starbound Units
|
|
||||||
*
|
|
||||||
* Все координаты "местности" сохраняются, поэтому, если отрисовывать слишком далеко от 0, 0
|
|
||||||
* то геометрия может начать искажаться из-за погрешности плавающей запятой
|
|
||||||
*/
|
|
||||||
fun render(
|
|
||||||
size: AABB,
|
size: AABB,
|
||||||
isScreenspaceRender: Boolean = true
|
layers: LayeredRenderer
|
||||||
) {
|
) {
|
||||||
val layers = LayeredRenderer()
|
|
||||||
client.lightRenderer.begin()
|
client.lightRenderer.begin()
|
||||||
|
|
||||||
for (chunk in collectPositionAware(size.encasingChunkPosAABB())) {
|
for (chunk in collectPositionAware(size.encasingChunkPosAABB())) {
|
||||||
@ -42,7 +35,6 @@ class ClientWorld(
|
|||||||
//client.lightRenderer.addShadowGeometry(renderer)
|
//client.lightRenderer.addShadowGeometry(renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
layers.render(client.gl.matrixStack)
|
|
||||||
/*
|
/*
|
||||||
for ((lightPosition, color) in listOf(
|
for ((lightPosition, color) in listOf(
|
||||||
(client.screenToWorld(client.mouseCoordinatesF)) to Color.RED,
|
(client.screenToWorld(client.mouseCoordinatesF)) to Color.RED,
|
||||||
|
@ -16,6 +16,7 @@ import ru.dbotthepony.kstarbound.client.gl.ScissorRect
|
|||||||
import ru.dbotthepony.kstarbound.client.input.UserInput
|
import ru.dbotthepony.kstarbound.client.input.UserInput
|
||||||
import ru.dbotthepony.kstarbound.client.render.Camera
|
import ru.dbotthepony.kstarbound.client.render.Camera
|
||||||
import ru.dbotthepony.kstarbound.client.render.GPULightRenderer
|
import ru.dbotthepony.kstarbound.client.render.GPULightRenderer
|
||||||
|
import ru.dbotthepony.kstarbound.client.render.LayeredRenderer
|
||||||
import ru.dbotthepony.kstarbound.client.render.TextAlignY
|
import ru.dbotthepony.kstarbound.client.render.TextAlignY
|
||||||
import ru.dbotthepony.kstarbound.client.render.TileRenderers
|
import ru.dbotthepony.kstarbound.client.render.TileRenderers
|
||||||
import ru.dbotthepony.kstarbound.util.JVMTimeSource
|
import ru.dbotthepony.kstarbound.util.JVMTimeSource
|
||||||
@ -40,26 +41,21 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
val window: Long
|
val window: Long
|
||||||
val camera = Camera(this)
|
val camera = Camera(this)
|
||||||
val input = UserInput()
|
val input = UserInput()
|
||||||
|
val gl: GLStateTracker
|
||||||
|
|
||||||
var gameTerminated = false
|
var gameTerminated = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var viewportWidth = 800
|
|
||||||
private set
|
|
||||||
|
|
||||||
var viewportHeight = 600
|
|
||||||
private set
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Матрица преобразования экранных координат (в пикселях) в нормализованные координаты
|
* Матрица преобразования экранных координат (в пикселях) в нормализованные координаты
|
||||||
*/
|
*/
|
||||||
var viewportMatrixScreen = updateViewportMatrixScreen()
|
var viewportMatrixScreen: Matrix4f
|
||||||
private set
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Матрица преобразования мировых координат в нормализованные координаты
|
* Матрица преобразования мировых координат в нормализованные координаты
|
||||||
*/
|
*/
|
||||||
var viewportMatrixWorld = updateViewportMatrixWorld()
|
var viewportMatrixWorld: Matrix4f
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val startupTextList = ArrayList<String>()
|
private val startupTextList = ArrayList<String>()
|
||||||
@ -172,29 +168,29 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 6)
|
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 6)
|
||||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE)
|
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
|
||||||
window = GLFW.glfwCreateWindow(viewportWidth, viewportHeight, "KStarbound", MemoryUtil.NULL, MemoryUtil.NULL)
|
window = GLFW.glfwCreateWindow(800, 600, "KStarbound", MemoryUtil.NULL, MemoryUtil.NULL)
|
||||||
require(window != MemoryUtil.NULL) { "Unable to create GLFW window" }
|
require(window != MemoryUtil.NULL) { "Unable to create GLFW window" }
|
||||||
startupTextList.add("Created GLFW window")
|
startupTextList.add("Created GLFW window")
|
||||||
|
|
||||||
input.installCallback(window)
|
input.installCallback(window)
|
||||||
|
|
||||||
|
GLFW.glfwMakeContextCurrent(window)
|
||||||
|
gl = GLStateTracker(starbound)
|
||||||
|
|
||||||
GLFW.glfwSetFramebufferSizeCallback(window) { _, w, h ->
|
GLFW.glfwSetFramebufferSizeCallback(window) { _, w, h ->
|
||||||
if (w == 0 || h == 0) {
|
if (w == 0 || h == 0) {
|
||||||
isRenderingGame = false
|
isRenderingGame = false
|
||||||
return@glfwSetFramebufferSizeCallback
|
} else {
|
||||||
}
|
isRenderingGame = true
|
||||||
|
viewportMatrixScreen = updateViewportMatrixScreen()
|
||||||
|
viewportMatrixWorld = updateViewportMatrixWorld()
|
||||||
|
gl.setViewport(0, 0, w, h)
|
||||||
|
|
||||||
isRenderingGame = true
|
lightRenderer.resizeFramebuffer(w, h)
|
||||||
viewportWidth = w
|
|
||||||
viewportHeight = h
|
|
||||||
viewportMatrixScreen = updateViewportMatrixScreen()
|
|
||||||
viewportMatrixWorld = updateViewportMatrixWorld()
|
|
||||||
glViewport(0, 0, w, h)
|
|
||||||
|
|
||||||
lightRenderer.resizeFramebuffer(viewportWidth, viewportHeight)
|
for (callback in onViewportChanged) {
|
||||||
|
callback.invoke(w, h)
|
||||||
for (callback in onViewportChanged) {
|
}
|
||||||
callback.invoke(w, h)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,12 +209,14 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
(vidmode.width() - pWidth[0]) / 2,
|
(vidmode.width() - pWidth[0]) / 2,
|
||||||
(vidmode.height() - pHeight[0]) / 2
|
(vidmode.height() - pHeight[0]) / 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
gl.setViewport(0, 0, pWidth[0], pHeight[0])
|
||||||
|
viewportMatrixScreen = updateViewportMatrixScreen()
|
||||||
|
viewportMatrixWorld = updateViewportMatrixWorld()
|
||||||
} finally {
|
} finally {
|
||||||
stack.close()
|
stack.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFW.glfwMakeContextCurrent(window)
|
|
||||||
|
|
||||||
// vsync
|
// vsync
|
||||||
GLFW.glfwSwapInterval(0)
|
GLFW.glfwSwapInterval(0)
|
||||||
|
|
||||||
@ -226,7 +224,9 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
putDebugLog("Initialized GLFW window")
|
putDebugLog("Initialized GLFW window")
|
||||||
}
|
}
|
||||||
|
|
||||||
val gl = GLStateTracker(starbound)
|
val viewportWidth by gl::viewportWidth
|
||||||
|
val viewportHeight by gl::viewportHeight
|
||||||
|
|
||||||
val tileRenderers = TileRenderers(this)
|
val tileRenderers = TileRenderers(this)
|
||||||
val lightRenderer = GPULightRenderer(gl)
|
val lightRenderer = GPULightRenderer(gl)
|
||||||
|
|
||||||
@ -236,8 +236,6 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
|
|
||||||
var world: ClientWorld? = ClientWorld(this, 0L, 0)
|
var world: ClientWorld? = ClientWorld(this, 0L, 0)
|
||||||
|
|
||||||
fun ensureSameThread() = gl.ensureSameThread()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
putDebugLog("Initialized OpenGL context")
|
putDebugLog("Initialized OpenGL context")
|
||||||
gl.clearColor = Color.SLATE_GREY
|
gl.clearColor = Color.SLATE_GREY
|
||||||
@ -269,87 +267,34 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
|
|
||||||
val settings = ClientSettings()
|
val settings = ClientSettings()
|
||||||
|
|
||||||
|
private val onDrawGUI = ArrayList<() -> Unit>()
|
||||||
|
private val onPreDrawWorld = ArrayList<(LayeredRenderer) -> Unit>()
|
||||||
|
private val onPostDrawWorld = ArrayList<() -> Unit>()
|
||||||
|
private val onPostDrawWorldOnce = ArrayList<(LayeredRenderer) -> Unit>()
|
||||||
private val onViewportChanged = ArrayList<(width: Int, height: Int) -> Unit>()
|
private val onViewportChanged = ArrayList<(width: Int, height: Int) -> Unit>()
|
||||||
|
|
||||||
fun onViewportChanged(callback: (width: Int, height: Int) -> Unit) {
|
fun onViewportChanged(callback: (width: Int, height: Int) -> Unit) {
|
||||||
onViewportChanged.add(callback)
|
onViewportChanged.add(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val onDrawGUI = ArrayList<() -> Unit>()
|
|
||||||
|
|
||||||
fun onDrawGUI(lambda: () -> Unit) {
|
fun onDrawGUI(lambda: () -> Unit) {
|
||||||
onDrawGUI.add(lambda)
|
onDrawGUI.add(lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val onPreDrawWorld = ArrayList<() -> Unit>()
|
fun onPreDrawWorld(lambda: (LayeredRenderer) -> Unit) {
|
||||||
|
|
||||||
fun onPreDrawWorld(lambda: () -> Unit) {
|
|
||||||
onPreDrawWorld.add(lambda)
|
onPreDrawWorld.add(lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val onPostDrawWorld = ArrayList<() -> Unit>()
|
|
||||||
|
|
||||||
fun onPostDrawWorld(lambda: () -> Unit) {
|
fun onPostDrawWorld(lambda: () -> Unit) {
|
||||||
onPostDrawWorld.add(lambda)
|
onPostDrawWorld.add(lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val onPostDrawWorldOnce = ArrayList<() -> Unit>()
|
fun onPostDrawWorldOnce(lambda: (LayeredRenderer) -> Unit) {
|
||||||
|
|
||||||
fun onPostDrawWorldOnce(lambda: () -> Unit) {
|
|
||||||
onPostDrawWorldOnce.add(lambda)
|
onPostDrawWorldOnce.add(lambda)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scissorStack = LinkedList<ScissorRect>()
|
|
||||||
|
|
||||||
fun pushScissorRect(x: Float, y: Float, width: Float, height: Float) {
|
|
||||||
return pushScissorRect(x.roundToInt(), y.roundToInt(), width.roundToInt(), height.roundToInt())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
fun pushScissorRect(x: Int, y: Int, width: Int, height: Int) {
|
|
||||||
var x = x
|
|
||||||
var y = y
|
|
||||||
var width = width
|
|
||||||
var height = height
|
|
||||||
|
|
||||||
val peek = scissorStack.lastOrNull()
|
|
||||||
|
|
||||||
if (peek != null) {
|
|
||||||
x = x.coerceAtLeast(peek.x)
|
|
||||||
y = y.coerceAtLeast(peek.y)
|
|
||||||
width = width.coerceAtMost(peek.width)
|
|
||||||
height = height.coerceAtMost(peek.height)
|
|
||||||
|
|
||||||
if (peek.x == x && peek.y == y && peek.width == width && peek.height == height) {
|
|
||||||
scissorStack.add(peek)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val rect = ScissorRect(x, y, width, height)
|
|
||||||
scissorStack.add(rect)
|
|
||||||
gl.scissorRect = rect
|
|
||||||
gl.scissor = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun popScissorRect() {
|
|
||||||
scissorStack.removeLast()
|
|
||||||
|
|
||||||
val peek = scissorStack.lastOrNull()
|
|
||||||
|
|
||||||
if (peek == null) {
|
|
||||||
gl.scissor = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val y = viewportHeight - peek.y - peek.height
|
|
||||||
gl.scissorRect = ScissorRect(peek.x, y, peek.width, peek.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentScissorRect get() = scissorStack.lastOrNull()
|
|
||||||
|
|
||||||
fun renderFrame(): Boolean {
|
fun renderFrame(): Boolean {
|
||||||
ensureSameThread()
|
gl.ensureSameThread()
|
||||||
|
|
||||||
if (GLFW.glfwWindowShouldClose(window)) {
|
if (GLFW.glfwWindowShouldClose(window)) {
|
||||||
close()
|
close()
|
||||||
@ -364,40 +309,48 @@ class StarboundClient(val starbound: Starbound) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val measure = JVMTimeSource.INSTANCE.seconds
|
val measure = JVMTimeSource.INSTANCE.seconds
|
||||||
|
val world = world
|
||||||
|
|
||||||
if (frameRenderTime != 0.0 && starbound.initialized)
|
if (world != null) {
|
||||||
world?.think(frameRenderTime)
|
val layers = LayeredRenderer()
|
||||||
|
|
||||||
gl.clearColor = Color.SLATE_GREY
|
if (frameRenderTime != 0.0 && starbound.initialized)
|
||||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
world.think(frameRenderTime)
|
||||||
gl.matrixStack.clear(viewportMatrixWorld.toMutableMatrix4f())
|
|
||||||
|
|
||||||
gl.matrixStack.push()
|
gl.clearColor = Color.SLATE_GREY
|
||||||
.translateWithMultiplication(viewportWidth / 2f, viewportHeight / 2f, 2f) // центр экрана + координаты отрисовки мира
|
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
|
||||||
.scale(x = settings.zoom * PIXELS_IN_STARBOUND_UNITf, y = settings.zoom * PIXELS_IN_STARBOUND_UNITf) // масштабируем до нужного размера
|
gl.matrixStack.clear(viewportMatrixWorld.toMutableMatrix4f())
|
||||||
.translateWithMultiplication(-camera.pos.x, -camera.pos.y) // перемещаем вид к камере
|
|
||||||
|
|
||||||
for (lambda in onPreDrawWorld) {
|
gl.matrixStack.push()
|
||||||
lambda.invoke()
|
.translateWithMultiplication(viewportWidth / 2f, viewportHeight / 2f, 2f) // центр экрана + координаты отрисовки мира
|
||||||
|
.scale(x = settings.zoom * PIXELS_IN_STARBOUND_UNITf, y = settings.zoom * PIXELS_IN_STARBOUND_UNITf) // масштабируем до нужного размера
|
||||||
|
.translateWithMultiplication(-camera.pos.x, -camera.pos.y) // перемещаем вид к камере
|
||||||
|
|
||||||
|
for (lambda in onPreDrawWorld) {
|
||||||
|
lambda.invoke(layers)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in onPostDrawWorldOnce.size - 1 downTo 0) {
|
||||||
|
onPostDrawWorldOnce[i].invoke(layers)
|
||||||
|
onPostDrawWorldOnce.removeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
world.addLayers(
|
||||||
|
layers = layers,
|
||||||
|
size = AABB.rectangle(
|
||||||
|
camera.pos.toDoubleVector(),
|
||||||
|
viewportWidth / settings.zoom / PIXELS_IN_STARBOUND_UNIT,
|
||||||
|
viewportHeight / settings.zoom / PIXELS_IN_STARBOUND_UNIT))
|
||||||
|
|
||||||
|
layers.render(gl.matrixStack)
|
||||||
|
|
||||||
|
for (lambda in onPostDrawWorld) {
|
||||||
|
lambda.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.matrixStack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in onPostDrawWorldOnce.size - 1 downTo 0) {
|
|
||||||
onPostDrawWorldOnce[i].invoke()
|
|
||||||
onPostDrawWorldOnce.removeAt(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
world?.render(
|
|
||||||
AABB.rectangle(
|
|
||||||
camera.pos.toDoubleVector(),
|
|
||||||
viewportWidth / settings.zoom / PIXELS_IN_STARBOUND_UNIT,
|
|
||||||
viewportHeight / settings.zoom / PIXELS_IN_STARBOUND_UNIT))
|
|
||||||
|
|
||||||
for (lambda in onPostDrawWorld) {
|
|
||||||
lambda.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.matrixStack.pop()
|
|
||||||
|
|
||||||
gl.matrixStack.clear(viewportMatrixScreen.toMutableMatrix4f())
|
gl.matrixStack.clear(viewportMatrixScreen.toMutableMatrix4f())
|
||||||
|
|
||||||
val thisTime = System.currentTimeMillis()
|
val thisTime = System.currentTimeMillis()
|
||||||
|
@ -24,10 +24,12 @@ import ru.dbotthepony.kvector.vector.Color
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.lang.ref.Cleaner
|
import java.lang.ref.Cleaner
|
||||||
|
import java.util.*
|
||||||
import java.util.concurrent.ThreadFactory
|
import java.util.concurrent.ThreadFactory
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@ -150,6 +152,7 @@ class GLStateTracker(val locator: ISBFileLocator) {
|
|||||||
val thread: Thread = Thread.currentThread()
|
val thread: Thread = Thread.currentThread()
|
||||||
val box2dRenderer = Box2DRenderer(this)
|
val box2dRenderer = Box2DRenderer(this)
|
||||||
|
|
||||||
|
private val scissorStack = LinkedList<ScissorRect>()
|
||||||
private val cleanerBacklog = ArrayList<() -> Unit>()
|
private val cleanerBacklog = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
@ -347,6 +350,75 @@ class GLStateTracker(val locator: ISBFileLocator) {
|
|||||||
checkForGLError()
|
checkForGLError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var viewportX: Int = 0
|
||||||
|
private set
|
||||||
|
var viewportY: Int = 0
|
||||||
|
private set
|
||||||
|
var viewportWidth: Int = 0
|
||||||
|
private set
|
||||||
|
var viewportHeight: Int = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun setViewport(x: Int, y: Int, width: Int, height: Int) {
|
||||||
|
ensureSameThread()
|
||||||
|
|
||||||
|
if (viewportX != x || viewportY != y || viewportWidth != width || viewportHeight != height) {
|
||||||
|
glViewport(x, y, width, height)
|
||||||
|
checkForGLError("Setting viewport")
|
||||||
|
viewportX = x
|
||||||
|
viewportY = y
|
||||||
|
viewportWidth = width
|
||||||
|
viewportHeight = height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pushScissorRect(x: Float, y: Float, width: Float, height: Float) {
|
||||||
|
return pushScissorRect(x.roundToInt(), y.roundToInt(), width.roundToInt(), height.roundToInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
fun pushScissorRect(x: Int, y: Int, width: Int, height: Int) {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
var width = width
|
||||||
|
var height = height
|
||||||
|
|
||||||
|
val peek = scissorStack.lastOrNull()
|
||||||
|
|
||||||
|
if (peek != null) {
|
||||||
|
x = x.coerceAtLeast(peek.x)
|
||||||
|
y = y.coerceAtLeast(peek.y)
|
||||||
|
width = width.coerceAtMost(peek.width)
|
||||||
|
height = height.coerceAtMost(peek.height)
|
||||||
|
|
||||||
|
if (peek.x == x && peek.y == y && peek.width == width && peek.height == height) {
|
||||||
|
scissorStack.add(peek)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rect = ScissorRect(x, y, width, height)
|
||||||
|
scissorStack.add(rect)
|
||||||
|
scissorRect = rect
|
||||||
|
scissor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun popScissorRect() {
|
||||||
|
scissorStack.removeLast()
|
||||||
|
|
||||||
|
val peek = scissorStack.lastOrNull()
|
||||||
|
|
||||||
|
if (peek == null) {
|
||||||
|
scissor = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = viewportHeight - peek.y - peek.height
|
||||||
|
scissorRect = ScissorRect(peek.x, y, peek.width, peek.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentScissorRect get() = scissorStack.lastOrNull()
|
||||||
|
|
||||||
fun ensureSameThread() {
|
fun ensureSameThread() {
|
||||||
if (thread !== Thread.currentThread()) {
|
if (thread !== Thread.currentThread()) {
|
||||||
throw IllegalAccessException("Trying to access $this outside of $thread!")
|
throw IllegalAccessException("Trying to access $this outside of $thread!")
|
||||||
|
Loading…
Reference in New Issue
Block a user