@remotion/studio 4.0.482 → 4.0.483

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.
Files changed (34) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/InspectorPanel/styles.js +2 -0
  3. package/dist/components/InspectorSequenceSection.js +45 -2
  4. package/dist/components/SelectedOutlineUvControls.js +461 -2
  5. package/dist/components/Timeline/EasingEditorModal.js +39 -1
  6. package/dist/components/Timeline/Timeline.js +2 -1
  7. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  8. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  9. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  10. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  11. package/dist/components/Timeline/TimelineSelection.d.ts +7 -1
  12. package/dist/components/Timeline/TimelineSelection.js +19 -3
  13. package/dist/components/Timeline/TimelineSequence.js +20 -8
  14. package/dist/components/Timeline/TimelineSequenceItem.js +16 -13
  15. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  16. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  17. package/dist/components/Timeline/TimelineTrack.js +2 -4
  18. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  19. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  20. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  21. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  22. package/dist/components/element-drag-and-drop.d.ts +3 -0
  23. package/dist/components/element-drag-and-drop.js +30 -0
  24. package/dist/components/import-assets.d.ts +11 -0
  25. package/dist/components/import-assets.js +23 -1
  26. package/dist/components/selected-outline-uv.d.ts +71 -1
  27. package/dist/components/selected-outline-uv.js +332 -10
  28. package/dist/esm/{chunk-nkqfa5bw.js → chunk-fq0j774v.js} +2191 -817
  29. package/dist/esm/internals.mjs +2191 -817
  30. package/dist/esm/previewEntry.mjs +2201 -827
  31. package/dist/esm/renderEntry.mjs +1 -1
  32. package/dist/helpers/timeline-layout.d.ts +3 -3
  33. package/dist/helpers/timeline-layout.js +3 -1
  34. package/package.json +11 -11
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSelectedUvHandles = exports.getUvCoordinateForPoint = exports.getUvHandleConnectionLines = exports.getUvHandlePosition = exports.tuplesEqual = void 0;
3
+ exports.getSelectedUvHandles = exports.roundNumericUvEllipseValue = exports.getUvCoordinateForPoint = exports.getUvEllipseInteractiveControls = exports.getUvHandleConnectionEllipses = exports.getUvHandleConnectionLines = exports.getUvHandlePosition = exports.tuplesEqual = void 0;
4
4
  exports.constrainUv = constrainUv;
5
5
  exports.roundUvCoordinate = roundUvCoordinate;
6
6
  const remotion_1 = require("remotion");
@@ -14,6 +14,76 @@ const parseUvCoordinate = (value) => {
14
14
  }
15
15
  return null;
16
16
  };
