PhysicalConnectivity/src/main/kotlin/net/shadowfacts/cacao/CacaoHandledScreen.kt

183 lines
4.9 KiB
Kotlin

package net.shadowfacts.cacao
import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.screen.ScreenHandler
import net.minecraft.sound.SoundEvents
import net.minecraft.text.Text
import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.KeyModifiers
import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.window.ScreenHandlerWindow
import net.shadowfacts.cacao.window.Window
import org.lwjgl.glfw.GLFW
import org.lwjgl.opengl.GL11
import java.util.*
/**
* @author shadowfacts
*/
open class CacaoHandledScreen<Handler: ScreenHandler>(
handler: Handler,
playerInv: PlayerInventory,
title: Text,
): HandledScreen<Handler>(handler, playerInv, title), AbstractCacaoScreen {
private val _windows = LinkedList<Window>()
override val windows: List<Window> = _windows
override fun <T: Window> addWindow(window: T, index: Int): T {
if (window is ScreenHandlerWindow && window.screenHandler != handler) {
throw RuntimeException("Adding ScreenHandlerWindow to CacaoHandledScreen with different screen handler is not supported")
}
_windows.add(index, window)
window.screen = this
window.wasAdded()
window.resize(width, height)
return window
}
override fun <T : Window> addWindow(window: T): T {
return addWindow(window, _windows.size)
}
override fun removeWindow(window: Window) {
_windows.remove(window)
if (windows.isEmpty()) {
onClose()
}
}
override fun init() {
super.init()
windows.forEach {
it.resize(width, height)
}
}
override fun onClose() {
super.onClose()
windows.forEach {
// todo: VC callbacks
it.firstResponder = null
}
}
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
}
override fun drawForeground(matrixStack: MatrixStack, mouseX: Int, mouseY: Int) {
// no-op
}
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
val mouse = Point(mouseX, mouseY)
matrixStack.push()
matrixStack.translate(0.0, 0.0, -350.0)
for (i in windows.indices) {
val it = windows[i]
if (i == windows.size - 1) {
renderBackground(matrixStack)
}
if (it is ScreenHandlerWindow) {
if (i == windows.size - 1) {
super.render(matrixStack, mouseX, mouseY, delta)
} else {
// if the screen handler window is not the frontmost, we fake the mouse x/y to disable the slot mouseover effect
super.render(matrixStack, -1, -1, delta)
}
matrixStack.pop()
}
it.draw(matrixStack, mouse, delta)
}
drawMouseoverTooltip(matrixStack, mouseX, mouseY)
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val window = windows.lastOrNull()
val result = window?.mouseClicked(Point(mouseX, mouseY), MouseButton.fromMC(button))
return if (result == true) {
RenderHelper.playSound(SoundEvents.UI_BUTTON_CLICK)
true
} else if (window is ScreenHandlerWindow) {
super.mouseClicked(mouseX, mouseY, button)
} else {
false
}
}
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
val window = windows.lastOrNull()
val startPoint = Point(mouseX, mouseY)
val delta = Point(deltaX, deltaY)
val result = window?.mouseDragged(startPoint, delta, MouseButton.fromMC(button))
return if (result == true) {
true
} else if (window is ScreenHandlerWindow) {
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
} else {
false
}
}
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
val window = windows.lastOrNull()
val result = window?.mouseReleased(Point(mouseX, mouseY), MouseButton.fromMC(button))
return if (result == true) {
true
} else if (window is ScreenHandlerWindow) {
super.mouseReleased(mouseX, mouseY, button)
} else {
false
}
}
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
val window = windows.lastOrNull()
val result = window?.mouseScrolled(Point(mouseX, mouseY), amount)
return result == true
}
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
windows.lastOrNull()?.removeFromScreen()
return true
} else {
val modifiersSet by lazy { KeyModifiers(modifiers) }
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
return true
}
return super.keyPressed(keyCode, scanCode, modifiers)
}
}
override fun charTyped(char: Char, modifiers: Int): Boolean {
val modifiersSet by lazy { KeyModifiers(modifiers) }
if (findResponder { it.charTyped(char, modifiersSet) }) {
return true
}
return super.charTyped(char, modifiers)
}
override fun shouldCloseOnEsc(): Boolean {
return false
}
}