Added SetThemeEvent.

This commit is contained in:
2026-03-12 03:06:58 +08:00
parent f421f40cf0
commit 3d684e8157
6 changed files with 571 additions and 6 deletions
@@ -0,0 +1,100 @@
package cn.rdlevel.rdkt.core.data
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
public enum class Easing {
@SerialName("Linear")
LINEAR,
@SerialName("InSine")
IN_SINE,
@SerialName("OutSine")
OUT_SINE,
@SerialName("InOutSine")
IN_OUT_SINE,
@SerialName("InQuad")
IN_QUAD,
@SerialName("OutQuad")
OUT_QUAD,
@SerialName("InOutQuad")
IN_OUT_QUAD,
@SerialName("InCubic")
IN_CUBIC,
@SerialName("OutCubic")
OUT_CUBIC,
@SerialName("InOutCubic")
IN_OUT_CUBIC,
@SerialName("InQuart")
IN_QUART,
@SerialName("OutQuart")
OUT_QUART,
@SerialName("InOutQuart")
IN_OUT_QUART,
@SerialName("InQuint")
IN_QUINT,
@SerialName("OutQuint")
OUT_QUINT,
@SerialName("InOutQuint")
IN_OUT_QUINT,
@SerialName("InExpo")
IN_EXPO,
@SerialName("OutExpo")
OUT_EXPO,
@SerialName("InOutExpo")
IN_OUT_EXPO,
@SerialName("InCirc")
IN_CIRC,
@SerialName("OutCirc")
OUT_CIRC,
@SerialName("InOutCirc")
IN_OUT_CIRC,
@SerialName("InElastic")
IN_ELASTIC,
@SerialName("OutElastic")
OUT_ELASTIC,
@SerialName("InOutElastic")
IN_OUT_ELASTIC,
@SerialName("InBack")
IN_BACK,
@SerialName("OutBack")
OUT_BACK,
@SerialName("InOutBack")
IN_OUT_BACK,
@SerialName("InBounce")
IN_BOUNCE,
@SerialName("OutBounce")
OUT_BOUNCE,
@SerialName("InOutBounce")
IN_OUT_BOUNCE,
}
@@ -123,6 +123,10 @@ private sealed class AbstractSelectedRoomsAndTopLayer : SelectedRoomsAndTopLayer
override fun hashCode(): Int {
return rooms.hashCode()
}
override fun toString(): String {
return rooms.toString()
}
}
/**
@@ -0,0 +1,397 @@
@file:OptIn(RDKTInternalAPI::class)
package cn.rdlevel.rdkt.core.data.action
import cn.rdlevel.rdkt.core.annotations.RDKTInternalAPI
import cn.rdlevel.rdkt.core.data.Easing
import cn.rdlevel.rdkt.core.serialization.EnumIndexSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonClassDiscriminator
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@OptIn(ExperimentalSerializationApi::class)
@Serializable
@JsonClassDiscriminator("preset")
@JsonIgnoreUnknownKeys
public sealed interface Theme {
/**
* Whether to skip row painting effects when applying the theme.
*/
public var skipPaintEffects: Boolean
@Serializable
@SerialName("None")
public class None : AbstractTheme()
@Serializable
@SerialName("OrientalTechno")
public class OrientalTechno : AbstractTheme(), VariedTheme<OrientalTechno.Variant> {
override var variant: Variant = Variant.OPEN
@Serializable(Variant.Serializer::class)
public enum class Variant {
OPEN, CLOSED;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("BoyWard")
public class BoyWard : AbstractTheme()
@Serializable
@SerialName("GirlWard")
public class GirlWard : AbstractTheme()
@Serializable
@SerialName("Skyline")
public class Skyline : AbstractTheme(), VariedTheme<Skyline.Variant> {
override var variant: Variant = Variant.PINK
@Serializable(Variant.Serializer::class)
public enum class Variant {
PINK, BLUE;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("InsomniacDay")
public class InsomniacDay : AbstractTheme(), VariedTheme<InsomniacDay.Variant> {
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("ColeWardNight")
public class ColeWardNight : AbstractTheme(), VariedTheme<ColeWardNight.Variant> {
override var variant: Variant = Variant.NIGHT
@Serializable(Variant.Serializer::class)
public enum class Variant {
NIGHT, SUNRISE;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("Kaleidoscope")
public class Kaleidoscope : AbstractTheme()
@Serializable
@SerialName("CoffeeShop")
public class CoffeeShop : AbstractTheme(), VariedTheme<CoffeeShop.Variant> {
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("PoliticiansRally")
public class PoliticiansRally : AbstractTheme()
@Serializable
@SerialName("TrainDay")
public class TrainDay : AbstractPositionedTheme(), VariedTheme<TrainDay.Variant> {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -528.0..176.0
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("DesertDay")
public class DesertDay : AbstractPositionedTheme(), VariedTheme<DesertDay.Variant> {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -528.0..176.0
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("Stadium")
public class Stadium : AbstractTheme(), VariedTheme<Stadium.Variant> {
override var variant: Variant = Variant.SUNNY
@Serializable(Variant.Serializer::class)
public enum class Variant {
SUNNY, STORMY;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("HospitalWard")
public class HospitalWard : AbstractPositionedTheme(), VariedTheme<HospitalWard.Variant> {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -490.0..1172.0
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("PaigeOffice")
public class PaigeOffice : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -358.0..42.0
}
@Serializable
@SerialName("Basement")
public class Basement : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -32.0..320.0
}
@Serializable
@SerialName("Garden")
public class Garden : AbstractTheme(), VariedTheme<Garden.Variant> {
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("Rooftop")
public class Rooftop : AbstractTheme(), VariedTheme<Rooftop.Variant> {
override var variant: Variant = Variant.STANDARD
@Serializable(Variant.Serializer::class)
public enum class Variant {
STANDARD, SUMMER, AUTUMN;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("AthleteWard")
public class AthleteWard : AbstractPositionedTheme(), VariedTheme<AthleteWard.Variant> {
override val positionXRange: ClosedFloatingPointRange<Double> get() = 0.0..732.0
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("RecordsRoom")
public class RecordsRoom : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -475.0..0.0
}
@Serializable
@SerialName("AbandonedWard")
public class AbandonedWard : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -42.0..706.0
}
@Serializable
@SerialName("Intimate")
public class Intimate : AbstractTheme(), VariedTheme<Intimate.Variant> {
override var variant: Variant = Variant.STANDARD
@Serializable(Variant.Serializer::class)
public enum class Variant {
STANDARD, SIMPLE;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("Sky")
public class Sky : AbstractTheme(), VariedTheme<Sky.Variant> {
override var variant: Variant = Variant.DAY
@Serializable(Variant.Serializer::class)
public enum class Variant {
DAY, NIGHT;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("Space")
public class Space : AbstractTheme()
@Serializable
@SerialName("NeonMuseum")
public class NeonMuseum : AbstractTheme()
@Serializable
@SerialName("BackAlley")
public class BackAlley : AbstractTheme()
@Serializable
@SerialName("Airport")
public class Airport : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = 0.0..248.0
}
@Serializable
@SerialName("RollerDisco")
public class RollerDisco : AbstractPositionedTheme() {
override val positionXRange: ClosedFloatingPointRange<Double> get() = -1000.0..1000.0
}
@Serializable
@SerialName("Matrix")
public class Matrix : AbstractTheme()
@Serializable
@SerialName("CrossesStraight")
public class CrossesStraight : AbstractTheme(), VariedTheme<CrossesStraight.Variant> {
override var variant: Variant = Variant.STRAIGHT
@Serializable(Variant.Serializer::class)
public enum class Variant {
STRAIGHT, FALLING;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("CubesFalling")
public class CubesFalling : AbstractTheme(), VariedTheme<CubesFalling.Variant> {
override var variant: Variant = Variant.STANDARD
@Serializable(Variant.Serializer::class)
public enum class Variant {
STANDARD, NICE_BLUE;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("HallOfMirrors")
public class HallOfMirrors : AbstractTheme()
@Serializable
@SerialName("FloatingHeart")
public class FloatingHeart : AbstractTheme(), VariedTheme<FloatingHeart.Variant> {
override var variant: Variant = Variant.STANDARD
@Serializable(Variant.Serializer::class)
public enum class Variant {
STANDARD, WITH_CUBES;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("FloatingHeartBroken")
public class FloatingHeartBroken : AbstractTheme(), VariedTheme<FloatingHeartBroken.Variant> {
override var variant: Variant = Variant.STANDARD
@Serializable(Variant.Serializer::class)
public enum class Variant {
STANDARD, WITH_CUBES;
public object Serializer : KSerializer<Variant> by EnumIndexSerializer()
}
}
@Serializable
@SerialName("ZenGarden")
public class ZenGarden : AbstractTheme()
@Serializable
@SerialName("Vaporwave")
public class Vaporwave : AbstractTheme()
@Serializable
@SerialName("ProceduralTree")
public class ProceduralTree : AbstractTheme()
}
public sealed interface VariedTheme<E : Enum<E>> : Theme {
public var variant: E
}
@Serializable
public data class ThemePosition(
var x: Int = 0,
var duration: Double = 0.0,
var ease: Easing = Easing.LINEAR,
)
public sealed interface PositionedTheme : Theme {
public var enablePosition: Boolean
public val positionXRange: ClosedFloatingPointRange<Double>
public var positionX: Double
public var positionDuration: Double
public var positionEase: Easing
}
@RDKTInternalAPI
public sealed class AbstractTheme : Theme {
override var skipPaintEffects: Boolean = false
}
@RDKTInternalAPI
public sealed class AbstractPositionedTheme : AbstractTheme(), PositionedTheme {
override var enablePosition: Boolean = false
override var positionX: Double = 0.0
set(value) {
require(value in positionXRange) { "positionX must be within the range of ${positionXRange.start} to ${positionXRange.endInclusive}." }
field = value
}
override var positionDuration: Double = 0.0
override var positionEase: Easing = Easing.LINEAR
}
@@ -0,0 +1,24 @@
@file:OptIn(RDKTInternalAPI::class)
package cn.rdlevel.rdkt.core.events
import cn.rdlevel.rdkt.core.annotations.RDKTInternalAPI
import cn.rdlevel.rdkt.core.data.ROOM1
import cn.rdlevel.rdkt.core.data.SelectedRooms
import cn.rdlevel.rdkt.core.data.action.Theme
import cn.rdlevel.rdkt.core.data.roomsOf
import cn.rdlevel.rdkt.core.serialization.Flatten
import cn.rdlevel.rdkt.core.serialization.flatten
import kotlinx.serialization.*
@OptIn(ExperimentalSerializationApi::class)
@Serializable(SetThemeEvent.Serializer::class)
@KeepGeneratedSerializer
@SerialName("SetTheme")
public data class SetThemeEvent(
@Flatten
var theme: Theme,
override var rooms: SelectedRooms = roomsOf(ROOM1),
) : ActionEvent(), MutableRoomsSpecificEvent {
public object Serializer : KSerializer<SetThemeEvent> by generatedSerializer().flatten()
}
@@ -4,13 +4,12 @@ import cn.rdlevel.rdkt.core.annotations.RDKTInternalAPI
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialInfo
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonTransformingSerializer
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.*
/**
* Annotation to indicate that a field should be flattened when serialized.
*
* @see FieldFlatteningSerializer
*/
@OptIn(ExperimentalSerializationApi::class)
@SerialInfo
@@ -34,12 +33,15 @@ public annotation class Flatten
*
* @param tSerializer The serializer, usually the [generated one][kotlinx.serialization.KeepGeneratedSerializer], for the type T that this serializer will delegate to.
*/
@OptIn(ExperimentalSerializationApi::class)
@RDKTInternalAPI
public class FieldFlatteningSerializer<T>(
tSerializer: KSerializer<T>
private val tSerializer: KSerializer<T>
) : JsonTransformingSerializer<T>(tSerializer) {
private val flattenFieldNames: MutableList<String> = mutableListOf()
private val notFlattenFieldNames: MutableList<String> = mutableListOf()
private val classDiscriminator: String =
descriptor.annotations.filterIsInstance<JsonClassDiscriminator>().firstOrNull()?.discriminator ?: "type"
init {
(0..<descriptor.elementsCount).forEach {
@@ -72,7 +74,7 @@ public class FieldFlatteningSerializer<T>(
element.jsonObject.forEach { (k, v) ->
if (k in notFlattenFieldNames) {
this@base.put(k, v)
} else {
} else if (k != classDiscriminator) {
put(k, v)
}
}
@@ -0,0 +1,38 @@
package cn.rdlevel.rdkt.core.test
import cn.rdlevel.rdkt.core.data.Easing
import cn.rdlevel.rdkt.core.data.ROOM1
import cn.rdlevel.rdkt.core.data.ROOM3
import cn.rdlevel.rdkt.core.data.action.Theme
import cn.rdlevel.rdkt.core.data.roomsOf
import cn.rdlevel.rdkt.core.events.Event
import cn.rdlevel.rdkt.core.events.SetThemeEvent
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlin.test.Test
class SetThemeEventTest {
@OptIn(ExperimentalSerializationApi::class)
@Test
fun test() {
val json = Json {
isLenient = true
allowTrailingComma = true
encodeDefaults = true
}
val event: Event = SetThemeEvent(Theme.TrainDay().apply {
skipPaintEffects = true
variant = Theme.TrainDay.Variant.NIGHT
enablePosition = true
positionX = 100.0
positionDuration = 2.5
positionEase = Easing.OUT_EXPO
}).apply {
rooms = roomsOf(ROOM1, ROOM3)
}
val text = json.encodeToString(event)
println(text)
val event2: Event = json.decodeFromString(text)
println(event2)
}
}