@vosjs/studio-core 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1050,6 +1050,12 @@ interface TextOverlayClip extends OverlayClipBase {
1050
1050
  letterSpacing?: number;
1051
1051
  /** Line height multiplier (default OVERLAY_LINE_HEIGHT). */
1052
1052
  lineHeight?: number;
1053
+ /**
1054
+ * Legibility shadow strength 0..1 (the preset's when absent; 0 = none).
1055
+ * Words on a plate ground carry none: the shadow exists for words over
1056
+ * footage.
1057
+ */
1058
+ shadow?: number;
1053
1059
  /** Text outline, drawn under the fill. */
1054
1060
  stroke?: TextOverlayStroke;
1055
1061
  /** Background pill behind the text block (absent = none). */
package/dist/index.js CHANGED
@@ -1266,6 +1266,7 @@ var CARD_FOV = 30;
1266
1266
  var OVERLAY_Z = -2;
1267
1267
  var CARD_Z = -4;
1268
1268
  var BACKGROUND_Z = -6;
1269
+ var CARD_OVERSCAN = 1.25;
1269
1270
  var CAMERA_NEAR = 0.1;
1270
1271
  var CAMERA_FAR = 100;
1271
1272
  function planeSizeAtDepth(distance, fovDeg, aspect) {
@@ -1361,6 +1362,7 @@ function resolveOverlayStyle(clip) {
1361
1362
  )
1362
1363
  } : {},
1363
1364
  ...clip.color ? { color: clip.color } : {},
1365
+ ...clip.shadow !== void 0 ? { shadow: Math.min(1, Math.max(0, clip.shadow)) } : {},
1364
1366
  fontStyle: clip.italic ? "italic" : "normal",
1365
1367
  align: clip.align ?? "center",
1366
1368
  letterSpacing: clip.letterSpacing ?? 0,
@@ -2850,11 +2852,15 @@ function expandEndCard(doc, outputDuration) {
2850
2852
  enter: "rise",
2851
2853
  exit: "none",
2852
2854
  align: "center",
2853
- ...card.ink ? { color: card.ink } : {}
2855
+ ...card.ink ? { color: card.ink } : {},
2856
+ shadow: 0
2854
2857
  });
2855
- if (card.headline?.trim()) clips.push(text("endcard-title", card.headline.trim(), "title", 0.44, 0.35));
2856
- if (card.sub?.trim()) clips.push(text("endcard-sub", card.sub.trim(), "caption", 0.57, 0.5));
2857
- if (card.wordmark?.trim()) clips.push(text("endcard-mark", card.wordmark.trim(), "label", 0.88, 0.65));
2858
+ if (card.headline?.trim())
2859
+ clips.push(text("endcard-title", card.headline.trim(), "title", 0.44, 0.35));
2860
+ if (card.sub?.trim())
2861
+ clips.push(text("endcard-sub", card.sub.trim(), "caption", 0.57, 0.5));
2862
+ if (card.wordmark?.trim())
2863
+ clips.push(text("endcard-mark", card.wordmark.trim(), "label", 0.88, 0.65));
2858
2864
  const overlays = [...doc.overlays ?? [], ...clips];
2859
2865
  return { doc: { ...doc, segments, overlays }, endStart, seconds };
2860
2866
  }
