1818package com.lambda.config.settings.complex
1919
2020import com.google.gson.reflect.TypeToken
21+ import com.lambda.brigadier.CommandResult.Companion.failure
22+ import com.lambda.brigadier.CommandResult.Companion.success
23+ import com.lambda.brigadier.argument.boolean
2124import com.lambda.brigadier.argument.value
2225import com.lambda.brigadier.argument.word
23- import com.lambda.brigadier.execute
26+ import com.lambda.brigadier.executeWithResult
27+ import com.lambda.brigadier.optional
2428import com.lambda.brigadier.required
2529import com.lambda.config.AbstractSetting
30+ import com.lambda.config.settings.complex.Bind.Companion.mouseBind
2631import com.lambda.gui.dsl.ImGuiBuilder
32+ import com.lambda.util.InputUtils
2733import com.lambda.util.KeyCode
28- import com.lambda.util.KeyboardUtils
34+ import com.lambda.util.Mouse
2935import com.lambda.util.StringUtils.capitalize
3036import com.lambda.util.extension.CommandBuilder
3137import imgui.ImGui.isMouseClicked
@@ -37,22 +43,23 @@ import org.lwjgl.glfw.GLFW
3743
3844class KeybindSetting (
3945 override val name : String ,
40- defaultValue : KeyCode ,
46+ defaultValue : Bind ,
4147 description : String ,
4248 visibility : () -> Boolean ,
43- ) : AbstractSetting<KeyCode >(
49+ ) : AbstractSetting<Bind >(
4450 defaultValue,
45- TypeToken .get(KeyCode ::class.java).type,
51+ TypeToken .get(Bind ::class.java).type,
4652 description,
4753 visibility
4854) {
4955 private var listening = false
5056
5157 override fun ImGuiBuilder.buildLayout () {
52- val key = value
53- val scancode = if (key == KeyCode .UNBOUND ) - 69 else GLFW .glfwGetKeyScancode(key.code)
54- val translated = if (key == KeyCode .UNBOUND ) key else KeyCode .virtualMapUS(key.code, scancode)
55- val preview = if (listening) " $name : Press any key…" else " $name : $translated "
58+ val bind = value
59+ val scancode = if (bind.code == KeyCode .UNBOUND .code) - 69 else GLFW .glfwGetKeyScancode(bind.code)
60+ val translated = if (bind.keyCode == KeyCode .UNBOUND ) bind.keyCode else KeyCode .virtualMapUS(bind.code, scancode)
61+ val preview = if (listening) " $name : Press any key…"
62+ else if (bind.isMouseButton) " Mouse ${bind.code} " else " $name : $translated "
5663
5764 if (listening) {
5865 withStyleColor(ImGuiCol .Button , 0.20f , 0.50f , 1.00f , 1.00f ) {
@@ -75,7 +82,7 @@ class KeybindSetting(
7582 }
7683
7784 onItemClick(ImGuiMouseButton .Right ) {
78- value = KeyCode . UNBOUND
85+ value = Bind . EMPTY
7986 listening = false
8087 }
8188
@@ -85,38 +92,78 @@ class KeybindSetting(
8592
8693 sameLine()
8794 smallButton(" Unbind" ) {
88- value = KeyCode . UNBOUND
95+ value = Bind . EMPTY
8996 listening = false
9097 }
9198 onItemHover(ImGuiHoveredFlags .Stationary ) {
9299 lambdaTooltip(" Clear binding" )
93100 }
94101
95- val poll = KeyboardUtils .lastEvent
96- if (listening && poll.isPressed) {
97- when (val key = poll.translated) {
98- KeyCode .ESCAPE -> listening = false
99- KeyCode .BACKSPACE , KeyCode .DELETE -> {
100- value = KeyCode .UNBOUND
101- listening = false
102- }
103- else -> {
104- value = key
105- listening = false
102+ val keyboardPoll = InputUtils .lastKeyboardEvent
103+ val mousePoll = InputUtils .lastMouseEvent
104+ if (listening) {
105+ if (keyboardPoll.isPressed) {
106+ when (val key = keyboardPoll.translated) {
107+ KeyCode .ESCAPE -> {}
108+ KeyCode .BACKSPACE , KeyCode .DELETE -> value = Bind .EMPTY
109+ else -> value = Bind (key)
106110 }
111+ listening = false
112+ } else if (mousePoll.action == Mouse .Action .Click .ordinal) {
113+ value = mouseBind(mousePoll.button)
114+ listening = false
107115 }
108116 }
109117 }
110118
111119 override fun CommandBuilder.buildCommand (registry : CommandRegistryAccess ) {
112- required(word(name)) { parameter ->
120+ required(word(name)) { name ->
113121 suggests { _, builder ->
114122 KeyCode .entries.forEach { builder.suggest(it.name.capitalize()) }
123+ (1 .. 10 ).forEach { builder.suggest(it) }
115124 builder.buildFuture()
116125 }
117- execute {
118- trySetValue(KeyCode .valueOf(parameter().value()))
126+ optional(boolean(" mouse button" )) { isMouseButton ->
127+ executeWithResult {
128+ val isMouse = if (isMouseButton != null ) isMouseButton().value() else false
129+ var bind = Bind .EMPTY
130+ if (isMouse) {
131+ val num = try {
132+ name().value().toInt()
133+ } catch (_: NumberFormatException ) {
134+ return @executeWithResult failure(" ${name().value()} doesn't match with a mouse button" )
135+ }
136+ bind = mouseBind(num)
137+ } else {
138+ bind = try {
139+ Bind (KeyCode .valueOf(name().value()))
140+ } catch (_: IllegalArgumentException ) {
141+ return @executeWithResult failure(" ${name().value()} doesn't match with a bind" )
142+ }
143+ }
144+
145+ trySetValue(bind)
146+ return @executeWithResult success()
147+ }
119148 }
120149 }
121150 }
122151}
152+
153+ data class Bind (
154+ val keyCode : KeyCode = KeyCode .UNBOUND ,
155+ val code : Int = keyCode.code,
156+ val isMouseButton : Boolean = false
157+ ) {
158+ val name: String
159+ get() = if (isMouseButton) " Mouse $code " else keyCode.name
160+
161+ override fun toString () =
162+ " Key Code: $keyCode , Code: $code , Mouse Button: $isMouseButton "
163+
164+ companion object {
165+ val EMPTY = Bind ()
166+
167+ fun mouseBind (code : Int ) = Bind (code = code, isMouseButton = true )
168+ }
169+ }
0 commit comments