forked from SparkUniverse/Elementa
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWindowScreen.kt
More file actions
167 lines (133 loc) · 6.06 KB
/
WindowScreen.kt
File metadata and controls
167 lines (133 loc) · 6.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package gg.essential.elementa
import gg.essential.elementa.components.Window
import gg.essential.elementa.constraints.animation.*
import gg.essential.universal.UKeyboard
import gg.essential.universal.UMatrixStack
import gg.essential.universal.UMouse
import gg.essential.universal.UScreen
import java.awt.Color
import kotlin.math.floor
import kotlin.reflect.KMutableProperty0
/**
* Version of [UScreen] with a [Window] provided and a few useful
* functions for Elementa Gui programming.
*/
abstract class WindowScreen @JvmOverloads constructor(
private val version: ElementaVersion,
private val enableRepeatKeys: Boolean = true,
private val drawDefaultBackground: Boolean = true,
restoreCurrentGuiOnClose: Boolean = false,
newGuiScale: Int = -1
) : UScreen(restoreCurrentGuiOnClose, newGuiScale) {
val window = Window(version)
private var isInitialized = false
@Deprecated("Add ElementaVersion as the first argument to opt-in to improved behavior.")
@JvmOverloads
constructor(
enableRepeatKeys: Boolean = true,
drawDefaultBackground: Boolean = true,
restoreCurrentGuiOnClose: Boolean = false,
newGuiScale: Int = -1
) : this(ElementaVersion.v0, enableRepeatKeys, drawDefaultBackground, restoreCurrentGuiOnClose, newGuiScale)
init {
window.onKeyType { typedChar, keyCode ->
defaultKeyBehavior(typedChar, keyCode)
}
}
open fun afterInitialization() { }
override fun onDrawScreen(matrixStack: UMatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
if (!isInitialized) {
isInitialized = true
afterInitialization()
}
if (drawDefaultBackground)
super.onDrawBackground(matrixStack, 0)
super.onDrawScreen(matrixStack, mouseX, mouseY, partialTicks)
// Now, we need to hook up Elementa to this GuiScreen. In practice, Elementa
// is not constrained to being used solely inside of a GuiScreen, all the programmer
// needs to do is call the [Window] events when appropriate, whenever that may be.
// In our example, it is in the overridden [GuiScreen#drawScreen] method.
window.draw(matrixStack)
}
override fun onMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int) {
super.onMouseClicked(mouseX, mouseY, mouseButton)
// Restore decimal value to mouse locations if not present.
// See [ElementaVersion.V2] for more info
val (adjustedMouseX, adjustedMouseY) =
if (version >= ElementaVersion.v2 && (mouseX == floor(mouseX) && mouseY == floor(mouseY))) {
val x = UMouse.Scaled.x
val y = UMouse.Scaled.y
mouseX + (x - floor(x)) to mouseY + (y - floor(y))
} else {
mouseX to mouseY
}
// We also need to pass along clicks
window.mouseClick(adjustedMouseX, adjustedMouseY, mouseButton)
}
override fun onMouseReleased(mouseX: Double, mouseY: Double, state: Int) {
super.onMouseReleased(mouseX, mouseY, state)
// We also need to pass along mouse releases
window.mouseRelease()
}
@Suppress("DEPRECATION")
@Deprecated(
"Provided `delta` values have different units depending on Minecraft versions. See ElementaVersion.V11 for details.",
replaceWith = ReplaceWith("onMouseScrolled(mouseX, mouseY, deltaHorizontal, deltaVertical)")
)
override fun onMouseScrolled(delta: Double) {
super.onMouseScrolled(delta)
if (version < ElementaVersion.v11) {
// We also need to pass along scrolling
window.mouseScroll(delta.coerceIn(-1.0, 1.0))
}
}
override fun onMouseScrolled(mouseX: Double, mouseY: Double, deltaHorizontal: Double, deltaVertical: Double) {
super.onMouseScrolled(mouseX, mouseY, deltaHorizontal, deltaVertical)
if (version >= ElementaVersion.v11) {
window.mouseScroll(deltaHorizontal, deltaVertical)
}
}
override fun onKeyPressed(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) {
// We also need to pass along typed keys
window.keyType(typedChar, keyCode)
}
override fun initScreen(width: Int, height: Int) {
window.onWindowResize()
super.initScreen(width, height)
// Since we want our users to be able to hold a key
// to type. This is a wrapper around a base LWJGL function.
// - Keyboard.enableRepeatEvents in <= 1.12.2
if (enableRepeatKeys)
UKeyboard.allowRepeatEvents(true)
}
override fun onScreenClose() {
super.onScreenClose()
// We need to disable repeat events when leaving the gui.
if (enableRepeatKeys)
UKeyboard.allowRepeatEvents(false)
}
fun defaultKeyBehavior(typedChar: Char, keyCode: Int) {
super.onKeyPressed(keyCode, typedChar, UKeyboard.getModifiers())
}
/**
* Field animation API
*/
fun KMutableProperty0<Int>.animate(strategy: AnimationStrategy, time: Float, newValue: Int, delay: Float = 0f) {
window.apply { this@animate.animate(strategy, time, newValue, delay) }
}
fun KMutableProperty0<Float>.animate(strategy: AnimationStrategy, time: Float, newValue: Float, delay: Float = 0f) {
window.apply { this@animate.animate(strategy, time, newValue, delay) }
}
fun KMutableProperty0<Long>.animate(strategy: AnimationStrategy, time: Float, newValue: Long, delay: Float = 0f) {
window.apply { this@animate.animate(strategy, time, newValue, delay) }
}
fun KMutableProperty0<Double>.animate(strategy: AnimationStrategy, time: Float, newValue: Double, delay: Float = 0f) {
window.apply { this@animate.animate(strategy, time, newValue, delay) }
}
fun KMutableProperty0<Color>.animate(strategy: AnimationStrategy, time: Float, newValue: Color, delay: Float = 0f) {
window.apply { this@animate.animate(strategy, time, newValue, delay) }
}
fun KMutableProperty0<*>.stopAnimating() {
window.apply { this@stopAnimating.stopAnimating() }
}
}