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: Handler, playerInv: PlayerInventory, title: Text, ): HandledScreen(handler, playerInv, title), AbstractCacaoScreen { private val _windows = LinkedList() override val windows: List = _windows override fun 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 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 } }