commit #22
This commit is contained in:
parent
745a83d757
commit
379fc8eebb
7 changed files with 160 additions and 1 deletions
|
@ -15,6 +15,7 @@ allprojects {
|
|||
kotlinOptions.jvmTarget = "19"
|
||||
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
|
||||
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.ExperimentalUnsignedTypes"
|
||||
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.time.ExperimentalTime"
|
||||
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.contracts.ExperimentalContracts"
|
||||
kotlinOptions.freeCompilerArgs += "-Xcontext-receivers"
|
||||
}
|
||||
|
|
|
@ -28,4 +28,6 @@ object Washs {
|
|||
val bar = StairvilleTlb(DmxAddress(121u))
|
||||
val sideLight = StairvilleClb4(DmxAddress(126u))
|
||||
|
||||
val devices = persistentSetOf(*FrontLights.all.toTypedArray(), spotLeft, spotRight, *Tops.both.toTypedArray(), *Washs.both.toTypedArray(), bar)
|
||||
val fogMachine = FogMachine(DmxAddress(200u)) // TODO: Adresse korrigieren
|
||||
|
||||
val devices = persistentSetOf(*FrontLights.all.toTypedArray(), spotLeft, spotRight, *Tops.both.toTypedArray(), *Washs.both.toTypedArray(), bar, fogMachine)
|
|
@ -0,0 +1,23 @@
|
|||
package de.moritzruth.lampenfieber.device
|
||||
|
||||
import de.moritzruth.theaterdsl.device.Device
|
||||
import de.moritzruth.theaterdsl.device.PercentageDV
|
||||
import de.moritzruth.theaterdsl.dmx.DmxAddress
|
||||
import de.moritzruth.theaterdsl.dmx.DmxDataWriter
|
||||
import de.moritzruth.theaterdsl.dmx.DmxValue
|
||||
import de.moritzruth.theaterdsl.value.percent
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
|
||||
class FogMachine(override val firstChannel: DmxAddress) : Device {
|
||||
override val numberOfChannels = 4u
|
||||
|
||||
override fun writeDmxData(writer: DmxDataWriter) {
|
||||
writer.writePercentage(10.percent)
|
||||
writer.writePercentage(power.getCurrentValue())
|
||||
writer.writeRaw(DmxValue(0u)) // ignored
|
||||
writer.writeRaw(DmxValue(0u)) // ignored
|
||||
}
|
||||
|
||||
val power = PercentageDV()
|
||||
override val dvs = persistentSetOf(power)
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
package de.moritzruth.theaterdsl.show
|
||||
|
||||
import de.moritzruth.lampenfieber.device.fogMachine
|
||||
import de.moritzruth.theaterdsl.device.Device
|
||||
import de.moritzruth.theaterdsl.device.DynamicValue
|
||||
import de.moritzruth.theaterdsl.dmx.EnttecOpenDmxUsb
|
||||
import de.moritzruth.theaterdsl.dmx.PerDeviceDmxDataWriter
|
||||
import de.moritzruth.theaterdsl.util.InstantAsEpochMillisecondsSerializer
|
||||
import de.moritzruth.theaterdsl.util.mapState
|
||||
import de.moritzruth.theaterdsl.value.Percentage
|
||||
import de.moritzruth.theaterdsl.value.percent
|
||||
import io.github.oshai.KLogger
|
||||
import io.github.oshai.KotlinLogging
|
||||
import io.ktor.http.*
|
||||
|
@ -32,13 +35,21 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||
import kotlin.math.roundToLong
|
||||
import kotlin.system.measureTimeMillis
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.TimeSource
|
||||
import kotlin.time.toJavaDuration
|
||||
|
||||
data class FogState(val power: Percentage, val time: TimeSource.Monotonic.ValueTimeMark = TimeSource.Monotonic.markNow()) {
|
||||
companion object {
|
||||
fun off() = FogState(0.percent)
|
||||
}
|
||||
}
|
||||
|
||||
class ShowContext(
|
||||
val devices: ImmutableSet<Device>,
|
||||
val show: Show,
|
||||
val logger: KLogger,
|
||||
val stateFlow: MutableStateFlow<ShowState>,
|
||||
val fogState: MutableStateFlow<FogState>,
|
||||
val outputDataFreeze: AtomicInteger
|
||||
) {
|
||||
val stepFlow = stateFlow.mapState {
|
||||
|
@ -92,11 +103,13 @@ suspend fun runShow(show: Show, devices: ImmutableSet<Device>) = coroutineScope
|
|||
show,
|
||||
logger,
|
||||
stateFlow,
|
||||
MutableStateFlow(FogState.off()),
|
||||
AtomicInteger(0)
|
||||
)
|
||||
|
||||
startDataWriting(context)
|
||||
startStepRunning(context)
|
||||
startFogHandling(context)
|
||||
startWebsocketServer(context)
|
||||
|
||||
launch {
|
||||
|
@ -124,6 +137,15 @@ fun CoroutineScope.startDataWriting(context: ShowContext) = launch {
|
|||
}
|
||||
}
|
||||
|
||||
fun CoroutineScope.startFogHandling(context: ShowContext) = launch {
|
||||
context.fogState.collectLatest { state ->
|
||||
fogMachine.power.static(state.power)
|
||||
|
||||
delay(1000)
|
||||
fogMachine.power.off()
|
||||
}
|
||||
}
|
||||
|
||||
fun CoroutineScope.startStepRunning(context: ShowContext) = launch {
|
||||
var lastPosition = ShowPosition.START
|
||||
var lastStepJob: Job? = null
|
||||
|
@ -197,6 +219,12 @@ private fun CoroutineScope.startWebsocketServer(context: ShowContext) = launch(D
|
|||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
post("/fog") {
|
||||
val power = call.receive<Percentage>()
|
||||
context.fogState.value = FogState(power)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
get("/show") {
|
||||
call.respond(context.show.acts.toMutableList())
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package de.moritzruth.theaterdsl.value
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@JvmInline
|
||||
value class Percentage(val value: Double) : Comparable<Percentage> {
|
||||
companion object {
|
||||
|
|
21
ui/src/components/Button.vue
Normal file
21
ui/src/components/Button.vue
Normal file
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<button
|
||||
class="px-5 py-2 active:bg-green-800 transition duration-200 font-bold text-5"
|
||||
:class="isActive ? 'bg-green-800' : 'bg-green-600'"
|
||||
@click="e => emit('click', e)"
|
||||
>
|
||||
<slot/>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
isActive?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(["click"])
|
||||
</script>
|
81
ui/src/components/FogControl.vue
Normal file
81
ui/src/components/FogControl.vue
Normal file
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div class="flex items-center gap-3">
|
||||
<span>Nebel: </span>
|
||||
<Button
|
||||
v-for="p in buttonPowers"
|
||||
@mousedown="onButtonActive(p[0])"
|
||||
@mouseup="onButtonInactive(p[0])"
|
||||
:is-active="isActive && p[0] === power"
|
||||
>
|
||||
{{ p[0] * 100 }}%
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from "./Button.vue"
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { onKeyDown, onKeyUp, useEventListener, useIntervalFn } from "@vueuse/core"
|
||||
|
||||
const activation = ref<"button" | "key" | null>(null)
|
||||
const isActive = computed(() => activation.value !== null)
|
||||
const power = ref(0)
|
||||
|
||||
function onButtonActive(p: number) {
|
||||
activation.value = "button"
|
||||
power.value = p
|
||||
}
|
||||
|
||||
function onButtonInactive(p: number) {
|
||||
if (activation.value === "button" && power.value === p) {
|
||||
activation.value = null
|
||||
power.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
useEventListener(document.body, "mouseup", () => {
|
||||
if (activation.value === "button") activation.value = null
|
||||
})
|
||||
|
||||
const buttonPowers: Array<[number, string]> = [[0.1, "7"], [0.25, "8"], [0.5, "9"], [1, "0"]]
|
||||
|
||||
for (const p of buttonPowers) {
|
||||
onKeyDown(p[1], () => {
|
||||
activation.value = "key"
|
||||
power.value = p[0]
|
||||
})
|
||||
|
||||
onKeyUp(p[1], () => {
|
||||
if (activation.value === "key" && power.value === p[0]) {
|
||||
activation.value = null
|
||||
power.value = 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function send() {
|
||||
fetch("/api/fog", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(power.value),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const sendTimer = useIntervalFn(send, 200, { immediate: false })
|
||||
|
||||
watch(power, () => {
|
||||
if (activation.value === null) {
|
||||
sendTimer.pause()
|
||||
send()
|
||||
} else {
|
||||
send()
|
||||
sendTimer.resume()
|
||||
}
|
||||
})
|
||||
</script>
|
Loading…
Add table
Reference in a new issue