One stage at a time instead of the whole pipeline at once
The page showed the script, every shot's directing controls, your pictures, filming, the joins and the cut simultaneously. That is four different jobs on one screen, and the first of them - reading the words and getting them right - is the one that matters most and was the easiest to skip past. It is now four stages with a stepper: the words, the layout, filming, the cut. Each shows only what belongs to it, and you can step back to look at an earlier one at any time. This also fixes something that was simply wrong: approving the script used to hide every shot control, so the setting, camera and cutaways became uneditable at exactly the moment you were meant to be arranging them. Directing now lives in its own stage, after the words are settled and before anything is filmed.
This commit is contained in:
parent
b523474cbf
commit
29a054f8c8
1 changed files with 81 additions and 10 deletions
89
script.html
89
script.html
|
|
@ -49,6 +49,12 @@
|
||||||
.tlhead{position:absolute;top:0;bottom:0;width:2px;background:var(--accent2);pointer-events:none}
|
.tlhead{position:absolute;top:0;bottom:0;width:2px;background:var(--accent2);pointer-events:none}
|
||||||
.tlruler{position:absolute;left:0;right:0;bottom:0;height:14px;font:9px/14px var(--mono);color:var(--muted)}
|
.tlruler{position:absolute;left:0;right:0;bottom:0;height:14px;font:9px/14px var(--mono);color:var(--muted)}
|
||||||
.tlruler span{position:absolute;transform:translateX(-50%)}
|
.tlruler span{position:absolute;transform:translateX(-50%)}
|
||||||
|
.steps{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:24px}
|
||||||
|
.steps button{background:#0f1117;border:1px solid var(--line);color:var(--muted);
|
||||||
|
border-radius:999px;padding:8px 15px;font:12px/1 var(--mono);cursor:pointer}
|
||||||
|
.steps button.done{color:var(--ink)}
|
||||||
|
.steps button.on{background:var(--accent);border-color:var(--accent);color:#fff;cursor:default}
|
||||||
|
.steps button[disabled]{opacity:.35;cursor:not-allowed}
|
||||||
.stage{position:relative;width:100%;max-width:300px}
|
.stage{position:relative;width:100%;max-width:300px}
|
||||||
.stage>video{width:100%;aspect-ratio:9/16;border-radius:10px;background:#000;display:block}
|
.stage>video{width:100%;aspect-ratio:9/16;border-radius:10px;background:#000;display:block}
|
||||||
.ovl{position:absolute;inset:0;border-radius:10px;overflow:hidden;background:#000;display:none}
|
.ovl{position:absolute;inset:0;border-radius:10px;overflow:hidden;background:#000;display:none}
|
||||||
|
|
@ -161,6 +167,38 @@ function shotHtml(s, locked) {
|
||||||
+ '</div></div>';
|
+ '</div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Four jobs, one at a time. Which one you are on follows from the project's
|
||||||
|
// status; VIEW lets you step back to look at an earlier one without pretending
|
||||||
|
// the work has been undone.
|
||||||
|
var STAGES = ["The words", "The layout", "Filming", "The cut"];
|
||||||
|
var VIEW = null;
|
||||||
|
|
||||||
|
function stageOf(st) {
|
||||||
|
if (st === "ready" || st === "film_failed") return 4;
|
||||||
|
if (st === "queued_to_film" || st === "filming") return 3;
|
||||||
|
if (st === "approved") return 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stepper(stage, view) {
|
||||||
|
return '<div class="steps">' + STAGES.map(function (n, k) {
|
||||||
|
var i = k + 1;
|
||||||
|
var cls = i === view ? "on" : (i <= stage ? "done" : "");
|
||||||
|
return '<button type="button" class="' + cls + '" data-stage="' + i + '"'
|
||||||
|
+ (i <= stage ? '' : ' disabled') + '>' + i + ' · ' + esc(n) + '</button>';
|
||||||
|
}).join("") + '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stage one shows the writing and nothing else: no frames, no camera, no
|
||||||
|
// settings. Just what the pet actually says.
|
||||||
|
function linesHtml(s) {
|
||||||
|
return '<div class="shot" style="grid-template-columns:1fr;padding:16px 20px"><div>'
|
||||||
|
+ '<span class="n">Shot ' + (s.index || "") + '</span>'
|
||||||
|
+ '<p class="line" style="margin:8px 0 6px">' + esc(s.line || "") + '</p>'
|
||||||
|
+ '<p class="foot">' + (s.word_count || 0) + ' words · about '
|
||||||
|
+ (s.est_seconds || 0) + 's</p></div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
function render(r) {
|
function render(r) {
|
||||||
DATA = r;
|
DATA = r;
|
||||||
var p = r.project, s = r.script, out = document.getElementById("out");
|
var p = r.project, s = r.script, out = document.getElementById("out");
|
||||||
|
|
@ -190,7 +228,12 @@ function render(r) {
|
||||||
document.getElementById("title").textContent = s.title || "The script";
|
document.getElementById("title").textContent = s.title || "The script";
|
||||||
document.getElementById("sub").textContent = s.premise || "";
|
document.getElementById("sub").textContent = s.premise || "";
|
||||||
|
|
||||||
var locked = p.status === "approved";
|
var stage = stageOf(p.status);
|
||||||
|
if (VIEW === null || VIEW > stage) VIEW = stage;
|
||||||
|
// Shot controls belong to the layout stage. Elsewhere the shots are shown
|
||||||
|
// but not touchable, which is what "locked" means to shotHtml.
|
||||||
|
var locked = VIEW !== 2;
|
||||||
|
var canEditScript = (stage === 1);
|
||||||
var warn = (s._warnings && s._warnings.length)
|
var warn = (s._warnings && s._warnings.length)
|
||||||
? '<div class="warn"><strong>Worth a look:</strong> ' + s._warnings.map(esc).join(" · ") + '</div>' : "";
|
? '<div class="warn"><strong>Worth a look:</strong> ' + s._warnings.map(esc).join(" · ") + '</div>' : "";
|
||||||
|
|
||||||
|
|
@ -299,8 +342,9 @@ function render(r) {
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var actions = locked
|
var actions = !canEditScript
|
||||||
? '<div class="card"><p style="margin:0"><strong>Approved.</strong> Filming is switched on once payment is live. Nothing has been charged.</p></div>'
|
? '<div class="card"><p style="margin:0"><strong>These words are settled.</strong> '
|
||||||
|
+ 'Everything after this arranges how they are shot, so the writing is left alone.</p></div>'
|
||||||
: '<div class="card">'
|
: '<div class="card">'
|
||||||
+ '<h2 class="sec">Change the words</h2>'
|
+ '<h2 class="sec">Change the words</h2>'
|
||||||
+ '<div class="field"><label for="fb">What would you change</label>'
|
+ '<div class="field"><label for="fb">What would you change</label>'
|
||||||
|
|
@ -312,13 +356,30 @@ function render(r) {
|
||||||
+ '<button class="btn" id="approve" style="margin-left:10px">Approve and lock it</button>'
|
+ '<button class="btn" id="approve" style="margin-left:10px">Approve and lock it</button>'
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
|
|
||||||
out.innerHTML = cams + head + warn + full
|
var body;
|
||||||
+ '<h2 class="sec">The shots</h2>'
|
if (VIEW === 1) {
|
||||||
+ s.segments.map(function (x) { return shotHtml(x, locked); }).join("")
|
body = head + warn + full
|
||||||
+ own
|
+ '<h2 class="sec">The words, shot by shot</h2>'
|
||||||
+ film
|
+ s.segments.map(linesHtml).join("")
|
||||||
+ post
|
|
||||||
+ actions;
|
+ actions;
|
||||||
|
} else if (VIEW === 2) {
|
||||||
|
body = head
|
||||||
|
+ '<p class="note" style="margin:0 0 22px"><strong>How it will be laid out.</strong> '
|
||||||
|
+ 'Each shot has a setting, a camera move and an opening frame that carries your '
|
||||||
|
+ 'pet’s likeness. Cutaways sit across the joins so the cut is never on screen. '
|
||||||
|
+ 'All of it has been chosen for you — change anything you disagree with, or '
|
||||||
|
+ 'go straight to filming.</p>'
|
||||||
|
+ '<h2 class="sec">The shots</h2>'
|
||||||
|
+ s.segments.map(function (x) { return shotHtml(x, false); }).join("")
|
||||||
|
+ own
|
||||||
|
+ film;
|
||||||
|
} else if (VIEW === 3) {
|
||||||
|
body = head + film;
|
||||||
|
} else {
|
||||||
|
body = head + post + film;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.innerHTML = cams + stepper(stage, VIEW) + body;
|
||||||
|
|
||||||
wire(locked);
|
wire(locked);
|
||||||
}
|
}
|
||||||
|
|
@ -447,6 +508,16 @@ function bindPics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function wire(locked) {
|
function wire(locked) {
|
||||||
|
[].forEach.call(document.querySelectorAll("[data-stage]"), function (b) {
|
||||||
|
b.onclick = function () {
|
||||||
|
var want = parseInt(b.getAttribute("data-stage"), 10);
|
||||||
|
if (want === VIEW) return;
|
||||||
|
VIEW = want;
|
||||||
|
hideMsg("msg");
|
||||||
|
render(DATA);
|
||||||
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
|
};
|
||||||
|
});
|
||||||
bindPics();
|
bindPics();
|
||||||
bindFilm((DATA && DATA.project) || {});
|
bindFilm((DATA && DATA.project) || {});
|
||||||
bindPost();
|
bindPost();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue