@remotion/studio 4.0.481 → 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 (56) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/Editor.js +1 -1
  3. package/dist/components/GlobalKeybindings.js +1 -1
  4. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +3 -2
  5. package/dist/components/InspectorPanel/styles.js +2 -0
  6. package/dist/components/InspectorSequenceSection.js +45 -2
  7. package/dist/components/MediaVolumeProvider.js +4 -4
  8. package/dist/components/Modals.js +2 -1
  9. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  10. package/dist/components/NewComposition/CodemodFooter.js +25 -3
  11. package/dist/components/NewComposition/InputDragger.d.ts +4 -0
  12. package/dist/components/NewComposition/InputDragger.js +18 -2
  13. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  14. package/dist/components/NewComposition/NewComposition.js +178 -0
  15. package/dist/components/PreviewToolbar.js +3 -3
  16. package/dist/components/SelectedOutlineOverlay.d.ts +6 -0
  17. package/dist/components/SelectedOutlineOverlay.js +18 -2
  18. package/dist/components/SelectedOutlineUvControls.js +461 -2
  19. package/dist/components/Timeline/EasingEditorModal.js +39 -1
  20. package/dist/components/Timeline/Timeline.js +2 -1
  21. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  22. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  23. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  24. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  25. package/dist/components/Timeline/TimelineSelection.d.ts +13 -4
  26. package/dist/components/Timeline/TimelineSelection.js +100 -39
  27. package/dist/components/Timeline/TimelineSequence.js +20 -8
  28. package/dist/components/Timeline/TimelineSequenceItem.js +17 -16
  29. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  30. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  31. package/dist/components/Timeline/TimelineTrack.js +2 -4
  32. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  33. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  34. package/dist/components/Timeline/timeline-field-display-utils.js +3 -0
  35. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  36. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  37. package/dist/components/composition-menu-items.js +17 -0
  38. package/dist/components/element-drag-and-drop.d.ts +3 -0
  39. package/dist/components/element-drag-and-drop.js +30 -0
  40. package/dist/components/import-assets.d.ts +11 -0
  41. package/dist/components/import-assets.js +23 -1
  42. package/dist/components/selected-outline-uv.d.ts +71 -1
  43. package/dist/components/selected-outline-uv.js +332 -10
  44. package/dist/esm/{chunk-4rq5gt8c.js → chunk-fq0j774v.js} +3438 -1648
  45. package/dist/esm/internals.mjs +3438 -1648
  46. package/dist/esm/previewEntry.mjs +3455 -1665
  47. package/dist/esm/renderEntry.mjs +1 -1
  48. package/dist/helpers/calculate-timeline.js +6 -2
  49. package/dist/helpers/get-sequence-visible-range.d.ts +1 -0
  50. package/dist/helpers/get-sequence-visible-range.js +15 -1
  51. package/dist/helpers/timeline-layout.d.ts +3 -3
  52. package/dist/helpers/timeline-layout.js +3 -1
  53. package/dist/state/modals.d.ts +2 -0
  54. package/package.json +11 -11
  55. package/dist/components/Timeline/TimelineItemStack.d.ts +0 -5
  56. package/dist/components/Timeline/TimelineItemStack.js +0 -29
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getElementDragData = exports.hasElementDragType = void 0;
4
+ const studio_shared_1 = require("@remotion/studio-shared");
5
+ const hasElementDragType = (dataTransfer) => {
6
+ var _a;
7
+ return Array.from((_a = dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.types) !== null && _a !== void 0 ? _a : []).includes(studio_shared_1.ELEMENT_DRAG_MIME_TYPE);
8
+ };
9
+ exports.hasElementDragType = hasElementDragType;
10
+ const getElementDragData = (dataTransfer) => {
11
+ if (!dataTransfer) {
12
+ return null;
13
+ }
14
+ for (const type of [
15
+ studio_shared_1.ELEMENT_DRAG_MIME_TYPE,
16
+ 'application/json',
17
+ 'text/plain',
18
+ ]) {
19
+ const raw = dataTransfer.getData(type);
20
+ if (!raw) {
21
+ continue;
22
+ }
23
+ const parsed = (0, studio_shared_1.parseElementDragData)(raw);
24
+ if (parsed) {
25
+ return parsed;
26
+ }
27
+ }
28
+ return null;
29
+ };
30
+ exports.getElementDragData = getElementDragData;
@@ -72,3 +72,14 @@ export declare const insertComponent: ({ component, compositionFile, composition
72
72
  compositionId: string;
73
73
  dropPosition: InsertElementDropPosition | null;
74
74
  }) => Promise<void>;
75
+ export declare const insertElement: ({ compositionFile, compositionId, dropPosition, element, }: {
76
+ compositionFile: string;
77
+ compositionId: string;
78
+ dropPosition: InsertElementDropPosition | null;
79
+ element: {
80
+ slug: string;
81
+ displayName: string;
82
+ sourceCode: string;
83
+ dimensions: import("@remotion/studio-shared").ComponentDimensions;
84
+ };
85
+ }) => Promise<void>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.insertComponent = exports.insertExistingAssets = exports.insertRemoteAudio = exports.importRemoteAsset = exports.importAssets = exports.pickFilesToImport = exports.getComponentDimensions = exports.getAssetElementFromPath = exports.getAssetElement = void 0;
3
+ exports.insertElement = exports.insertComponent = exports.insertExistingAssets = exports.insertRemoteAudio = exports.importRemoteAsset = exports.importAssets = exports.pickFilesToImport = exports.getComponentDimensions = exports.getAssetElementFromPath = exports.getAssetElement = void 0;
4
4
  const media_utils_1 = require("@remotion/media-utils");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const remotion_1 = require("remotion");
@@ -569,3 +569,25 @@ const insertComponent = async ({ component, compositionFile, compositionId, drop
569
569
  }
570
570
  };
571
571
  exports.insertComponent = insertComponent;
572
+ const insertElement = async ({ compositionFile, compositionId, dropPosition, element, }) => {
573
+ try {
574
+ const response = await (0, call_api_1.callApi)('/api/insert-element', {
575
+ compositionFile,
576
+ compositionId,
577
+ element,
578
+ position: getCenteredPosition({
579
+ dimensions: element.dimensions,
580
+ dropPosition,
581
+ }),
582
+ });
583
+ if (!response.success) {
584
+ (0, NotificationCenter_1.showNotification)(`Could not add Element: ${response.reason}`, 4000);
585
+ return;
586
+ }
587
+ (0, NotificationCenter_1.showNotification)(`Added ${element.displayName} to source file`, 2000);
588
+ }
589
+ catch (error) {
590
+ (0, NotificationCenter_1.showNotification)(`Could not add Element: ${error instanceof Error ? error.message : String(error)}`, 4000);
591
+ }
592
+ };
593
+ exports.insertElement = insertElement;
@@ -1,13 +1,35 @@
1
1
  import type { CanUpdateSequencePropStatusKeyframed, CanUpdateSequencePropStatusStatic, GetEffectDragOverrides, PropStatuses, InteractivitySchemaField, SequencePropsSubscriptionKey, InteractivitySchema, TSequence } from 'remotion';
2
2
  import { type OutlinePoint } from './selected-outline-geometry';
3
3
  export type UvCoordinate = readonly [number, number];
4
+ type UvEllipseDimensions = {
5
+ readonly width: number;
6
+ readonly height: number;
7
+ };
4
8
  export type UvCoordinateFieldSchema = Extract<InteractivitySchemaField, {
5
9
  type: 'uv-coordinate';
6
10
  }>;
11
+ export type NumericUvEllipseFieldSchema = Extract<InteractivitySchemaField, {
12
+ type: 'number' | 'rotation-degrees';
13
+ }>;
14
+ export type UvEllipseControlField = {
15
+ readonly fieldKey: string;
16
+ readonly fieldSchema: NumericUvEllipseFieldSchema;
17
+ readonly fieldDefault: number | null | undefined;
18
+ readonly propStatus: CanUpdateSequencePropStatusStatic | CanUpdateSequencePropStatusKeyframed;
19
+ readonly value: number;
20
+ };
21
+ export type UvEllipseControls = {
22
+ readonly width: UvEllipseControlField;
23
+ readonly height: UvEllipseControlField;
24
+ readonly rotation: UvEllipseControlField | null;
25
+ readonly innerScale: UvEllipseControlField | null;
26
+ };
7
27
  export type SelectedOutlineUvHandle = {
8
28
  readonly clientId: string;
9
29
  readonly propStatus: CanUpdateSequencePropStatusStatic | CanUpdateSequencePropStatusKeyframed;
10
30
  readonly effectIndex: number;
31
+ readonly effectValues: Record<string, unknown>;
32
+ readonly ellipseControls: UvEllipseControls | null;
11
33
  readonly fieldDefault: UvCoordinate | undefined;
12
34
  readonly fieldKey: string;
13
35
  readonly fieldSchema: UvCoordinateFieldSchema;
@@ -17,12 +39,49 @@ export type SelectedOutlineUvHandle = {
17
39
  readonly sourceFrame: number;
18
40
  readonly value: UvCoordinate;
19
41
  };
20
- type UvConnectionHandle = Pick<SelectedOutlineUvHandle, 'effectIndex' | 'fieldKey' | 'fieldSchema' | 'value'>;
42
+ type UvConnectionHandle = Pick<SelectedOutlineUvHandle, 'effectIndex' | 'fieldKey' | 'fieldSchema' | 'value'> & {
43
+ readonly effectValues?: Record<string, unknown>;
44
+ readonly ellipseControls?: UvEllipseControls | null;
45
+ };
21
46
  type UvHandleConnectionLine = {
22
47
  readonly key: string;
23
48
  readonly from: OutlinePoint;
24
49
  readonly to: OutlinePoint;
25
50
  };
51
+ type UvHandleConnectionEllipse = {
52
+ readonly key: string;
53
+ readonly points: readonly OutlinePoint[];
54
+ };
55
+ export type UvEllipseResizeAxis = 'width' | 'height';
56
+ export type UvEllipseResizeControl = {
57
+ readonly key: string;
58
+ readonly axis: UvEllipseResizeAxis;
59
+ readonly field: UvEllipseControlField;
60
+ readonly position: OutlinePoint;
61
+ readonly cursor: string;
62
+ };
63
+ export type UvEllipseRotationControl = {
64
+ readonly key: string;
65
+ readonly field: UvEllipseControlField;
66
+ readonly position: OutlinePoint;
67
+ readonly cursor: string;
68
+ };
69
+ export type UvEllipseStartControl = {
70
+ readonly key: string;
71
+ readonly field: UvEllipseControlField;
72
+ readonly position: OutlinePoint;
73
+ readonly cursor: string;
74
+ };
75
+ export type UvEllipseInteractiveControls = {
76
+ readonly handle: SelectedOutlineUvHandle;
77
+ readonly center: OutlinePoint;
78
+ readonly width: number;
79
+ readonly height: number;
80
+ readonly rotation: number;
81
+ readonly resize: readonly UvEllipseResizeControl[];
82
+ readonly rotationControl: UvEllipseRotationControl | null;
83
+ readonly startControl: UvEllipseStartControl | null;
84
+ };
26
85
  type SelectedEffectFields = {
27
86
  readonly allFields: boolean;
28
87
  readonly fieldKeys: ReadonlySet<string>;
@@ -33,9 +92,20 @@ export declare const getUvHandleConnectionLines: ({ handles, points, }: {
33
92
  readonly handles: readonly UvConnectionHandle[];
34
93
  readonly points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
35
94
  }) => UvHandleConnectionLine[];
95
+ export declare const getUvHandleConnectionEllipses: ({ handles, dimensions, points, }: {
96
+ readonly handles: readonly UvConnectionHandle[];
97
+ readonly dimensions?: UvEllipseDimensions | null | undefined;
98
+ readonly points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
99
+ }) => UvHandleConnectionEllipse[];
100
+ export declare const getUvEllipseInteractiveControls: ({ handles, dimensions, points, }: {
101
+ readonly handles: readonly SelectedOutlineUvHandle[];
102
+ readonly dimensions?: UvEllipseDimensions | null | undefined;
103
+ readonly points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint];
104
+ }) => UvEllipseInteractiveControls[];
36
105
  export declare const getUvCoordinateForPoint: (points: readonly [OutlinePoint, OutlinePoint, OutlinePoint, OutlinePoint], point: OutlinePoint) => UvCoordinate;
37
106
  export declare function constrainUv(value: UvCoordinate, schema: UvCoordinateFieldSchema): UvCoordinate;
38
107
  export declare function roundUvCoordinate(value: UvCoordinate, schema: UvCoordinateFieldSchema): UvCoordinate;
108
+ export declare const roundNumericUvEllipseValue: (value: number, schema: NumericUvEllipseFieldSchema) => number;
39
109
  export declare const getSelectedUvHandles: ({ propStatuses, clientId, getEffectDragOverrides, nodePath, selectedEffects, sequence, sourceFrame, }: {
40
110
  readonly propStatuses: PropStatuses;
41
111
  readonly clientId: string | null;
@@ -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,