diff --git a/trailer.html b/trailer.html index 764a700..3ce228b 100644 --- a/trailer.html +++ b/trailer.html @@ -50,6 +50,23 @@ .whoin .p input{width:100%;box-sizing:border-box;font:inherit;padding:5px 7px; border:1px solid var(--line);border-radius:6px;background:transparent;color:inherit} .whoin .p .go{margin-top:5px;font-size:12px;padding:3px 9px} + .guide{border:1px solid var(--line);border-radius:12px;padding:14px 16px;margin:0 0 18px} + .guide h4{margin:0 0 10px;font-size:15px} + .guide ol{list-style:none;margin:0;padding:0;display:grid;gap:7px} + .guide li{display:flex;gap:10px;align-items:baseline;font-size:13px;color:var(--muted)} + .guide li .n{flex:none;width:20px;height:20px;border-radius:50%;border:1px solid var(--line); + display:inline-flex;align-items:center;justify-content:center;font-size:11px} + .guide li.done .n{background:#1f7a3a;border-color:#1f7a3a;color:#fff} + .guide li.now{color:inherit;font-weight:600} + .guide li.now .n{background:#4B8BF5;border-color:#4B8BF5;color:#fff} + .guide li .d{font-weight:400;color:var(--muted);display:block;margin-top:2px} + .guide li .btn{margin-left:4px} + .fchk{font-size:12px;margin:0 0 10px;padding:7px 10px;border-radius:8px;border:1px solid var(--line)} + .fchk.ok{color:#1f7a3a;border-color:transparent;padding-left:0} + .fchk.bad{border-color:#b4531f} + .fchk .w{display:block;margin:3px 0} + .fchk .w.serious{color:#b4531f;font-weight:600} + .fchk .go{font-size:12px;padding:2px 9px;margin-left:6px} .ffault{display:flex;gap:8px;margin:0 0 10px} .ffault input{flex:1;min-width:0;font:inherit;font-size:12px;padding:5px 8px; border:1px solid var(--line);border-radius:6px;background:transparent;color:inherit} @@ -224,7 +241,12 @@ return (Date.now() - t) < 25 * 60 * 1000; } + var DRAFTNOW = null; + function busyShots() { + var ps = String(PKG.pics_state || ""); + if (ps && ps !== "ready" + && (Date.now() - (Date.parse(PKG.pics_started || "") || 0)) < 15 * 60 * 1000) return true; if (String(PKG.look_state || "") && (Date.now() - (Date.parse(PKG.look_started || "") || 0)) < 15 * 60 * 1000) return true; return (PKG.shots || []).some(function (s) { @@ -821,7 +843,8 @@ var body = insertHtml("start"); shots.forEach(function (s) { body += shotHtml(s, voice) + insertHtml(s.id); }); - return head + probs + '
' + barHtml(meta) + '
' + DRAFTNOW = draft; + return head + guideHtml(meta) + probs + '
' + barHtml(meta) + '
' + '
' + reelHtml() + '
' + spineHtml() + cutsHtml(meta) + reviewsHtml(meta) + wholeHtml() + castHtml + body; } @@ -849,6 +872,103 @@ }).join(""); } + // WHAT TO DO NEXT. The steps of making a trailer, in order, with the one + // button that matters now. Everything else on the page is still there for + // anyone who wants it; nobody has to understand it to get a film made. + function guideHtml(meta) { + var shots = PKG.shots || []; + if (!shots.length || meta.writer !== RUN.lead_writer) return ""; + var ds = String(meta.draw_state || ""); + var drawing = ds && !/^(drawn|failed)/.test(ds); + var toDraw = Number(PKG.pictures_to_draw || 0); + var drawn = shots.filter(function (x) { return x.opening_url; }); + var unchecked = drawn.filter(function (x) { + return !x.clip_url && !((x.frame_check || {}).verdict); }).length; + var faulty = drawn.filter(function (x) { + return !x.clip_url && (x.frame_check || {}).verdict === "broken"; }); + var ps = String(PKG.pics_state || ""); + var checking = ps && ps !== "ready"; + var reelReady = String(PKG.reel_state || "") === "ready"; + var unfilmed = shots.filter(function (x) { return !x.clip_url; }).length; + var objections = String((DRAFTNOW || {}).problems || "").split("\n").filter(Boolean).length; + var price = function (n) { return "$" + n.toFixed(2); }; + + var steps = []; + steps.push({ t: "Read the script", done: true, + d: objections ? "The checker has " + objections + " objection" + (objections === 1 ? "" : "s") + + " - they are listed just below." : "" }); + steps.push({ t: "Tell the writer what to change", done: true, optional: true, + d: "Write in the box \u201cYour notes on the script as a whole\u201d, or under any shot, then press " + + "\u201cRevise the whole script\u201d. Skip this if you are happy." }); + + var s3 = { t: "Draw the pictures", done: toDraw === 0 && drawn.length > 0 }; + if (drawing) s3.d = "Drawing now\u2026 " + esc(ds) + ". You can leave this page open."; + else if (!s3.done) s3.btn = ''; + steps.push(s3); + + var s4 = { t: "Check the pictures", done: s3.done && !unchecked && !faulty.length }; + if (checking) s4.d = "Looking at every picture for mistakes\u2026 " + esc(ps); + else if (s3.done && unchecked) { + s4.d = "A second model looks at every picture for the mistakes these tools make - the wrong time " + + "of day, the wrong clothes, extra people, six fingers - and redraws any that are broken."; + s4.btn = ''; + } else if (s3.done && faulty.length) + s4.d = faulty.length + " picture" + (faulty.length === 1 ? " still has" : "s still have") + + " a problem: shot" + (faulty.length === 1 ? " " : "s ") + + faulty.map(function (x) { return x.id; }).join(", ") + + ". Scroll to " + (faulty.length === 1 ? "it" : "them") + " and press \u201cFix this\u201d, " + + "or carry on if you think the checker is being fussy."; + steps.push(s4); + + var s5 = { t: "Listen to the storyboard", done: reelReady }; + if (s3.done && !reelReady) + s5.btn = ''; + steps.push(s5); + + var s6 = { t: "Film it", done: unfilmed === 0 }; + if (s3.done && unfilmed) + s6.btn = ''; + steps.push(s6); + + var nowSet = false; + return '

What to do next

    ' + steps.map(function (st, i) { + var isNow = !nowSet && !st.done && !st.optional; + if (isNow) nowSet = true; + return '
  1. ' + + '' + (st.done && !st.optional ? '\u2713' : (i + 1)) + '' + + '' + esc(st.t) + (st.optional ? ' (if you want)' : '') + + ((isNow || (st.btn && /primary/.test(st.btn))) && st.btn ? ' ' + st.btn : '') + + (st.d && (isNow || st.optional || i === 0) ? '' + st.d + '' : '') + + '
  2. '; + }).join("") + '
'; + } + + // What the checker saw in this shot's opening picture, in its own sentence. + function frameCheckHtml(s) { + var fc = s.frame_check || {}; + if (!s.opening_url || s.clip_url || !fc.verdict || s.fixing || s.drawing) return ""; + var faults = (fc.faults || []).filter(function (f) { return f && f.what; }); + var dup = (fc.duplicated || []).filter(Boolean); + var retried = s.frame_retried ? ' (' + esc(s.frame_retried) + ')' : ''; + if (!faults.length && !dup.length) + return '
\u2713 picture checked - nothing wrong' + retried + '
'; + var rows = dup.map(function (d) { + return { what: "The same person appears twice: " + d, serious: true }; }) + .concat(faults.map(function (f) { return { what: f.what, serious: f.severity === "serious" }; })); + return '
' + + 'The checker looked at this picture and sees:' + retried + + rows.map(function (r, i) { + return '' + esc(r.what) + + ' '; + }).join("") + + '
'; + } + // "That is not right" - about the PICTURE, in the author's own words. The // picture is what the shot is filmed from, so a fault here is inherited by // the film and cannot be fixed by filming again. @@ -1037,6 +1157,7 @@ + (s.day ? ' · ' + esc(s.day) + '' : '') + '' + media + + frameCheckHtml(s) + frameFaultHtml(s) + whoInHtml(s) + '

' + esc(s.action || "") + '

' @@ -1225,6 +1346,28 @@ z.classList.add("on"); return; } + if ((el = hit("data-chkpics"))) { + el.disabled = true; el.textContent = "starting\u2026"; + r = await act("check_pictures", { draft_id: CUR }); + if (r) { showMsg("msg", r.shots ? "Checking " + r.shots + " pictures. Broken ones are redrawn " + + "automatically. This takes a few minutes." : (r.note || "Already checked."), "ok"); await refresh(); } + return; + } + if ((el = hit("data-fixfault"))) { + var ff = el.getAttribute("data-fixfault").split("|"); + var fs = (PKG.shots || []).filter(function (x) { return String(x.id) === ff[0]; })[0] || {}; + var fcx = fs.frame_check || {}; + var all = (fcx.duplicated || []).filter(Boolean).map(function (d) { + return "The same person appears twice: " + d + ". Each person appears once only."; }) + .concat((fcx.faults || []).filter(function (f) { return f && f.what; }) + .map(function (f) { return f.what; })); + var say = all[Number(ff[1])] || ""; + if (!say) return; + el.disabled = true; el.textContent = "working\u2026"; + r = await act("report_frame_fault", { draft_id: CUR, shot_id: ff[0], note: say }); + if (r) { showMsg("msg", "Redrawing shot " + ff[0] + " to fix that. About a minute.", "ok"); await refresh(); } + return; + } if ((el = hit("data-ffgo"))) { var fsid = el.getAttribute("data-ffgo"); var fbox = document.getElementById("ff-" + fsid);