rework controls

This commit is contained in:
りき萌 2023-05-02 13:58:21 +02:00
parent 7c7a671315
commit 91e2470947
7 changed files with 87 additions and 40 deletions

View file

@ -1,6 +1,9 @@
package net.liquidev.dawd3.audio.device
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtFloat
import net.minecraft.util.Identifier
import java.nio.ByteBuffer
import java.util.concurrent.atomic.AtomicInteger
class ControlName(parent: Identifier, name: String) {
@ -20,37 +23,58 @@ class ControlName(parent: Identifier, name: String) {
}
}
data class ControlDescriptor(
data class ControlDescriptor<T>(
val name: ControlName,
val initialValue: Float,
val initialValue: T,
) {
constructor(
parent: Identifier,
name: String,
initialValue: Float,
initialValue: T,
) : this(ControlName(parent, name), initialValue)
}
class Control(val descriptor: ControlDescriptor) {
sealed interface Control {
fun valueToNBT(): NbtElement
fun valueFromNBT(element: NbtElement)
fun valueToBytes(): ByteArray
fun valueFromBytes(buffer: ByteArray)
}
class FloatControl(val descriptor: ControlDescriptor<Float>) : Control {
private val internalValue = AtomicInteger(descriptor.initialValue.toBits())
var value: Float
get() = Float.fromBits(internalValue.get())
set(value) = internalValue.set(value.toBits())
override fun valueToNBT(): NbtElement = NbtFloat.of(value)
override fun valueFromNBT(element: NbtElement) {
value = (element as? NbtFloat)?.floatValue() ?: 0f
}
override fun valueToBytes(): ByteArray =
ByteBuffer.allocate(4).putFloat(value).array()
override fun valueFromBytes(buffer: ByteArray) {
value = ByteBuffer.wrap(buffer).getFloat()
}
}
interface ControlSet {
fun visitControls(visit: (ControlDescriptor, Control) -> Unit)
fun visitControls(visit: (ControlName, Control) -> Unit)
}
object NoControls : ControlSet {
override fun visitControls(visit: (ControlDescriptor, Control) -> Unit) {}
override fun visitControls(visit: (ControlName, Control) -> Unit) {}
}
class ControlMap(set: ControlSet) {
private val map = hashMapOf<ControlName, Control>()
init {
set.visitControls { controlDescriptor, control -> map[controlDescriptor.name] = control }
set.visitControls { controlName, control -> map[controlName] = control }
}
operator fun get(name: ControlName): Control? = map[name]

View file

@ -18,12 +18,12 @@ class AmplifierDevice : Device<AmplifierDevice.Controls> {
}
class Controls : ControlSet {
val amplitude = Control(amplitudeControl)
val amplitudeCV = Control(amplitudeCVControl)
val amplitude = FloatControl(amplitudeControl)
val amplitudeCV = FloatControl(amplitudeCVControl)
override fun visitControls(visit: (ControlDescriptor, Control) -> Unit) {
visit(amplitudeControl, amplitude)
visit(amplitudeCVControl, amplitudeCV)
override fun visitControls(visit: (ControlName, Control) -> Unit) {
visit(amplitudeControl.name, amplitude)
visit(amplitudeCVControl.name, amplitudeCV)
}
}

View file

@ -12,10 +12,10 @@ class ConstantDevice : Device<ConstantDevice.Controls> {
}
class Controls : ControlSet {
val value = Control(valueControl)
val value = FloatControl(valueControl)
override fun visitControls(visit: (ControlDescriptor, Control) -> Unit) {
visit(valueControl, value)
override fun visitControls(visit: (ControlName, Control) -> Unit) {
visit(valueControl.name, value)
}
}

View file

@ -16,12 +16,12 @@ class FmaDevice : Device<FmaDevice.Controls> {
}
class Controls : ControlSet {
val multiply = Control(multiplyControl)
val add = Control(addControl)
val multiply = FloatControl(multiplyControl)
val add = FloatControl(addControl)
override fun visitControls(visit: (ControlDescriptor, Control) -> Unit) {
visit(multiplyControl, multiply)
visit(addControl, add)
override fun visitControls(visit: (ControlName, Control) -> Unit) {
visit(multiplyControl.name, multiply)
visit(addControl.name, add)
}
}

View file

@ -8,7 +8,10 @@ import net.liquidev.dawd3.block.entity.D3BlockEntity
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.client.world.ClientWorld
import net.minecraft.nbt.*
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtHelper
import net.minecraft.nbt.NbtList
import net.minecraft.util.math.BlockPos
private typealias DeviceBlockFactory = FabricBlockEntityTypeBuilder.Factory<DeviceBlockEntity>
@ -63,11 +66,13 @@ class DeviceBlockEntity(
super.readNbt(nbt)
val controlsNbt = nbt.getCompound(Nbt.controls)
controls.visitControls { controlDescriptor, control ->
val controlName = controlDescriptor.name.toString()
if (controlName in controlsNbt) {
val value = controlsNbt.getFloat(controlName)
control.value = value
controls.visitControls { controlName, control ->
val controlNameString = controlName.toString()
if (controlNameString in controlsNbt) {
val element = controlsNbt.get(controlNameString)
if (element != null) {
control.valueFromNBT(element)
}
}
}
@ -119,8 +124,8 @@ class DeviceBlockEntity(
super.writeNbt(nbt)
val controlsNbt = NbtCompound()
controls.visitControls { controlDescriptor, control ->
controlsNbt.put(controlDescriptor.name.toString(), NbtFloat.of(control.value))
controls.visitControls { controlName, control ->
controlsNbt.put(controlName.toString(), control.valueToNBT())
}
nbt.put(Nbt.controls, controlsNbt)

View file

@ -11,7 +11,7 @@ import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
data class TweakControl(val position: BlockPos, val control: Identifier, val newValue: Float) {
data class TweakControl(val position: BlockPos, val control: Identifier, val data: ByteArray) {
companion object {
val id = Identifier(Mod.id, "tweak_control")
@ -28,8 +28,8 @@ data class TweakControl(val position: BlockPos, val control: Identifier, val new
?: return@execute
val controlName =
ControlName.fromString(packet.control.toString()) ?: return@execute
val control = blockEntity.controlMap[controlName]
control?.value = packet.newValue
val control = blockEntity.controlMap[controlName] ?: return@execute
control.valueFromBytes(packet.data)
val witnesses = PlayerLookup.tracking(blockEntity)
for (witness in witnesses) {
@ -42,7 +42,7 @@ data class TweakControl(val position: BlockPos, val control: Identifier, val new
TweakControl(
packet.position,
packet.control,
packet.newValue,
packet.data,
).serialize()
)
}
@ -63,7 +63,7 @@ data class TweakControl(val position: BlockPos, val control: Identifier, val new
val controlName =
ControlName.fromString(packet.control.toString()) ?: return@execute
val control = blockEntity.controlMap[controlName]
control?.value = packet.newValue
control?.valueFromBytes(packet.data)
}
}
}
@ -73,7 +73,7 @@ data class TweakControl(val position: BlockPos, val control: Identifier, val new
TweakControl(
position = buffer.readBlockPos(),
control = buffer.readIdentifier(),
newValue = buffer.readFloat(),
data = buffer.readByteArray(),
)
}
@ -81,7 +81,25 @@ data class TweakControl(val position: BlockPos, val control: Identifier, val new
val buffer = PacketByteBufs.create()
buffer.writeBlockPos(position)
buffer.writeIdentifier(control)
buffer.writeFloat(newValue)
buffer.writeByteArray(data)
return buffer
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as TweakControl
if (position != other.position) return false
if (control != other.control) return false
return data.contentEquals(other.data)
}
override fun hashCode(): Int {
var result = position.hashCode()
result = 31 * result + control.hashCode()
result = 31 * result + data.contentHashCode()
return result
}
}

View file

@ -1,7 +1,7 @@
package net.liquidev.dawd3.ui.widget
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
import net.liquidev.dawd3.audio.device.Control
import net.liquidev.dawd3.audio.device.FloatControl
import net.liquidev.dawd3.common.Degrees
import net.liquidev.dawd3.common.Radians
import net.liquidev.dawd3.common.clamp
@ -23,7 +23,7 @@ import kotlin.math.sin
class Knob(
x: Int,
y: Int,
val control: Control,
val control: FloatControl,
val min: Float,
val max: Float,
val color: Color,
@ -130,16 +130,16 @@ class Knob(
if (draggingInfo != null) {
val guiScale = client.options.guiScale.value.toFloat()
val deltaY = (draggingInfo.previousMouseY - event.absoluteMouseY) * guiScale
// Reflect the change locally immediately for lower latency.
control.value = alterValue(control.value, by = deltaY.toFloat())
ClientPlayNetworking.send(
TweakControl.id,
TweakControl(
context.blockPosition,
control.descriptor.name.id,
newValue = alterValue(control.value, by = deltaY.toFloat()),
control.valueToBytes()
).serialize()
)
// Reflect the change locally immediately for lower latency.
control.value = alterValue(control.value, by = deltaY.toFloat())
draggingInfo.previousMouseY = event.absoluteMouseY
}
}