This commit is contained in:
Moritz Ruth 2023-05-26 10:45:32 +02:00
parent 379fc8eebb
commit a9ff97627b
Signed by: moritzruth
GPG key ID: C9BBAB79405EE56D
8 changed files with 167 additions and 41 deletions

View file

@ -261,7 +261,7 @@ fun ShowBuilderContext.fourthAct() = act("Vierter Akt") {
+"Adrian / von links"
}
leftSpotTarget = "Kai & Adrian (rechtzeitig positionieren!)"
leftSpotTarget = "Kai & Adrian"
onRun {
Washs.left.colorWheelMode.static(CoemarProWash.ColorWheelMode.Rotate(5.percent, true))

View file

@ -62,7 +62,7 @@ fun ShowBuilderContext.secondAct() = act("Zweiter Akt") {
+"Astronaut / liegt in der Mitte der Bühne"
}
rightSpotTarget = "Paula (rechtzeitig positionieren!)"
rightSpotTarget = "Paula"
onRun {
FrontLights.center.forEach { it.brightness.off() }

View file

@ -86,8 +86,8 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
val actorsOnStage = mutableListOf<String>()
val props = PropPosition.values().associateWith<PropPosition, StringWithDetails?> { null }.toMutableMap()
var leftSpotTarget: String?
var rightSpotTarget: String?
var leftSpotTarget_: String? = null
var rightSpotTarget_: String? = null
var curtainState_ = CurtainState.CLOSED
object : ActBuilderContext {
@ -107,10 +107,21 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
val actorExits = mutableSetOf<StringWithDetails>()
var runner: StepRunner? = null
val builderContext = object : StepDataBuilderContext {
object : StepDataBuilderContext {
override val props = PropsBuilderMap(changedProps)
override var rightSpotTarget: String? = null
override var leftSpotTarget: String? = null
override var rightSpotTarget: String?
get() = rightSpotTarget_
set(value) {
rightSpotTarget_ = value
}
override var leftSpotTarget: String?
get() = leftSpotTarget_
set(value) {
leftSpotTarget_ = value
}
override var curtainState: CurtainState
get() = curtainState_
set(value) {
@ -124,11 +135,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
override fun onRun(block: StepRunner) {
runner = block
}
}
builderContext.also(build)
leftSpotTarget = builderContext.leftSpotTarget
rightSpotTarget = builderContext.rightSpotTarget
}.build()
val logger = KotlinLogging.logger("createAct / $actName / $sceneName / #${steps.size + 1} ${cue.format()}")
@ -173,8 +180,8 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
actorsOnStage.toImmutableList(),
props.toImmutableMap(),
changedProps.isNotEmpty(),
leftSpotTarget,
rightSpotTarget,
leftSpotTarget_,
rightSpotTarget_,
curtainState_,
runner
)

View file

@ -0,0 +1,43 @@
<template>
<div
class="flex flex-col items-center justify-center py-4"
:class="$style.root"
:data-blinking="isBlinking"
>
<slot/>
</div>
</template>
<style module>
.root[data-blinking="true"] {
animation: alternate infinite 1000ms ease-in-out pulse;
}
@keyframes pulse {
from {
@apply bg-red-900;
}
to {
@apply bg-transparent;
}
}
</style>
<script setup lang="ts">
import { toRef, watch } from "vue"
import { autoResetRef } from "@vueuse/core"
import { computed } from "vue"
const props = defineProps<{
value: unknown
blinkSeconds: number
}>()
const value = toRef(props, "value")
const isBlinking = autoResetRef(false, computed(() => props.blinkSeconds * 1000))
watch(value, () => {
isBlinking.value = true
})
</script>

View file

@ -1,9 +1,5 @@
<template>
<div
class="flex flex-col items-center justify-center py-4"
:class="$style.box"
:data-blinking="isBlinking"
>
<ChangeBlinkingBox :blink-seconds="20" :value="prop">
<div class="text-s1 tracking-wide text-gray-500">
{{ positionName }}
</div>
@ -21,27 +17,9 @@
</div>
</transition>
</div>
</div>
</ChangeBlinkingBox>
</template>
<style module>
.box {
&[data-blinking="true"] {
animation: alternate infinite 1000ms ease-in-out pulse;
}
}
@keyframes pulse {
from {
@apply bg-red-900;
}
to {
@apply bg-transparent;
}
}
</style>
<style scoped>
.fade-enter-active,
.fade-leave-active {
@ -58,6 +36,7 @@
import { toRef, watch } from "vue"
import { autoResetRef } from "@vueuse/core"
import { parseStringWithDetails } from "../state"
import ChangeBlinkingBox from "./ChangeBlinkingBox.vue"
const props = defineProps<{
prop: string | null

View file

@ -7,7 +7,8 @@
<StepSelection class="w-1/2"/>
<div class="w-1/2 flex flex-col space-y-4">
<MessageEdit class="h-1/2"/>
<ActorsOnStageBox class="h-1/2"/>
<ActorsOnStageBox class="flex-grow"/>
<FogControl/>
</div>
</div>
<MusicProgressBar class="h-10"/>
@ -22,6 +23,7 @@
import ActorsOnStageBox from "../components/ActorsOnStageBox.vue"
import { goToPosition } from "../syncing"
import { current, getNextValidPosition, getPreviousValidPosition, state } from "../state"
import FogControl from "../components/FogControl.vue"
onKeyStroke("ArrowRight", () => {
const position = getNextValidPosition(state.position)

77
ui/src/pages/spot.vue Normal file
View file

@ -0,0 +1,77 @@
<template>
<div class="flex flex-col h-full">
<h1 class="font-800 text-9 p-4 pb-0">
{{ current.act === null ? "" : `${current.act.name}`}}{{ current.scene.name }}
</h1>
<div class="h-full flex flex-col space-y-10 p-10 text-10">
<div class="flex gap-5 items-center h-18">
<div>
Aktuelles Ziel:
</div>
<ChangeBlinkingBox class="px-8 h-full min-w-50" :value="currentTarget" :blink-seconds="10">
{{ currentTarget ?? "Niemand" }}
</ChangeBlinkingBox>
</div>
<div v-if="nextStepWithChange !== null" class="h-full flex flex-col space-y-2 text-7">
<div class="flex gap-5 items-center">
<div>Nächstes Ziel:</div>
<div>{{ nextStepWithChange.target }}</div>
</div>
<div>
{{ nextStepWithChange.delta === 0
? "in dieser Szene (rechtzeitig positionieren!)"
: nextStepWithChange.delta === 1
? "in der nächsten Szene"
: `in ${nextStepWithChange.delta} Szenen`
}}
</div>
</div>
</div>
<MusicProgressBar class="h-10"/>
</div>
</template>
<style module>
</style>
<script setup lang="ts">
import { useRoute } from "vue-router"
import { computed } from "vue"
import { current, getNextValidPosition, getSceneIndex, getStep, ShowPosition, START_STEP } from "../state"
import ChangeBlinkingBox from "../components/ChangeBlinkingBox.vue"
import MusicProgressBar from "../components/MusicProgressBar.vue"
const route = useRoute()
const isLeft = computed(() => route.query.side === "left")
const targetProperty = computed<"leftSpotTarget" | "rightSpotTarget">(() => isLeft.value ? "leftSpotTarget" : "rightSpotTarget")
const currentTarget = computed(() => current.step[targetProperty.value])
interface StepWithChange {
delta: number
position: ShowPosition
target: string
}
const nextStepWithChange = computed<StepWithChange | null>(() => {
let position: ShowPosition | null = getNextValidPosition(current.step.position)
let lastTarget: string | null = currentTarget.value
while(position !== null) {
const step = getStep(position)
if (step[targetProperty.value] !== null && step[targetProperty.value] !== lastTarget) {
return {
position: step.position,
delta: getSceneIndex(step.position) - current.sceneIndex,
target: step[targetProperty.value]!
}
}
lastTarget = step[targetProperty.value]
position = getNextValidPosition(position)
}
return null
})
</script>

View file

@ -19,6 +19,8 @@ export interface Step {
actorsOnStage: string[]
props: PropMap
hasChangedProps: boolean
leftSpotTarget: string | null
rightSpotTarget: string | null
}
export type StepCue = {
@ -95,7 +97,9 @@ export const START_STEP: Step = {
},
hasChangedProps: false,
actorEntrances: [],
actorExits: []
actorExits: [],
leftSpotTarget: null,
rightSpotTarget: null
}
const START_SCENE: Scene = {
@ -129,6 +133,16 @@ export function getAct(position: ShowPosition) {
return show.value.acts[position.act]
}
export function getSceneIndex(position: ShowPosition) {
let index = position.scene
for (let actIndex = 0; actIndex < position.act; actIndex++) {
index += show.value.acts[actIndex]!.scenes.length
}
return index
}
export function getActiveMusicAt(position: ShowPosition): ShowMusic | null {
let activeMusic: ShowMusic | null = null
@ -162,13 +176,17 @@ export function getActiveMusicAt(position: ShowPosition): ShowMusic | null {
export const current = reactiveComputed<{
act: Act | null
scene: Scene
sceneIndex: number
step: Step
activeMusic: ShowMusic | null
allScenes: Scene[]
}>(() => ({
act: getAct(state.position),
scene: getScene(state.position),
sceneIndex: getSceneIndex(state.position),
step: getStep(state.position),
activeMusic: state.activeMusic
activeMusic: state.activeMusic,
allScenes: show.value.acts.flatMap(act => act.scenes)
}))
export function parseStringWithDetails(string: string) {