diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddClassicBeatEvent.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddClassicBeatEvent.kt new file mode 100644 index 0000000..749b7e5 --- /dev/null +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/AddClassicBeatEvent.kt @@ -0,0 +1,60 @@ +package cn.rdlevel.rdkt.core.events + + +import cn.rdlevel.rdkt.core.data.sound.AudioData +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlin.jvm.JvmStatic + +/** + * Plays a classy beat on the specified row. + * + * @property tick The duration to advance a pulse in beats. + * @property swing The duration between an odd pulse and its previous pulse in beats. Setting this to 0 will disable swing. The value should be between 0 and the doubled value of [tick]. + * @property hold The duration to hold the beat in beats. Setting this to 0 will disable hold. + * @property setXs The pattern of Xs to set on the row when [hold] is on. + * @property length The number of pulses to have. + * @property sound The sound to play. Setting this to null will use the row's current sound. + */ +@Serializable +public data class AddClassicBeatEvent( + var tick: Double = 1.0, + var swing: Double = 0.0, + var hold: Double = 0.0, + var setXs: SetXMode = SetXMode.NO_CHANGE, + var length: Int = 7, + var sound: AudioData? = null, +) : RowEvent() { + /** + * Represents the pattern of Xs to set on the row when [hold] is on. + */ + public enum class SetXMode { + /** + * Do not change the pattern on the row. + */ + @SerialName("NoChange") + NO_CHANGE, + + /** + * Sets pattern to -xx-xx. + */ + @SerialName("ThreeBeat") + THREE_BEAT, + + /** + * Sets pattern to -x-x-x. + */ + @SerialName("FourBeat") + FOUR_BEAT, + } + + public companion object { + /** + * Creates a new [AddClassicBeatEvent] using the provided block to set its properties. + */ + @JvmStatic + public fun of(block: AddClassicBeatEvent.() -> Unit): AddClassicBeatEvent { + return AddClassicBeatEvent().apply(block) + } + } +} \ No newline at end of file diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventProperties.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventProperties.kt index 2245929..f607e6d 100644 --- a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventProperties.kt +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventProperties.kt @@ -12,6 +12,13 @@ public interface BeatSpecificEvent : Event { * This property is mutable, allowing the beat to be set directly. */ override var beat: Double + + public companion object { + @JvmStatic + public fun requireBeatInBound(beat: Double) { + require(beat >= 1) { "Beat must be greater than or equal to 1." } + } + } } /** diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventTabs.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventTabs.kt index 8689e0b..cd2579c 100644 --- a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventTabs.kt +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/events/EventTabs.kt @@ -1,5 +1,6 @@ package cn.rdlevel.rdkt.core.events +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable /** @@ -17,7 +18,7 @@ public sealed class SoundEvent : AbstractEvent(), YSpecificEvent { public sealed class BeatSpecificSoundEvent : BeatSpecificEvent, SoundEvent() { override var beat: Double = 1.0 set(value) { - require(value >= 1) { "Beat must be greater than or equal to 1." } + BeatSpecificEvent.requireBeatInBound(value) field = value } } @@ -26,7 +27,26 @@ public sealed class BeatSpecificSoundEvent : BeatSpecificEvent, SoundEvent() { * An event that belongs to the rows tab. */ @Serializable -public sealed class RowEvent : AbstractEvent() +public sealed class RowEvent : AbstractEvent(), BeatSpecificEvent, RowSpecificEvent, YSpecificEvent { + override var beat: Double = 1.0 + set(value) { + BeatSpecificEvent.requireBeatInBound(value) + field = value + } + + @SerialName("row") + override var rowId: Int = 0 + set(value) { + RowSpecificEvent.requireRowInBound(value) + field = value + } + + /** + * This property does not affect the actual position in the editor for [RowEvent]. + */ + override var y: Int = 0 + +} /** * An event that belongs to the actions tab. diff --git a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/settings/LevelSettings.kt b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/settings/LevelSettings.kt index aef06d7..2239045 100644 --- a/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/settings/LevelSettings.kt +++ b/core/src/commonMain/kotlin/cn/rdlevel/rdkt/core/settings/LevelSettings.kt @@ -124,7 +124,7 @@ public class LevelSettings { } /** - * Whether the use grayscale for the syringe strip. + * Whether to use grayscale for the syringe strip. */ public var songLabelGrayscale: Boolean = false