summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2025-03-21 23:19:14 -0300
committerSoniEx2 <endermoneymod@gmail.com>2025-03-21 23:19:14 -0300
commit8f4da9a630ee4cb549c75a85b7e6ac842ef874f1 (patch)
tree0f93e56e26eacbe97f6dd0be6f89f2f3947e3763 /src
parent32f4966e8d3e824619fabbd225ee8e74b62be7c7 (diff)
Improve GUI accessibility
Diffstat (limited to 'src')
-rw-r--r--src/client/kotlin/space/autistic/radio/client/gui/FmReceiverScreen.kt157
1 files changed, 149 insertions, 8 deletions
diff --git a/src/client/kotlin/space/autistic/radio/client/gui/FmReceiverScreen.kt b/src/client/kotlin/space/autistic/radio/client/gui/FmReceiverScreen.kt
index e4ea8ea..8886498 100644
--- a/src/client/kotlin/space/autistic/radio/client/gui/FmReceiverScreen.kt
+++ b/src/client/kotlin/space/autistic/radio/client/gui/FmReceiverScreen.kt
@@ -15,12 +15,15 @@ import net.minecraft.client.gui.screen.Screen
 import net.minecraft.client.gui.widget.ButtonWidget
 import net.minecraft.client.gui.widget.ClickableWidget
 import net.minecraft.client.gui.widget.CyclingButtonWidget
+import net.minecraft.client.gui.widget.SliderWidget
 import net.minecraft.client.render.GameRenderer
 import net.minecraft.client.util.InputUtil
+import net.minecraft.screen.ScreenTexts
 import net.minecraft.text.StringVisitable
 import net.minecraft.text.Text
 import net.minecraft.util.Colors
 import net.minecraft.util.Identifier
+import net.minecraft.util.math.MathHelper
 import org.lwjgl.glfw.GLFW
 import org.slf4j.LoggerFactory
 import org.slf4j.event.Level
@@ -33,7 +36,6 @@ import java.lang.invoke.MethodHandles
 import java.util.*
 import javax.sound.sampled.AudioSystem
 import javax.sound.sampled.Mixer
-import kotlin.collections.ArrayList
 import kotlin.math.max
 import kotlin.reflect.jvm.javaMethod
 
@@ -94,12 +96,106 @@ class FmReceiverScreen : Screen(Text.translatable("pirate-radio.fm-receiver")) {
     }.dimensions(20, 20, 20, 20)
         .narrationSupplier { ButtonWidget.getNarrationMessage(Text.translatable("pirate-radio.volume.minus.narrated")) }
         .build()
+    private var frequencySlider = makeFrequencySlider(0, 0, 320, 20)
+    private fun makeFrequencySlider(x: Int, y: Int, width: Int, height: Int) = object : SliderWidget(
+        x, y, width, height, ScreenTexts.EMPTY, (PirateRadioClient.frequency - 768).toDouble() / (1080.0 - 768.0)
+    ) {
+        init {
+            updateMessage()
+        }
+
+        override fun updateMessage() {
+            message = Text.translatable(
+                "pirate-radio.frequency.selected", PirateRadioClient.frequency / 10, PirateRadioClient.frequency % 10
+            )
+        }
+
+        override fun applyValue() {
+            PirateRadioClient.frequency = MathHelper.clampedLerp(768.0, 1080.0, value).toInt()
+        }
+
+        override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
+            val oldValue = this.value
+            val oldFrequency = PirateRadioClient.frequency
+            val changed = super.keyPressed(keyCode, scanCode, modifiers)
+            val bl = keyCode == GLFW.GLFW_KEY_LEFT
+            if (bl || keyCode == GLFW.GLFW_KEY_RIGHT) {
+                if (changed) {
+                    val delta = if (bl) -1 else 1
+                    val newValue = (oldFrequency + delta - 768).toDouble() / (1080.0 - 768.0)
+                    this.value = MathHelper.clamp(newValue, 0.0, 1.0)
+                    if (oldValue != this.value) {
+                        this.applyValue()
+                    }
+
+                    this.updateMessage()
+                }
+            }
+            return changed
+        }
+    }
+
+    private var volumeSlider = makeVolumeSlider(0, 20, 320, 20)
+    private fun makeVolumeSlider(x: Int, y: Int, width: Int, height: Int) = object : SliderWidget(
+        x, y, width, height, ScreenTexts.EMPTY, PirateRadioClient.volume.toDouble() / 10.0
+    ) {
+        init {
+            updateMessage()
+        }
+
+        override fun updateMessage() {
+            message = if (PirateRadioClient.volume == 0) {
+                Text.translatable("pirate-radio.volume.selected", Text.translatable("pirate-radio.volume.off"))
+            } else {
+                Text.translatable("pirate-radio.volume.selected", PirateRadioClient.volume)
+            }
+        }
+
+        override fun applyValue() {
+            PirateRadioClient.volume = MathHelper.clampedLerp(0.0, 10.0, value).toInt()
+        }
+
+
+        override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
+            val oldValue = this.value
+            val oldVolume = PirateRadioClient.volume
+            val changed = super.keyPressed(keyCode, scanCode, modifiers)
+            val bl = keyCode == GLFW.GLFW_KEY_LEFT
+            if (bl || keyCode == GLFW.GLFW_KEY_RIGHT) {
+                if (changed) {
+                    val delta = if (bl) -1 else 1
+                    val newValue = (oldVolume + delta).toDouble() / 10.0
+                    this.value = MathHelper.clamp(newValue, 0.0, 1.0)
+                    if (oldValue != this.value) {
+                        this.applyValue()
+                    }
+
+                    this.updateMessage()
+                }
+            }
+            return changed
+        }
+    }
+
     private val toggleModes = ButtonWidget.builder(Text.translatable("pirate-radio.mode")) {
         PirateRadioClient.mode = when (PirateRadioClient.mode) {
             FmSimulatorMode.FULL -> FmSimulatorMode.FAST
             else -> FmSimulatorMode.FULL
         }
     }.position(0, 40).build()
