Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8cb49bf
ElementaVersion: v12
Traben-0 Mar 29, 2026
7e60e5a
Dependencies: Bump UC
Traben-0 Mar 29, 2026
ac698e9
UIKeyboardEvents: Create new key events
Traben-0 Mar 29, 2026
def76ba
WindowScreen & UIComponent: implement `UScreen.InputHandler` & split …
Traben-0 Mar 29, 2026
0d413f7
Misc: usage suppressions
Traben-0 Mar 29, 2026
8b8f630
API: update
Traben-0 Mar 29, 2026
2060917
Review: fix deprecation text
Traben-0 Apr 6, 2026
92f656f
Review: convert to using `-> Boolean` functions
Traben-0 Apr 6, 2026
e94c8da
Review: comments
Traben-0 Apr 6, 2026
7e90891
Review: no longer use old listeners
Traben-0 Apr 6, 2026
67abf9f
Review: comment
Traben-0 Apr 6, 2026
5314522
Review: formatting
Traben-0 Apr 6, 2026
33f2fdd
Review: inline new functions into Window
Traben-0 Apr 6, 2026
fb410e0
Review: comment
Traben-0 Apr 6, 2026
9df4981
Review: rename functions
Traben-0 Apr 6, 2026
53c76df
Review: OVERRIDE_DEPRECATION -> Deprecation
Traben-0 Apr 6, 2026
78cdc62
Review: replace incorrect toChar() usage with a properly constructed …
Traben-0 Apr 6, 2026
cb51859
Review: call uSuperInputHandler() super methods
Traben-0 Apr 6, 2026
5dbf1ad
Review: fixup comments
Traben-0 Apr 6, 2026
daf24cb
Review: fixup function names
Traben-0 Apr 6, 2026
c5d856e
Review: keyCode -> key
Traben-0 Apr 6, 2026
6371b34
Review: revert unstable diff
Traben-0 Apr 6, 2026
3e478f7
API
Traben-0 Apr 6, 2026
299cb80
fix diff
Traben-0 Apr 6, 2026
df772bc
implement new listeners in AbstractTextInput
Traben-0 Apr 6, 2026
c9e2864
implement new listeners in MarkDownComponent
Traben-0 Apr 6, 2026
4ab4828
Review: drop functions in favour of directly modifying the listener l…
Traben-0 Apr 9, 2026
413d6ae
Review: OVERRIDE_DEPRECATION -> actual deprecation message
Traben-0 Apr 9, 2026
952c49d
Review: remove use of `run { }`
Traben-0 Apr 9, 2026
1412578
Review: uSuperInputHandler() -> super
Traben-0 Apr 9, 2026
1f717a0
Review: remove redundant checks
Traben-0 Apr 9, 2026
5f6f1a6
Review: space
Traben-0 Apr 9, 2026
41039e1
Review: return true
Traben-0 Apr 9, 2026
d749d5c
Review: call handleChar only if keycode wasn't handled
Traben-0 Apr 9, 2026
d6b9656
Review: missing condition
Traben-0 Apr 9, 2026
aa2a4d8
Review: fixup docs
Traben-0 Apr 9, 2026
443e7ba
Review: add isCopy, isCut, and isPaste helper functions to UIKeyEvent
Traben-0 Apr 9, 2026
7b7264c
API
Traben-0 Apr 9, 2026
304a3dd
Review: remove suppressions
Traben-0 Apr 26, 2026
849f494
bump UC
Traben-0 Apr 26, 2026
49d637e
implement UC modifier changes
Traben-0 Apr 26, 2026
75bda3e
suppress deprecated UKeyboard usages and note future changes to be made
Traben-0 Apr 26, 2026
a37641e
api changes
Traben-0 Apr 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions api/Elementa.api
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public final class gg/essential/elementa/ElementaVersion : java/lang/Enum {
public static final field V1 Lgg/essential/elementa/ElementaVersion;
public static final field V10 Lgg/essential/elementa/ElementaVersion;
public static final field V11 Lgg/essential/elementa/ElementaVersion;
public static final field V12 Lgg/essential/elementa/ElementaVersion;
public static final field V2 Lgg/essential/elementa/ElementaVersion;
public static final field V3 Lgg/essential/elementa/ElementaVersion;
public static final field V4 Lgg/essential/elementa/ElementaVersion;
Expand Down Expand Up @@ -89,6 +90,8 @@ public abstract class gg/essential/elementa/UIComponent : java/util/Observable,
protected final fun getMousePosition ()Lkotlin/Pair;
public final fun getMouseReleaseListeners ()Ljava/util/List;
public final fun getMouseScrollListeners ()Ljava/util/List;
public final fun getOnCharTyped ()Ljava/util/List;
public final fun getOnKeyPressed ()Ljava/util/List;
public fun getParent ()Lgg/essential/elementa/UIComponent;
public fun getRadius ()F
public fun getRight ()F
Expand Down Expand Up @@ -243,7 +246,7 @@ public final class gg/essential/elementa/VanillaFontRenderer : gg/essential/elem
public final class gg/essential/elementa/VanillaFontRenderer$Companion {
}

public abstract class gg/essential/elementa/WindowScreen : gg/essential/universal/UScreen {
public abstract class gg/essential/elementa/WindowScreen : gg/essential/universal/UScreen, gg/essential/universal/UScreen$InputHandler {
public fun <init> ()V
public fun <init> (Lgg/essential/elementa/ElementaVersion;)V
public fun <init> (Lgg/essential/elementa/ElementaVersion;Z)V
Expand Down Expand Up @@ -278,6 +281,11 @@ public abstract class gg/essential/elementa/WindowScreen : gg/essential/universa
public fun onMouseScrolled (DDDD)V
public fun onScreenClose ()V
public final fun stopAnimating (Lkotlin/reflect/KMutableProperty0;)V
public fun uCharTyped (I)Z
public fun uKeyPressed (IILgg/essential/universal/UKeyboard$Modifiers;)Z
public fun uMouseClicked (DDILgg/essential/universal/UKeyboard$Modifiers;)Z
public fun uMouseReleased (DDILgg/essential/universal/UKeyboard$Modifiers;)Z
public fun uMouseScrolled (DDDD)Z
}

public class gg/essential/elementa/components/GradientComponent : gg/essential/elementa/components/UIBlock {
Expand Down Expand Up @@ -756,6 +764,7 @@ public final class gg/essential/elementa/components/Window : gg/essential/elemen
public final fun addFloatingComponent (Lgg/essential/elementa/UIComponent;)V
public fun afterInitialization ()V
public fun animationFrame ()V
public final fun charTyped (Lgg/essential/elementa/events/UICharEvent;)Z
public fun draw (Lgg/essential/universal/UMatrixStack;)V
public final fun drawFloatingComponents ()V
public final fun drawFloatingComponents (Lgg/essential/universal/UMatrixStack;)V
Expand All @@ -775,6 +784,7 @@ public final class gg/essential/elementa/components/Window : gg/essential/elemen
public fun hitTest (FF)Lgg/essential/elementa/UIComponent;
public final fun invalidateCachedConstraints ()V
public final fun isAreaVisible (DDDD)Z
public final fun keyPressed (Lgg/essential/elementa/events/UIKeyEvent;)Z
public fun keyType (CI)V
public fun mouseClick (DDI)V
public fun mouseRelease ()V
Expand Down Expand Up @@ -938,7 +948,8 @@ public abstract class gg/essential/elementa/components/input/AbstractTextInput :
public final fun isActive ()Z
protected fun isBreakingCharacter (C)Z
public final fun onActivate (Lkotlin/jvm/functions/Function1;)Lgg/essential/elementa/components/input/AbstractTextInput;
protected abstract fun onEnterPressed ()V
protected fun onEnterPressed ()V
protected abstract fun onEnterPressed (Lgg/essential/universal/UKeyboard$Modifiers;)V
public final fun onUpdate (Lkotlin/jvm/functions/Function1;)Lgg/essential/elementa/components/input/AbstractTextInput;
protected fun recalculateAllVisualLines ()V
protected abstract fun recalculateDimensions ()V
Expand Down Expand Up @@ -1119,7 +1130,7 @@ public class gg/essential/elementa/components/input/UITextInput : gg/essential/e
protected final fun getPlaceholderWidth ()F
public fun getText ()Ljava/lang/String;
protected fun getTextForRender ()Ljava/lang/String;
protected fun onEnterPressed ()V
protected fun onEnterPressed (Lgg/essential/universal/UKeyboard$Modifiers;)V
protected fun recalculateDimensions ()V
protected fun screenPosToVisualPos (FF)Lgg/essential/elementa/components/input/AbstractTextInput$LinePosition;
protected fun scrollIntoView (Lgg/essential/elementa/components/input/AbstractTextInput$LinePosition;)V
Expand Down Expand Up @@ -2717,6 +2728,12 @@ public final class gg/essential/elementa/effects/StencilEffect$Companion {
public final fun enableStencil ()V
}

public final class gg/essential/elementa/events/UICharEvent {
public fun <init> (I)V
public final fun getCodepoint ()I
public final fun getString ()Ljava/lang/String;
}

public final class gg/essential/elementa/events/UIClickEvent : gg/essential/elementa/events/UIEvent {
public fun <init> (FFILgg/essential/elementa/UIComponent;Lgg/essential/elementa/UIComponent;I)V
public final fun component1 ()F
Expand Down Expand Up @@ -2750,6 +2767,16 @@ public abstract class gg/essential/elementa/events/UIEvent {
public final fun stopPropagation ()V
}

public final class gg/essential/elementa/events/UIKeyEvent {
public fun <init> (IILgg/essential/universal/UKeyboard$Modifiers;)V
public final fun getKey ()I
public final fun getModifiers ()Lgg/essential/universal/UKeyboard$Modifiers;
public final fun getScanCode ()I
public final fun isCopy ()Z
public final fun isCut ()Z
public final fun isPaste ()Z
}

public final class gg/essential/elementa/events/UIScrollEvent : gg/essential/elementa/events/UIEvent {
public fun <init> (DDLgg/essential/elementa/UIComponent;Lgg/essential/elementa/UIComponent;)V
public fun <init> (DLgg/essential/elementa/UIComponent;Lgg/essential/elementa/UIComponent;)V
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
kotlin = "1.9.25"
kotlinx-coroutines = "1.5.2"
jetbrains-annotations = "23.0.0"
universalcraft = "466"
universalcraft = "485+feature-em-1645-closing-uscreen-via-esc-on-119-puts-you-in-the-menu-rather"
commonmark = "0.17.1"
dom4j = "2.1.1"

Expand Down
28 changes: 28 additions & 0 deletions src/main/kotlin/gg/essential/elementa/ElementaVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import gg.essential.elementa.components.Window
import gg.essential.elementa.constraints.SuperConstraint
import gg.essential.elementa.constraints.animation.AnimationComponent
import gg.essential.elementa.effects.Effect
import gg.essential.universal.UScreen
import gg.essential.universal.render.URenderPipeline
import gg.essential.universal.shader.BlendState

Expand Down Expand Up @@ -204,8 +205,31 @@ enum class ElementaVersion {
*
* See [UniversalCraft#128](https://github.com/SparkUniverse/UniversalCraft/pull/128) for the underlying changes.
*/
@Deprecated(DEPRECATION_MESSAGE)
V11,

/**
* Improvements for key press inputs.
*
* WindowScreen now implements [UScreen.InputHandler] which provides new functions for key and mouse inputs that
* follow more modern Minecraft input method conventions, most notably allowing us to mark an input as handled to
* prevent followup execution in Minecraft itself.
*
* As of V12 the key & character input events have been split up and moved to these new methods.
* `keyType(typedChar: Char, keyCode: Int)` in [Window] has been split into:
* - keyPressed(keyEvent: UIKeyEvent)
* - charTyped(charEvent: UICharEvent)
* With the backing list for the new listeners now requiring manual modification to set up.
* E.G. `UIComponent.onKeyPressed.add { }` & `UIComponent.onCharTyped.add { }` replace the old `UIComponent.onKeyType { }`
*
* Also see [gg.essential.elementa.events.UIKeyEvent] & [gg.essential.elementa.events.UICharEvent].
*
* Note: The other improved inputs provided by [UScreen.InputHandler] have not been implemented by V12. (e.g. mouse inputs)
*
* See [UniversalCraft#125](https://github.com/SparkUniverse/UniversalCraft/pull/125) for the underlying changes.
*/
V12,

;

/**
Expand Down Expand Up @@ -258,14 +282,18 @@ Be sure to read through all the changes between your current version and your ne
internal val v9 = V9
@Suppress("DEPRECATION")
internal val v10 = V10
@Suppress("DEPRECATION")
internal val v11 = V11
internal val v12 = V12

internal val atLeastV9Active: Boolean
get() = active >= v9
internal val atLeastV10Active: Boolean
get() = active >= v10
internal val atLeastV11Active: Boolean
get() = active >= v11
internal val atLeastV12Active: Boolean
get() = active >= v12

@PublishedApi
internal var active: ElementaVersion = v0
Expand Down
13 changes: 13 additions & 0 deletions src/main/kotlin/gg/essential/elementa/UIComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import gg.essential.elementa.dsl.animate
import gg.essential.elementa.dsl.toConstraint
import gg.essential.elementa.effects.Effect
import gg.essential.elementa.effects.ScissorEffect
import gg.essential.elementa.events.UICharEvent
import gg.essential.elementa.events.UIClickEvent
import gg.essential.elementa.events.UIKeyEvent
import gg.essential.elementa.events.UIScrollEvent
import gg.essential.elementa.font.FontProvider
import gg.essential.elementa.state.v2.ReferenceHolder
Expand Down Expand Up @@ -119,7 +121,12 @@ abstract class UIComponent : Observable(), ReferenceHolder {
get() = field.also { ownFlags += Flags.RequiresMouseMove }
val mouseDragListeners = mutableListOf<UIComponent.(mouseX: Float, mouseY: Float, button: Int) -> Unit>()
get() = field.also { ownFlags += Flags.RequiresMouseDrag }
@Deprecated("See [ElementaVersion.V12]. Replaced by either the `onKeyPressed` or `onCharTyped` listener lists.")
val keyTypedListeners = mutableListOf<UIComponent.(typedChar: Char, keyCode: Int) -> Unit>()
// Requires ElementaVersion.V12
val onKeyPressed = mutableListOf<UIComponent.(keyEvent: UIKeyEvent) -> Boolean>()
// Requires ElementaVersion.V12
val onCharTyped = mutableListOf<UIComponent.(keyEvent: UICharEvent) -> Boolean>()

private var currentlyHovered = false
private val beforeHideAnimations = mutableListOf<AnimatingConstraints.() -> Unit>()
Expand Down Expand Up @@ -836,7 +843,9 @@ abstract class UIComponent : Observable(), ReferenceHolder {
this.forEachChild { it.superCall() }
}

@Deprecated("See [ElementaVersion.V12]. Listeners are now directly called from [Window].")
open fun keyType(typedChar: Char, keyCode: Int) {
@Suppress("DEPRECATION")
for (listener in keyTypedListeners)
this.listener(typedChar, keyCode)
}
Expand Down Expand Up @@ -1021,11 +1030,15 @@ abstract class UIComponent : Observable(), ReferenceHolder {
mouseScrollListeners.add { method.accept(it) }
}

@Deprecated("See [ElementaVersion.V12]. Replaced by either the `onKeyPressed` or `onCharTyped` listener lists.")
fun onKeyType(method: UIComponent.(typedChar: Char, keyCode: Int) -> Unit) = apply {
@Suppress("DEPRECATION")
keyTypedListeners.add(method)
}

@Deprecated("See [ElementaVersion.V12]. Replaced by either the `onKeyPressed` or `onCharTyped` listener lists.")
fun onKeyTypeConsumer(method: BiConsumer<Char, Int>) {
@Suppress("DEPRECATION")
keyTypedListeners.add { t: Char, u: Int -> method.accept(t, u) }
}

Expand Down
71 changes: 68 additions & 3 deletions src/main/kotlin/gg/essential/elementa/WindowScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package gg.essential.elementa

import gg.essential.elementa.components.Window
import gg.essential.elementa.constraints.animation.*
import gg.essential.elementa.events.UICharEvent
import gg.essential.elementa.events.UIKeyEvent
import gg.essential.universal.UKeyboard
import gg.essential.universal.UMatrixStack
import gg.essential.universal.UMouse
Expand All @@ -21,7 +23,7 @@ abstract class WindowScreen @JvmOverloads constructor(
private val drawDefaultBackground: Boolean = true,
restoreCurrentGuiOnClose: Boolean = false,
newGuiScale: Int = -1
) : UScreen(restoreCurrentGuiOnClose, newGuiScale) {
) : UScreen(restoreCurrentGuiOnClose, newGuiScale), UScreen.InputHandler {
val window = Window(version)
private var isInitialized = false

Expand All @@ -35,8 +37,22 @@ abstract class WindowScreen @JvmOverloads constructor(
) : this(ElementaVersion.v0, enableRepeatKeys, drawDefaultBackground, restoreCurrentGuiOnClose, newGuiScale)

init {
window.onKeyType { typedChar, keyCode ->
defaultKeyBehavior(typedChar, keyCode)
if (version >= ElementaVersion.v12) {
window.onKeyPressed.add { keyEvent ->
super.uKeyPressed(keyEvent.key, keyEvent.scanCode, keyEvent.modifiers)
}
window.onCharTyped.add { charEvent ->
super.uCharTyped(charEvent.codepoint)
}
} else {
@Suppress("DEPRECATION")
window.onKeyType { typedChar, keyCode ->
defaultKeyBehavior(typedChar, keyCode)
}

// This will ensure that inputs go to the old `on*(): Unit` input functions
// rather than the V12+ `u*(): Boolean` functions
inputHandler = null
}
}

Expand All @@ -60,6 +76,8 @@ abstract class WindowScreen @JvmOverloads constructor(
window.draw(matrixStack)
}

@Deprecated("See [ElementaVersion.V12]")
@Suppress("DEPRECATION")
override fun onMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int) {
super.onMouseClicked(mouseX, mouseY, mouseButton)

Expand All @@ -79,13 +97,35 @@ abstract class WindowScreen @JvmOverloads constructor(
window.mouseClick(adjustedMouseX, adjustedMouseY, mouseButton)
Comment thread
Johni0702 marked this conversation as resolved.
}

// Called only when ElementaVersion >= V12
override fun uMouseClicked(x: Double, y: Double, button: Int, modifiers: UKeyboard.Modifiers): Boolean {
super.uMouseClicked(x, y, button, modifiers)

// We also need to pass along clicks
window.mouseClick(x, y, button)

return false // TODO returning implementation, see uKeyPressed()
}

@Deprecated("See [ElementaVersion.V12]")
@Suppress("DEPRECATION")
override fun onMouseReleased(mouseX: Double, mouseY: Double, state: Int) {
super.onMouseReleased(mouseX, mouseY, state)

// We also need to pass along mouse releases
window.mouseRelease()
}

// Called only when ElementaVersion >= V12
override fun uMouseReleased(x: Double, y: Double, button: Int, modifiers: UKeyboard.Modifiers): Boolean {
super.uMouseReleased(x, y, button, modifiers)

// We also need to pass along mouse releases
window.mouseRelease()

return false // TODO returning implementation, see uKeyPressed()
}

@Suppress("DEPRECATION")
@Deprecated(
"Provided `delta` values have different units depending on Minecraft versions. See ElementaVersion.V11 for details.",
Expand All @@ -100,6 +140,8 @@ abstract class WindowScreen @JvmOverloads constructor(
}
}

@Deprecated("See [ElementaVersion.V12]")
@Suppress("DEPRECATION")
override fun onMouseScrolled(mouseX: Double, mouseY: Double, deltaHorizontal: Double, deltaVertical: Double) {
super.onMouseScrolled(mouseX, mouseY, deltaHorizontal, deltaVertical)

Expand All @@ -108,11 +150,32 @@ abstract class WindowScreen @JvmOverloads constructor(
}
}

// Called only when ElementaVersion >= V12
override fun uMouseScrolled(x: Double, y: Double, scrollX: Double, scrollY: Double): Boolean {
super.uMouseScrolled(x, y, scrollX, scrollY)

window.mouseScroll(scrollX, scrollY)

return false // TODO returning implementation, see uKeyPressed()
}

@Suppress("DEPRECATION")
@Deprecated("Method is not called when ElementaVersion >= V12. See ElementaVersion.V12 for details.")
override fun onKeyPressed(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) {
// We also need to pass along typed keys
window.keyType(typedChar, keyCode)
}

// Called only when ElementaVersion >= V12
override fun uKeyPressed(key: Int, scanCode: Int, modifiers: UKeyboard.Modifiers): Boolean {
return window.keyPressed(UIKeyEvent(key, scanCode, modifiers))
}

// Called only when ElementaVersion >= V12
override fun uCharTyped(codepoint: Int): Boolean {
return window.charTyped(UICharEvent(codepoint))
}

override fun initScreen(width: Int, height: Int) {
window.onWindowResize()

Expand All @@ -133,7 +196,9 @@ abstract class WindowScreen @JvmOverloads constructor(
UKeyboard.allowRepeatEvents(false)
}

@Deprecated("[See ElementaVersion.V12] This method is not called when ElementaVersion >= V12.")
fun defaultKeyBehavior(typedChar: Char, keyCode: Int) {
@Suppress("DEPRECATION")
super.onKeyPressed(keyCode, typedChar, UKeyboard.getModifiers())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class ScrollComponent constructor(
private val mouseScrollLambda: UIComponent.(UIScrollEvent) -> Unit = {
if (Window.of(this).version >= ElementaVersion.v5) {
// new behavior
@Suppress("DEPRECATION") // Modifiers not provided for mouse sroll events
val scrollDirection = if (!UKeyboard.isShiftKeyDown()) primaryScrollDirection else secondaryScrollDirection
if (scrollDirection != null) {
if (onScroll(it.delta.toFloat(), isHorizontal = scrollDirection == Direction.Horizontal) || !passthroughScroll) {
Expand All @@ -157,6 +158,7 @@ class ScrollComponent constructor(
}
} else {
// old behavior
@Suppress("DEPRECATION") // Modifiers not provided for mouse sroll events
if (UKeyboard.isShiftKeyDown() && horizontalScrollEnabled) {
onScroll(it.delta.toFloat(), isHorizontal = true)
} else if (!UKeyboard.isShiftKeyDown() && verticalScrollEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ abstract class TreeNode {

arrowComponent.onMouseClick { event ->
event.stopImmediatePropagation()
@Suppress("DEPRECATION") //TODO pass modifiers when they become available, see [ElementaVersion.V12]
val isRecursive = UKeyboard.isShiftKeyDown()

if (opened) {
Expand Down
Loading
Loading