@vosjs/studio-core 0.16.0 → 0.17.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 +43 -1
- package/dist/index.js +336 -60
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1221,7 +1221,22 @@ interface TextOverlayBox {
|
|
|
1221
1221
|
*/
|
|
1222
1222
|
interface MediaOverlayClip extends OverlayClipBase {
|
|
1223
1223
|
kind: 'image' | 'video';
|
|
1224
|
+
/**
|
|
1225
|
+
* The picture: an asset URL, a take-dir file, or a DOCUMENT MEDIA by
|
|
1226
|
+
* reference, `media:<id>` (`media:` alone is the primary), which brings
|
|
1227
|
+
* the media's facts with it (its cursor track, its recorded page) and
|
|
1228
|
+
* follows the media's kind. The lowering resolves the reference to the
|
|
1229
|
+
* media's own key; the document keeps the reference.
|
|
1230
|
+
*/
|
|
1224
1231
|
key: string;
|
|
1232
|
+
/**
|
|
1233
|
+
* The layer as a CARD: drawn by the card painter on its own plane above
|
|
1234
|
+
* the primary card (the layered shadow, the media clipped to its corners,
|
|
1235
|
+
* a browser bar, the border, a lean, and for a document media its cursor
|
|
1236
|
+
* dot and click rings). Absent, the layer is the flat picture it always
|
|
1237
|
+
* was, byte-identically.
|
|
1238
|
+
*/
|
|
1239
|
+
frame?: LayerCard;
|
|
1225
1240
|
/**
|
|
1226
1241
|
* The card shadow. Absent = 'soft' — the baked look every
|
|
1227
1242
|
* doc predating the field renders, so absence lowers byte-identically. 'strong' is the
|
|
@@ -1247,6 +1262,27 @@ interface MediaOverlayClip extends OverlayClipBase {
|
|
|
1247
1262
|
loop?: boolean;
|
|
1248
1263
|
}
|
|
1249
1264
|
type OverlayClip = TextOverlayClip | MediaOverlayClip;
|
|
1265
|
+
/**
|
|
1266
|
+
* A layer's own card. The bar is ALLOWED on any card and opens off; its
|
|
1267
|
+
* address defaults to the media's recorded page when the layer shows a
|
|
1268
|
+
* document media. The lean is the tilt convention, in degrees.
|
|
1269
|
+
*/
|
|
1270
|
+
interface LayerCard {
|
|
1271
|
+
browserBar?: Partial<BrowserBarStyle>;
|
|
1272
|
+
lean?: {
|
|
1273
|
+
rx: number;
|
|
1274
|
+
ry: number;
|
|
1275
|
+
};
|
|
1276
|
+
/** The layered shadow's strength; absent = LAYER_CARD_SHADOW. */
|
|
1277
|
+
shadow?: number;
|
|
1278
|
+
shadowContact?: number;
|
|
1279
|
+
shadowColor?: string;
|
|
1280
|
+
/** Draw the media's cursor and clicks inside the card; absent = yes when it has a track. */
|
|
1281
|
+
cursor?: boolean;
|
|
1282
|
+
}
|
|
1283
|
+
declare const LAYER_CARD_SHADOW = 0.32;
|
|
1284
|
+
/** The prefix of a media overlay key that names a document media. */
|
|
1285
|
+
declare const MEDIA_KEY_PREFIX = "media:";
|
|
1250
1286
|
/**
|
|
1251
1287
|
* Ceiling on `transform.scale` for text overlays, shared by the canvas box
|
|
1252
1288
|
* and the panel so the two can never disagree about where growth stops (a
|
|
@@ -3280,6 +3316,12 @@ declare function mediaAtOutput(rated: readonly MediaSegment[], t: number): strin
|
|
|
3280
3316
|
declare function mediaFrame(doc: Pick<ProjectDoc, 'source' | 'media' | 'frame'>, id: string | undefined | null): FrameStyle;
|
|
3281
3317
|
/** The card-owned fields of a frame, alone (what a media's card is made of). */
|
|
3282
3318
|
declare function cardFields(frame: FrameStyle): Pick<FrameStyle, MediaFrameKey>;
|
|
3319
|
+
/** The overlay key that shows a document media (`''` = the primary). */
|
|
3320
|
+
declare const mediaRef: (id: string) => string;
|
|
3321
|
+
/** The media id an overlay key names, `''` for the primary, null for a plain key. */
|
|
3322
|
+
declare function mediaRefId(key: string | undefined | null): string | null;
|
|
3323
|
+
/** The document media a layer's key shows, or null for a plain key or a stranger. */
|
|
3324
|
+
declare function layerMedia(doc: Pick<ProjectDoc, 'source' | 'media'>, key: string | undefined | null): ProjectDoc['source'] | null;
|
|
3283
3325
|
/** The next free media id (`m1`, `m2`, …). */
|
|
3284
3326
|
declare function nextMediaId(doc: Pick<ProjectDoc, 'media'>): string;
|
|
3285
3327
|
|
|
@@ -3863,4 +3905,4 @@ declare function rejectSpan(rejected: RejectedSpan[] | undefined, lane: Rejected
|
|
|
3863
3905
|
anchor?: StepAnchor;
|
|
3864
3906
|
}, note?: string): RejectedSpan;
|
|
3865
3907
|
|
|
3866
|
-
export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type Anim, type AnimKind, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, type BakedText3dAsset, type BakedText3dMaterial, type BrowserBarStyle, type BuildDigestInput, CAMERA_FAR, CAMERA_NEAR, CAM_CHAIN_GAP, CAM_EASE, CAM_PAN, CAM_PAN_EASE, CAM_RAMP_IN, CAM_RAMP_OUT, CAM_SIZE_MAX, CAM_SIZE_MIN, CAM_SPAN_MIN, CAPTURE_COVERAGE_MIN, CARD_EDGE_OVERDRAW, CARD_ENTER_KINDS, CARD_EXIT_KINDS, CARD_FADE_SECONDS, CARD_FOV, CARD_Z, CHANNEL_SPECS_HASH, CHANNEL_SPECS_VERIFIED, CLICK_FX_INTENSITY, CLICK_FX_PRE, CLICK_HIGHLIGHT_FADE, CLICK_PAIR_MAX, CLICK_PULSE_DUR, CLICK_RECT_MAX_FRAC, CLICK_RIPPLE_DUR, CLICK_SYNTH_RELEASE, CROP_MAX_PX, CROP_MIN_FRAC, CROP_MIN_PX, CROP_PAD, CURSOR_IDLE_EPS_FRAC, CURSOR_IDLE_FADE_IN, CURSOR_IDLE_FADE_OUT, CURSOR_IDLE_HOLD, type CamBubbleRect, type CamPoseSpan, type CamStyle, type CaptureNormalization, type CardLayout, type ClickFxStyle, type CopiedLayout, type CopyLayoutOptions, type CopyStyleOptions, type CursorEvent, type CursorFadeKey, type CursorIdleOptions, type CursorStyle, type CursorTrack, DARK_GROUND, DEFAULT_BROWSER_BAR, DEFAULT_CAM_POSE, DEFAULT_CAM_STYLE, DEFAULT_CLICK_FX, DEFAULT_CURSOR_STYLE, DEFAULT_DUCK, DEFAULT_FRAME_STYLE, DEFAULT_SPEED_PARAMS, DEFAULT_TILT_POSE, DEFAULT_ZOOM_LEVEL, DEFAULT_ZOOM_STYLE, DESTINATIONS, DIGEST_CROP_MAX, DIGEST_FULL_MAX, DIGEST_VERSION, DOC_SCHEMA_VERSION, DRAG_FIT_LEVEL, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocSegment, type DuckOptions, END_CARD_FROM, END_CARD_RECEDE, END_CARD_SECONDS, ENTRANCE_SECONDS, EXPORT_RESOLUTION_OPTIONS, EXPORT_SHORT_EDGE, type EndCard, type EnvelopePoint, type ExportResolution, type ExtractClickOptions, FOLLOW_RECENTER, FOLLOW_SAFE_RATIO, FRAME_BORDER_COLOR_DEFAULT, FRAME_BORDER_DEFAULT, FRAME_BORDER_WIDTH_DEFAULT, FREEZE_DEFAULT_SECONDS, FREEZE_SECONDS_MAX, FREEZE_SECONDS_MIN, type FocusBounds, type FollowEvent, type FollowOptions, type FrameEntrance, type FrameGeometry, type FrameStyle, type FreezeExtent, type FreezeSpan, HOUSE_GRADIENT, IDLE_KINDS, type IdleKind, type IngestOptions, LAYOUT_FRAME_FIELDS, LOOK_KINDS, type LayoutParts, type Look, type LookBrand, type LookKind, type LookPlacement, type LowerProgramOptions, type LoweredAudioClip, type LoweredClick, type LoweredComposition, type LoweredZoomSpan, MEDIA_ENTER_KINDS, MEDIA_EXIT_KINDS, MEDIA_FRAME_KEYS, MINIMAL_BAR_THEMES, MOTION_DELTA, MOTION_EASE, type Media, type MediaFrame, type MediaFrameKey, type MediaOverlayClip, type MediaSegment, type MicRms, type MinimalBarTheme, type Moment, type MomentKind, type MomentsOptions, type MotionKey, type MotionPose, type MotionPose3D, type MusicBedInput, type NormRect, OBJECT_DEFAULT_SCALE, OVERLAY_FONT_FACES, OVERLAY_LINE_HEIGHT, OVERLAY_MEDIA_DEFAULT_RADIUS, OVERLAY_MEDIA_DEFAULT_WIDTH, OVERLAY_MIN_DURATION, OVERLAY_SCALE_MAX, OVERLAY_SIZE_MAX, OVERLAY_SIZE_MIN, OVERLAY_TRANSITION_DUR, OVERLAY_Z, type ObjectAnimation, type ObjectAsset, type ObjectClip, type ObjectPrimitiveShape, type OverlayClip, type OverlayFontFace, type OverlayKind, type OverlayPresetStyle, type OverlayRect, type OverlayTransform, type OverlayTransition, PLATE_GROUND, PLAYBACK_ACTIVITY, PRIMARY_MEDIA, PROGRAM_RETIME, type PlanOptions, type PlanTiltOptions, type PlaneSize, type ProgramAnchorDoc, type ProgramTweenEdit, type ProjectDoc, type PxRect, REJECT_OVERLAP, REST_TILT_ID, type RecordingArtifact, type RecordingMeta, type Rect, type RejectedLane, type RejectedSpan, type ResolvedOverlayBox, type ResolvedOverlayStyle, SCENE_MOTION, SCENE_QUIET, SPEED_RATE_MAX, SPEED_RATE_MIN, SPEED_SPAN_MIN, STAGE_CLIP_PREFIX, STILL_DEFAULT, STUDIO_ENTRY_ID, STYLE_FIELDS, type SmoothOptions, type SmoothPoint, type SpeedParams, type SpeedSpan, type StepAnchor, type StepSpan, type StudioAudioPlan, type StudioDoc, type StudioEntry, type StyleField, TEXT3D_DEPTH_DEFAULT, TEXT3D_DEPTH_MAX, TEXT3D_DEPTH_MIN, TEXT_ENTER_KINDS, TEXT_EXIT_KINDS, TEXT_PRESETS, TILT_AUTO_DEAD_ZONE, TILT_AUTO_MIN, TILT_CHAIN_GAP, TILT_DEG_MAX, TILT_EASE, TILT_INTENSITY_MAX, TILT_PAN, TILT_PAN_EASE, TILT_RAMP_IN, TILT_RAMP_OUT, TILT_SPAN_MIN, TILT_UI_DEG_MAX, TRANSITION_SPEED_MULT, type TemplateAnchor, type Text3dMaterial, type TextFxDirection, type TextFxKind, type TextFxSpec, type TextFxUnit, type TextOverlayBox, type TextOverlayClip, type TextOverlayPreset, type TextOverlayStroke, type TiltPersonality, type TiltSpan, type TiltStyleName, type TranscriptSegment, type TransitionSpeed, WINDOW_FOCUS_MIN, ZOOM_CHAIN_GAP, ZOOM_EASE, ZOOM_LEVELS, ZOOM_LEVEL_MAX, ZOOM_LEVEL_MIN, ZOOM_PAN, ZOOM_PAN_EASE, ZOOM_RAMP_IN, ZOOM_RAMP_IN_OVERLAP, ZOOM_RAMP_OUT, ZOOM_SPAN_MIN, ZOOM_STYLES, ZOOM_STYLE_OPTIONS, type ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomWindow, anchorKindOf, anchorSourceDuration, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, buildDigest, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipLength, clipsFrom, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cursorIdleFade, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, dropTemplate, duckCurve, effectiveSegments, endCardClips, enterKey, enterOf, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, focusBounds, followFocusEvents, frameGeometry, freezeLane, freezeOutputExtents, hexToRgbTriplet, houseLook, idleGaps, idleKey, isLookKind, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layoutOf, levelForFocusFraction, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaSource, micLane, migrateHostedDoc, migrateMotion, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parsePoseId, pickStyle, placeFreezes, planAutoSpeed, planAutoTilt, planAutoZoom, planForDigest, planeSizeAtDepth, platformBarKind, programDuration, projectFromArtifact, ratedSegments, recommendedExportResolution, refillAudioBeds, rejectSpan, removeSourceRange, removeSpeedInRange, resolveExportSize, resolveOverlayBox, resolveOverlayStyle, resolveText3dAsset, resolveZoomStyle, restLeanOf, sameMedia, sceneChanges, scrollRuns, setSpeedInRange, smoothCursor, spanOutputExtent, speedLane, studioAudioPlan, studioEntry, studioLayerData, tiltLane, tiltTrackFromDoc, transitionMult, videoLane, voiceKey, withBackdrop, withFreezes, withHolds, withoutRejected, wrapProgramLength, zoomCoversRect, zoomLane, zoomSpanForRange, zoomTrackFromDoc, zoomWindow };
|
|
3908
|
+
export { ASPECT_RATIOS, AUDIO_PLAN_STEP, type AnchorKind, type Anim, type AnimKind, type AnimStep, type AppliedTemplate, type ApplyTemplateOptions, type AspectRatioOption, type AudioClip, type AudioPlanPoint, type AudioPlanTrack, BACKGROUND_Z, BASE_FRAME_STYLE, type Backdrop, type BackgroundMedia, type BakedText3dAsset, type BakedText3dMaterial, type BrowserBarStyle, type BuildDigestInput, CAMERA_FAR, CAMERA_NEAR, CAM_CHAIN_GAP, CAM_EASE, CAM_PAN, CAM_PAN_EASE, CAM_RAMP_IN, CAM_RAMP_OUT, CAM_SIZE_MAX, CAM_SIZE_MIN, CAM_SPAN_MIN, CAPTURE_COVERAGE_MIN, CARD_EDGE_OVERDRAW, CARD_ENTER_KINDS, CARD_EXIT_KINDS, CARD_FADE_SECONDS, CARD_FOV, CARD_Z, CHANNEL_SPECS_HASH, CHANNEL_SPECS_VERIFIED, CLICK_FX_INTENSITY, CLICK_FX_PRE, CLICK_HIGHLIGHT_FADE, CLICK_PAIR_MAX, CLICK_PULSE_DUR, CLICK_RECT_MAX_FRAC, CLICK_RIPPLE_DUR, CLICK_SYNTH_RELEASE, CROP_MAX_PX, CROP_MIN_FRAC, CROP_MIN_PX, CROP_PAD, CURSOR_IDLE_EPS_FRAC, CURSOR_IDLE_FADE_IN, CURSOR_IDLE_FADE_OUT, CURSOR_IDLE_HOLD, type CamBubbleRect, type CamPoseSpan, type CamStyle, type CaptureNormalization, type CardLayout, type ClickFxStyle, type CopiedLayout, type CopyLayoutOptions, type CopyStyleOptions, type CursorEvent, type CursorFadeKey, type CursorIdleOptions, type CursorStyle, type CursorTrack, DARK_GROUND, DEFAULT_BROWSER_BAR, DEFAULT_CAM_POSE, DEFAULT_CAM_STYLE, DEFAULT_CLICK_FX, DEFAULT_CURSOR_STYLE, DEFAULT_DUCK, DEFAULT_FRAME_STYLE, DEFAULT_SPEED_PARAMS, DEFAULT_TILT_POSE, DEFAULT_ZOOM_LEVEL, DEFAULT_ZOOM_STYLE, DESTINATIONS, DIGEST_CROP_MAX, DIGEST_FULL_MAX, DIGEST_VERSION, DOC_SCHEMA_VERSION, DRAG_FIT_LEVEL, type Destination, type Digest, type DigestImageRef, type DigestPlan, type DigestTakeFacts, type DocSegment, type DuckOptions, END_CARD_FROM, END_CARD_RECEDE, END_CARD_SECONDS, ENTRANCE_SECONDS, EXPORT_RESOLUTION_OPTIONS, EXPORT_SHORT_EDGE, type EndCard, type EnvelopePoint, type ExportResolution, type ExtractClickOptions, FOLLOW_RECENTER, FOLLOW_SAFE_RATIO, FRAME_BORDER_COLOR_DEFAULT, FRAME_BORDER_DEFAULT, FRAME_BORDER_WIDTH_DEFAULT, FREEZE_DEFAULT_SECONDS, FREEZE_SECONDS_MAX, FREEZE_SECONDS_MIN, type FocusBounds, type FollowEvent, type FollowOptions, type FrameEntrance, type FrameGeometry, type FrameStyle, type FreezeExtent, type FreezeSpan, HOUSE_GRADIENT, IDLE_KINDS, type IdleKind, type IngestOptions, LAYER_CARD_SHADOW, LAYOUT_FRAME_FIELDS, LOOK_KINDS, type LayerCard, type LayoutParts, type Look, type LookBrand, type LookKind, type LookPlacement, type LowerProgramOptions, type LoweredAudioClip, type LoweredClick, type LoweredComposition, type LoweredZoomSpan, MEDIA_ENTER_KINDS, MEDIA_EXIT_KINDS, MEDIA_FRAME_KEYS, MEDIA_KEY_PREFIX, MINIMAL_BAR_THEMES, MOTION_DELTA, MOTION_EASE, type Media, type MediaFrame, type MediaFrameKey, type MediaOverlayClip, type MediaSegment, type MicRms, type MinimalBarTheme, type Moment, type MomentKind, type MomentsOptions, type MotionKey, type MotionPose, type MotionPose3D, type MusicBedInput, type NormRect, OBJECT_DEFAULT_SCALE, OVERLAY_FONT_FACES, OVERLAY_LINE_HEIGHT, OVERLAY_MEDIA_DEFAULT_RADIUS, OVERLAY_MEDIA_DEFAULT_WIDTH, OVERLAY_MIN_DURATION, OVERLAY_SCALE_MAX, OVERLAY_SIZE_MAX, OVERLAY_SIZE_MIN, OVERLAY_TRANSITION_DUR, OVERLAY_Z, type ObjectAnimation, type ObjectAsset, type ObjectClip, type ObjectPrimitiveShape, type OverlayClip, type OverlayFontFace, type OverlayKind, type OverlayPresetStyle, type OverlayRect, type OverlayTransform, type OverlayTransition, PLATE_GROUND, PLAYBACK_ACTIVITY, PRIMARY_MEDIA, PROGRAM_RETIME, type PlanOptions, type PlanTiltOptions, type PlaneSize, type ProgramAnchorDoc, type ProgramTweenEdit, type ProjectDoc, type PxRect, REJECT_OVERLAP, REST_TILT_ID, type RecordingArtifact, type RecordingMeta, type Rect, type RejectedLane, type RejectedSpan, type ResolvedOverlayBox, type ResolvedOverlayStyle, SCENE_MOTION, SCENE_QUIET, SPEED_RATE_MAX, SPEED_RATE_MIN, SPEED_SPAN_MIN, STAGE_CLIP_PREFIX, STILL_DEFAULT, STUDIO_ENTRY_ID, STYLE_FIELDS, type SmoothOptions, type SmoothPoint, type SpeedParams, type SpeedSpan, type StepAnchor, type StepSpan, type StudioAudioPlan, type StudioDoc, type StudioEntry, type StyleField, TEXT3D_DEPTH_DEFAULT, TEXT3D_DEPTH_MAX, TEXT3D_DEPTH_MIN, TEXT_ENTER_KINDS, TEXT_EXIT_KINDS, TEXT_PRESETS, TILT_AUTO_DEAD_ZONE, TILT_AUTO_MIN, TILT_CHAIN_GAP, TILT_DEG_MAX, TILT_EASE, TILT_INTENSITY_MAX, TILT_PAN, TILT_PAN_EASE, TILT_RAMP_IN, TILT_RAMP_OUT, TILT_SPAN_MIN, TILT_UI_DEG_MAX, TRANSITION_SPEED_MULT, type TemplateAnchor, type Text3dMaterial, type TextFxDirection, type TextFxKind, type TextFxSpec, type TextFxUnit, type TextOverlayBox, type TextOverlayClip, type TextOverlayPreset, type TextOverlayStroke, type TiltPersonality, type TiltSpan, type TiltStyleName, type TranscriptSegment, type TransitionSpeed, WINDOW_FOCUS_MIN, ZOOM_CHAIN_GAP, ZOOM_EASE, ZOOM_LEVELS, ZOOM_LEVEL_MAX, ZOOM_LEVEL_MIN, ZOOM_PAN, ZOOM_PAN_EASE, ZOOM_RAMP_IN, ZOOM_RAMP_IN_OVERLAP, ZOOM_RAMP_OUT, ZOOM_SPAN_MIN, ZOOM_STYLES, ZOOM_STYLE_OPTIONS, type ZoomSpan, type ZoomStyleName, type ZoomStyleParams, type ZoomWindow, anchorKindOf, anchorSourceDuration, animStep, applyLook, applyTemplate, aspectRatioValue, audioLane, backdropMedia, buildDigest, camBubbleRect, camBubbleRectAt, camLane, camMoveLane, camRectFromPose, camRestPose, camTrackFromDoc, cardEnter, cardExit, cardFields, cardInset, cardPointToScreen, cardPoseTrack, clampCamFrac, clampCamSize, clampFocus, clampFreezeSeconds, clampSpeedRate, clampTiltDeg, clampZoomLevel, clipEnvelope, clipLength, clipsFrom, computeCardLayout, computeMicRms, computePeaks, copyLayout, copyStyle, cropBox, cursorIdleFade, deriveViewportCrop, destinationById, destinationsForChannel, docCardLayout, docFreezes, docMediaList, docOutputDuration, docRestTime, docStillTime, docToCropSpace, docToFullSpace, dropTemplate, duckCurve, effectiveSegments, endCardClips, enterKey, enterOf, entranceSeconds, envelopeAt, envelopeValueAt, exitKey, exitOf, exitSeconds, expandEndCard, expectedFrameSize, exportSizeFor, extractClicks, focusBounds, followFocusEvents, frameGeometry, freezeLane, freezeOutputExtents, hexToRgbTriplet, houseLook, idleGaps, idleKey, isLookKind, isMusicBed, isPlayback, isProgramDoc, isRecordingDoc, isRejected, isStageClip, isUnitStep, lastLayerEnd, layerMedia, layoutOf, levelForFocusFraction, lookFromBrand, lookKindForGround, lowerProgramDoc, lowerStudioDoc, lowerToComposition, mediaAtOutput, mediaDuration, mediaFrame, mediaKey, mediaRef, mediaRefId, mediaSource, micLane, migrateHostedDoc, migrateMotion, momentsFromDoc, motionTrack, musicBedClip, nextMediaId, normalizeCaptureSpace, objectMotionBase, objectMotionPoseAt, objectsLane, outputDurationOf, outputEnd, outputRangeToSource, overlapFraction, overlayFaceFor, overlayFontFaces, overlayFontString, overlayFxSpec, overlayHit, overlayLines, overlayMotionBase, overlayMotionPoseAt, overlayRect, overlaysLane, ownFreezes, pageDisplayUrl, parsePoseId, pickStyle, placeFreezes, planAutoSpeed, planAutoTilt, planAutoZoom, planForDigest, planeSizeAtDepth, platformBarKind, programDuration, projectFromArtifact, ratedSegments, recommendedExportResolution, refillAudioBeds, rejectSpan, removeSourceRange, removeSpeedInRange, resolveExportSize, resolveOverlayBox, resolveOverlayStyle, resolveText3dAsset, resolveZoomStyle, restLeanOf, sameMedia, sceneChanges, scrollRuns, setSpeedInRange, smoothCursor, spanOutputExtent, speedLane, studioAudioPlan, studioEntry, studioLayerData, tiltLane, tiltTrackFromDoc, transitionMult, videoLane, voiceKey, withBackdrop, withFreezes, withHolds, withoutRejected, wrapProgramLength, zoomCoversRect, zoomLane, zoomSpanForRange, zoomTrackFromDoc, zoomWindow };
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,8 @@ function clipLength(clip) {
|
|
|
98
98
|
return clip.loop ? Math.max(span, clip.loopLen ?? span) : span;
|
|
99
99
|
}
|
|
100
100
|
var MOTION_EASE = "power2.inOut";
|
|
101
|
+
var LAYER_CARD_SHADOW = 0.32;
|
|
102
|
+
var MEDIA_KEY_PREFIX = "media:";
|
|
101
103
|
var OVERLAY_SCALE_MAX = 8;
|
|
102
104
|
var OVERLAY_MEDIA_DEFAULT_WIDTH = 0.35;
|
|
103
105
|
var OVERLAY_MEDIA_DEFAULT_RADIUS = 12;
|
|
@@ -582,6 +584,15 @@ function cardFields(frame) {
|
|
|
582
584
|
}
|
|
583
585
|
return out;
|
|
584
586
|
}
|
|
587
|
+
var mediaRef = (id) => MEDIA_KEY_PREFIX + id;
|
|
588
|
+
function mediaRefId(key) {
|
|
589
|
+
if (typeof key !== "string" || !key.startsWith(MEDIA_KEY_PREFIX)) return null;
|
|
590
|
+
return key.slice(MEDIA_KEY_PREFIX.length);
|
|
591
|
+
}
|
|
592
|
+
function layerMedia(doc, key) {
|
|
593
|
+
const id = mediaRefId(key);
|
|
594
|
+
return id === null ? null : mediaSource(doc, id);
|
|
595
|
+
}
|
|
585
596
|
function nextMediaId(doc) {
|
|
586
597
|
const taken = new Set((doc.media ?? []).map((m) => m.id));
|
|
587
598
|
let n = 1;
|
|
@@ -2698,6 +2709,8 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
2698
2709
|
// over its whole life, so it must repaint every visible frame \u2014 the
|
|
2699
2710
|
// signature alone would freeze it between edits (the olVisSig trap).
|
|
2700
2711
|
if (ol0.track) olAnim = true
|
|
2712
|
+
// A layer CARD is painted on its own plane every frame it is visible.
|
|
2713
|
+
if (ol0.card) olAnim = true
|
|
2701
2714
|
// Video overlays advance every frame; images redraw until decoded.
|
|
2702
2715
|
if (ol0.kind === 'video') olAnim = true
|
|
2703
2716
|
else if (ol0.kind === 'image') {
|
|
@@ -2707,6 +2720,76 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
2707
2720
|
}
|
|
2708
2721
|
var ovSig = W + 'x' + H + '|' + olVisSig
|
|
2709
2722
|
var ovDirty = ov.sig !== ovSig || ov.active || olAnim
|
|
2723
|
+
// The layer cards visible this frame, with their pose, for the card
|
|
2724
|
+
// planes below (the overlay loop collects them instead of painting).
|
|
2725
|
+
var lcList = []
|
|
2726
|
+
// Acquire a media overlay's element through the shared cache and sync it
|
|
2727
|
+
// to CLIP-LOCAL time (pure f(t); muted always \u2014 soundtracks belong to
|
|
2728
|
+
// doc.audio). Null until it has a frame to draw. One seam for the flat
|
|
2729
|
+
// picture and the layer card.
|
|
2730
|
+
function olAcquire(ol, olT) {
|
|
2731
|
+
var olEl = ns.videoCache ? ns.videoCache.get(ol.key) : null
|
|
2732
|
+
if (!olEl && ns.videoCache) {
|
|
2733
|
+
if (ol.kind === 'image') {
|
|
2734
|
+
olEl = new Image()
|
|
2735
|
+
olEl.crossOrigin = 'anonymous'
|
|
2736
|
+
olEl.src = ol.key
|
|
2737
|
+
} else {
|
|
2738
|
+
olEl = document.createElement('video')
|
|
2739
|
+
olEl.crossOrigin = 'anonymous'
|
|
2740
|
+
olEl.muted = true
|
|
2741
|
+
olEl.playsInline = true
|
|
2742
|
+
olEl.preload = 'auto'
|
|
2743
|
+
olEl.src = ol.key
|
|
2744
|
+
olEl.load()
|
|
2745
|
+
}
|
|
2746
|
+
ns.videoCache.set(ol.key, olEl)
|
|
2747
|
+
}
|
|
2748
|
+
if (!olEl) return null
|
|
2749
|
+
var olIsImg = ol.kind === 'image'
|
|
2750
|
+
if (!olIsImg && olEl.play) {
|
|
2751
|
+
var olDur = olEl.duration || 0
|
|
2752
|
+
var olMT = olT
|
|
2753
|
+
if (ol.loop && olDur > 0) olMT = olT % olDur
|
|
2754
|
+
else if (olDur > 0) olMT = Math.min(olT, olDur - 0.001)
|
|
2755
|
+
try {
|
|
2756
|
+
if (playing) {
|
|
2757
|
+
if (olEl.playbackRate !== 1) olEl.playbackRate = 1
|
|
2758
|
+
var olDrift = Math.abs(olEl.currentTime - olMT)
|
|
2759
|
+
if (olDur > 0 && !olEl.seeking && olDrift > 0.3 && (!ol.loop || olDur - olDrift > 0.3)) olEl.currentTime = olMT
|
|
2760
|
+
if (!ol.loop && olDur > 0 && olT >= olDur) { if (!olEl.paused) olEl.pause() }
|
|
2761
|
+
else if (olEl.paused) { var olP = olEl.play(); if (olP && olP.catch) olP.catch(function () {}) }
|
|
2762
|
+
} else {
|
|
2763
|
+
if (!olEl.paused) olEl.pause()
|
|
2764
|
+
var olTarget = Math.min(olMT, olEl.duration || olMT)
|
|
2765
|
+
// Coalesce scrub seeks (the backgroundMedia pattern): re-assigning
|
|
2766
|
+
// currentTime aborts the in-flight seek, so a per-frame scrub keeps
|
|
2767
|
+
// a remote source seeking forever. Defer until 'seeked' lands.
|
|
2768
|
+
if (olEl.readyState >= 1 && !olEl.seeking && Math.abs(olEl.currentTime - olTarget) > 0.02) {
|
|
2769
|
+
if (ns.pendingDecodes) {
|
|
2770
|
+
var olDp = new Promise(function (resolve) {
|
|
2771
|
+
var olDone = function () { olEl.removeEventListener('seeked', olDone); resolve() }
|
|
2772
|
+
olEl.addEventListener('seeked', olDone)
|
|
2773
|
+
setTimeout(olDone, 250)
|
|
2774
|
+
})
|
|
2775
|
+
ns.pendingDecodes.add(olDp)
|
|
2776
|
+
olDp.finally(function () { ns.pendingDecodes.delete(olDp) })
|
|
2777
|
+
}
|
|
2778
|
+
olEl.currentTime = olTarget
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
} catch (e) {}
|
|
2782
|
+
}
|
|
2783
|
+
// Video readiness is STICKY through seeks (the cam-bubble pattern):
|
|
2784
|
+
// readyState dips below HAVE_CURRENT_DATA while a scrub seek is in
|
|
2785
|
+
// flight, and this layer repaints every frame a video clip is visible \u2014
|
|
2786
|
+
// gating each frame on it would blink the clip out for the whole drag.
|
|
2787
|
+
// After the first decoded frame, keep drawing: Chrome paints the
|
|
2788
|
+
// element's retained frame mid-seek.
|
|
2789
|
+
if (!olIsImg && olEl.readyState >= 2) olEl.__vosHasFrame = true
|
|
2790
|
+
var olReady = olIsImg ? !!(olEl.complete && olEl.naturalWidth) : !!(olEl.readyState >= 2 || olEl.__vosHasFrame)
|
|
2791
|
+
return olReady ? olEl : null
|
|
2792
|
+
}
|
|
2710
2793
|
if (ovDirty) {
|
|
2711
2794
|
ovC.clearRect(0, 0, W, H)
|
|
2712
2795
|
// --- text overlays (compositor v2): OUTPUT-anchored clips, styles resolved
|
|
@@ -2764,71 +2847,19 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
2764
2847
|
if (olPose) olA *= Math.max(0, Math.min(1, olPose[4]))
|
|
2765
2848
|
if (olA <= 0.004) continue
|
|
2766
2849
|
if (ol.kind === 'image' || ol.kind === 'video') {
|
|
2850
|
+
// A layer CARD is painted by the card painter on its own plane, below:
|
|
2851
|
+
// collect it with its pose and skip the flat picture.
|
|
2852
|
+
if (ol.card) {
|
|
2853
|
+
lcList.push({ ol: ol, t: olT, a: olA * (ol.opacity == null ? 1 : ol.opacity), x: olMX, y: olMY, s: olMS, r: olMR, yof: olYof })
|
|
2854
|
+
continue
|
|
2855
|
+
}
|
|
2767
2856
|
// Media overlay: lazy-acquire through the shared cache (SET_DATA-added
|
|
2768
2857
|
// clips load without a LOAD \u2014 the backgroundMedia pattern), sync video
|
|
2769
2858
|
// to CLIP-LOCAL time (pure f(t)), draw a rounded media card centered on
|
|
2770
2859
|
// the fraction anchor. Muted always \u2014 soundtracks belong to doc.audio.
|
|
2771
|
-
var olEl =
|
|
2772
|
-
if (!olEl && ns.videoCache) {
|
|
2773
|
-
if (ol.kind === 'image') {
|
|
2774
|
-
olEl = new Image()
|
|
2775
|
-
olEl.crossOrigin = 'anonymous'
|
|
2776
|
-
olEl.src = ol.key
|
|
2777
|
-
} else {
|
|
2778
|
-
olEl = document.createElement('video')
|
|
2779
|
-
olEl.crossOrigin = 'anonymous'
|
|
2780
|
-
olEl.muted = true
|
|
2781
|
-
olEl.playsInline = true
|
|
2782
|
-
olEl.preload = 'auto'
|
|
2783
|
-
olEl.src = ol.key
|
|
2784
|
-
olEl.load()
|
|
2785
|
-
}
|
|
2786
|
-
ns.videoCache.set(ol.key, olEl)
|
|
2787
|
-
}
|
|
2860
|
+
var olEl = olAcquire(ol, olT)
|
|
2788
2861
|
if (!olEl) continue
|
|
2789
2862
|
var olIsImg = ol.kind === 'image'
|
|
2790
|
-
if (!olIsImg && olEl.play) {
|
|
2791
|
-
var olDur = olEl.duration || 0
|
|
2792
|
-
var olMT = olT
|
|
2793
|
-
if (ol.loop && olDur > 0) olMT = olT % olDur
|
|
2794
|
-
else if (olDur > 0) olMT = Math.min(olT, olDur - 0.001)
|
|
2795
|
-
try {
|
|
2796
|
-
if (playing) {
|
|
2797
|
-
if (olEl.playbackRate !== 1) olEl.playbackRate = 1
|
|
2798
|
-
var olDrift = Math.abs(olEl.currentTime - olMT)
|
|
2799
|
-
if (olDur > 0 && !olEl.seeking && olDrift > 0.3 && (!ol.loop || olDur - olDrift > 0.3)) olEl.currentTime = olMT
|
|
2800
|
-
if (!ol.loop && olDur > 0 && olT >= olDur) { if (!olEl.paused) olEl.pause() }
|
|
2801
|
-
else if (olEl.paused) { var olP = olEl.play(); if (olP && olP.catch) olP.catch(function () {}) }
|
|
2802
|
-
} else {
|
|
2803
|
-
if (!olEl.paused) olEl.pause()
|
|
2804
|
-
var olTarget = Math.min(olMT, olEl.duration || olMT)
|
|
2805
|
-
// Coalesce scrub seeks (the backgroundMedia pattern): re-assigning
|
|
2806
|
-
// currentTime aborts the in-flight seek, so a per-frame scrub keeps
|
|
2807
|
-
// a remote source seeking forever. Defer until 'seeked' lands.
|
|
2808
|
-
if (olEl.readyState >= 1 && !olEl.seeking && Math.abs(olEl.currentTime - olTarget) > 0.02) {
|
|
2809
|
-
if (ns.pendingDecodes) {
|
|
2810
|
-
var olDp = new Promise(function (resolve) {
|
|
2811
|
-
var olDone = function () { olEl.removeEventListener('seeked', olDone); resolve() }
|
|
2812
|
-
olEl.addEventListener('seeked', olDone)
|
|
2813
|
-
setTimeout(olDone, 250)
|
|
2814
|
-
})
|
|
2815
|
-
ns.pendingDecodes.add(olDp)
|
|
2816
|
-
olDp.finally(function () { ns.pendingDecodes.delete(olDp) })
|
|
2817
|
-
}
|
|
2818
|
-
olEl.currentTime = olTarget
|
|
2819
|
-
}
|
|
2820
|
-
}
|
|
2821
|
-
} catch (e) {}
|
|
2822
|
-
}
|
|
2823
|
-
// Video readiness is STICKY through seeks (the cam-bubble pattern):
|
|
2824
|
-
// readyState dips below HAVE_CURRENT_DATA while a scrub seek is in
|
|
2825
|
-
// flight, and this layer repaints every frame a video clip is visible \u2014
|
|
2826
|
-
// gating each frame on it would blink the clip out for the whole drag.
|
|
2827
|
-
// After the first decoded frame, keep drawing: Chrome paints the
|
|
2828
|
-
// element's retained frame mid-seek.
|
|
2829
|
-
if (!olIsImg && olEl.readyState >= 2) olEl.__vosHasFrame = true
|
|
2830
|
-
var olReady = olIsImg ? !!(olEl.complete && olEl.naturalWidth) : !!(olEl.readyState >= 2 || olEl.__vosHasFrame)
|
|
2831
|
-
if (!olReady) continue
|
|
2832
2863
|
var olNW = (olIsImg ? olEl.naturalWidth : olEl.videoWidth) || 16
|
|
2833
2864
|
var olNH = (olIsImg ? olEl.naturalHeight : olEl.videoHeight) || 9
|
|
2834
2865
|
var olDW = ol.w * W * olMS
|
|
@@ -3340,6 +3371,194 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
3340
3371
|
}
|
|
3341
3372
|
obM.scale.setScalar(obPS * obRefH * (obE.norm || 1))
|
|
3342
3373
|
}
|
|
3374
|
+
// --- layer cards (many cards): a media overlay that names a frame is
|
|
3375
|
+
// drawn by the card painter on its OWN plane in the prop group
|
|
3376
|
+
// (renderOrder 1.25: above the primary card, below the props): the
|
|
3377
|
+
// layered shadow (the primary's table and strengths), the media clipped
|
|
3378
|
+
// to its corners, the browser bar after it, the border, and for a
|
|
3379
|
+
// document media its click rings and cursor dot inside the card, at
|
|
3380
|
+
// clip-local time. Chrome scales WITH the card (a smaller window has
|
|
3381
|
+
// smaller chrome), the way the primary's scales with cf. The plane is
|
|
3382
|
+
// sized to the canvas at the card depth, placed at the clip's anchor,
|
|
3383
|
+
// leaned by the card's own rx/ry (the tilt convention) and turned by the
|
|
3384
|
+
// clip's rotation. Locals lc*.
|
|
3385
|
+
var lcC = obC.cards || (obC.cards = new Map())
|
|
3386
|
+
var lcSeen = {}
|
|
3387
|
+
var lcK = obRefH / H
|
|
3388
|
+
for (var lci = 0; lci < lcList.length; lci++) {
|
|
3389
|
+
var lcI = lcList[lci], lcO = lcI.ol, lcCard = lcO.card
|
|
3390
|
+
var lcEl = olAcquire(lcO, lcI.t)
|
|
3391
|
+
if (!lcEl) continue
|
|
3392
|
+
lcSeen[lcO.id] = true
|
|
3393
|
+
var lcE = lcC.get(lcO.id)
|
|
3394
|
+
if (!lcE) {
|
|
3395
|
+
var lcCv = document.createElement('canvas')
|
|
3396
|
+
var lcTx = new THREE3.CanvasTexture(lcCv)
|
|
3397
|
+
if (THREE3.SRGBColorSpace) lcTx.colorSpace = THREE3.SRGBColorSpace
|
|
3398
|
+
if (THREE3.LinearFilter) { lcTx.minFilter = THREE3.LinearFilter; lcTx.magFilter = THREE3.LinearFilter }
|
|
3399
|
+
lcTx.generateMipmaps = false
|
|
3400
|
+
var lcM = new THREE3.Mesh(new THREE3.PlaneGeometry(1, 1), new THREE3.MeshBasicMaterial({ map: lcTx, transparent: true, depthTest: false, depthWrite: false }))
|
|
3401
|
+
lcM.renderOrder = 1.25
|
|
3402
|
+
lcM.frustumCulled = false
|
|
3403
|
+
obC.group.add(lcM)
|
|
3404
|
+
lcE = { mesh: lcM, canvas: lcCv, c2d: lcCv.getContext('2d'), texture: lcTx }
|
|
3405
|
+
lcC.set(lcO.id, lcE)
|
|
3406
|
+
}
|
|
3407
|
+
var lcIsImg = lcO.kind === 'image'
|
|
3408
|
+
var lcCrop = lcO.crop || null
|
|
3409
|
+
var lcNW = lcCrop ? lcCrop.w : ((lcIsImg ? lcEl.naturalWidth : lcEl.videoWidth) || 16)
|
|
3410
|
+
var lcNH = lcCrop ? lcCrop.h : ((lcIsImg ? lcEl.naturalHeight : lcEl.videoHeight) || 9)
|
|
3411
|
+
var lcW = Math.max(2, lcO.w * W * lcI.s)
|
|
3412
|
+
var lcS = s * (lcW / W)
|
|
3413
|
+
var lcBar = lcCard.bar || {}
|
|
3414
|
+
var lcBarH = lcBar.kind && lcBar.kind !== 'none' ? (lcBar.height || 44) * lcS : 0
|
|
3415
|
+
var lcMH = lcW * (lcNH / lcNW)
|
|
3416
|
+
var lcH = lcMH + lcBarH
|
|
3417
|
+
var lcRad = Math.min((lcO.radius || 0) * lcS, lcH / 2)
|
|
3418
|
+
var lcMg = Math.ceil(170 * lcS)
|
|
3419
|
+
var lcCW = Math.ceil(lcW + 2 * lcMg), lcCH = Math.ceil(lcH + 2 * lcMg)
|
|
3420
|
+
var lcCv2 = lcE.canvas, lcX = lcE.c2d
|
|
3421
|
+
if (lcCv2.width !== lcCW || lcCv2.height !== lcCH) { lcCv2.width = lcCW; lcCv2.height = lcCH }
|
|
3422
|
+
lcX.clearRect(0, 0, lcCW, lcCH)
|
|
3423
|
+
var lcX0 = lcMg, lcY0 = lcMg
|
|
3424
|
+
var lcSh = lcCard.shadow == null ? ${LAYER_CARD_SHADOW} : lcCard.shadow
|
|
3425
|
+
var lcRgb = '0,0,0'
|
|
3426
|
+
var lcHex = lcCard.shadowColor
|
|
3427
|
+
if (typeof lcHex === 'string' && /^#[0-9a-fA-F]{6}$/.test(lcHex)) lcRgb = parseInt(lcHex.slice(1, 3), 16) + ',' + parseInt(lcHex.slice(3, 5), 16) + ',' + parseInt(lcHex.slice(5, 7), 16)
|
|
3428
|
+
// the shadows are cast by a body drawn off the canvas and brought back
|
|
3429
|
+
// by shadowOffsetX (the primary's seam rule)
|
|
3430
|
+
var lcD = lcCW * 2 + lcCH * 2
|
|
3431
|
+
if (lcSh > 0) {
|
|
3432
|
+
var lcL = [[2, 1, 0.1], [12, 4, 0.1], [40, 16, 0.14], [120, 44, 0.3]]
|
|
3433
|
+
for (var lcj = 0; lcj < lcL.length; lcj++) {
|
|
3434
|
+
lcX.save()
|
|
3435
|
+
lcX.shadowColor = 'rgba(' + lcRgb + ',' + +(lcSh * lcL[lcj][2]).toFixed(3) + ')'
|
|
3436
|
+
lcX.shadowBlur = lcL[lcj][0] * lcS; lcX.shadowOffsetX = lcD; lcX.shadowOffsetY = lcL[lcj][1] * lcS
|
|
3437
|
+
lcX.fillStyle = '#000'
|
|
3438
|
+
rr(lcX0 - lcD, lcY0, lcW, lcH, lcRad, lcX); lcX.fill()
|
|
3439
|
+
lcX.restore()
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
if (lcCard.shadowContact > 0) {
|
|
3443
|
+
lcX.save()
|
|
3444
|
+
lcX.shadowColor = 'rgba(' + lcRgb + ',' + lcCard.shadowContact + ')'
|
|
3445
|
+
lcX.shadowBlur = 10 * lcS; lcX.shadowOffsetX = lcD; lcX.shadowOffsetY = 3 * lcS
|
|
3446
|
+
lcX.fillStyle = '#000'
|
|
3447
|
+
rr(lcX0 - lcD, lcY0, lcW, lcH, lcRad, lcX); lcX.fill()
|
|
3448
|
+
lcX.restore()
|
|
3449
|
+
}
|
|
3450
|
+
lcX.save()
|
|
3451
|
+
rr(lcX0, lcY0, lcW, lcH, lcRad, lcX); lcX.clip()
|
|
3452
|
+
var lcMY = lcY0 + lcBarH
|
|
3453
|
+
try {
|
|
3454
|
+
if (lcCrop) lcX.drawImage(lcEl, lcCrop.x, lcCrop.y, lcCrop.w, lcCrop.h, lcX0, lcMY, lcW, lcMH)
|
|
3455
|
+
else lcX.drawImage(lcEl, lcX0, lcMY, lcW, lcMH)
|
|
3456
|
+
} catch (e) {}
|
|
3457
|
+
if (lcBarH > 0) {
|
|
3458
|
+
var lcDark = lcBar.kind.indexOf('dark') >= 0, lcMin = lcBar.kind === 'minimal'
|
|
3459
|
+
var lcThm = (lcMin && lcBar.theme) || null
|
|
3460
|
+
lcX.fillStyle = lcMin ? (lcThm ? lcThm.bar : '#141417') : lcDark ? '#2a2a2e' : '#e9e9eb'
|
|
3461
|
+
lcX.fillRect(lcX0, lcY0, lcW, lcBarH)
|
|
3462
|
+
lcX.fillStyle = lcDark || (lcMin && !(lcThm && lcThm.light)) ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)'
|
|
3463
|
+
lcX.fillRect(lcX0, lcY0 + lcBarH - lcS, lcW, lcS)
|
|
3464
|
+
var lcMid = lcY0 + lcBarH / 2
|
|
3465
|
+
if (lcBar.showControls !== false && !lcMin) {
|
|
3466
|
+
if (lcBar.kind.indexOf('mac') === 0) {
|
|
3467
|
+
var lcLights = ['#ff5f57', '#febc2e', '#28c840']
|
|
3468
|
+
for (var lcl = 0; lcl < 3; lcl++) { lcX.fillStyle = lcLights[lcl]; lcX.beginPath(); lcX.arc(lcX0 + (20 + lcl * 20) * lcS, lcMid, 6 * lcS, 0, Math.PI * 2); lcX.fill() }
|
|
3469
|
+
} else {
|
|
3470
|
+
lcX.strokeStyle = lcDark ? 'rgba(255,255,255,0.75)' : 'rgba(0,0,0,0.6)'
|
|
3471
|
+
lcX.lineWidth = 1.5 * lcS
|
|
3472
|
+
var lcG = 4.5 * lcS, lcGx = lcX0 + lcW - 22 * lcS
|
|
3473
|
+
lcX.beginPath(); lcX.moveTo(lcGx - lcG, lcMid - lcG); lcX.lineTo(lcGx + lcG, lcMid + lcG); lcX.moveTo(lcGx + lcG, lcMid - lcG); lcX.lineTo(lcGx - lcG, lcMid + lcG); lcX.stroke()
|
|
3474
|
+
lcX.strokeRect(lcGx - 28 * lcS - lcG, lcMid - lcG, lcG * 2, lcG * 2)
|
|
3475
|
+
lcX.beginPath(); lcX.moveTo(lcGx - 56 * lcS - lcG, lcMid); lcX.lineTo(lcGx - 56 * lcS + lcG, lcMid); lcX.stroke()
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
if (lcBar.showUrl !== false && lcBar.url) {
|
|
3479
|
+
var lcPW = Math.min(lcW * 0.5, Math.max(200 * lcS, lcW * 0.34)), lcPH = lcBarH - 16 * lcS
|
|
3480
|
+
var lcPx = lcX0 + (lcW - lcPW) / 2, lcPy = lcY0 + 8 * lcS
|
|
3481
|
+
lcX.fillStyle = lcMin ? (lcThm ? lcThm.pill : '#26262b') : lcDark ? '#1d1d20' : '#ffffff'
|
|
3482
|
+
rr(lcPx, lcPy, lcPW, lcPH, lcPH / 2, lcX); lcX.fill()
|
|
3483
|
+
lcX.fillStyle = lcMin ? (lcThm ? lcThm.text : '#9a9aa1') : lcDark ? '#a1a1a6' : '#5f5f64'
|
|
3484
|
+
lcX.font = 13 * lcS + 'px -apple-system, system-ui, sans-serif'
|
|
3485
|
+
lcX.textAlign = 'center'; lcX.textBaseline = 'middle'
|
|
3486
|
+
var lcLabel = String(lcBar.url), lcMaxW = lcPW - 28 * lcS
|
|
3487
|
+
if (lcX.measureText(lcLabel).width > lcMaxW) {
|
|
3488
|
+
while (lcLabel.length > 1 && lcX.measureText(lcLabel + '\u2026').width > lcMaxW) lcLabel = lcLabel.slice(0, -1)
|
|
3489
|
+
lcLabel += '\u2026'
|
|
3490
|
+
}
|
|
3491
|
+
lcX.fillText(lcLabel, lcPx + lcPW / 2, lcPy + lcPH / 2)
|
|
3492
|
+
lcX.textAlign = 'start'; lcX.textBaseline = 'alphabetic'
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
// the media's facts: click rings and the cursor dot, video-anchored,
|
|
3496
|
+
// at clip-local time
|
|
3497
|
+
var lcCu = lcO.cur
|
|
3498
|
+
if (lcCu && lcCu.pts && lcCu.pts.length) {
|
|
3499
|
+
var lcSp = lcCu.space || { w: lcNW, h: lcNH }
|
|
3500
|
+
var lcSize = (lcCu.size || 24) * lcS * 0.5
|
|
3501
|
+
var lcT = lcI.t
|
|
3502
|
+
var lcCks = lcCu.clicks || []
|
|
3503
|
+
for (var lcc = 0; lcc < lcCks.length; lcc++) {
|
|
3504
|
+
var lcCk = lcCks[lcc]
|
|
3505
|
+
var lcAge = lcT - lcCk.t
|
|
3506
|
+
if (lcAge < -0.08 || lcAge > 0.6) continue
|
|
3507
|
+
var lcU = Math.max(0, Math.min(1, (lcAge + 0.08) / 0.68))
|
|
3508
|
+
var lcFade = 1 - Math.pow(1 - lcU, 3)
|
|
3509
|
+
lcX.save()
|
|
3510
|
+
lcX.strokeStyle = 'rgba(255,255,255,' + (0.9 * (1 - lcU)) + ')'
|
|
3511
|
+
lcX.lineWidth = Math.max(1, 3 * lcS * (1 - lcU * 0.6))
|
|
3512
|
+
lcX.beginPath(); lcX.arc(lcX0 + (lcCk.x / (lcSp.w || lcNW)) * lcW, lcMY + (lcCk.y / (lcSp.h || lcNH)) * lcMH, lcSize * 0.8 + lcFade * 44 * lcS, 0, Math.PI * 2); lcX.stroke()
|
|
3513
|
+
lcX.restore()
|
|
3514
|
+
}
|
|
3515
|
+
var lcPts = lcCu.pts, lcPX = lcPts[0].x, lcPY = lcPts[0].y
|
|
3516
|
+
for (var lcp = 0; lcp < lcPts.length; lcp++) { if (lcPts[lcp].t <= lcT) { lcPX = lcPts[lcp].x; lcPY = lcPts[lcp].y } }
|
|
3517
|
+
lcX.save()
|
|
3518
|
+
lcX.fillStyle = 'rgba(255,255,255,0.95)'; lcX.strokeStyle = 'rgba(0,0,0,0.4)'; lcX.lineWidth = 2 * lcS
|
|
3519
|
+
lcX.beginPath(); lcX.arc(lcX0 + (lcPX / (lcSp.w || lcNW)) * lcW, lcMY + (lcPY / (lcSp.h || lcNH)) * lcMH, lcSize, 0, Math.PI * 2); lcX.fill(); lcX.stroke()
|
|
3520
|
+
lcX.restore()
|
|
3521
|
+
}
|
|
3522
|
+
lcX.restore()
|
|
3523
|
+
if (lcO.border && lcO.border.width > 0) {
|
|
3524
|
+
var lcBW = lcO.border.width * lcS
|
|
3525
|
+
lcX.save(); lcX.strokeStyle = lcO.border.color || '#fff'; lcX.lineWidth = lcBW
|
|
3526
|
+
rr(lcX0 - lcBW / 2, lcY0 - lcBW / 2, lcW + lcBW, lcH + lcBW, lcRad > 0 ? lcRad + lcBW / 2 : 0, lcX); lcX.stroke()
|
|
3527
|
+
lcX.restore()
|
|
3528
|
+
}
|
|
3529
|
+
lcE.texture.needsUpdate = true
|
|
3530
|
+
var lcM2 = lcE.mesh
|
|
3531
|
+
lcM2.visible = true
|
|
3532
|
+
if (lcM2.material) lcM2.material.opacity = lcI.a
|
|
3533
|
+
var lcLean = lcCard.lean || [0, 0]
|
|
3534
|
+
var lcRx = (lcLean[0] || 0) * Math.PI / 180, lcRy = (lcLean[1] || 0) * Math.PI / 180, lcRz = -(lcI.r || 0) * Math.PI / 180
|
|
3535
|
+
var lcPlW = lcCW * lcK, lcPlH = lcCH * lcK
|
|
3536
|
+
var lcWX = (lcI.x - 0.5) * obRefH * obAspect
|
|
3537
|
+
var lcWY = -(lcI.y - 0.5) * obRefH - lcI.yof * lcK
|
|
3538
|
+
if (obOrtho) {
|
|
3539
|
+
lcM2.position.set((obOCX + (lcI.x - 0.5) * obOW) / obAX, obOCY - (lcI.y - 0.5) * obOH, -obOD)
|
|
3540
|
+
obB.e.set(lcRx, lcRy, lcRz); lcM2.quaternion.setFromEuler(obB.e)
|
|
3541
|
+
} else if (obB) {
|
|
3542
|
+
lcM2.position.copy(obCam.position).addScaledVector(obB.f, Math.abs(${CARD_Z}) - 0.01).addScaledVector(obB.r, lcWX).addScaledVector(obB.u, lcWY)
|
|
3543
|
+
obB.e.set(lcRx, lcRy, lcRz); lcM2.quaternion.copy(obCam.quaternion).multiply(obB.q.setFromEuler(obB.e))
|
|
3544
|
+
} else {
|
|
3545
|
+
lcM2.position.set(lcWX, lcWY, ${CARD_Z} + 0.01)
|
|
3546
|
+
lcM2.rotation.set(lcRx, lcRy, lcRz)
|
|
3547
|
+
}
|
|
3548
|
+
lcM2.scale.set(lcPlW, lcPlH, 1)
|
|
3549
|
+
}
|
|
3550
|
+
// A card off screen rests; one gone from the data is disposed.
|
|
3551
|
+
lcC.forEach(function (lcE2, lcId) {
|
|
3552
|
+
if (lcSeen[lcId]) return
|
|
3553
|
+
var lcStill = false
|
|
3554
|
+
for (var lcq = 0; lcq < ols.length; lcq++) if (ols[lcq].id === lcId && ols[lcq].card) lcStill = true
|
|
3555
|
+
if (lcStill) { lcE2.mesh.visible = false; return }
|
|
3556
|
+
obC.group.remove(lcE2.mesh)
|
|
3557
|
+
if (lcE2.mesh.geometry && lcE2.mesh.geometry.dispose) lcE2.mesh.geometry.dispose()
|
|
3558
|
+
if (lcE2.mesh.material && lcE2.mesh.material.dispose) lcE2.mesh.material.dispose()
|
|
3559
|
+
if (lcE2.texture && lcE2.texture.dispose) lcE2.texture.dispose()
|
|
3560
|
+
lcC.delete(lcId)
|
|
3561
|
+
})
|
|
3343
3562
|
// Dispose props no longer in the data (live removal).
|
|
3344
3563
|
obC.pool.forEach(function (obE2, obId) {
|
|
3345
3564
|
if (!obSeen[obId]) {
|
|
@@ -5118,6 +5337,7 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
5118
5337
|
}
|
|
5119
5338
|
}`;
|
|
5120
5339
|
function studioLayerData(layers, duration) {
|
|
5340
|
+
const rec = "source" in layers ? layers : null;
|
|
5121
5341
|
return {
|
|
5122
5342
|
// Music/SFX clips with their gain envelopes baked (shared truth for the
|
|
5123
5343
|
// preview scheduler and the export's offline mix). `duckEnv` (the mic-derived
|
|
@@ -5205,9 +5425,60 @@ function studioLayerData(layers, duration) {
|
|
|
5205
5425
|
})()
|
|
5206
5426
|
};
|
|
5207
5427
|
if (o.kind !== "text") {
|
|
5428
|
+
const lm = rec ? layerMedia(rec, o.key) : null;
|
|
5429
|
+
const lmImage = lm ? lm.sourceKind === "image" : o.kind === "image";
|
|
5430
|
+
const lmCard = o.frame ? {
|
|
5431
|
+
bar: {
|
|
5432
|
+
kind: o.frame.browserBar?.kind ?? "none",
|
|
5433
|
+
url: o.frame.browserBar?.url ?? (lm ? pageDisplayUrl(lm.meta.pageUrl) : ""),
|
|
5434
|
+
showUrl: o.frame.browserBar?.showUrl ?? true,
|
|
5435
|
+
showControls: o.frame.browserBar?.showControls ?? true,
|
|
5436
|
+
height: o.frame.browserBar?.height ?? 44,
|
|
5437
|
+
...o.frame.browserBar?.theme ? { theme: o.frame.browserBar.theme } : {}
|
|
5438
|
+
},
|
|
5439
|
+
lean: [
|
|
5440
|
+
round6(o.frame.lean?.rx ?? 0),
|
|
5441
|
+
round6(o.frame.lean?.ry ?? 0)
|
|
5442
|
+
],
|
|
5443
|
+
shadow: o.frame.shadow ?? LAYER_CARD_SHADOW,
|
|
5444
|
+
shadowContact: o.frame.shadowContact ?? 0,
|
|
5445
|
+
...o.frame.shadowColor ? { shadowColor: o.frame.shadowColor } : {}
|
|
5446
|
+
} : null;
|
|
5447
|
+
const lmFacts = lm && o.frame && o.frame.cursor !== false && lm.cursor.length ? (() => {
|
|
5448
|
+
const lfx = rec.cursor.clickFx;
|
|
5449
|
+
const sm = smoothCursor(lm.cursor, {
|
|
5450
|
+
factor: rec.cursor.smoothing,
|
|
5451
|
+
clickSnap: lfx.style !== "none" || lfx.press
|
|
5452
|
+
});
|
|
5453
|
+
const clicks = [];
|
|
5454
|
+
for (const ev of lm.cursor) {
|
|
5455
|
+
if (ev.type === "down")
|
|
5456
|
+
clicks.push({
|
|
5457
|
+
t: round6(ev.t / 1e3),
|
|
5458
|
+
x: round6(ev.x),
|
|
5459
|
+
y: round6(ev.y)
|
|
5460
|
+
});
|
|
5461
|
+
}
|
|
5462
|
+
return {
|
|
5463
|
+
cur: {
|
|
5464
|
+
pts: sm.map((p) => ({
|
|
5465
|
+
t: round6(p.t),
|
|
5466
|
+
x: round6(p.x),
|
|
5467
|
+
y: round6(p.y)
|
|
5468
|
+
})),
|
|
5469
|
+
space: { w: lm.meta.width, h: lm.meta.height },
|
|
5470
|
+
size: rec.cursor.size,
|
|
5471
|
+
clicks
|
|
5472
|
+
}
|
|
5473
|
+
};
|
|
5474
|
+
})() : {};
|
|
5208
5475
|
return {
|
|
5209
5476
|
...base,
|
|
5210
|
-
|
|
5477
|
+
...lm ? { kind: lmImage ? "image" : "video" } : {},
|
|
5478
|
+
key: lm ? lm.videoKey : o.key,
|
|
5479
|
+
...lm && lm.crop ? { crop: lm.crop } : {},
|
|
5480
|
+
...lmCard ? { card: lmCard } : {},
|
|
5481
|
+
...lmFacts,
|
|
5211
5482
|
w: round6(o.width ?? OVERLAY_MEDIA_DEFAULT_WIDTH),
|
|
5212
5483
|
radius: o.radius ?? OVERLAY_MEDIA_DEFAULT_RADIUS,
|
|
5213
5484
|
opacity: o.opacity ?? 1,
|
|
@@ -8522,11 +8793,13 @@ export {
|
|
|
8522
8793
|
FREEZE_SECONDS_MIN,
|
|
8523
8794
|
HOUSE_GRADIENT,
|
|
8524
8795
|
IDLE_KINDS,
|
|
8796
|
+
LAYER_CARD_SHADOW,
|
|
8525
8797
|
LAYOUT_FRAME_FIELDS,
|
|
8526
8798
|
LOOK_KINDS,
|
|
8527
8799
|
MEDIA_ENTER_KINDS,
|
|
8528
8800
|
MEDIA_EXIT_KINDS,
|
|
8529
8801
|
MEDIA_FRAME_KEYS,
|
|
8802
|
+
MEDIA_KEY_PREFIX,
|
|
8530
8803
|
MINIMAL_BAR_THEMES,
|
|
8531
8804
|
MOTION_DELTA,
|
|
8532
8805
|
MOTION_EASE,
|
|
@@ -8673,6 +8946,7 @@ export {
|
|
|
8673
8946
|
isStageClip,
|
|
8674
8947
|
isUnitStep,
|
|
8675
8948
|
lastLayerEnd,
|
|
8949
|
+
layerMedia,
|
|
8676
8950
|
layoutOf,
|
|
8677
8951
|
levelForFocusFraction,
|
|
8678
8952
|
lookFromBrand,
|
|
@@ -8684,6 +8958,8 @@ export {
|
|
|
8684
8958
|
mediaDuration,
|
|
8685
8959
|
mediaFrame,
|
|
8686
8960
|
mediaKey,
|
|
8961
|
+
mediaRef,
|
|
8962
|
+
mediaRefId,
|
|
8687
8963
|
mediaSource,
|
|
8688
8964
|
micLane,
|
|
8689
8965
|
migrateHostedDoc,
|