Storyboard: opening picture from the previous shot's first or last frame

This commit is contained in:
gator 2026-09-22 22:27:36 +00:00
parent 5f38bbe6dc
commit e359067b14

View file

@ -1474,6 +1474,25 @@
return out; return out;
} }
// THE OPENING PICTURE of a shot can be the previous shot's first frame, or
// its last frame once it is filmed - so "catching up with the bouncing
// ball" starts with the ball, the dog and Dorothy exactly where the last
// clip left them.
function prevShot(s) {
var all = (PKG.shots || []).slice().sort(function (a, b) { return String(a.id).localeCompare(String(b.id)); });
var i = all.findIndex(function (x) { return x.id === s.id; });
return i > 0 ? all[i - 1] : null;
}
function openingHtml(s) {
var p = prevShot(s);
if (!p) return "";
var from = s.opening_from ? ' <span class="tiny">now: the ' + esc(s.opening_from.frame) + ' frame of shot ' + esc(s.opening_from.shot) + '</span>' : (s.opening_url ? ' <span class="tiny">now: drawn for this shot</span>' : '');
return '<div class="sceneshare" style="margin:4px 0 8px"><b style="color:var(--ink)">Opening picture</b>'
+ '<button type="button" class="btn small ghost" data-useframe="first|' + esc(s.id) + '"' + (p.opening_url ? '' : ' disabled title="Shot ' + esc(p.id) + ' has no picture yet"') + '>Same as shot ' + esc(p.id) + '\'s first frame</button>'
+ '<button type="button" class="btn small ghost" data-useframe="last|' + esc(s.id) + '"' + (p.clip_url ? '' : ' disabled title="Shot ' + esc(p.id) + ' has not been filmed yet"') + '>Same as shot ' + esc(p.id) + '\'s last frame</button>'
+ from + '</div>';
}
function shotHtml(s, voice) { function shotHtml(s, voice) {
if (s.writing) { if (s.writing) {
return '<div class="shot"><div class="num">' + esc(s.id) + '</div><div class="body">' return '<div class="shot"><div class="num">' + esc(s.id) + '</div><div class="body">'
@ -1508,9 +1527,9 @@
+ '</div><span class="dur" data-dur="' + esc(s.id) + '"></span></div>'; + '</div><span class="dur" data-dur="' + esc(s.id) + '"></span></div>';
}).join(""); }).join("");
var media = backgroundHtml(s); var media = backgroundHtml(s) + openingHtml(s);
if (s.clip_url) { if (s.clip_url) {
media = '<div class="frames"><figure><video src="' + esc(s.clip_url) + '" controls ' media += '<div class="frames"><figure><video src="' + esc(s.clip_url) + '" controls '
+ 'preload="metadata"></video><figcaption>the filmed shot' + 'preload="metadata"></video><figcaption>the filmed shot'
+ (s.clip_seconds ? ' &middot; ' + Number(s.clip_seconds).toFixed(1) + 's' : '') + (s.clip_seconds ? ' &middot; ' + Number(s.clip_seconds).toFixed(1) + 's' : '')
+ (s.clip_stale ? ' &middot; <b style="color:#b4531f">filmed from an older picture — film it again</b>' : '') + (s.clip_stale ? ' &middot; <b style="color:#b4531f">filmed from an older picture — film it again</b>' : '')
@ -1519,7 +1538,7 @@
+ '" src="' + esc(s.opening_url) + '" alt=""><figcaption>filmed from this frame</figcaption></figure>' : '') + '" src="' + esc(s.opening_url) + '" alt=""><figcaption>filmed from this frame</figcaption></figure>' : '')
+ '</div>'; + '</div>';
} else if (s.opening_url || s.closing_url) { } else if (s.opening_url || s.closing_url) {
media = '<div class="frames">' media += '<div class="frames">'
+ (s.opening_url ? '<figure><img data-zoom="' + esc("shot " + s.id + " opens on") + (s.opening_url ? '<figure><img data-zoom="' + esc("shot " + s.id + " opens on")
+ '" src="' + esc(s.opening_url) + '" alt=""><figcaption>opens on</figcaption></figure>' : '') + '" src="' + esc(s.opening_url) + '" alt=""><figcaption>opens on</figcaption></figure>' : '')
+ (s.closing_url ? '<figure><img data-zoom="' + esc("shot " + s.id + " ends on") + (s.closing_url ? '<figure><img data-zoom="' + esc("shot " + s.id + " ends on")
@ -1660,6 +1679,14 @@
if (r) { showMsg("msg", "Shot " + ssid + " is now " + Number(r.seconds).toFixed(1) + " s." + (PKG.shots.some(function (x) { return x.id === ssid && x.clip_url; }) ? " The clip was filmed at the old length; make the shot again to refilm." : ""), "ok"); await refresh(); } if (r) { showMsg("msg", "Shot " + ssid + " is now " + Number(r.seconds).toFixed(1) + " s." + (PKG.shots.some(function (x) { return x.id === ssid && x.clip_url; }) ? " The clip was filmed at the old length; make the shot again to refilm." : ""), "ok"); await refresh(); }
return; return;
} }
if ((el = hit("data-useframe"))) {
var uf = el.getAttribute("data-useframe").split("|");
el.disabled = true;
r = await act("use_frame", { draft_id: CUR, shot_id: uf[1], frame: uf[0] });
if (r) { showMsg("msg", "Shot " + uf[1] + " opens on the " + r.frame + " frame of shot " + r.from + (r.frame === "last" ? " - taking the frame from the clip, a few seconds." : "."), "ok"); await refresh(); }
else el.disabled = false;
return;
}
if ((el = hit("data-scene"))) { var sk = el.getAttribute("data-scene"); OPEN[sk] = !OPEN[sk]; rememberOpen(); openTab(CUR); return; } if ((el = hit("data-scene"))) { var sk = el.getAttribute("data-scene"); OPEN[sk] = !OPEN[sk]; rememberOpen(); openTab(CUR); return; }
if ((el = hit("data-shareshot"))) { if ((el = hit("data-shareshot"))) {
var shid = el.getAttribute("data-shareshot"); var shid = el.getAttribute("data-shareshot");