17
+ const parseFiniteNumber = (value) => {
18
+ if (typeof value === 'number' && Number.isFinite(value)) {
19
+ return value;
20
+ }
21
+ return null;
22
+ };
23
+ const getResizeCursor = (degrees) => {
24
+ const normalizedDegrees = ((degrees % 180) + 180) % 180;
25
+ const snappedDegrees = Math.round(normalizedDegrees / 45) * 45;
26
+ if (snappedDegrees === 0 || snappedDegrees === 180) {
27
+ return 'ew-resize';
28
+ }
29
+ if (snappedDegrees === 45) {
30
+ return 'nwse-resize';
31
+ }
32
+ if (snappedDegrees === 90) {
33
+ return 'ns-resize';
34
+ }
35
+ return 'nesw-resize';
36
+ };
37
+ const getRotatedEllipseUv = ({ center, dimensions, width, height, rotation, angle, radiusOffset = 0, }) => {
38
+ const rotationRadians = (rotation / 180) * Math.PI;
39
+ const cosRotation = Math.cos(rotationRadians);
40
+ const sinRotation = Math.sin(rotationRadians);
41
+ if (dimensions !== null &&
42
+ dimensions !== undefined &&
43
+ dimensions.width > 0 &&
44
+ dimensions.height > 0) {
45
+ const radiusX = width * dimensions.width * 0.5 + radiusOffset * dimensions.width;
46
+ const radiusY = height * dimensions.height * 0.5 + radiusOffset * dimensions.height;
47
+ const pixelLocalX = Math.cos(angle) * radiusX;
48
+ const pixelLocalY = Math.sin(angle) * radiusY;
49
+ const rotatedX = pixelLocalX * cosRotation - pixelLocalY * sinRotation;
50
+ const rotatedY = pixelLocalX * sinRotation + pixelLocalY * cosRotation;
51
+ return [
52
+ center[0] + rotatedX / dimensions.width,
53
+ center[1] + rotatedY / dimensions.height,
54
+ ];
55
+ }
56
+ const radiusU = width / 2 + radiusOffset;
57
+ const radiusV = height / 2 + radiusOffset;
58
+ const localX = Math.cos(angle) * radiusU;
59
+ const localY = Math.sin(angle) * radiusV;
60
+ return [
61
+ center[0] + localX * cosRotation - localY * sinRotation,
62
+ center[1] + localX * sinRotation + localY * cosRotation,
63
+ ];
64
+ };
65
+ const getUvEllipseValues = (handle) => {
66
+ var _a, _b, _c, _d, _e, _f;
67
+ var _g, _h, _j, _k;
68
+ const { visual } = handle.fieldSchema;
69
+ if ((visual === null || visual === void 0 ? void 0 : visual.type) !== 'ellipse') {
70
+ return null;
71
+ }
72
+ const ellipseMetadata = visual;
73
+ const controls = handle.ellipseControls;
74
+ const width = (_g = controls === null || controls === void 0 ? void 0 : controls.width.value) !== null && _g !== void 0 ? _g : parseFiniteNumber((_a = handle.effectValues) === null || _a === void 0 ? void 0 : _a[ellipseMetadata.width]);
75
+ const height = (_h = controls === null || controls === void 0 ? void 0 : controls.height.value) !== null && _h !== void 0 ? _h : parseFiniteNumber((_b = handle.effectValues) === null || _b === void 0 ? void 0 : _b[ellipseMetadata.height]);
76
+ const rotation = ellipseMetadata.rotation
77
+ ? ((_j = (_c = controls === null || controls === void 0 ? void 0 : controls.rotation) === null || _c === void 0 ? void 0 : _c.value) !== null && _j !== void 0 ? _j : parseFiniteNumber((_d = handle.effectValues) === null || _d === void 0 ? void 0 : _d[ellipseMetadata.rotation]))
78
+ : 0;
79
+ const innerScale = ellipseMetadata.innerScale
80
+ ? ((_k = (_e = controls === null || controls === void 0 ? void 0 : controls.innerScale) === null || _e === void 0 ? void 0 : _e.value) !== null && _k !== void 0 ? _k : parseFiniteNumber((_f = handle.effectValues) === null || _f === void 0 ? void 0 : _f[ellipseMetadata.innerScale]))
81
+ : null;
82
+ if (width === null || height === null || rotation === null) {
83
+ return null;
84
+ }
85
+ return { width, height, rotation, innerScale };
86
+ };
17
87
  const tuplesEqual = (left, right) => {
18
88
  if (!Array.isArray(left) || left.length !== 2) {
19
89
  return false;
@@ -79,24 +149,24 @@ const getUvHandleConnectionLines = ({ handles, points, }) => {
79
149
  const seenPairs = new Set();
80
150
  const lines = [];
81
151
  for (const handle of handles) {
82
- const targetFieldKey = handle.fieldSchema.lineTo;
83
- if (targetFieldKey === undefined || targetFieldKey === handle.fieldKey) {
152
+ const { visual } = handle.fieldSchema;
153
+ if ((visual === null || visual === void 0 ? void 0 : visual.type) !== 'line' || visual.to === handle.fieldKey) {
84
154
  continue;
85
155
  }
86
- const target = handlesByField.get(`${handle.effectIndex}\u0000${targetFieldKey}`);
156
+ const target = handlesByField.get(`${handle.effectIndex}\u0000${visual.to}`);
87
157
  if (target === undefined) {
88
158
  continue;
89
159
  }
90
160
  const pairKey = [
91
161
  handle.effectIndex,
92
- ...[handle.fieldKey, targetFieldKey].sort(),
162
+ ...[handle.fieldKey, visual.to].sort(),
93
163
  ].join('\u0000');
94
164
  if (seenPairs.has(pairKey)) {
95
165
  continue;
96
166
  }
97
167
  seenPairs.add(pairKey);
98
168
  lines.push({
99
- key: `${handle.effectIndex}-${handle.fieldKey}-${targetFieldKey}`,
169
+ key: `${handle.effectIndex}-${handle.fieldKey}-${visual.to}`,
100
170
  from: (0, exports.getUvHandlePosition)(points, handle.value),
101
171
  to: (0, exports.getUvHandlePosition)(points, target.value),
102
172
  });
@@ -104,6 +174,169 @@ const getUvHandleConnectionLines = ({ handles, points, }) => {
104
174
  return lines;
105
175
  };
106
176
  exports.getUvHandleConnectionLines = getUvHandleConnectionLines;
177
+ const getUvHandleConnectionEllipses = ({ handles, dimensions, points, }) => {
178
+ var _a, _b;
179
+ const ellipses = [];
180
+ for (const handle of handles) {
181
+ const { visual } = handle.fieldSchema;
182
+ if ((visual === null || visual === void 0 ? void 0 : visual.type) === 'ellipse') {
183
+ const ellipseMetadata = visual;
184
+ const ellipseValues = getUvEllipseValues(handle);
185
+ if (ellipseValues === null) {
186
+ continue;
187
+ }
188
+ const rotatedEllipsePoints = [];
189
+ for (let i = 0; i <= 64; i++) {
190
+ const angle = (i / 64) * Math.PI * 2;
191
+ const uv = getRotatedEllipseUv({
192
+ center: handle.value,
193
+ dimensions,
194
+ width: ellipseValues.width,
195
+ height: ellipseValues.height,
196
+ rotation: ellipseValues.rotation,
197
+ angle,
198
+ });
199
+ rotatedEllipsePoints.push((0, exports.getUvHandlePosition)(points, uv));
200
+ }
201
+ ellipses.push({
202
+ key: [
203
+ handle.effectIndex,
204
+ handle.fieldKey,
205
+ ellipseMetadata.width,
206
+ ellipseMetadata.height,
207
+ (_a = ellipseMetadata.rotation) !== null && _a !== void 0 ? _a : 'rotation',
208
+ ].join('-'),
209
+ points: rotatedEllipsePoints,
210
+ });
211
+ if (ellipseMetadata.innerScale !== undefined &&
212
+ ellipseValues.innerScale !== null) {
213
+ const startEllipsePoints = [];
214
+ for (let i = 0; i <= 64; i++) {
215
+ const angle = (i / 64) * Math.PI * 2;
216
+ const uv = getRotatedEllipseUv({
217
+ center: handle.value,
218
+ dimensions,
219
+ width: ellipseValues.width * ellipseValues.innerScale,
220
+ height: ellipseValues.height * ellipseValues.innerScale,
221
+ rotation: ellipseValues.rotation,
222
+ angle,
223
+ });
224
+ startEllipsePoints.push((0, exports.getUvHandlePosition)(points, uv));
225
+ }
226
+ ellipses.push({
227
+ key: [
228
+ handle.effectIndex,
229
+ handle.fieldKey,
230
+ ellipseMetadata.width,
231
+ ellipseMetadata.height,
232
+ (_b = ellipseMetadata.rotation) !== null && _b !== void 0 ? _b : 'rotation',
233
+ ellipseMetadata.innerScale,
234
+ ].join('-'),
235
+ points: startEllipsePoints,
236
+ });
237
+ }
238
+ continue;
239
+ }
240
+ }
241
+ return ellipses;
242
+ };
243
+ exports.getUvHandleConnectionEllipses = getUvHandleConnectionEllipses;
244
+ const getUvEllipseInteractiveControls = ({ handles, dimensions, points, }) => {
245
+ var _a;
246
+ const controls = [];
247
+ for (const handle of handles) {
248
+ if (((_a = handle.fieldSchema.visual) === null || _a === void 0 ? void 0 : _a.type) !== 'ellipse' ||
249
+ handle.ellipseControls === null ||
250
+ handle.ellipseControls === undefined) {
251
+ continue;
252
+ }
253
+ const ellipseValues = getUvEllipseValues(handle);
254
+ if (ellipseValues === null) {
255
+ continue;
256
+ }
257
+ const center = (0, exports.getUvHandlePosition)(points, handle.value);
258
+ const { rotation } = ellipseValues;
259
+ const widthPoint = (0, exports.getUvHandlePosition)(points, getRotatedEllipseUv({
260
+ center: handle.value,
261
+ dimensions,
262
+ width: ellipseValues.width,
263
+ height: 0,
264
+ rotation,
265
+ angle: 0,
266
+ }));
267
+ const heightPoint = (0, exports.getUvHandlePosition)(points, getRotatedEllipseUv({
268
+ center: handle.value,
269
+ dimensions,
270
+ width: 0,
271
+ height: ellipseValues.height,
272
+ rotation,
273
+ angle: Math.PI / 2,
274
+ }));
275
+ const rotationPoint = handle.ellipseControls.rotation === null
276
+ ? null
277
+ : (0, exports.getUvHandlePosition)(points, getRotatedEllipseUv({
278
+ center: handle.value,
279
+ dimensions,
280
+ width: 0,
281
+ height: Math.max(ellipseValues.height, 0.001),
282
+ rotation,
283
+ angle: Math.PI / 2,
284
+ radiusOffset: 0.08,
285
+ }));
286
+ const startPoint = handle.ellipseControls.innerScale === null ||
287
+ ellipseValues.innerScale === null
288
+ ? null
289
+ : (0, exports.getUvHandlePosition)(points, getRotatedEllipseUv({
290
+ center: handle.value,
291
+ dimensions,
292
+ width: ellipseValues.width * ellipseValues.innerScale,
293
+ height: 0,
294
+ rotation,
295
+ angle: 0,
296
+ }));
297
+ controls.push({
298
+ handle,
299
+ center,
300
+ width: ellipseValues.width,
301
+ height: ellipseValues.height,
302
+ rotation,
303
+ resize: [
304
+ {
305
+ key: `${handle.effectIndex}-${handle.fieldKey}-width`,
306
+ axis: 'width',
307
+ field: handle.ellipseControls.width,
308
+ position: widthPoint,
309
+ cursor: getResizeCursor(rotation),
310
+ },
311
+ {
312
+ key: `${handle.effectIndex}-${handle.fieldKey}-height`,
313
+ axis: 'height',
314
+ field: handle.ellipseControls.height,
315
+ position: heightPoint,
316
+ cursor: getResizeCursor(rotation + 90),
317
+ },
318
+ ],
319
+ rotationControl: handle.ellipseControls.rotation === null || rotationPoint === null
320
+ ? null
321
+ : {
322
+ key: `${handle.effectIndex}-${handle.fieldKey}-rotation`,
323
+ field: handle.ellipseControls.rotation,
324
+ position: rotationPoint,
325
+ cursor: getResizeCursor(rotation + 90),
326
+ },
327
+ startControl: handle.ellipseControls.innerScale === null || startPoint === null
328
+ ? null
329
+ : {
330
+ key: `${handle.effectIndex}-${handle.fieldKey}-start`,
331
+ field: handle.ellipseControls.innerScale,
332
+ position: startPoint,
333
+ cursor: getResizeCursor(rotation),
334
+ },
335
+ });
336
+ }
337
+ return controls;
338
+ };
339
+ exports.getUvEllipseInteractiveControls = getUvEllipseInteractiveControls;
107
340
  const vectorBetween = (from, to) => {
108
341
  return { x: to.x - from.x, y: to.y - from.y };
109
342
  };
@@ -178,6 +411,77 @@ function roundUvCoordinate(value, schema) {
178
411
  (0, timeline_field_utils_1.roundToDecimalPlaces)(value[1], decimalPlaces),
179
412
  ];
180
413
  }
414
+ const roundNumericUvEllipseValue = (value, schema) => {
415
+ var _a, _b;
416
+ const min = (_a = schema.min) !== null && _a !== void 0 ? _a : -Infinity;
417
+ const max = (_b = schema.max) !== null && _b !== void 0 ? _b : Infinity;
418
+ const decimalPlaces = (0, timeline_field_utils_1.getTimelineDisplayDecimalPlaces)({
419
+ defaultDecimalPlaces: schema.type === 'rotation-degrees' ? 1 : 3,
420
+ step: schema.step,
421
+ });
422
+ return (0, timeline_field_utils_1.roundToDecimalPlaces)((0, selected_outline_geometry_1.clamp)(value, min, max), decimalPlaces);
423
+ };
424
+ exports.roundNumericUvEllipseValue = roundNumericUvEllipseValue;
425
+ const getNumericUvEllipseControlField = ({ activeSchema, effectStatus, effectValues, fieldKey, }) => {
426
+ const fieldSchema = activeSchema[fieldKey];
427
+ if ((fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) !== 'number' &&
428
+ (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) !== 'rotation-degrees') {
429
+ return null;
430
+ }
431
+ const propStatus = effectStatus.props[fieldKey];
432
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static' && (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'keyframed') {
433
+ return null;
434
+ }
435
+ const value = parseFiniteNumber(effectValues[fieldKey]);
436
+ if (value === null) {
437
+ return null;
438
+ }
439
+ return {
440
+ fieldKey,
441
+ fieldSchema,
442
+ fieldDefault: fieldSchema.default,
443
+ propStatus,
444
+ value,
445
+ };
446
+ };
447
+ const getUvEllipseControls = ({ activeSchema, effectStatus, effectValues, fieldSchema, }) => {
448
+ const { visual } = fieldSchema;
449
+ if ((visual === null || visual === void 0 ? void 0 : visual.type) !== 'ellipse') {
450
+ return null;
451
+ }
452
+ const width = getNumericUvEllipseControlField({
453
+ activeSchema,
454
+ effectStatus,
455
+ effectValues,
456
+ fieldKey: visual.width,
457
+ });
458
+ const height = getNumericUvEllipseControlField({
459
+ activeSchema,
460
+ effectStatus,
461
+ effectValues,
462
+ fieldKey: visual.height,
463
+ });
464
+ const rotation = visual.rotation === undefined
465
+ ? null
466
+ : getNumericUvEllipseControlField({
467
+ activeSchema,
468
+ effectStatus,
469
+ effectValues,
470
+ fieldKey: visual.rotation,
471
+ });
472
+ const innerScale = visual.innerScale === undefined
473
+ ? null
474
+ : getNumericUvEllipseControlField({
475
+ activeSchema,
476
+ effectStatus,
477
+ effectValues,
478
+ fieldKey: visual.innerScale,
479
+ });
480
+ if (width === null || height === null) {
481
+ return null;
482
+ }
483
+ return { width, height, rotation, innerScale };
484
+ };
181
485
  const getSelectedUvHandles = ({ propStatuses, clientId, getEffectDragOverrides, nodePath, selectedEffects, sequence, sourceFrame, }) => {
182
486
  if (clientId === null || selectedEffects === undefined) {
183
487
  return [];
@@ -215,8 +519,9 @@ const getSelectedUvHandles = ({ propStatuses, clientId, getEffectDragOverrides,
215
519
  shouldResortToDefaultValueIfUndefined: false,
216
520
  });
217
521
  });
522
+ const effectValues = {};
218
523
  for (const [fieldKey, fieldSchema] of Object.entries(activeSchema)) {
219
- if (fieldSchema.type !== 'uv-coordinate') {
524
+ if (fieldSchema.type === 'hidden') {
220
525
  continue;
221
526
  }
222
527
  const propStatus = effectStatus.props[fieldKey];
@@ -224,14 +529,24 @@ const getSelectedUvHandles = ({ propStatuses, clientId, getEffectDragOverrides,
224
529
  (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'keyframed') {
225
530
  continue;
226
531
  }
227
- const dragOverrideValue = dragOverrides[fieldKey];
228
- const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
532
+ effectValues[fieldKey] = remotion_1.Internals.getEffectiveVisualModeValue({
229
533
  propStatus,
230
- dragOverrideValue,
534
+ dragOverrideValue: dragOverrides[fieldKey],
231
535
  defaultValue: fieldSchema.default,
232
536
  frame: sourceFrame,
233
537
  shouldResortToDefaultValueIfUndefined: true,
234
538
  });
539
+ }
540
+ for (const [fieldKey, fieldSchema] of Object.entries(activeSchema)) {
541
+ if (fieldSchema.type !== 'uv-coordinate') {
542
+ continue;
543
+ }
544
+ const propStatus = effectStatus.props[fieldKey];
545
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static' &&
546
+ (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'keyframed') {
547
+ continue;
548
+ }
549
+ const effectiveValue = effectValues[fieldKey];
235
550
  const value = parseUvCoordinate(effectiveValue);
236
551
  if (value === null) {
237
552
  continue;
@@ -240,6 +555,13 @@ const getSelectedUvHandles = ({ propStatuses, clientId, getEffectDragOverrides,
240
555
  clientId,
241
556
  propStatus,
242
557
  effectIndex,
558
+ effectValues,
559
+ ellipseControls: getUvEllipseControls({
560
+ activeSchema,
561
+ effectStatus,
562
+ effectValues,
563
+ fieldSchema,
564
+ }),
243
565
  fieldDefault: fieldSchema.default,
244
566
  fieldKey,
245
567
  fieldSchema,