diff options
author | Linnea Gräf <nea@nea.moe> | 2024-10-13 19:53:10 +0200 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-10-13 19:53:10 +0200 |
commit | 87b851373071490bb371ba1160f85f0341579cb2 (patch) | |
tree | 45d267d83baad2e3cb6caad6127f6a4d40e7fcbf /src/compat | |
parent | e6142bb93619dee768fc18b87ffdd28558d4bcab (diff) | |
download | Firmament-87b851373071490bb371ba1160f85f0341579cb2.tar.gz Firmament-87b851373071490bb371ba1160f85f0341579cb2.tar.bz2 Firmament-87b851373071490bb371ba1160f85f0341579cb2.zip |
Add YACL config menu
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/yacl/java/KeybindingBuilder.kt | 16 | ||||
-rw-r--r-- | src/compat/yacl/java/KeybindingController.kt | 71 | ||||
-rw-r--r-- | src/compat/yacl/java/YaclIntegration.kt | 119 |
3 files changed, 206 insertions, 0 deletions
diff --git a/src/compat/yacl/java/KeybindingBuilder.kt b/src/compat/yacl/java/KeybindingBuilder.kt new file mode 100644 index 0000000..322ddff --- /dev/null +++ b/src/compat/yacl/java/KeybindingBuilder.kt @@ -0,0 +1,16 @@ +package moe.nea.firmament.compat.yacl + +import dev.isxander.yacl3.api.Controller +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.controller.ControllerBuilder +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.keybindings.SavedKeyBinding + +class KeybindingBuilder( + val option: Option<SavedKeyBinding>, + val managedOption: ManagedOption<SavedKeyBinding> +) : ControllerBuilder<SavedKeyBinding> { + override fun build(): Controller<SavedKeyBinding> { + return KeybindingController(option, managedOption) + } +} diff --git a/src/compat/yacl/java/KeybindingController.kt b/src/compat/yacl/java/KeybindingController.kt new file mode 100644 index 0000000..6be9dd1 --- /dev/null +++ b/src/compat/yacl/java/KeybindingController.kt @@ -0,0 +1,71 @@ +package moe.nea.firmament.compat.yacl + +import dev.isxander.yacl3.api.Controller +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.utils.Dimension +import dev.isxander.yacl3.gui.AbstractWidget +import dev.isxander.yacl3.gui.YACLScreen +import dev.isxander.yacl3.gui.controllers.ControllerWidget +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.KeyBindingHandler +import moe.nea.firmament.gui.config.KeyBindingStateManager +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.keybindings.SavedKeyBinding + +class KeybindingController( + val option: Option<SavedKeyBinding>, + val managedOption: ManagedOption<SavedKeyBinding>, +) : Controller<SavedKeyBinding> { + val handler = managedOption.handler as KeyBindingHandler + override fun option(): Option<SavedKeyBinding> { + return option + } + + override fun formatValue(): Text { + return option.pendingValue().format() + } + + override fun provideWidget(screen: YACLScreen, widgetDimension: Dimension<Int>): AbstractWidget { + lateinit var button: ControllerWidget<KeybindingController> + val sm = KeyBindingStateManager( + { option.pendingValue() }, + { option.requestSet(it) }, + { screen.focused = null }, + { screen.focused = button } + ) + button = object : ControllerWidget<KeybindingController>(this, screen, widgetDimension) { + override fun getHoveredControlWidth(): Int { + return 130 + } + + override fun getValueText(): Text { + return sm.label + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return sm.keyboardEvent(keyCode, true) + } + + override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return sm.keyboardEvent(keyCode, false) + } + + override fun unfocus() { + sm.onLostFocus() + } + + override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { + if (button == 0 && isHovered) { + sm.onClick() + return true + } + return super.mouseClicked(mouseX, mouseY, button) + } + } + option.addListener { t, u -> + sm.updateLabel() + } + sm.updateLabel() + return button + } +} diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt new file mode 100644 index 0000000..6c9354a --- /dev/null +++ b/src/compat/yacl/java/YaclIntegration.kt @@ -0,0 +1,119 @@ +package moe.nea.firmament.compat.yacl + +import com.google.auto.service.AutoService +import dev.isxander.yacl3.api.Binding +import dev.isxander.yacl3.api.ButtonOption +import dev.isxander.yacl3.api.ConfigCategory +import dev.isxander.yacl3.api.LabelOption +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.YetAnotherConfigLib +import dev.isxander.yacl3.api.controller.ControllerBuilder +import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder +import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder +import dev.isxander.yacl3.api.controller.StringControllerBuilder +import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.DurationUnit +import net.minecraft.client.gui.screen.Screen +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.AllConfigsGui +import moe.nea.firmament.gui.config.BooleanHandler +import moe.nea.firmament.gui.config.ClickHandler +import moe.nea.firmament.gui.config.DurationHandler +import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider +import moe.nea.firmament.gui.config.HudMeta +import moe.nea.firmament.gui.config.HudMetaHandler +import moe.nea.firmament.gui.config.IntegerHandler +import moe.nea.firmament.gui.config.KeyBindingHandler +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.gui.config.StringHandler +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.FirmFormatters + + +@AutoService(FirmamentConfigScreenProvider::class) +class YaclIntegration : FirmamentConfigScreenProvider { + fun buildCategories() = + AllConfigsGui.allConfigs + .map(::buildCategory) + + private fun buildCategory(managedConfig: ManagedConfig): ConfigCategory { + return ConfigCategory.createBuilder() + .name(managedConfig.labelText) + .also { + it.rootGroupBuilder() + .options(buildOptions(managedConfig.sortedOptions)) + } + .build() + } + + fun buildOptions(options: List<ManagedOption<*>>): Collection<Option<*>> = + options.map { buildOption(it) } + + private fun <T : Any> buildOption(managedOption: ManagedOption<T>): Option<*> { + val handler = managedOption.handler + val binding = Binding.generic(managedOption.default(), managedOption::value, managedOption::value.setter) + fun <T> createDefaultBinding(function: (Option<T>) -> ControllerBuilder<T>): Option.Builder<T> { + return Option.createBuilder<T>() + .name(managedOption.labelText) + .binding(binding as Binding<T>) + .controller { function(it) } + } + when (handler) { + is ClickHandler -> return ButtonOption.createBuilder() + .name(managedOption.labelText) + .action { t, u -> + handler.runnable() + } + .build() + + is HudMetaHandler -> return ButtonOption.createBuilder() + .name(managedOption.labelText) + .action { t, u -> + handler.openEditor(managedOption as ManagedOption<HudMeta>, t) + } + .build() + + is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).build() + is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).build() + is IntegerHandler -> return createDefaultBinding { + IntegerSliderControllerBuilder.create(it).range(handler.min, handler.max).step(1) + }.build() + + is DurationHandler -> return Option.createBuilder<Double>() + .name(managedOption.labelText) + .binding((binding as Binding<Duration>).xmap({ it.toDouble(DurationUnit.SECONDS) }, { it.seconds })) + .controller { + DoubleSliderControllerBuilder.create(it) + .formatValue { Text.literal(FirmFormatters.formatTimespan(it.seconds)) } + .step(0.1) + .range(handler.min.toDouble(DurationUnit.SECONDS), handler.max.toDouble(DurationUnit.SECONDS)) + } + .build() + + is KeyBindingHandler -> return createDefaultBinding { + KeybindingBuilder(it, managedOption as ManagedOption<SavedKeyBinding>) + }.build() + + else -> return LabelOption.create(Text.literal("This option is currently unhandled for this config menu. Please report this as a bug.")) + } + } + + + fun buildConfig(): YetAnotherConfigLib { + return YetAnotherConfigLib.createBuilder() + .title(Text.literal("Firmament")) + .categories(buildCategories()) + .build() + } + + override val key: String + get() = "yacl" + + override fun open(parent: Screen?): Screen { + return buildConfig().generateScreen(parent) + } + +} |