From fb7cfd1f44a0c93fd67e71f48d108946ed912b94 Mon Sep 17 00:00:00 2001 From: DJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:16:37 -0400 Subject: [PATCH 1/4] UScreen: improved input handling * smuggle super return values, ensuring proper behavior. * introduce new u-prefixed methods with additional arguments and boolean return type. --- api/UniversalCraft.api | 21 +++ .../kotlin/gg/essential/universal/UScreen.kt | 173 +++++++++++++++--- 2 files changed, 165 insertions(+), 29 deletions(-) diff --git a/api/UniversalCraft.api b/api/UniversalCraft.api index 39faaaf..1b12fc3 100644 --- a/api/UniversalCraft.api +++ b/api/UniversalCraft.api @@ -797,6 +797,13 @@ public abstract class gg/essential/universal/UScreen : net/minecraft/client/gui/ public fun setNewGuiScale (I)V public fun setUnlocalizedName (Ljava/lang/String;)V public final fun tick ()V + public fun uCharTyped (CLgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyPressed (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyReleased (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uMouseClicked (DDI)Z + public fun uMouseDragged (DDIJ)Z + public fun uMouseReleased (DDI)Z + public fun uMouseScrolled (D)Z public fun updateGuiScale ()V } @@ -867,6 +874,13 @@ public abstract class gg/essential/universal/UScreen : net/minecraft/client/gui/ public fun setNewGuiScale (I)V public fun setUnlocalizedName (Ljava/lang/String;)V public final fun tick ()V + public fun uCharTyped (CLgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyPressed (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyReleased (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uMouseClicked (DDI)Z + public fun uMouseDragged (DDIJ)Z + public fun uMouseReleased (DDI)Z + public fun uMouseScrolled (D)Z public fun updateGuiScale ()V } @@ -911,6 +925,13 @@ public abstract class gg/essential/universal/UScreen : net/minecraft/client/gui/ public final fun restorePreviousScreen ()V public fun setNewGuiScale (I)V public fun setUnlocalizedName (Ljava/lang/String;)V + public fun uCharTyped (CLgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyPressed (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uKeyReleased (IILgg/essential/universal/UKeyboard$Modifiers;)Z + public fun uMouseClicked (DDI)Z + public fun uMouseDragged (DDIJ)Z + public fun uMouseReleased (DDI)Z + public fun uMouseScrolled (D)Z public fun updateGuiScale ()V public final fun updateScreen ()V } diff --git a/src/main/kotlin/gg/essential/universal/UScreen.kt b/src/main/kotlin/gg/essential/universal/UScreen.kt index e1537f1..9871b22 100644 --- a/src/main/kotlin/gg/essential/universal/UScreen.kt +++ b/src/main/kotlin/gg/essential/universal/UScreen.kt @@ -58,6 +58,14 @@ abstract class UScreen( //$$ } //#endif + private var smuggleKeyPressed = true + private var smuggleKeyReleased = true + private var smuggleCharTyped = true + private var smuggleMouseClicked = true + private var smuggleMouseReleased = true + private var smuggleMouseDragged = true + private var smuggleMouseScrolled = true + //#if MC>=11502 //$$ private var lastClick = 0L //$$ private var lastDraggedDx = -1.0 @@ -91,44 +99,37 @@ abstract class UScreen( //$$ } //$$ //$$ final override fun keyPressed(keyCode: Int, scanCode: Int, modifierCode: Int): Boolean { - //$$ onKeyPressed(keyCode, 0.toChar(), modifierCode.toModifiers()) - //$$ return false + //$$ return uKeyPressed(keyCode, scanCode, modifierCode.toModifiers()) //$$ } //$$ //$$ final override fun keyReleased(keyCode: Int, scanCode: Int, modifierCode: Int): Boolean { - //$$ onKeyReleased(keyCode, 0.toChar(), modifierCode.toModifiers()) - //$$ return false + //$$ return uKeyReleased(keyCode, scanCode, modifierCode.toModifiers()) //$$ } //$$ //$$ final override fun charTyped(char: Char, modifierCode: Int): Boolean { - //$$ onKeyPressed(0, char, modifierCode.toModifiers()) - //$$ return false + //$$ return uCharTyped(char, modifierCode.toModifiers()) //$$ } //$$ //$$ final override fun mouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int): Boolean { //$$ if (mouseButton == 1) //$$ lastClick = UMinecraft.getTime() - //$$ onMouseClicked(mouseX, mouseY, mouseButton) - //$$ return false + //$$ return uMouseClicked(mouseX, mouseY, mouseButton) //$$ } //$$ //$$ final override fun mouseReleased(mouseX: Double, mouseY: Double, mouseButton: Int): Boolean { - //$$ onMouseReleased(mouseX, mouseY, mouseButton) - //$$ return false + //$$ return uMouseReleased(mouseX, mouseY, mouseButton) //$$ } //$$ //$$ final override fun mouseDragged(x: Double, y: Double, mouseButton: Int, dx: Double, dy: Double): Boolean { //$$ lastDraggedDx = dx //$$ lastDraggedDy = dy - //$$ onMouseDragged(x, y, mouseButton, UMinecraft.getTime() - lastClick) - //$$ return false + //$$ return uMouseDragged(x, y, mouseButton, UMinecraft.getTime() - lastClick) //$$ } //$$ //$$ final override fun mouseScrolled(mouseX: Double, mouseY: Double, delta: Double): Boolean { //$$ lastScrolledX = mouseX //$$ lastScrolledY = mouseY - //$$ onMouseScrolled(delta) - //$$ return false + //$$ return uMouseScrolled(delta) //$$ } //$$ //$$ final override fun tick(): Unit = onTick() @@ -169,26 +170,31 @@ abstract class UScreen( } final override fun keyTyped(typedChar: Char, keyCode: Int) { - onKeyPressed(keyCode, typedChar, UKeyboard.getModifiers()) + if (keyCode != 0) { + uKeyPressed(keyCode, 0, UKeyboard.getModifiers()) + } + if (typedChar != 0.toChar()) { + uCharTyped(typedChar, UKeyboard.getModifiers()) + } } final override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) { - onMouseClicked(mouseX.toDouble(), mouseY.toDouble(), mouseButton) + uMouseClicked(mouseX.toDouble(), mouseY.toDouble(), mouseButton) } final override fun mouseReleased(mouseX: Int, mouseY: Int, state: Int) { - onMouseReleased(mouseX.toDouble(), mouseY.toDouble(), state) + uMouseReleased(mouseX.toDouble(), mouseY.toDouble(), state) } final override fun mouseClickMove(mouseX: Int, mouseY: Int, clickedMouseButton: Int, timeSinceLastClick: Long) { - onMouseDragged(mouseX.toDouble(), mouseY.toDouble(), clickedMouseButton, timeSinceLastClick) + uMouseDragged(mouseX.toDouble(), mouseY.toDouble(), clickedMouseButton, timeSinceLastClick) } final override fun handleMouseInput() { super.handleMouseInput() val scrollDelta = Mouse.getEventDWheel() if (scrollDelta != 0) - onMouseScrolled(scrollDelta.toDouble()) + uMouseScrolled(scrollDelta.toDouble()) } final override fun updateScreen() { @@ -265,36 +271,44 @@ abstract class UScreen( onDrawScreen(mouseX, mouseY, partialTicks) } + // TODO: should I bother smuggling the scanCode into these methods to pass to super? + + @Deprecated(DEPRECATED_INPUT) open fun onKeyPressed(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) { //#if MC>=11502 //$$ if (keyCode != 0) { - //$$ super.keyPressed(keyCode, 0, modifiers.toInt()) + //$$ smuggleKeyPressed = super.keyPressed(keyCode, 0, modifiers.toInt()) //$$ } //$$ if (typedChar != 0.toChar()) { - //$$ super.charTyped(typedChar, modifiers.toInt()) + //$$ smuggleCharTyped = super.charTyped(typedChar, modifiers.toInt()) //$$ } //#else - try { - super.keyTyped(typedChar, keyCode) - } catch (e: IOException) { - e.printStackTrace() + // If we are calling through from uCharTyped, don't call super + if (keyCode != 0) { + try { + super.keyTyped(typedChar, keyCode) + } catch (e: IOException) { + e.printStackTrace() + } } //#endif } + @Deprecated(DEPRECATED_INPUT) open fun onKeyReleased(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) { //#if MC>=11502 //$$ if (keyCode != 0) { - //$$ super.keyReleased(keyCode, 0, modifiers.toInt()) + //$$ smuggleKeyReleased = super.keyReleased(keyCode, 0, modifiers.toInt()) //$$ } //#endif } + @Deprecated(DEPRECATED_INPUT) open fun onMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int) { //#if MC>=11502 //$$ if (mouseButton == 1) //$$ lastClick = UMinecraft.getTime() - //$$ super.mouseClicked(mouseX, mouseY, mouseButton) + //$$ smuggleMouseClicked = super.mouseClicked(mouseX, mouseY, mouseButton) //#else try { super.mouseClicked(mouseX.toInt(), mouseY.toInt(), mouseButton) @@ -304,28 +318,127 @@ abstract class UScreen( //#endif } + @Deprecated(DEPRECATED_INPUT) open fun onMouseReleased(mouseX: Double, mouseY: Double, state: Int) { //#if MC>=11502 - //$$ super.mouseReleased(mouseX, mouseY, state) + //$$ smuggleMouseReleased = super.mouseReleased(mouseX, mouseY, state) //#else super.mouseReleased(mouseX.toInt(), mouseY.toInt(), state) //#endif } + @Deprecated(DEPRECATED_INPUT) open fun onMouseDragged(x: Double, y: Double, clickedButton: Int, timeSinceLastClick: Long) { //#if MC>=11502 - //$$ super.mouseDragged(x, y, clickedButton, lastDraggedDx, lastDraggedDy) + //$$ smuggleMouseDragged = super.mouseDragged(x, y, clickedButton, lastDraggedDx, lastDraggedDy) //#else super.mouseClickMove(x.toInt(), y.toInt(), clickedButton, timeSinceLastClick) //#endif } + @Deprecated(DEPRECATED_INPUT) open fun onMouseScrolled(delta: Double) { //#if MC>=11502 //$$ super.mouseScrolled(lastScrolledX, lastScrolledY, delta) //#endif } + /** + * Called when a key is pressed. + * + * @param keyCode the key code of the key. See [UKeyboard]. + * @param scanCode the platform specific scanCode of the key. Always 0 on versions that use LWJGL2. + * @param modifiers the modifiers of the event. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uKeyPressed(keyCode: Int, scanCode: Int, modifiers: UKeyboard.Modifiers?): Boolean { + @Suppress("DEPRECATION") + onKeyPressed(keyCode, 0.toChar(), modifiers) + return smuggleKeyPressed + } + + /** + * Called when a key is released. Only called on versions that use LWJGL3. + * + * @param keyCode the key code of the key. See [UKeyboard]. + * @param scanCode the platform specific scanCode of the key. + * @param modifiers the modifiers of the event. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uKeyReleased(keyCode: Int, scanCode: Int, modifiers: UKeyboard.Modifiers?): Boolean { + @Suppress("DEPRECATION") + onKeyReleased(keyCode, 0.toChar(), modifiers) + return smuggleKeyReleased + } + + /** + * Called when a character is typed. + * + * @param char the character that was typed + * @param modifiers the modifiers of the event. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uCharTyped(char: Char, modifiers: UKeyboard.Modifiers?): Boolean { + @Suppress("DEPRECATION") + onKeyPressed(0, char, modifiers) + return smuggleCharTyped + } + + /** + * Called when the mouse is clicked. + * + * @param mouseX the X position of the mouse. + * @param mouseY the Y position of the mouse. + * @param mouseButton the mouse button that was clicked. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int): Boolean { + @Suppress("DEPRECATION") + onMouseClicked(mouseX, mouseY, mouseButton) + return smuggleMouseClicked + } + + /** + * Called when the mouse is released. + * + * @param mouseX the X position of the mouse. + * @param mouseY the Y position of the mouse. + * @param mouseButton the mouse button that was released. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uMouseReleased(mouseX: Double, mouseY: Double, mouseButton: Int): Boolean { + @Suppress("DEPRECATION") + onMouseReleased(mouseX, mouseY, mouseButton) + return smuggleMouseReleased + } + + /** + * Called when the mouse is dragged (moved while the mouse button is down). + * + * @param x the current mouse X. + * @param y the current mouse Y. + * @param clickedButton the button that is being held. + * @param timeSinceLastClick the time since the last click (the start of the drag). + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uMouseDragged(x: Double, y: Double, clickedButton: Int, timeSinceLastClick: Long): Boolean { + @Suppress("DEPRECATION") + onMouseDragged(x, y, clickedButton, timeSinceLastClick) + return smuggleMouseDragged + } + + /** + * Called when the mouse is scrolled. + * + * @param delta the distance scrolled. + * @return `true` if the input has been handled, `false` otherwise. + */ + open fun uMouseScrolled(delta: Double): Boolean { + @Suppress("DEPRECATION") + onMouseScrolled(delta) + return smuggleMouseScrolled + } + open fun onTick() { //#if MC>=11502 //$$ super.tick() @@ -377,6 +490,8 @@ abstract class UScreen( } companion object { + private const val DEPRECATED_INPUT = "Use the u prefixed input methods for better behavior." + @JvmStatic val currentScreen: GuiScreen? get() = UMinecraft.getMinecraft().currentScreen From fbb561168439d12a951ce935350678fe3c2b8ebf Mon Sep 17 00:00:00 2001 From: DJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:31:07 -0400 Subject: [PATCH 2/4] UScreen: smuggle scan code to super.keyPressed/Released --- src/main/kotlin/gg/essential/universal/UScreen.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/gg/essential/universal/UScreen.kt b/src/main/kotlin/gg/essential/universal/UScreen.kt index 9871b22..ad6719d 100644 --- a/src/main/kotlin/gg/essential/universal/UScreen.kt +++ b/src/main/kotlin/gg/essential/universal/UScreen.kt @@ -66,6 +66,8 @@ abstract class UScreen( private var smuggleMouseDragged = true private var smuggleMouseScrolled = true + private var lastScanCode = 0 + //#if MC>=11502 //$$ private var lastClick = 0L //$$ private var lastDraggedDx = -1.0 @@ -271,13 +273,11 @@ abstract class UScreen( onDrawScreen(mouseX, mouseY, partialTicks) } - // TODO: should I bother smuggling the scanCode into these methods to pass to super? - @Deprecated(DEPRECATED_INPUT) open fun onKeyPressed(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) { //#if MC>=11502 //$$ if (keyCode != 0) { - //$$ smuggleKeyPressed = super.keyPressed(keyCode, 0, modifiers.toInt()) + //$$ smuggleKeyPressed = super.keyPressed(keyCode, lastScanCode, modifiers.toInt()) //$$ } //$$ if (typedChar != 0.toChar()) { //$$ smuggleCharTyped = super.charTyped(typedChar, modifiers.toInt()) @@ -298,7 +298,7 @@ abstract class UScreen( open fun onKeyReleased(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) { //#if MC>=11502 //$$ if (keyCode != 0) { - //$$ smuggleKeyReleased = super.keyReleased(keyCode, 0, modifiers.toInt()) + //$$ smuggleKeyReleased = super.keyReleased(keyCode, lastScanCode, modifiers.toInt()) //$$ } //#endif } @@ -352,6 +352,7 @@ abstract class UScreen( * @return `true` if the input has been handled, `false` otherwise. */ open fun uKeyPressed(keyCode: Int, scanCode: Int, modifiers: UKeyboard.Modifiers?): Boolean { + lastScanCode = scanCode @Suppress("DEPRECATION") onKeyPressed(keyCode, 0.toChar(), modifiers) return smuggleKeyPressed @@ -366,6 +367,7 @@ abstract class UScreen( * @return `true` if the input has been handled, `false` otherwise. */ open fun uKeyReleased(keyCode: Int, scanCode: Int, modifiers: UKeyboard.Modifiers?): Boolean { + lastScanCode = scanCode @Suppress("DEPRECATION") onKeyReleased(keyCode, 0.toChar(), modifiers) return smuggleKeyReleased From f960c005bd25f5c7378d12086b3f5d53601fae36 Mon Sep 17 00:00:00 2001 From: DJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com> Date: Mon, 14 Aug 2023 12:04:35 -0400 Subject: [PATCH 3/4] UScreen: support uKeyReleased on legacy versions --- src/main/kotlin/gg/essential/universal/UScreen.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/gg/essential/universal/UScreen.kt b/src/main/kotlin/gg/essential/universal/UScreen.kt index ad6719d..be684b0 100644 --- a/src/main/kotlin/gg/essential/universal/UScreen.kt +++ b/src/main/kotlin/gg/essential/universal/UScreen.kt @@ -15,6 +15,7 @@ import net.minecraft.client.gui.GuiScreen //$$ import net.minecraft.util.text.TranslationTextComponent //#endif //#else +import org.lwjgl.input.Keyboard import org.lwjgl.input.Mouse import java.io.IOException @@ -180,6 +181,15 @@ abstract class UScreen( } } + // Handles key release events on legacy versions + // Not final since that would be a breaking change + override fun handleKeyboardInput() { + super.handleKeyboardInput() + if (!Keyboard.getEventKeyState()) { + uKeyReleased(Keyboard.getEventKey(), 0, UKeyboard.getModifiers()) + } + } + final override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) { uMouseClicked(mouseX.toDouble(), mouseY.toDouble(), mouseButton) } @@ -359,10 +369,10 @@ abstract class UScreen( } /** - * Called when a key is released. Only called on versions that use LWJGL3. + * Called when a key is released. * * @param keyCode the key code of the key. See [UKeyboard]. - * @param scanCode the platform specific scanCode of the key. + * @param scanCode the platform specific scanCode of the key. Always 0 on versions that use LWJGL2. * @param modifiers the modifiers of the event. * @return `true` if the input has been handled, `false` otherwise. */ From d62457f56ddd2676577e07e0d20dbeaf0c33052b Mon Sep 17 00:00:00 2001 From: DJtheRedstoner <52044242+DJtheRedstoner@users.noreply.github.com> Date: Mon, 14 Aug 2023 19:18:52 -0400 Subject: [PATCH 4/4] update api --- api/UniversalCraft.api | 1 + 1 file changed, 1 insertion(+) diff --git a/api/UniversalCraft.api b/api/UniversalCraft.api index 1b12fc3..e23b2ca 100644 --- a/api/UniversalCraft.api +++ b/api/UniversalCraft.api @@ -901,6 +901,7 @@ public abstract class gg/essential/universal/UScreen : net/minecraft/client/gui/ public fun getNewGuiScale ()I public final fun getRestoreCurrentGuiOnClose ()Z public fun getUnlocalizedName ()Ljava/lang/String; + public fun handleKeyboardInput ()V public final fun handleMouseInput ()V public final fun initGui ()V public fun initScreen (II)V