///|
pub(all) struct Cue {
scene : Int
line : Int
character : String
preceding_character : String
preceding_text : String
simultaneous : Bool
dialogue : Array[String]
directions : Array[String]
parts : Array[SpeechPart]
} derive(Eq, Debug, ToJson)
///|
/// Cue context never crosses scene boundaries. Simultaneous speech is flagged,
/// not falsely presented as a sequential spoken trigger.
pub fn cue_sheet(doc : Document, character : String) -> Array[Cue] {
let ts = turns(doc)
let ss = scenes(doc)
let out : Array[Cue] = []
for i = 0; i < ts.length(); i = i + 1 {
let turn = ts[i]
if turn.character != character {
continue
}
let scene = scene_at_line(ss, turn.line)
let mut preceding_character = ""
let mut preceding_text = ""
if i > 0 && scene_at_line(ss, ts[i - 1].line) == scene {
let previous = ts[i - 1]
preceding_character = previous.character
if previous.dialogue.length() > 0 {
preceding_text = plain_text(
previous.dialogue[previous.dialogue.length() - 1],
)
}
}
out.push({
scene,
line: turn.line,
character,
preceding_character,
preceding_text,
simultaneous: turn.dual || (i + 1 < ts.length() && ts[i + 1].dual),
dialogue: turn.dialogue.copy(),
directions: turn.directions.copy(),
parts: turn.parts.copy(),
})
}
out
}
///|
pub fn cue_text(doc : Document, character : String) -> String {
let out = StringBuilder()
out.write_stringview(("CUE SHEET: " + character + "\n")[:])
for cue in cue_sheet(doc, character) {
out.write_stringview(
("\nScene \{cue.scene}, line \{cue.line}" +
(if cue.simultaneous { " [SIMULTANEOUS]\n" } else { "\n" }))[:],
)
if cue.preceding_character != "" {
out.write_stringview(
("Context — " +
cue.preceding_character +
": " +
cue.preceding_text +
"\n")[:],
)
}
for part in cue.parts {
out.write_stringview((plain_text(part.text) + "\n")[:])
}
}
out.to_string()
}