+    private val cycleModes = CyclingButtonWidget.builder { info: FmSimulatorMode ->
+        when (info) {
+            FmSimulatorMode.FAST -> Text.translatable("pirate-radio.mode.fast")
+            FmSimulatorMode.FULL -> Text.translatable("pirate-radio.mode.full")
+            FmSimulatorMode.DEAF -> Text.translatable("pirate-radio.mode.deaf")
+        }
+    }.values(
+        listOf(
+            FmSimulatorMode.FULL, FmSimulatorMode.FAST
+        )
+    ).initially(PirateRadioClient.mode).build(0, 40, 320, 20, Text.translatable("pirate-radio.mode")) { _, it ->
+        PirateRadioClient.mode = it
+    }
     private val audioDevice = CyclingButtonWidget.builder { info: Mixer.Info ->
         when (info) {
             PirateRadioClient.minecraftAudioDevice -> Text.translatable("pirate-radio.device.system-matching-minecraft")
@@ -119,7 +215,7 @@ class FmReceiverScreen : Screen(Text.translatable("pirate-radio.fm-receiver")) {
             PirateRadioClient.audioDevice = it
         }
 
-    private val buttons = arrayOf(
+    private val buttons = arrayListOf<ClickableWidget>(
         frequencyPlusWidget, frequencyMinusWidget, volumePlusWidget, volumeMinusWidget, toggleModes, audioDevice
     )
 
@@ -134,13 +230,8 @@ class FmReceiverScreen : Screen(Text.translatable("pirate-radio.fm-receiver")) {
         }
         if (failure == null) {
             try {
+                setBaseLayout(0)
                 instance!!.export("init").apply()
-                addDrawableChild(frequencyPlusWidget)
-                addDrawableChild(frequencyMinusWidget)
-                addDrawableChild(volumePlusWidget)
-                addDrawableChild(volumeMinusWidget)
-                addDrawableChild(toggleModes)
-                addDrawableChild(audioDevice)
             } catch (e: ChicoryException) {
                 failure = WasmScreenException("Skin failed to initialize", e)
                 logger.error("Failed to initialize.", failure)
@@ -342,6 +433,51 @@ class FmReceiverScreen : Screen(Text.translatable("pirate-radio.fm-receiver")) {
 
     private fun getHeight(): Int = height
 
+    private fun setBaseLayout(layout: Int) {
+        when (layout) {
+            0 -> {
+                clearChildren()
+                addDrawableChild(frequencyPlusWidget)
+                addDrawableChild(frequencyMinusWidget)
+                addDrawableChild(volumePlusWidget)
+                addDrawableChild(volumeMinusWidget)
+                addDrawableChild(toggleModes)
+                addDrawableChild(audioDevice)
+                buttons.clear()
+                buttons.addAll(
+                    listOf(
+                        frequencyPlusWidget,
+                        frequencyMinusWidget,
+                        volumePlusWidget,
+                        volumeMinusWidget,
+                        toggleModes,
+                        audioDevice
+                    )
+                )
+            }
+
+            1 -> {
+                clearChildren()
+                frequencySlider = makeFrequencySlider(
+                    frequencySlider.x,
+                    frequencySlider.y,
+                    frequencySlider.width,
+                    frequencySlider.height
+                )
+                volumeSlider = makeVolumeSlider(volumeSlider.x, volumeSlider.y, volumeSlider.width, volumeSlider.height)
+                addDrawableChild(frequencySlider)
+                addDrawableChild(volumeSlider)
+                addDrawableChild(cycleModes)
+                addDrawableChild(audioDevice)
+                cycleModes.value = PirateRadioClient.mode
+                buttons.clear()
+                buttons.addAll(listOf(frequencySlider, volumeSlider, cycleModes, audioDevice))
+            }
+
+            else -> throw WasmScreenException("Invalid base layout: $layout", null)
+        }
+    }
+
     // useful for drawing the stereo pilot, not that it's implemented
     private fun drawImage(
         red: Float, green: Float, blue: Float, alpha: Float, x: Int, y: Int, u: Float, v: Float, w: Int, h: Int
@@ -478,6 +614,11 @@ class FmReceiverScreen : Screen(Text.translatable("pirate-radio.fm-receiver")) {
         )
         importValues.addFunction(
             bindFunc(
+                "buttons", "set-base-layout", lookup, this::setBaseLayout.javaMethod!!, this
+            )
+        )
+        importValues.addFunction(
+            bindFunc(
                 "simulator", "get-frequency", lookup, this::getFrequency.javaMethod!!, this
             )
         )