@@ -3526,24 +3532,33 @@ var ON_FRAME = `(ctx, content, dt) => {
3526
3532
  // the GPU texture allocated at the original dims and re-uploads the new canvas
3527
3533
  // against stale dims \u2192 stretch/duplicate; dispose() forces a full realloc) and
3528
3534
  // rebuilding each frustum-filling plane at the new aspect + syncing the camera.
3529
- if (cv.width !== W || cv.height !== H) {
3535
+ // Card OVERSCAN (stage.ts CARD_OVERSCAN): a frame whose inset bleeds the
3536
+ // card past an edge paints it on a canvas and a plane larger than the
3537
+ // frame by ck about the centre, so a tilt that turns the bled edge back
3538
+ // toward the viewer shows card there, not the texture's edge. Every doc
3539
+ // that keeps its card inside the frame (and the flat stub, which has no
3540
+ // card layer) stays at 1: byte- and pixel-identical.
3541
+ var d = ctx.data || {}
3542
+ var ckIns = (d.frame && d.frame.inset) || {}
3543
+ var ck = r.card && (ckIns.left < 0 || ckIns.right < 0 || ckIns.top < 0 || ckIns.bottom < 0) ? ${CARD_OVERSCAN} : 1
3544
+ var cW = Math.round(W * ck), cH = Math.round(H * ck)
3545
+ if (cv.width !== cW || cv.height !== cH) {
3530
3546
  var THREE = ctx.THREE
3531
3547
  var aspect = W / H
3532
3548
  var cm = ctx.camera
3533
3549
  if (cm && cm.isPerspectiveCamera) { cm.aspect = aspect; cm.updateProjectionMatrix() }
3534
- var lyr = [[bg, ${BACKGROUND_Z}], [card, ${CARD_Z}], [ov, ${OVERLAY_Z}]]
3550
+ var lyr = [[bg, ${BACKGROUND_Z}, 1], [card, ${CARD_Z}, ck], [ov, ${OVERLAY_Z}, 1]]
3535
3551
  for (var Li = 0; Li < lyr.length; Li++) {
3536
- var Ly = lyr[Li][0], Lz = lyr[Li][1]
3537
- if (Ly.canvas) { Ly.canvas.width = W; Ly.canvas.height = H }
3552
+ var Ly = lyr[Li][0], Lz = lyr[Li][1], Lk = lyr[Li][2]
3553
+ if (Ly.canvas) { Ly.canvas.width = Math.round(W * Lk); Ly.canvas.height = Math.round(H * Lk) }
3538
3554
  if (Ly.texture && Ly.texture.dispose) Ly.texture.dispose()
3539
3555
  if (Ly.mesh && THREE) {
3540
3556
  if (Ly.mesh.geometry && Ly.mesh.geometry.dispose) Ly.mesh.geometry.dispose()
3541
- var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2)
3557
+ var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2) * Lk
3542
3558
  Ly.mesh.geometry = new THREE.PlaneGeometry(Lh * aspect, Lh)
3543
3559
  }
3544
3560
  }
3545
3561
  }
3546
- var d = ctx.data || {}
3547
3562
  var frame = d.frame || {}
3548
3563
  var TL = globalThis.__vosTimeline
3549
3564
  // Output-timeline seconds (engine-fed master clock) \u2192 source seconds on screen.
@@ -3862,7 +3877,15 @@ var ON_FRAME = `(ctx, content, dt) => {
3862
3877
 
3863
3878
  // The CARD layer canvas starts transparent each frame \u2014 the padding around
3864
3879
  // the contain-fit card shows the background layer through the plane's alpha.
3865
- c.clearRect(0, 0, W, H)
3880
+ // Under overscan the canvas is larger than the frame and every frame-space
3881
+ // draw below rides a base translation to its centre.
3882
+ if (ck !== 1) c.setTransform(1, 0, 0, 1, 0, 0)
3883
+ c.clearRect(0, 0, cv.width, cv.height)
3884
+ if (ck !== 1) c.setTransform(1, 0, 0, 1, (cW - W) / 2, (cH - H) / 2)
3885
+ // Footage is nearly always drawn SMALLER than it was recorded (a 1920
3886
+ // recording in a padded 1080 card, or a 440-wide tile): the default
3887
+ // bilinear tap aliases and blurs a large downscale; 'high' resamples.
3888
+ c.imageSmoothingQuality = 'high'
3866
3889
 
3867
3890
  // video destination rect (contain within the padded area). The optional browser-bar
3868
3891
  // strip is part of the card: it takes barH from the available height and the video
@@ -3973,14 +3996,21 @@ var ON_FRAME = `(ctx, content, dt) => {
3973
3996
  // corners, drawn by the clip alone, hid theirs inside the arc.
3974
3997
  var shD = ceZs * (cardW + cardH) + 2 * (W + H)
3975
3998
  var shX = cardX - shD / ceZs
3976
- // soft shadow behind the card (bar strip + video)
3999
+ // The card shadow is LAYERED: three shadows whose blur and offset grow
4000
+ // while each stays at a low alpha (shadow is the strength they share),
4001
+ // so the card reads as lifted a little off the ground. One wide layer at
4002
+ // the full strength was the old paint, and at the default 0.4 it read as
4003
+ // a dark pool under the card.
3977
4004
  if (shadow > 0) {
3978
- c.save()
3979
- c.shadowColor = 'rgba(' + shRgb + ',' + shadow + ')'
3980
- c.shadowBlur = 60 * s2; c.shadowOffsetX = shD; c.shadowOffsetY = 24 * s2
3981
- c.fillStyle = '#000'
3982
- rr(shX, cardY, cardW, cardH, radius); c.fill()
3983
- c.restore()
4005
+ var shL = [[3, 1, 0.2], [14, 6, 0.22], [48, 22, 0.3]]
4006
+ for (var shI = 0; shI < shL.length; shI++) {
4007
+ c.save()
4008
+ c.shadowColor = 'rgba(' + shRgb + ',' + +(shadow * shL[shI][2]).toFixed(3) + ')'
4009
+ c.shadowBlur = shL[shI][0] * s2; c.shadowOffsetX = shD; c.shadowOffsetY = shL[shI][1] * s2
4010
+ c.fillStyle = '#000'
4011
+ rr(shX, cardY, cardW, cardH, radius); c.fill()
4012
+ c.restore()
4013
+ }
3984
4014
  }
3985
4015
  // contact shadow: tight and close, over the ambient layer
3986
4016
  if (shC > 0) {
@@ -5884,8 +5914,8 @@ var LOOKS = {
5884
5914
  cardWidth: 0.84,
5885
5915
  headroom: 0.16,
5886
5916
  radius: 12,
5887
- shadow: 0.22,
5888
- shadowContact: 0.16,
5917
+ shadow: 0.42,
5918
+ shadowContact: 0,
5889
5919
  border: 0.08,
5890
5920
  borderColor: "#000000"
5891
5921
  },
@@ -5895,8 +5925,8 @@ var LOOKS = {
5895
5925
  cardWidth: 0.84,
5896
5926
  headroom: 0.16,
5897
5927
  radius: 12,
5898
- shadow: 0.35,
5899
- shadowContact: 0.2,
5928
+ shadow: 0.5,
5929
+ shadowContact: 0,
5900
5930
  border: 0
5901
5931
  },
5902
5932
  dark: {
@@ -5905,8 +5935,8 @@ var LOOKS = {
5905
5935
  cardWidth: 0.86,
5906
5936
  headroom: 0.14,
5907
5937
  radius: 12,
5908
- shadow: 0.5,
5909
- shadowContact: 0.3,
5938
+ shadow: 0.7,
5939
+ shadowContact: 0,
5910
5940
  shadowColor: "#000000",
5911
5941
  border: 0.12,
5912
5942
  borderColor: "#ffffff"