Add better key binding support

This commit is contained in:
nea
2023-08-25 14:18:43 +02:00
parent a79452c254
commit 7842319416
10 changed files with 262 additions and 26 deletions

View File

@@ -0,0 +1,113 @@
package moe.nea.firmament.gui.config
import io.github.cottonmc.cotton.gui.widget.WButton
import io.github.cottonmc.cotton.gui.widget.data.InputResult
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement
import moe.nea.firmament.keybindings.FirmamentKeyBindings
import moe.nea.firmament.keybindings.SavedKeyBinding
import net.minecraft.client.util.InputUtil
import net.minecraft.text.Text
import net.minecraft.util.Formatting
import org.lwjgl.glfw.GLFW
class KeyBindingHandler(name: String, managedConfig: ManagedConfig) : ManagedConfig.OptionHandler<SavedKeyBinding> {
init {
FirmamentKeyBindings.registerKeyBinding(name, managedConfig)
}
override fun toJson(element: SavedKeyBinding): JsonElement? {
return Json.encodeToJsonElement(element)
}
override fun fromJson(element: JsonElement): SavedKeyBinding {
return Json.decodeFromJsonElement(element)
}
override fun emitGuiElements(opt: ManagedOption<SavedKeyBinding>, guiAppender: GuiAppender) {
var editing = false
var lastPressed = 0
var lastPressedNonModifier = 0
var updateButton: (() -> Unit)? = null
val button = object : WButton() {
override fun onKeyPressed(ch: Int, key: Int, modifiers: Int): InputResult {
if (!editing) {
return super.onKeyPressed(ch, key, modifiers)
}
if (ch == GLFW.GLFW_KEY_ESCAPE) {
lastPressedNonModifier = 0
editing = false
lastPressed = 0
updateButton!!()
return InputResult.PROCESSED
}
if (ch == GLFW.GLFW_KEY_LEFT_SHIFT || ch == GLFW.GLFW_KEY_RIGHT_SHIFT
|| ch == GLFW.GLFW_KEY_LEFT_ALT || ch == GLFW.GLFW_KEY_RIGHT_ALT
|| ch == GLFW.GLFW_KEY_LEFT_CONTROL || ch == GLFW.GLFW_KEY_RIGHT_CONTROL
) {
lastPressed = ch
} else {
opt.value = SavedKeyBinding(
ch, modifiers
)
editing = false
lastPressed = 0
lastPressedNonModifier = 0
}
updateButton!!()
return InputResult.PROCESSED
}
override fun onFocusLost() {
super.onFocusLost()
lastPressedNonModifier = 0
editing = false
lastPressed = 0
updateButton!!()
}
override fun onKeyReleased(ch: Int, key: Int, modifiers: Int): InputResult {
if (!editing)
return super.onKeyReleased(ch, key, modifiers)
if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
opt.value = SavedKeyBinding(
ch, modifiers
)
editing = false
lastPressed = 0
lastPressedNonModifier = 0
}
updateButton!!()
return InputResult.PROCESSED
}
}
fun updateLabel() {
val stroke = Text.literal("")
if (opt.value.shift) {
stroke.append("SHIFT + ") // TODO: translations?
}
if (opt.value.alt) {
stroke.append("ALT + ")
}
if (opt.value.ctrl) {
stroke.append("CTRL + ")
}
stroke.append(InputUtil.Type.KEYSYM.createFromCode(opt.value.keyCode).localizedText)
if (editing)
stroke.styled { it.withColor(Formatting.YELLOW) }
button.setLabel(stroke)
}
updateButton = ::updateLabel
updateButton()
button.setOnClick {
editing = true
button.requestFocus()
updateButton()
}
guiAppender.appendLabeledRow(opt.labelText, button)
}
}

View File

@@ -14,21 +14,22 @@ import io.github.cottonmc.cotton.gui.widget.WLabel
import io.github.cottonmc.cotton.gui.widget.data.Axis
import io.github.cottonmc.cotton.gui.widget.data.Insets
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment
import moe.nea.jarvis.api.Point
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.WTightScrollPanel
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.ScreenUtil.setScreenLater
import moe.nea.jarvis.api.Point
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
import kotlin.io.path.createDirectories
import kotlin.io.path.readText
import kotlin.io.path.writeText
import kotlin.time.Duration
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.WTightScrollPanel
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.ScreenUtil.setScreenLater
abstract class ManagedConfig(override val name: String) : ManagedConfigElement() {
@@ -106,6 +107,18 @@ abstract class ManagedConfig(override val name: String) : ManagedConfigElement()
}, HudMetaHandler(this, label, width, height))
}
protected fun keyBinding(
propertyName: String,
default: () -> Int,
): ManagedOption<SavedKeyBinding> = keyBindingWithDefaultModifiers(propertyName) { SavedKeyBinding(default()) }
protected fun keyBindingWithDefaultModifiers(
propertyName: String,
default: () -> SavedKeyBinding,
): ManagedOption<SavedKeyBinding> {
return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
}
protected fun integer(
propertyName: String,
min: Int,
@@ -125,7 +138,7 @@ abstract class ManagedConfig(override val name: String) : ManagedConfigElement()
fun reloadGui() {
latestGuiAppender?.reloadables?.forEach {it() }
latestGuiAppender?.reloadables?.forEach { it() }
}
fun getConfigEditor(parent: Screen? = null): CottonClientScreen {
@@ -137,7 +150,11 @@ abstract class ManagedConfig(override val name: String) : ManagedConfigElement()
guiapp.appendFullRow(WBox(Axis.HORIZONTAL).also {
it.add(WButton(Text.literal("")).also {
it.setOnClick {
AllConfigsGui.showAllGuis()
if (parent != null) {
setScreenLater(parent)
} else {
AllConfigsGui.showAllGuis()
}
}
})
it.add(WLabel(Text.translatable("firmament.config.${name}")).also {