commit 77
This commit is contained in:
parent
18dc17d6d5
commit
9a8dcabdd6
22 changed files with 258 additions and 149 deletions
|
@ -14,7 +14,7 @@ fun SceneBuilderContext.songMittsommernacht() {
|
|||
step(StepCue.MusicStart("Mittsommernacht", 4.minutes + 30.seconds)) {
|
||||
actors {
|
||||
// TODO: Expand
|
||||
+"Einwohner von Huntington / von links & durch Mitte"
|
||||
+"Einwohner / von links & durch Mitte"
|
||||
}
|
||||
|
||||
curtainState = CurtainState.OPEN
|
||||
|
@ -281,7 +281,7 @@ fun SceneBuilderContext.songMittsommernacht() {
|
|||
|
||||
step(StepCue.MusicEnd) {
|
||||
actors {
|
||||
-"Einwohner von Huntington"
|
||||
-"Einwohner"
|
||||
+"Mina / durch Mitte, mit Koffer & Taschentuch"
|
||||
+"Lucy / durch Mitte"
|
||||
+"Jonathan / von links"
|
||||
|
|
|
@ -6,6 +6,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging
|
|||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import kotlinx.collections.immutable.toImmutableSet
|
||||
import java.util.*
|
||||
|
||||
@DslMarker
|
||||
annotation class TheaterDslMarker
|
||||
|
@ -103,8 +104,8 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
|
||||
override fun step(cue: StepCue, build: StepDataBuilderContext.() -> Unit) {
|
||||
val changedProps = mutableMapOf<PropPosition, StringWithDetails?>()
|
||||
val actorEntrances = mutableSetOf<StringWithDetails>()
|
||||
val actorExits = mutableSetOf<StringWithDetails>()
|
||||
val actorEntrances = TreeSet<StringWithDetails>()
|
||||
val actorExits = TreeSet<StringWithDetails>()
|
||||
var runner: StepRunner? = null
|
||||
|
||||
object : StepDataBuilderContext {
|
||||
|
@ -168,6 +169,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
|
||||
actorsOnStage.removeAll(actorExitsNames.toSet())
|
||||
actorsOnStage.addAll(actorEntrancesNames)
|
||||
actorsOnStage.sort()
|
||||
|
||||
changedProps.forEach { (k, v) -> props[k] = v }
|
||||
|
||||
|
|
|
@ -37,24 +37,9 @@ sealed interface StepCue {
|
|||
override fun format() = "curtain: $state${if (whileMoving) "(while moving)" else ""}"
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("LIGHT")
|
||||
data class Light(val state: State, val whileFading: Boolean) : StepCue {
|
||||
enum class State {
|
||||
@SerialName("on")
|
||||
ON,
|
||||
|
||||
@SerialName("off")
|
||||
OFF
|
||||
}
|
||||
|
||||
override fun format() = "light: $state${if (whileFading) "(while fading)" else ""}"
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("CUSTOM")
|
||||
data class Custom(val text: String) : StepCue {
|
||||
override fun format() = "custom: $text"
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
|
|||
*/
|
||||
@JvmInline
|
||||
@Serializable
|
||||
value class StringWithDetails(val value: String) {
|
||||
value class StringWithDetails(val value: String) : Comparable<StringWithDetails> {
|
||||
companion object {
|
||||
const val DELIMITER = " / "
|
||||
}
|
||||
|
@ -15,4 +15,6 @@ value class StringWithDetails(val value: String) {
|
|||
val main get() = value.split(DELIMITER)[0]
|
||||
val details: String? get() = value.split(DELIMITER, limit = 2).takeIf { it.size == 2 }?.let { it[1] }
|
||||
val hasDetails get() = details !== null
|
||||
|
||||
override fun compareTo(other: StringWithDetails): Int = value.compareTo(other.value)
|
||||
}
|
|
@ -4,10 +4,10 @@
|
|||
<div class="text-s1">Janus, created by Moritz Ruth</div>
|
||||
</div>
|
||||
<div v-else class="h-100dvh flex flex-col">
|
||||
<div class="font-black text-2xl md:text-4xl p-4 md:p-8 pb-0 md:pb-0 flex-shrink-0">
|
||||
<div class="font-black text-2xl md:text-4xl px-4 pt-4 flex-shrink-0 truncate">
|
||||
{{ current.act === null ? "" : `${current.act.name} — ` }}{{ current.scene.name }}
|
||||
</div>
|
||||
<div class="flex-grow p-4 md:p-8 overflow-hidden">
|
||||
<div class="flex-grow p-4 overflow-hidden">
|
||||
<router-view/>
|
||||
</div>
|
||||
<MusicProgressBar class="h-10 flex-shrink-0"/>
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
<template>
|
||||
<div class="overflow-y-auto">
|
||||
<transition-group name="list" tag="div">
|
||||
<div v-if="current.step.actorsOnStage.length === 0" key="" class="text-gray-400">Niemand</div>
|
||||
<div
|
||||
v-for="actor in current.step.actorsOnStage"
|
||||
:key="parseStringWithDetails(actor).main"
|
||||
class="truncate text-4.5"
|
||||
>
|
||||
{{ actor }}
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
<transition-group name="list" tag="div" class="overflow-y-auto md:columns-200px">
|
||||
<div v-if="current.step.actorsOnStage.length === 0" key="" class="text-gray-400">Niemand</div>
|
||||
<div
|
||||
v-for="actor in current.step.actorsOnStage"
|
||||
:key="parseStringWithDetails(actor).main"
|
||||
class="truncate line-height-normal"
|
||||
>
|
||||
{{ actor }}
|
||||
</div>
|
||||
</transition-group>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
<template>
|
||||
<div :data-blinking="isBlinking" class="overflow-hidden text-6 box p-4">
|
||||
{{ message }}
|
||||
<div :data-blinking="isBlinking" class="overflow-hidden text-6 py-2" :class="$style.root">
|
||||
<div v-if="message.trim().length === 0" class="text-gray-400">
|
||||
Keine Nachricht vorhanden.
|
||||
</div>
|
||||
<template v-else>{{ message }}</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
<style module>
|
||||
.root {
|
||||
&[data-blinking="true"] {
|
||||
animation: alternate infinite 500ms ease-in-out pulse;
|
||||
}
|
||||
|
@ -22,25 +25,15 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { state } from "../state"
|
||||
<script setup lang="ts">
|
||||
import { state } from "@/state"
|
||||
import { toRef, watch } from "vue"
|
||||
import { autoResetRef } from "@vueuse/core"
|
||||
|
||||
export default {
|
||||
name: "MessageDisplay",
|
||||
setup() {
|
||||
const message = toRef(state, "message")
|
||||
const isBlinking = autoResetRef(false, 10 * 1000)
|
||||
const message = toRef(state, "message")
|
||||
const isBlinking = autoResetRef(false, 10 * 1000)
|
||||
|
||||
watch(message, () => {
|
||||
isBlinking.value = message.value !== ""
|
||||
})
|
||||
|
||||
return {
|
||||
message,
|
||||
isBlinking
|
||||
}
|
||||
}
|
||||
}
|
||||
watch(message, () => {
|
||||
isBlinking.value = message.value !== ""
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div :class="scrollable ? 'overflow-y-auto' : 'overflow-hidden'" class="flex flex-col space-y-5">
|
||||
<div v-for="(act, actIndex) in show.acts">
|
||||
<div :class="scrollable ? 'overflow-y-auto' : 'overflow-hidden'" class="flex flex-col gap-5">
|
||||
<div v-for="(act, index) in show.acts" :key="index">
|
||||
<MotionsListAct :act="act" :center-current="Boolean(centerCurrent)"/>
|
||||
</div>
|
||||
<div class="h-[50%] flex-shrink-0"/>
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import MotionsListAct from "./MotionsListAct.vue"
|
||||
import { show } from "../state"
|
||||
import { show } from "@/state"
|
||||
|
||||
const props = defineProps<{
|
||||
centerCurrent?: boolean
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div class="pt-2">
|
||||
<div class="font-bold text-7 flex gap-5 items-center pb-4">
|
||||
<span class="flex-grow h-2px bg-white"></span>
|
||||
<div class="font-bold text-7 flex gap-7 items-center pb-4">
|
||||
<span class="flex-grow h-2px bg-gray-300"></span>
|
||||
<span>{{ act.name }}</span>
|
||||
<span class="flex-grow h-2px bg-white"></span>
|
||||
<span class="flex-grow h-2px bg-gray-300"></span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col gap-6">
|
||||
<div
|
||||
v-for="(scene, sceneIndex) in scenes"
|
||||
:key="sceneIndex"
|
||||
>
|
||||
<div class="text-gray-400 pl-3 text-5">
|
||||
<div class="text-gray-400 pl-3 text-5 pb-1">
|
||||
{{ scene.name }}
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
|
@ -32,7 +32,7 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Act, Scene, ShowPosition, Step } from "../state"
|
||||
import { Act, Scene, ShowPosition, Step } from "@/state"
|
||||
import { computed } from "vue"
|
||||
import MotionsListStep from "./MotionsListStep.vue"
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div :class="isActive && 'bg-green-800'" class="transition p-3">
|
||||
<div :class="isActive && 'bg-green-800'" class="transition p-3 rounded-2xl">
|
||||
<div class="flex space-x-2">
|
||||
<div class="flex-grow">
|
||||
<CueBox :step="step" text-class="text-6"/>
|
||||
<CueBox class="flex-shrink-0" text-class="text-6" :step="step"/>
|
||||
<div v-if="step.actorEntrances.length + step.actorExits.length > 0" class="py-2 pl-8 space-y-2 text-7">
|
||||
<div class="flex flex-col space-y-1">
|
||||
<div
|
||||
|
@ -47,7 +47,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { parseStringWithDetails, ShowPosition, START_STEP, state, Step } from "../state"
|
||||
import { parseStringWithDetails, ShowPosition, START_STEP, state, Step } from "@/state"
|
||||
import CueBox from "./CueBox.vue"
|
||||
import CaretDoubleRightIcon from "virtual:icons/ph/caret-double-right"
|
||||
import CaretDoubleLeftIcon from "virtual:icons/ph/caret-double-left"
|
||||
|
@ -63,7 +63,7 @@
|
|||
}>()
|
||||
|
||||
const position = toRef(state, "position")
|
||||
const element = useCurrentElement()
|
||||
const element = useCurrentElement<HTMLElement>()
|
||||
const allPositions = computed(() => [props.step.position, ...(props.morePositions ?? [])])
|
||||
const isActive = computed(() => allPositions.value.some(p => isEqual(p, position.value)))
|
||||
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
<template>
|
||||
<ChangeBlinkingBox :blink-seconds="20" :value="prop" class="items-center">
|
||||
<div class="text-s1 tracking-wide text-gray-500">
|
||||
<ChangeBlinkingBox :blink-seconds="20" :value="prop" class="flex flex-col items-center">
|
||||
<div class="text-s1 tracking-wide text-gray-400">
|
||||
{{ positionName }}
|
||||
</div>
|
||||
<div class="flex-grow w-full">
|
||||
<transition mode="out-in" name="fade">
|
||||
<div :key="prop" class="flex flex-col items-center justify-center">
|
||||
<template v-if="prop !== null">
|
||||
<div class="font-bold text-3 text-center">
|
||||
{{ parseStringWithDetails(prop).main }}
|
||||
</div>
|
||||
<div v-if="parseStringWithDetails(prop).details" class="text-center px-2">
|
||||
{{ parseStringWithDetails(prop).details }}
|
||||
</div>
|
||||
</template>
|
||||
<div :key="prop ?? ''" class="flex flex-col items-center justify-center">
|
||||
<div v-if="prop !== null" class="font-bold text-5 text-center">
|
||||
{{ prop }}
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
@ -32,10 +27,9 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import { toRef, watch } from "vue"
|
||||
import { autoResetRef } from "@vueuse/core"
|
||||
import { parseStringWithDetails } from "../state"
|
||||
import ChangeBlinkingBox from "./ChangeBlinkingBox.vue"
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
Publikum
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.row" class="border-t border-b border-dark-300 h-30">
|
||||
<div :class="$style.row" class="border-t border-b border-dark-300 h-20">
|
||||
<PropBox :prop="current.step.props.PROSCENIUM_RIGHT" position-name="Rechte Vorbühne"/>
|
||||
<PropBox :prop="current.step.props.PROSCENIUM_CENTER" position-name="Mitte der Vorbühne"/>
|
||||
<PropBox :prop="current.step.props.PROSCENIUM_LEFT" position-name="Linke der Vorbühne"/>
|
||||
</div>
|
||||
<div :class="$style.row" class="flex-grow h-0">
|
||||
<div :class="$style.row" class="flex-grow h-20">
|
||||
<PropBox :prop="current.step.props.RIGHT" position-name="Rechts"/>
|
||||
<PropBox :prop="current.step.props.CENTER" position-name="Mitte"/>
|
||||
<PropBox :prop="current.step.props.LEFT" position-name="Links"/>
|
||||
</div>
|
||||
<div :class="$style.row" class="border-t border-dark-300 py-3 h-20">
|
||||
<div :class="$style.row" class="border-t border-dark-300 h-11">
|
||||
<div/>
|
||||
<PropBox :prop="current.step.props.BACKDROP" position-name="Rückwand"/>
|
||||
<div/>
|
||||
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { current } from "../state"
|
||||
<script setup lang="ts">
|
||||
import { current } from "@/state"
|
||||
import PropBox from "./PropBox.vue"
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="absolute right-3 top-2 text-5 pointer-events-none flex items-center gap-1">
|
||||
<div class="absolute right-3 top-2 text-5 pointer-events-none flex items-center gap-1 <md:hidden">
|
||||
<ClockIcon/>
|
||||
<span class="font-bold tabular-nums tracking-tighter">{{ format.format(syncedTime) }}</span>
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { syncedTime } from "../syncing"
|
||||
import { syncedTime } from "@/syncing"
|
||||
import ClockIcon from "virtual:icons/ph/clock-bold"
|
||||
|
||||
const format = new Intl.DateTimeFormat("de", {
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<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 space-x-4 p-4 pt-8 flex-grow overflow-hidden">
|
||||
<MotionsList center-current class="w-3/7" scrollable/>
|
||||
<div class="w-4/7 flex flex-col space-y-4">
|
||||
<ActorsOnStageBox class="h-full text-7"/>
|
||||
<MessageEdit class="h-40"/>
|
||||
<CurtainLightControl/>
|
||||
</div>
|
||||
</div>
|
||||
<MusicProgressBar class="h-10"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MusicProgressBar from "../../components/MusicProgressBar.vue"
|
||||
import MotionsList from "../../components/MotionsList.vue"
|
||||
import { current } from "../../state"
|
||||
import ActorsOnStageBox from "../../components/ActorsOnStageBox.vue"
|
||||
import MessageEdit from "../../components/MessageEdit.vue"
|
||||
import CurtainLightControl from "../../components/CurtainLightControl.vue"
|
||||
</script>
|
75
ui/src/pages/for/fly-crew.vue
Normal file
75
ui/src/pages/for/fly-crew.vue
Normal file
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-50">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="text-gray text-2xl">
|
||||
Aktuelle Anweisung
|
||||
</div>
|
||||
<ChangeBlinkingBox :blink-seconds="10" :value="currentState" class="text-7 md:text-10">
|
||||
{{ getDisplayedCommand(currentState) }}
|
||||
</ChangeBlinkingBox>
|
||||
</div>
|
||||
<div v-if="nextStepWithChange !== null" class="flex flex-col gap-2">
|
||||
<div class="text-gray text-6">
|
||||
Nächste Anweisung
|
||||
<span class="whitespace-nowrap">
|
||||
[{{
|
||||
nextStepWithChange.delta === 0
|
||||
? "in dieser Szene"
|
||||
: nextStepWithChange.delta === 1
|
||||
? "in der nächsten Szene"
|
||||
: `in ${nextStepWithChange.delta} Szenen`
|
||||
}}]
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-7 md:text-10">{{ getDisplayedCommand(nextStepWithChange.state) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module>
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue"
|
||||
import { current, CurtainState, getNextValidPosition, getSceneIndex, getStep, ShowPosition } from "@/state"
|
||||
import ChangeBlinkingBox from "@/components/ChangeBlinkingBox.vue"
|
||||
|
||||
const currentState = computed(() => current.step.curtainState)
|
||||
|
||||
interface StepWithChange {
|
||||
delta: number
|
||||
position: ShowPosition
|
||||
state: CurtainState
|
||||
}
|
||||
|
||||
function getDisplayedCommand(value: CurtainState) {
|
||||
if (value === "open") {
|
||||
return "Öffnen"
|
||||
} else {
|
||||
return "Schließen"
|
||||
}
|
||||
}
|
||||
|
||||
const nextStepWithChange = computed<StepWithChange | null>(() => {
|
||||
let position: ShowPosition | null = getNextValidPosition(current.step.position)
|
||||
let lastState: CurtainState = currentState.value
|
||||
|
||||
while (position !== null) {
|
||||
const step = getStep(position)
|
||||
|
||||
if (step.curtainState !== lastState) {
|
||||
return {
|
||||
position: step.position,
|
||||
delta: getSceneIndex(step.position) - current.sceneIndex,
|
||||
state: step.curtainState
|
||||
}
|
||||
}
|
||||
|
||||
lastState = step.curtainState
|
||||
position = getNextValidPosition(position)
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
</script>
|
36
ui/src/pages/for/sound-operator.vue
Executable file
36
ui/src/pages/for/sound-operator.vue
Executable file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="grid grid-cols-2 gap-6 h-full">
|
||||
<MotionsList center-current scrollable/>
|
||||
<div class="flex flex-col gap-5 overflow-y-auto">
|
||||
<div>
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
Vorhang
|
||||
</div>
|
||||
<div class="text-4.5">
|
||||
{{ current.step.curtainState === "open" ? "öffnen" : "schließen" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow overflow-y-hidden flex flex-col">
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
Auf der Bühne
|
||||
</div>
|
||||
<ActorsOnStageBox class="flex-grow text-8"/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
Umbaulicht
|
||||
</div>
|
||||
<CurtainLightControl/>
|
||||
</div>
|
||||
<MessageEdit class="h-25 md:h-40 mb-1"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MotionsList from "../../components/MotionsList.vue"
|
||||
import ActorsOnStageBox from "../../components/ActorsOnStageBox.vue"
|
||||
import MessageEdit from "../../components/MessageEdit.vue"
|
||||
import CurtainLightControl from "../../components/CurtainLightControl.vue"
|
||||
import { current } from "@/state"
|
||||
</script>
|
33
ui/src/pages/for/stage.vue
Executable file
33
ui/src/pages/for/stage.vue
Executable file
|
@ -0,0 +1,33 @@
|
|||
<template>
|
||||
<div class="grid grid-cols-2 gap-6 h-full" :class="$style.root">
|
||||
<MotionsList center-current scrollable/>
|
||||
<div class="flex flex-col gap-5 overflow-y-hidden">
|
||||
<StageTopDownView/>
|
||||
<div class="flex-grow overflow-hidden">
|
||||
<div class="pb-2 font-bold text-6 tracking-wider uppercase">
|
||||
Auf der Bühne
|
||||
</div>
|
||||
<ActorsOnStageBox class="flex-grow h-full text-7"/>
|
||||
</div>
|
||||
<div class="h-35">
|
||||
<div class="font-bold text-6 tracking-wider uppercase">
|
||||
Nachricht
|
||||
</div>
|
||||
<MessageDisplay/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module lang="scss">
|
||||
.root {
|
||||
grid-template-columns: 2fr 3fr;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MotionsList from "@/components/MotionsList.vue"
|
||||
import ActorsOnStageBox from "@/components/ActorsOnStageBox.vue"
|
||||
import MessageDisplay from "@/components/MessageDisplay.vue"
|
||||
import StageTopDownView from "@/components/StageTopDownView.vue"
|
||||
</script>
|
|
@ -2,8 +2,7 @@
|
|||
<div class="grid md:grid-cols-2 gap-6 h-full" :class="$style.root">
|
||||
<StepSelection/>
|
||||
<div class="flex flex-col gap-5 overflow-y-auto">
|
||||
<MessageEdit class="h-25 md:h-40"/>
|
||||
<div class="text-5">
|
||||
<div>
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
Vorhang
|
||||
</div>
|
||||
|
@ -11,11 +10,11 @@
|
|||
{{ current.step.curtainState === "open" ? "öffnen" : "schließen" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-grow overflow-hidden">
|
||||
<div class="flex-grow overflow-y-hidden flex flex-col">
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
Auf der Bühne
|
||||
</div>
|
||||
<ActorsOnStageBox class="flex-grow h-full"/>
|
||||
<ActorsOnStageBox class="flex-grow text-4.5"/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="pb-2 font-bold text-3.5 tracking-wider uppercase">
|
||||
|
@ -29,6 +28,7 @@
|
|||
</div>
|
||||
<CurtainLightControl/>
|
||||
</div>
|
||||
<MessageEdit class="h-25 md:h-40 mb-1"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,6 +1,14 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-4 text-xl">
|
||||
<router-link to="/mixer">audio operator</router-link>
|
||||
<div class="flex flex-col items-center gap-4 text-2xl pt-20">
|
||||
<router-link
|
||||
v-for="dashboard in DASHBOARDS"
|
||||
:key="dashboard.to"
|
||||
class="flex items-center gap-2 rounded-xl bg-gray-900 p-5 hover:bg-gray-800 transition"
|
||||
:to="dashboard.to"
|
||||
>
|
||||
<component :is="dashboard.icon"/>
|
||||
<div class="font-bold">{{ dashboard.label }}</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -9,5 +17,38 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { type Component } from "vue"
|
||||
import FlyingSaucerIcon from "virtual:icons/ph/flying-saucer"
|
||||
import CircleWavyIcon from "virtual:icons/ph/circle-wavy"
|
||||
import FadersIcon from "virtual:icons/ph/faders"
|
||||
import StorefrontIcon from "virtual:icons/ph/storefront"
|
||||
|
||||
interface Dashboard {
|
||||
to: string
|
||||
label: string
|
||||
icon: Component
|
||||
}
|
||||
|
||||
const DASHBOARDS: Dashboard[] = [
|
||||
{
|
||||
to: "/for/fly-crew",
|
||||
label: "Fly crew",
|
||||
icon: FlyingSaucerIcon
|
||||
},
|
||||
{
|
||||
to: "/for/followspot-operator",
|
||||
label: "Followspot operator",
|
||||
icon: CircleWavyIcon
|
||||
},
|
||||
{
|
||||
to: "/for/sound-operator",
|
||||
label: "Sound operator",
|
||||
icon: FadersIcon
|
||||
},
|
||||
{
|
||||
to: "/for/stage",
|
||||
label: "Stage",
|
||||
icon: StorefrontIcon
|
||||
}
|
||||
]
|
||||
</script>
|
|
@ -1,23 +0,0 @@
|
|||
<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 space-x-4 p-4 pt-8 flex-grow overflow-hidden">
|
||||
<MotionsList center-current class="w-3/7"/>
|
||||
<div class="w-4/7 flex flex-col space-y-4">
|
||||
<StageTopDownView class="h-full"/>
|
||||
<MessageDisplay class="h-30"/>
|
||||
</div>
|
||||
</div>
|
||||
<MusicProgressBar class="h-15"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MusicProgressBar from "../../components/MusicProgressBar.vue"
|
||||
import { current } from "../../state"
|
||||
import MotionsList from "../../components/MotionsList.vue"
|
||||
import StageTopDownView from "../../components/StageTopDownView.vue"
|
||||
import MessageDisplay from "../../components/MessageDisplay.vue"
|
||||
</script>
|
|
@ -21,9 +21,11 @@ export interface Step {
|
|||
hasChangedProps: boolean
|
||||
leftSpotTarget: string | null
|
||||
rightSpotTarget: string | null
|
||||
curtainState: "open" | "closed"
|
||||
curtainState: CurtainState
|
||||
}
|
||||
|
||||
export type CurtainState = "open" | "closed"
|
||||
|
||||
export type StepCue = {
|
||||
type: "TEXT",
|
||||
speaker: string
|
||||
|
@ -37,13 +39,9 @@ export type StepCue = {
|
|||
type: "MUSIC_END"
|
||||
} | {
|
||||
type: "CURTAIN",
|
||||
state: "open" | "closed"
|
||||
state: CurtainState
|
||||
whileMoving: boolean
|
||||
} | {
|
||||
type: "LIGHTS"
|
||||
state: "on" | "off"
|
||||
whileFading: boolean
|
||||
} | {
|
||||
} | {
|
||||
type: "CUSTOM"
|
||||
text: string
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue