From f6d02dfcd960513b2259f9e6383d4ea5e2556d10 Mon Sep 17 00:00:00 2001 From: NoMathExpectation <85624722+NoMathExpectation@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:07:31 +0800 Subject: [PATCH] Added AddFreeTimeBeatEvent and PulseFreeTimeBeatEvent. --- .../rdkt/core/events/AddFreeTimeBeatEvent.kt | 40 +++++++++ .../core/events/PulseFreeTimeBeatEvent.kt | 90 +++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddFreeTimeBeatEvent.kt create mode 100644 core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/PulseFreeTimeBeatEvent.kt diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddFreeTimeBeatEvent.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddFreeTimeBeatEvent.kt new file mode 100644 index 0000000..61b87ac --- /dev/null +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddFreeTimeBeatEvent.kt @@ -0,0 +1,40 @@ +package cn.rdlevel.rdkt.core.events + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Adds a freetime beat to the row. + */ +@Serializable +@SerialName("AddFreeTimeBeat") +public class AddFreeTimeBeatEvent() : RowEvent() { + /** + * The start pulse of the freetime beat. It must be between 0 and 6, where 0 is the first pulse. + */ + public var pulse: Int = 0 + set(value) { + require(value in 0..6) { "Pulse must be between 0 and 6, but found: $value." } + field = value + } + + /** + * The hold time this pulse will last in beats. 0 means disable the hold. + */ + public var hold: Double = 0.0 + + public constructor( + pulse: Int, + hold: Double, + ) : this() { + this.pulse = pulse + this.hold = hold + } + + public constructor( + pulse: Int, + ) : this() { + this.pulse = pulse + } +} \ No newline at end of file diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/PulseFreeTimeBeatEvent.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/PulseFreeTimeBeatEvent.kt new file mode 100644 index 0000000..b1bdd57 --- /dev/null +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/PulseFreeTimeBeatEvent.kt @@ -0,0 +1,90 @@ +@file:OptIn(RDKTInternalAPI::class) + +package cn.rdlevel.rdkt.core.events + + +import cn.rdlevel.rdkt.core.annotations.RDKTInternalAPI +import cn.rdlevel.rdkt.core.serialization.TransformSerializer +import kotlinx.serialization.Serializable +import kotlin.jvm.JvmOverloads + +/** + * Advance or modify existing freetime beat on the specified row. + * + * @property action The action to perform on the freetime beat. + * @property hold The hold time this pulse will last in beats. 0 means disable the hold. + */ +@Serializable(PulseFreeTimeBeatEvent.Serializer::class) +public data class PulseFreeTimeBeatEvent @JvmOverloads constructor( + var action: Action = Action.Increment, + var hold: Int = 0, +) : RowEvent() { + /** + * Represents the action to perform on the freetime beat. + */ + public sealed class Action(public val action: String) { + /** + * Advance the pulse of the freetime beat by 1. + */ + public object Increment : Action("Increment") + + /** + * Retreat the pulse of the freetime beat by 1. + */ + public object Decrement : Action("Decrement") + + /** + * Set the pulse of the freetime beat to a specific value. + * + * @property pulse The pulse to set the freetime beat to. It must be between 0 and 6, where 0 is the first pulse. + */ + public class Custom(pulse: Int) : Action("Custom") { + public var pulse: Int = pulse + set(value) { + require(value in 0..6) { "Pulse must be between 0 and 6, but found: $value." } + field = value + } + + init { + this.pulse = pulse + } + } + + /** + * Remove the freetime beat. + */ + public object Remove : Action("Remove") + } + + public object Serializer : TransformSerializer(Data.serializer()) { + override fun toData(value: PulseFreeTimeBeatEvent): Data { + return Data( + action = value.action.action, + hold = value.hold, + customPulse = (value.action as? Action.Custom)?.pulse, + ) + } + + override fun fromData(data: Data): PulseFreeTimeBeatEvent { + val action = when (data.action) { + "Increment" -> Action.Increment + "Decrement" -> Action.Decrement + "Custom" -> Action.Custom(data.customPulse ?: error("Custom action requires customPulse value.")) + "Remove" -> Action.Remove + else -> throw IllegalArgumentException("Unknown action: ${data.action}") + } + return PulseFreeTimeBeatEvent( + action = action, + hold = data.hold, + ) + } + + @RDKTInternalAPI + @Serializable + public data class Data( + var action: String = "Increment", + var hold: Int = 0, + var customPulse: Int? = null, + ) + } +} \ No newline at end of file