commit #23
This commit is contained in:
parent
379fc8eebb
commit
a9ff97627b
8 changed files with 167 additions and 41 deletions
|
@ -261,7 +261,7 @@ fun ShowBuilderContext.fourthAct() = act("Vierter Akt") {
|
||||||
+"Adrian / von links"
|
+"Adrian / von links"
|
||||||
}
|
}
|
||||||
|
|
||||||
leftSpotTarget = "Kai & Adrian (rechtzeitig positionieren!)"
|
leftSpotTarget = "Kai & Adrian"
|
||||||
|
|
||||||
onRun {
|
onRun {
|
||||||
Washs.left.colorWheelMode.static(CoemarProWash.ColorWheelMode.Rotate(5.percent, true))
|
Washs.left.colorWheelMode.static(CoemarProWash.ColorWheelMode.Rotate(5.percent, true))
|
||||||
|
|
|
@ -62,7 +62,7 @@ fun ShowBuilderContext.secondAct() = act("Zweiter Akt") {
|
||||||
+"Astronaut / liegt in der Mitte der Bühne"
|
+"Astronaut / liegt in der Mitte der Bühne"
|
||||||
}
|
}
|
||||||
|
|
||||||
rightSpotTarget = "Paula (rechtzeitig positionieren!)"
|
rightSpotTarget = "Paula"
|
||||||
|
|
||||||
onRun {
|
onRun {
|
||||||
FrontLights.center.forEach { it.brightness.off() }
|
FrontLights.center.forEach { it.brightness.off() }
|
||||||
|
|
|
@ -86,8 +86,8 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
||||||
val actorsOnStage = mutableListOf<String>()
|
val actorsOnStage = mutableListOf<String>()
|
||||||
val props = PropPosition.values().associateWith<PropPosition, StringWithDetails?> { null }.toMutableMap()
|
val props = PropPosition.values().associateWith<PropPosition, StringWithDetails?> { null }.toMutableMap()
|
||||||
|
|
||||||
var leftSpotTarget: String?
|
var leftSpotTarget_: String? = null
|
||||||
var rightSpotTarget: String?
|
var rightSpotTarget_: String? = null
|
||||||
var curtainState_ = CurtainState.CLOSED
|
var curtainState_ = CurtainState.CLOSED
|
||||||
|
|
||||||
object : ActBuilderContext {
|
object : ActBuilderContext {
|
||||||
|
@ -107,10 +107,21 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
||||||
val actorExits = mutableSetOf<StringWithDetails>()
|
val actorExits = mutableSetOf<StringWithDetails>()
|
||||||
var runner: StepRunner? = null
|
var runner: StepRunner? = null
|
||||||
|
|
||||||
val builderContext = object : StepDataBuilderContext {
|
object : StepDataBuilderContext {
|
||||||
override val props = PropsBuilderMap(changedProps)
|
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
|
override var curtainState: CurtainState
|
||||||
get() = curtainState_
|
get() = curtainState_
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -124,11 +135,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
||||||
override fun onRun(block: StepRunner) {
|
override fun onRun(block: StepRunner) {
|
||||||
runner = block
|
runner = block
|
||||||
}
|
}
|
||||||
}
|
}.build()
|
||||||
|
|
||||||
builderContext.also(build)
|
|
||||||
leftSpotTarget = builderContext.leftSpotTarget
|
|
||||||
rightSpotTarget = builderContext.rightSpotTarget
|
|
||||||
|
|
||||||
val logger = KotlinLogging.logger("createAct / $actName / $sceneName / #${steps.size + 1} ${cue.format()}")
|
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(),
|
actorsOnStage.toImmutableList(),
|
||||||
props.toImmutableMap(),
|
props.toImmutableMap(),
|
||||||
changedProps.isNotEmpty(),
|
changedProps.isNotEmpty(),
|
||||||
leftSpotTarget,
|
leftSpotTarget_,
|
||||||
rightSpotTarget,
|
rightSpotTarget_,
|
||||||
curtainState_,
|
curtainState_,
|
||||||
runner
|
runner
|
||||||
)
|
)
|
||||||
|
|
43
ui/src/components/ChangeBlinkingBox.vue
Normal file
43
ui/src/components/ChangeBlinkingBox.vue
Normal 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>
|
|
@ -1,9 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<ChangeBlinkingBox :blink-seconds="20" :value="prop">
|
||||||
class="flex flex-col items-center justify-center py-4"
|
|
||||||
:class="$style.box"
|
|
||||||
:data-blinking="isBlinking"
|
|
||||||
>
|
|
||||||
<div class="text-s1 tracking-wide text-gray-500">
|
<div class="text-s1 tracking-wide text-gray-500">
|
||||||
{{ positionName }}
|
{{ positionName }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,27 +17,9 @@
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ChangeBlinkingBox>
|
||||||
</template>
|
</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>
|
<style scoped>
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
|
@ -58,6 +36,7 @@
|
||||||
import { toRef, watch } from "vue"
|
import { toRef, watch } from "vue"
|
||||||
import { autoResetRef } from "@vueuse/core"
|
import { autoResetRef } from "@vueuse/core"
|
||||||
import { parseStringWithDetails } from "../state"
|
import { parseStringWithDetails } from "../state"
|
||||||
|
import ChangeBlinkingBox from "./ChangeBlinkingBox.vue"
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
prop: string | null
|
prop: string | null
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<StepSelection class="w-1/2"/>
|
<StepSelection class="w-1/2"/>
|
||||||
<div class="w-1/2 flex flex-col space-y-4">
|
<div class="w-1/2 flex flex-col space-y-4">
|
||||||
<MessageEdit class="h-1/2"/>
|
<MessageEdit class="h-1/2"/>
|
||||||
<ActorsOnStageBox class="h-1/2"/>
|
<ActorsOnStageBox class="flex-grow"/>
|
||||||
|
<FogControl/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MusicProgressBar class="h-10"/>
|
<MusicProgressBar class="h-10"/>
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
import ActorsOnStageBox from "../components/ActorsOnStageBox.vue"
|
import ActorsOnStageBox from "../components/ActorsOnStageBox.vue"
|
||||||
import { goToPosition } from "../syncing"
|
import { goToPosition } from "../syncing"
|
||||||
import { current, getNextValidPosition, getPreviousValidPosition, state } from "../state"
|
import { current, getNextValidPosition, getPreviousValidPosition, state } from "../state"
|
||||||
|
import FogControl from "../components/FogControl.vue"
|
||||||
|
|
||||||
onKeyStroke("ArrowRight", () => {
|
onKeyStroke("ArrowRight", () => {
|
||||||
const position = getNextValidPosition(state.position)
|
const position = getNextValidPosition(state.position)
|
||||||
|
|
77
ui/src/pages/spot.vue
Normal file
77
ui/src/pages/spot.vue
Normal 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>
|
|
@ -19,6 +19,8 @@ export interface Step {
|
||||||
actorsOnStage: string[]
|
actorsOnStage: string[]
|
||||||
props: PropMap
|
props: PropMap
|
||||||
hasChangedProps: boolean
|
hasChangedProps: boolean
|
||||||
|
leftSpotTarget: string | null
|
||||||
|
rightSpotTarget: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StepCue = {
|
export type StepCue = {
|
||||||
|
@ -95,7 +97,9 @@ export const START_STEP: Step = {
|
||||||
},
|
},
|
||||||
hasChangedProps: false,
|
hasChangedProps: false,
|
||||||
actorEntrances: [],
|
actorEntrances: [],
|
||||||
actorExits: []
|
actorExits: [],
|
||||||
|
leftSpotTarget: null,
|
||||||
|
rightSpotTarget: null
|
||||||
}
|
}
|
||||||
|
|
||||||
const START_SCENE: Scene = {
|
const START_SCENE: Scene = {
|
||||||
|
@ -129,6 +133,16 @@ export function getAct(position: ShowPosition) {
|
||||||
return show.value.acts[position.act]
|
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 {
|
export function getActiveMusicAt(position: ShowPosition): ShowMusic | null {
|
||||||
let activeMusic: ShowMusic | null = null
|
let activeMusic: ShowMusic | null = null
|
||||||
|
|
||||||
|
@ -162,13 +176,17 @@ export function getActiveMusicAt(position: ShowPosition): ShowMusic | null {
|
||||||
export const current = reactiveComputed<{
|
export const current = reactiveComputed<{
|
||||||
act: Act | null
|
act: Act | null
|
||||||
scene: Scene
|
scene: Scene
|
||||||
|
sceneIndex: number
|
||||||
step: Step
|
step: Step
|
||||||
activeMusic: ShowMusic | null
|
activeMusic: ShowMusic | null
|
||||||
|
allScenes: Scene[]
|
||||||
}>(() => ({
|
}>(() => ({
|
||||||
act: getAct(state.position),
|
act: getAct(state.position),
|
||||||
scene: getScene(state.position),
|
scene: getScene(state.position),
|
||||||
|
sceneIndex: getSceneIndex(state.position),
|
||||||
step: getStep(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) {
|
export function parseStringWithDetails(string: string) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue