From 784231941661a3108549a1b5cd499bc5f7de2e46 Mon Sep 17 00:00:00 2001 From: nea Date: Fri, 25 Aug 2023 14:18:43 +0200 Subject: Add better key binding support --- .../nea/firmament/gui/config/KeyBindingHandler.kt | 113 +++++++++++++++++++++ .../moe/nea/firmament/gui/config/ManagedConfig.kt | 35 +++++-- 2 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt (limited to 'src/main/kotlin/moe/nea/firmament/gui') diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt new file mode 100644 index 0000000..5a4e3af --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt @@ -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 { + 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, 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) + } + +} diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt index 56aca46..8743293 100644 --- a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt +++ b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt @@ -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 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.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 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 = keyBindingWithDefaultModifiers(propertyName) { SavedKeyBinding(default()) } + + protected fun keyBindingWithDefaultModifiers( + propertyName: String, + default: () -> SavedKeyBinding, + ): ManagedOption { + 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 { -- cgit