@vvfx/dsl-ir 0.0.1-beta.10

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 (39) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +240 -0
  3. package/dist/common/particle-expression.d.ts +6 -0
  4. package/dist/common/transform.d.ts +11 -0
  5. package/dist/common/utils.d.ts +19 -0
  6. package/dist/dsl/number-expression.d.ts +7 -0
  7. package/dist/dsl/parse-particle-shape.d.ts +2 -0
  8. package/dist/dsl/particle-shape.d.ts +86 -0
  9. package/dist/dsl/schema.d.ts +100 -0
  10. package/dist/dsl/validator/index.d.ts +2 -0
  11. package/dist/dsl/validator/labels.d.ts +1 -0
  12. package/dist/dsl/validator/particle.d.ts +8 -0
  13. package/dist/dsl/validator/types.d.ts +33 -0
  14. package/dist/dsl/validator/validation.d.ts +15 -0
  15. package/dist/dsl2ir/assemble.d.ts +3 -0
  16. package/dist/dsl2ir/content-conversion.d.ts +11 -0
  17. package/dist/dsl2ir/convert-layers.d.ts +4 -0
  18. package/dist/dsl2ir/convert-particle.d.ts +4 -0
  19. package/dist/dsl2ir/convert-property.d.ts +6 -0
  20. package/dist/dsl2ir/convert.d.ts +4 -0
  21. package/dist/dsl2ir/recombine/compare-properties.d.ts +18 -0
  22. package/dist/dsl2ir/recombine/convert.d.ts +5 -0
  23. package/dist/dsl2ir/recombine/update-ir.d.ts +6 -0
  24. package/dist/dsl2ir/recombine/update-layer-order.d.ts +5 -0
  25. package/dist/dsl2ir/recombine/update-layer.d.ts +4 -0
  26. package/dist/dsl2ir/recombine/update-particle.d.ts +4 -0
  27. package/dist/dsl2ir/types.d.ts +35 -0
  28. package/dist/index.d.ts +10 -0
  29. package/dist/index.js +4424 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/index.mjs +4418 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/ir2dsl/assemble.d.ts +5 -0
  34. package/dist/ir2dsl/convert-layers.d.ts +10 -0
  35. package/dist/ir2dsl/convert-particle.d.ts +4 -0
  36. package/dist/ir2dsl/convert.d.ts +4 -0
  37. package/dist/ir2dsl/expand-precompositions.d.ts +6 -0
  38. package/dist/ir2dsl/types.d.ts +45 -0
  39. package/package.json +45 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,4418 @@
1
+ /*!
2
+ * Name: @vvfx/dsl-ir
3
+ * Description: Editable DSL and Animation IR bidirectional converter
4
+ * Author: Ant Group CO., Ltd.
5
+ * Contributors: 澄弈
6
+ * Version: v0.0.1-beta.10
7
+ */
8
+
9
+ import { IREndBehavior, assertIRScene, isIRId } from '@vvfx/animation-ir';
10
+ import { getIRResourceSourceUrl, getIRSceneEntryComposition, createIRResourceSource, createIRScene } from '@vvfx/animation-ir/adapter';
11
+
12
+ function _extends() {
13
+ _extends = Object.assign || function assign(target) {
14
+ for(var i = 1; i < arguments.length; i++){
15
+ var source = arguments[i];
16
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
17
+ }
18
+ return target;
19
+ };
20
+ return _extends.apply(this, arguments);
21
+ }
22
+
23
+ function _type_of(obj) {
24
+ "@swc/helpers - typeof";
25
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
26
+ }
27
+
28
+ var byteToHex = [];
29
+ for(var i = 0; i < 256; ++i){
30
+ byteToHex.push((i + 0x100).toString(16).slice(1));
31
+ }
32
+ function unsafeStringify(arr, offset) {
33
+ if (offset === void 0) offset = 0;
34
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
35
+ }
36
+
37
+ var getRandomValues;
38
+ var rnds8 = new Uint8Array(16);
39
+ function rng() {
40
+ if (!getRandomValues) {
41
+ if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
42
+ throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
43
+ }
44
+ getRandomValues = crypto.getRandomValues.bind(crypto);
45
+ }
46
+ return getRandomValues(rnds8);
47
+ }
48
+
49
+ var randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
50
+ var native = {
51
+ randomUUID: randomUUID
52
+ };
53
+
54
+ function _v4(options, buf, offset) {
55
+ var _ref, _options_random;
56
+ options = options || {};
57
+ var rnds = (_ref = (_options_random = options.random) != null ? _options_random : options.rng == null ? void 0 : options.rng.call(options)) != null ? _ref : rng();
58
+ if (rnds.length < 16) {
59
+ throw new Error('Random bytes length must be >= 16');
60
+ }
61
+ rnds[6] = rnds[6] & 0x0f | 0x40;
62
+ rnds[8] = rnds[8] & 0x3f | 0x80;
63
+ return unsafeStringify(rnds);
64
+ }
65
+ function v4(options, buf, offset) {
66
+ if (native.randomUUID && true && !options) {
67
+ return native.randomUUID();
68
+ }
69
+ return _v4(options);
70
+ }
71
+
72
+ var HEX_COLOR_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
73
+ var EPSILON$1 = 1e-6;
74
+ /** Generate a 32-character hexadecimal UUID v4. */ function createId() {
75
+ return v4().replaceAll('-', '');
76
+ }
77
+ /** Convert normalized RGB(A) channels to a canonical hex color. */ function colorToHex(color) {
78
+ var _color_, _color_1, _color_2, _color_3;
79
+ var colorChannels = [
80
+ (_color_ = color[0]) != null ? _color_ : 0,
81
+ (_color_1 = color[1]) != null ? _color_1 : 0,
82
+ (_color_2 = color[2]) != null ? _color_2 : 0,
83
+ color.length >= 4 ? (_color_3 = color[3]) != null ? _color_3 : 1 : 1
84
+ ];
85
+ var hexParts = colorChannels.map(function(channel) {
86
+ var byteValue = Math.max(0, Math.min(255, Math.round(channel * 255)));
87
+ return byteValue.toString(16).padStart(2, '0');
88
+ });
89
+ return hexParts[3] === 'ff' ? "#" + hexParts.slice(0, 3).join('') : "#" + hexParts.join('');
90
+ }
91
+ /** Normalize supported hex forms for semantic comparison. */ function normalizeHex(hexColor) {
92
+ var normalizedHex = hexColor.replace(/^#/, '').toLowerCase();
93
+ if (normalizedHex.length === 3) {
94
+ var _ref = [
95
+ normalizedHex[0] + normalizedHex[0],
96
+ normalizedHex[1] + normalizedHex[1],
97
+ normalizedHex[2] + normalizedHex[2]
98
+ ], red = _ref[0], green = _ref[1], blue = _ref[2];
99
+ return "#" + red + green + blue;
100
+ }
101
+ if (normalizedHex.length === 6) {
102
+ return "#" + normalizedHex;
103
+ }
104
+ if (normalizedHex.length === 8) {
105
+ var alpha = normalizedHex.slice(6, 8);
106
+ return alpha === 'ff' ? "#" + normalizedHex.slice(0, 6) : "#" + normalizedHex;
107
+ }
108
+ return hexColor.toLowerCase();
109
+ }
110
+ /** Compare nullable hex colors after normalization. */ function isHexEqual(leftHex, rightHex) {
111
+ if (leftHex == null && rightHex == null) {
112
+ return true;
113
+ }
114
+ if (leftHex == null || rightHex == null) {
115
+ return false;
116
+ }
117
+ return normalizeHex(leftHex) === normalizeHex(rightHex);
118
+ }
119
+ function isValidHexColor(value) {
120
+ return typeof value === 'string' && HEX_COLOR_PATTERN.test(value);
121
+ }
122
+ function hexToIRColor(hexColor) {
123
+ var hex = hexColor.replace(/^#/, '');
124
+ if (hex.length === 3) {
125
+ return [
126
+ parseHexByte("" + hex[0] + hex[0], hexColor) / 255,
127
+ parseHexByte("" + hex[1] + hex[1], hexColor) / 255,
128
+ parseHexByte("" + hex[2] + hex[2], hexColor) / 255,
129
+ 1
130
+ ];
131
+ }
132
+ if (hex.length === 6 || hex.length === 8) {
133
+ return [
134
+ parseHexByte(hex.slice(0, 2), hexColor) / 255,
135
+ parseHexByte(hex.slice(2, 4), hexColor) / 255,
136
+ parseHexByte(hex.slice(4, 6), hexColor) / 255,
137
+ hex.length === 8 ? parseHexByte(hex.slice(6, 8), hexColor) / 255 : 1
138
+ ];
139
+ }
140
+ throw new Error("[dsl-ir:color] Invalid hex color: " + hexColor);
141
+ }
142
+ function resolveFiniteNumber(value, fallback) {
143
+ return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
144
+ }
145
+ function secondsToFrames(seconds, frameRate) {
146
+ return resolveFiniteNumber(seconds, 0) * frameRate;
147
+ }
148
+ function isScalarEqual(leftValue, rightValue) {
149
+ return Math.abs(leftValue - rightValue) <= EPSILON$1;
150
+ }
151
+ function isNumberArrayEqual(leftValues, rightValues) {
152
+ if (leftValues.length !== rightValues.length) {
153
+ return false;
154
+ }
155
+ return leftValues.every(function(value, index) {
156
+ return Math.abs(value - rightValues[index]) <= EPSILON$1;
157
+ });
158
+ }
159
+ function isRecord$1(value) {
160
+ return value != null && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && !Array.isArray(value);
161
+ }
162
+ function toJSONPath(path) {
163
+ if (path === '') {
164
+ return '$';
165
+ }
166
+ return path.startsWith('$') ? path : "$." + path;
167
+ }
168
+ function parseHexByte(value, source) {
169
+ if (!/^[\da-fA-F]{2}$/.test(value)) {
170
+ throw new Error("[dsl-ir:color] Invalid hex color: " + source);
171
+ }
172
+ return parseInt(value, 16);
173
+ }
174
+
175
+ function _set_prototype_of(o, p) {
176
+ _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
177
+ o.__proto__ = p;
178
+ return o;
179
+ };
180
+ return _set_prototype_of(o, p);
181
+ }
182
+
183
+ function _inherits(subClass, superClass) {
184
+ if (typeof superClass !== "function" && superClass !== null) {
185
+ throw new TypeError("Super expression must either be null or a function");
186
+ }
187
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
188
+ constructor: {
189
+ value: subClass,
190
+ writable: true,
191
+ configurable: true
192
+ }
193
+ });
194
+ if (superClass) _set_prototype_of(subClass, superClass);
195
+ }
196
+
197
+ function _instanceof(left, right) {
198
+ "@swc/helpers - instanceof";
199
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
200
+ return !!right[Symbol.hasInstance](left);
201
+ } else return left instanceof right;
202
+ }
203
+
204
+ function _is_native_reflect_construct() {
205
+ // Since Reflect.construct can't be properly polyfilled, some
206
+ // implementations (e.g. core-js@2) don't set the correct internal slots.
207
+ // Those polyfills don't allow us to subclass built-ins, so we need to
208
+ // use our fallback implementation.
209
+ try {
210
+ // If the internal slots aren't set, this throws an error similar to
211
+ // TypeError: this is not a Boolean object.
212
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
213
+ } catch (_) {}
214
+ return (_is_native_reflect_construct = function _is_native_reflect_construct() {
215
+ return !!result;
216
+ })();
217
+ }
218
+
219
+ function _construct(Parent, args, Class) {
220
+ if (_is_native_reflect_construct()) _construct = Reflect.construct;
221
+ else {
222
+ _construct = function construct(Parent, args, Class) {
223
+ var a = [
224
+ null
225
+ ];
226
+ a.push.apply(a, args);
227
+ var Constructor = Function.bind.apply(Parent, a);
228
+ var instance = new Constructor();
229
+ if (Class) _set_prototype_of(instance, Class.prototype);
230
+ return instance;
231
+ };
232
+ }
233
+ return _construct.apply(null, arguments);
234
+ }
235
+
236
+ function _get_prototype_of(o) {
237
+ _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
238
+ return o.__proto__ || Object.getPrototypeOf(o);
239
+ };
240
+ return _get_prototype_of(o);
241
+ }
242
+
243
+ function _is_native_function(fn) {
244
+ return Function.toString.call(fn).indexOf("[native code]") !== -1;
245
+ }
246
+
247
+ function _wrap_native_super(Class) {
248
+ var _cache = typeof Map === "function" ? new Map() : undefined;
249
+ _wrap_native_super = function _wrap_native_super(Class) {
250
+ if (Class === null || !_is_native_function(Class)) return Class;
251
+ if (typeof Class !== "function") throw new TypeError("Super expression must either be null or a function");
252
+ if (typeof _cache !== "undefined") {
253
+ if (_cache.has(Class)) return _cache.get(Class);
254
+ _cache.set(Class, Wrapper);
255
+ }
256
+ function Wrapper() {
257
+ return _construct(Class, arguments, _get_prototype_of(this).constructor);
258
+ }
259
+ Wrapper.prototype = Object.create(Class.prototype, {
260
+ constructor: {
261
+ value: Wrapper,
262
+ enumerable: false,
263
+ writable: true,
264
+ configurable: true
265
+ }
266
+ });
267
+ return _set_prototype_of(Wrapper, Class);
268
+ };
269
+ return _wrap_native_super(Class);
270
+ }
271
+
272
+ function _array_like_to_array(arr, len) {
273
+ if (len == null || len > arr.length) len = arr.length;
274
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
275
+ return arr2;
276
+ }
277
+
278
+ function _unsupported_iterable_to_array(o, minLen) {
279
+ if (!o) return;
280
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
281
+ var n = Object.prototype.toString.call(o).slice(8, -1);
282
+ if (n === "Object" && o.constructor) n = o.constructor.name;
283
+ if (n === "Map" || n === "Set") return Array.from(n);
284
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
285
+ }
286
+
287
+ function _create_for_of_iterator_helper_loose(o, allowArrayLike) {
288
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
289
+ if (it) return (it = it.call(o)).next.bind(it);
290
+ // Fallback for engines without symbol support
291
+ if (Array.isArray(o) || (it = _unsupported_iterable_to_array(o)) || allowArrayLike) {
292
+ if (it) o = it;
293
+ var i = 0;
294
+ return function() {
295
+ if (i >= o.length) return {
296
+ done: true
297
+ };
298
+ return {
299
+ done: false,
300
+ value: o[i++]
301
+ };
302
+ };
303
+ }
304
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
305
+ }
306
+
307
+ var DSL_CODE_LABELS = {
308
+ R001: 'DSL 根不是对象',
309
+ R002: '缺少 meta',
310
+ R003: '缺少 layers',
311
+ R004: 'layers 不是数组',
312
+ M001: 'meta 必填字段缺失',
313
+ M002a: 'meta.name 类型错误',
314
+ M002b: 'meta.duration 类型错误',
315
+ M002c: 'meta.fps 类型错误',
316
+ M002d: 'meta.width 类型错误',
317
+ M002e: 'meta.height 类型错误',
318
+ M002f: 'meta.loop 类型错误',
319
+ M003: 'background_color 类型错误',
320
+ M004: 'background_color 非十六进制',
321
+ M005: 'fps 必须 > 0',
322
+ M006: 'width/height 必须 > 0',
323
+ M007: 'duration 非正数',
324
+ L001: '图层缺少 id',
325
+ L002: 'id 不是字符串',
326
+ L003: 'id 为空字符串',
327
+ L004: 'name 缺失',
328
+ L005: 'name 不是字符串',
329
+ L006: 'type 缺失',
330
+ L007: 'type 非法枚举',
331
+ L008: 'width 缺失',
332
+ L009: 'width 非法',
333
+ L010: 'height 缺失',
334
+ L011: 'height 非法',
335
+ L012: 'description 缺失',
336
+ L013: 'description 不是对象',
337
+ L014: 'description.self 缺失',
338
+ L015: 'description.composite 缺失',
339
+ L016: 'description 字段非字符串',
340
+ L018: 'time_range 非二元数组',
341
+ L019: 'time_range 元素非数值',
342
+ L020: 'time_range 不可见',
343
+ L021: '图层项非对象',
344
+ L022: 'children 不是数组',
345
+ L023: 'time_range 超出 composition 范围',
346
+ L024: '图片层或粒子层尺寸必须大于 0',
347
+ P001: '变换属性缺失',
348
+ P002: '变换属性非对象',
349
+ P003: 'a 缺失',
350
+ P004: 'a 不是布尔值',
351
+ P005: '静态属性缺 value',
352
+ P006: '静态属性出现 animation',
353
+ P007: '动画属性缺 animation',
354
+ P008: 'animation 非数组',
355
+ P009: '动画属性出现 value',
356
+ P010: 'animation 为空',
357
+ P011: '三维属性 value 不是三元数组',
358
+ P012: 'opacity value 非标量',
359
+ P013: 'value 元素非数值',
360
+ P014: 'opacity value 越界',
361
+ P015: 'anchor 不支持动画',
362
+ C001: '曲线段非对象',
363
+ C002: 't 缺失',
364
+ C003: 't 非二元数组',
365
+ C004: 't 起止逆序',
366
+ C005: 't 元素非数值',
367
+ C006: 'start 缺失',
368
+ C007: 'end 缺失',
369
+ C008: '三维属性起止非三元数组',
370
+ C009: 'opacity 起止不是一元数组',
371
+ C010: 'opacity 起止为裸标量',
372
+ C011: 'easing 非四元数组(会触发下游崩溃)',
373
+ C012: 'easing 元素非数值',
374
+ C013: 'in/out 出现在非 position 属性',
375
+ C014: 'in/out 非三元数组',
376
+ C016: '曲线 t 越界',
377
+ S002: '曲线时间重叠',
378
+ S003: '曲线时间空隙',
379
+ S004: '曲线未单调',
380
+ X001: '图层 id 全局重复',
381
+ X002: 'parent 自引用',
382
+ X003: 'parent 非字符串',
383
+ X004: 'parent 引用悬空',
384
+ X005: 'parent 与物理嵌套不一致',
385
+ X006: 'parent 链成环',
386
+ A001: '图片层缺 asset',
387
+ A002: 'asset 非对象',
388
+ A003: 'asset.source 缺失',
389
+ A004: 'asset.source 非法枚举',
390
+ A005: 'llm_svg 的 format 非 svg',
391
+ A006: 'llm_svg 缺 svg',
392
+ A007: 'llm_svg 缺 prompt',
393
+ A008: 'user 缺 url',
394
+ A009: 'user 的 prompt 非空',
395
+ A010: 'null 层有不必要的 asset',
396
+ A011: '文字层缺 text 块',
397
+ A012: 'text 非对象',
398
+ A013: 'text.content 缺失/非字符串',
399
+ A014: 'text.size 缺失/非数值',
400
+ A015: 'text.color 缺失/非字符串',
401
+ A016: '图片层有不必要的 text',
402
+ A017: '文字层有不必要的 asset',
403
+ A018: 'text.font 类型错误',
404
+ A019: 'text.align 非法枚举',
405
+ A020: '文字排版数值非法',
406
+ A021: 'asset.url 类型错误',
407
+ A022: '粒子层缺 particle 块',
408
+ A023: 'particle 不是对象',
409
+ A024: '非粒子层有不必要的 particle 块',
410
+ A025: '粒子层有不必要的 asset',
411
+ A026: '粒子层有不必要的 text',
412
+ PT001: 'particle.emission 缺失或不是对象',
413
+ PT002: 'rateOverTime 非法',
414
+ PT003: 'bursts 不是数组',
415
+ PT004: 'burst 字段非法',
416
+ PT005: 'particle 包含未知字段',
417
+ PT006: 'particle.options 缺失或不是对象',
418
+ PT007: 'maxCount 非法',
419
+ PT008: 'startLifetime 非法',
420
+ PT009: 'particle.shape 非法'
421
+ };
422
+
423
+ var ValueType = /*#__PURE__*/ function(ValueType) {
424
+ ValueType[ValueType["CONSTANT"] = 0] = "CONSTANT";
425
+ ValueType[ValueType["RANDOM"] = 4] = "RANDOM";
426
+ return ValueType;
427
+ }({});
428
+
429
+ var PARTICLE_SHAPE_NAMES = [
430
+ 'None',
431
+ 'Sphere',
432
+ 'Cone',
433
+ 'Hemisphere',
434
+ 'Circle',
435
+ 'Donut',
436
+ 'Rectangle',
437
+ 'RectangleEdge',
438
+ 'Edge',
439
+ 'Texture'
440
+ ];
441
+ var PARTICLE_SHAPE_BASE_FIELDS = [
442
+ 'type',
443
+ 'shape',
444
+ 'arcMode',
445
+ 'alignSpeedDirection',
446
+ 'upDirection',
447
+ 'turbulenceX',
448
+ 'turbulenceY',
449
+ 'turbulenceZ'
450
+ ];
451
+ var PARTICLE_SHAPE_FIELDS_BY_TYPE = {
452
+ 0: [
453
+ 'type',
454
+ 'shape',
455
+ 'upDirection',
456
+ 'turbulenceX',
457
+ 'turbulenceY',
458
+ 'turbulenceZ'
459
+ ],
460
+ 1: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
461
+ 'radius',
462
+ 'arc'
463
+ ]),
464
+ 2: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
465
+ 'angle',
466
+ 'radius',
467
+ 'arc'
468
+ ]),
469
+ 3: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
470
+ 'radius',
471
+ 'arc'
472
+ ]),
473
+ 4: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
474
+ 'radius',
475
+ 'arc'
476
+ ]),
477
+ 5: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
478
+ 'radius',
479
+ 'donutRadius',
480
+ 'arc'
481
+ ]),
482
+ 6: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
483
+ 'width',
484
+ 'height'
485
+ ]),
486
+ 7: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
487
+ 'width',
488
+ 'height'
489
+ ]),
490
+ 8: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
491
+ 'width'
492
+ ]),
493
+ 9: [].concat(PARTICLE_SHAPE_BASE_FIELDS, [
494
+ 'detail',
495
+ 'random',
496
+ 'width',
497
+ 'height'
498
+ ])
499
+ };
500
+ var PARTICLE_SHAPE_NUMBER_FIELDS_BY_TYPE = {
501
+ 0: [],
502
+ 1: [
503
+ 'radius',
504
+ 'arc'
505
+ ],
506
+ 2: [
507
+ 'angle',
508
+ 'radius',
509
+ 'arc'
510
+ ],
511
+ 3: [
512
+ 'radius',
513
+ 'arc'
514
+ ],
515
+ 4: [
516
+ 'radius',
517
+ 'arc'
518
+ ],
519
+ 5: [
520
+ 'radius',
521
+ 'donutRadius',
522
+ 'arc'
523
+ ],
524
+ 6: [
525
+ 'width',
526
+ 'height'
527
+ ],
528
+ 7: [
529
+ 'width',
530
+ 'height'
531
+ ],
532
+ 8: [
533
+ 'width'
534
+ ],
535
+ 9: [
536
+ 'random',
537
+ 'width',
538
+ 'height'
539
+ ]
540
+ };
541
+ function lintParticle(particle, layer, particlePath) {
542
+ var issues = [];
543
+ reportUnknownFields(particle, new Set([
544
+ 'shape',
545
+ 'options',
546
+ 'emission'
547
+ ]), 'PT005', particlePath, issues);
548
+ if (Object.hasOwn(particle, 'shape')) {
549
+ checkParticleShapeValue(particle['shape'], "" + particlePath + ".shape", issues);
550
+ }
551
+ checkParticleOptionsValue(particle['options'], "" + particlePath + ".options", issues);
552
+ checkParticleEmissionValue(particle['emission'], layer, "" + particlePath + ".emission", issues);
553
+ return issues;
554
+ }
555
+ function checkParticleShapeValue(value, shapePath, issues) {
556
+ if (!isRecord$1(value)) {
557
+ addIssue$1(issues, 'PT009', "particle.shape is " + describeValueType$1(value) + ", expected an object", shapePath);
558
+ return;
559
+ }
560
+ var type = value['type'];
561
+ if (!isIntegerInRange$1(type, 0, PARTICLE_SHAPE_NAMES.length - 1)) {
562
+ addIssue$1(issues, 'PT009', 'particle.shape.type must be an integer from 0 to 9', "" + shapePath + ".type");
563
+ return;
564
+ }
565
+ var expectedName = PARTICLE_SHAPE_NAMES[type];
566
+ reportUnknownFields(value, new Set(PARTICLE_SHAPE_FIELDS_BY_TYPE[type]), 'PT009', shapePath, issues);
567
+ if (value['shape'] !== expectedName) {
568
+ addIssue$1(issues, 'PT009', "particle.shape.shape must be " + JSON.stringify(expectedName) + " when type is " + String(type), "" + shapePath + ".shape");
569
+ }
570
+ for(var _iterator = _create_for_of_iterator_helper_loose(PARTICLE_SHAPE_NUMBER_FIELDS_BY_TYPE[type]), _step; !(_step = _iterator()).done;){
571
+ var field = _step.value;
572
+ if (!isFiniteNumber(value[field])) {
573
+ addIssue$1(issues, 'PT009', "particle.shape." + field + " must be a finite number", shapePath + "." + field);
574
+ }
575
+ }
576
+ for(var _i = 0, _iter = [
577
+ 'turbulenceX',
578
+ 'turbulenceY',
579
+ 'turbulenceZ'
580
+ ]; _i < _iter.length; _i++){
581
+ var field1 = _iter[_i];
582
+ if (Object.hasOwn(value, field1) && !isTaggedParticleShapeExpression(value[field1])) {
583
+ addIssue$1(issues, 'PT009', "particle.shape." + field1 + " must be a tagged two-element expression", shapePath + "." + field1);
584
+ }
585
+ }
586
+ if (type === 0) {
587
+ if (Object.hasOwn(value, 'upDirection') && !isFiniteNumberArray$1(value['upDirection'])) {
588
+ addIssue$1(issues, 'PT009', 'particle.shape.upDirection must contain finite numbers', "" + shapePath + ".upDirection");
589
+ }
590
+ return;
591
+ }
592
+ if (!isIntegerInRange$1(value['arcMode'], 0, 3)) {
593
+ addIssue$1(issues, 'PT009', 'particle.shape.arcMode must be an integer from 0 to 3', "" + shapePath + ".arcMode");
594
+ }
595
+ if (Object.hasOwn(value, 'alignSpeedDirection') && typeof value['alignSpeedDirection'] !== 'boolean') {
596
+ addIssue$1(issues, 'PT009', 'particle.shape.alignSpeedDirection must be a boolean', "" + shapePath + ".alignSpeedDirection");
597
+ }
598
+ if (Object.hasOwn(value, 'upDirection') && !isFiniteNumberTuple$1(value['upDirection'], 3)) {
599
+ addIssue$1(issues, 'PT009', 'particle.shape.upDirection must contain three finite numbers', "" + shapePath + ".upDirection");
600
+ }
601
+ if (type === 9) {
602
+ checkParticleTextureShapeDetail(value['detail'], "" + shapePath + ".detail", issues);
603
+ }
604
+ }
605
+ function checkParticleTextureShapeDetail(value, detailPath, issues) {
606
+ if (!isRecord$1(value)) {
607
+ addIssue$1(issues, 'PT009', 'particle.shape.detail must be an object', detailPath);
608
+ return;
609
+ }
610
+ reportUnknownFields(value, new Set([
611
+ 'width',
612
+ 'height',
613
+ 'block',
614
+ 'anchors'
615
+ ]), 'PT009', detailPath, issues);
616
+ for(var _i = 0, _iter = [
617
+ 'width',
618
+ 'height'
619
+ ]; _i < _iter.length; _i++){
620
+ var field = _iter[_i];
621
+ if (!isFiniteNumber(value[field])) {
622
+ addIssue$1(issues, 'PT009', "particle.shape.detail." + field + " must be a finite number", detailPath + "." + field);
623
+ }
624
+ }
625
+ if (!isFiniteNumberTuple$1(value['block'], 2)) {
626
+ addIssue$1(issues, 'PT009', 'particle.shape.detail.block must contain two finite numbers', "" + detailPath + ".block");
627
+ }
628
+ if (!isFiniteNumberArray$1(value['anchors'])) {
629
+ addIssue$1(issues, 'PT009', 'particle.shape.detail.anchors must contain finite numbers', "" + detailPath + ".anchors");
630
+ }
631
+ }
632
+ function checkParticleOptionsValue(value, optionsPath, issues) {
633
+ if (!isRecord$1(value)) {
634
+ addIssue$1(issues, 'PT006', "particle.options is " + describeValueType$1(value) + ", expected an object", optionsPath);
635
+ return;
636
+ }
637
+ reportUnknownFields(value, new Set([
638
+ 'maxCount',
639
+ 'startLifetime'
640
+ ]), 'PT005', optionsPath, issues);
641
+ var maxCount = value['maxCount'];
642
+ if (!isFiniteNumber(maxCount) || !Number.isInteger(maxCount) || maxCount <= 0) {
643
+ addIssue$1(issues, 'PT007', 'particle.options.maxCount must be a positive integer', "" + optionsPath + ".maxCount");
644
+ }
645
+ if (!isParticleNumberExpression(value['startLifetime'], true)) {
646
+ addIssue$1(issues, 'PT008', 'particle.options.startLifetime must be a valid positive NumberExpression', "" + optionsPath + ".startLifetime");
647
+ }
648
+ }
649
+ function checkParticleEmissionValue(value, layer, emissionPath, issues) {
650
+ if (!isRecord$1(value)) {
651
+ addIssue$1(issues, 'PT001', "particle.emission is " + describeValueType$1(value) + ", expected an object", emissionPath);
652
+ return;
653
+ }
654
+ reportUnknownFields(value, new Set([
655
+ 'rateOverTime',
656
+ 'bursts'
657
+ ]), 'PT005', emissionPath, issues);
658
+ if (!isParticleNumberExpression(value['rateOverTime'], false)) {
659
+ addIssue$1(issues, 'PT002', 'particle.emission.rateOverTime must be a valid non-negative NumberExpression', "" + emissionPath + ".rateOverTime");
660
+ }
661
+ if (!Object.hasOwn(value, 'bursts')) {
662
+ return;
663
+ }
664
+ var bursts = value['bursts'];
665
+ if (!Array.isArray(bursts)) {
666
+ addIssue$1(issues, 'PT003', 'particle.emission.bursts must be an array', "" + emissionPath + ".bursts");
667
+ return;
668
+ }
669
+ bursts.forEach(function(burst, index) {
670
+ checkParticleBurst(burst, layer, emissionPath + ".bursts[" + index + "]", issues);
671
+ });
672
+ }
673
+ function checkParticleBurst(value, layer, burstPath, issues) {
674
+ if (!isRecord$1(value)) {
675
+ addIssue$1(issues, 'PT004', "particle burst is " + describeValueType$1(value) + ", expected an object", burstPath);
676
+ return;
677
+ }
678
+ reportUnknownFields(value, new Set([
679
+ 'time',
680
+ 'count',
681
+ 'cycles',
682
+ 'interval'
683
+ ]), 'PT004', burstPath, issues);
684
+ var time = value['time'];
685
+ var duration = readLayerDuration(layer);
686
+ if (!isFiniteNumber(time) || time < 0 || duration != null && time >= duration) {
687
+ addIssue$1(issues, 'PT004', 'particle burst time must be within the layer duration', "" + burstPath + ".time");
688
+ }
689
+ if (!isNonNegativeInteger(value['count'])) {
690
+ addIssue$1(issues, 'PT004', 'particle burst count must be a non-negative integer', "" + burstPath + ".count");
691
+ }
692
+ if (Object.hasOwn(value, 'cycles') && !isNonNegativeInteger(value['cycles'])) {
693
+ addIssue$1(issues, 'PT004', 'particle burst cycles must be a non-negative integer; 0 means unbounded', "" + burstPath + ".cycles");
694
+ }
695
+ if (Object.hasOwn(value, 'interval') && (!isFiniteNumber(value['interval']) || value['interval'] < 0)) {
696
+ addIssue$1(issues, 'PT004', 'particle burst interval must be a non-negative finite number', "" + burstPath + ".interval");
697
+ }
698
+ var cycles = Object.hasOwn(value, 'cycles') ? value['cycles'] : 1;
699
+ var interval = Object.hasOwn(value, 'interval') ? value['interval'] : 0;
700
+ if (isNonNegativeInteger(cycles) && (cycles === 0 || cycles > 1) && (!isFiniteNumber(interval) || interval <= 0)) {
701
+ addIssue$1(issues, 'PT004', 'particle burst interval must be greater than 0 when cycles is 0 or greater than 1', "" + burstPath + ".interval");
702
+ }
703
+ if (duration != null && isFiniteNumber(time) && time >= 0 && time < duration && isPositiveInteger(cycles) && isFiniteNumber(interval) && interval >= 0 && time + (cycles - 1) * interval >= duration) {
704
+ addIssue$1(issues, 'PT004', 'particle burst cycles extend beyond the layer duration', burstPath);
705
+ }
706
+ }
707
+ function reportUnknownFields(value, fieldSet, code, path, issues) {
708
+ for(var _iterator = _create_for_of_iterator_helper_loose(Object.keys(value)), _step; !(_step = _iterator()).done;){
709
+ var field = _step.value;
710
+ if (!fieldSet.has(field)) {
711
+ addIssue$1(issues, code, "unknown field " + JSON.stringify(field), path + "." + field);
712
+ }
713
+ }
714
+ }
715
+ function isParticleNumberExpression(value, positive) {
716
+ if (!Array.isArray(value) || value.length !== 2) {
717
+ return false;
718
+ }
719
+ var expression = value;
720
+ var type = expression[0];
721
+ var payload = expression[1];
722
+ if (type === ValueType.CONSTANT) {
723
+ return isParticleNumber(payload, positive);
724
+ }
725
+ if (type === ValueType.RANDOM) {
726
+ return isFiniteNumberTuple$1(payload, 2) && isParticleNumber(payload[0], positive) && isParticleNumber(payload[1], positive) && payload[0] <= payload[1];
727
+ }
728
+ return false;
729
+ }
730
+ function isParticleNumber(value, positive) {
731
+ return isFiniteNumber(value) && (positive ? value > 0 : value >= 0);
732
+ }
733
+ function readLayerDuration(layer) {
734
+ var timeRange = layer['time_range'];
735
+ if (!isFiniteNumberTuple$1(timeRange, 2)) {
736
+ return null;
737
+ }
738
+ return timeRange[1] - timeRange[0];
739
+ }
740
+ function isFiniteNumberTuple$1(value, length) {
741
+ return Array.isArray(value) && value.length === length && value.every(isFiniteNumber);
742
+ }
743
+ function isFiniteNumberArray$1(value) {
744
+ return Array.isArray(value) && value.every(isFiniteNumber);
745
+ }
746
+ function isTaggedParticleShapeExpression(value) {
747
+ return Array.isArray(value) && value.length === 2 && Number.isInteger(value[0]);
748
+ }
749
+ function isIntegerInRange$1(value, minimum, maximum) {
750
+ return isFiniteNumber(value) && Number.isInteger(value) && value >= minimum && value <= maximum;
751
+ }
752
+ function isNonNegativeInteger(value) {
753
+ return isFiniteNumber(value) && Number.isInteger(value) && value >= 0;
754
+ }
755
+ function isPositiveInteger(value) {
756
+ return isFiniteNumber(value) && Number.isInteger(value) && value > 0;
757
+ }
758
+ function isFiniteNumber(value) {
759
+ return typeof value === 'number' && Number.isFinite(value);
760
+ }
761
+ function describeValueType$1(value) {
762
+ if (value === null) {
763
+ return 'null';
764
+ }
765
+ if (Array.isArray(value)) {
766
+ return 'an array';
767
+ }
768
+ return typeof value === "undefined" ? "undefined" : _type_of(value);
769
+ }
770
+ function addIssue$1(issues, code, message, path) {
771
+ issues.push({
772
+ code: code,
773
+ message: message,
774
+ path: path
775
+ });
776
+ }
777
+
778
+ var SPATIAL_PROPERTIES = [
779
+ 'position',
780
+ 'rotation',
781
+ 'scale',
782
+ 'anchor'
783
+ ];
784
+ var VALID_LAYER_TYPE_SET = new Set([
785
+ 'null',
786
+ 'layer',
787
+ 'text',
788
+ 'particle'
789
+ ]);
790
+ var VALID_ASSET_SOURCE_SET = new Set([
791
+ 'user',
792
+ 'llm_svg'
793
+ ]);
794
+ var EPSILON = 1e-9;
795
+ /** Lint an unnormalized DSL value while preserving issue severity. */ function lintDSL(dsl) {
796
+ var context = {
797
+ issues: [],
798
+ duration: null
799
+ };
800
+ if (containsCircularReference(dsl)) {
801
+ addIssue(context, 'ERROR', 'R001', 'DSL root contains circular references, expected a JSON-compatible object', '');
802
+ return createLintReport(context.issues);
803
+ }
804
+ if (!checkRoot(dsl, context)) {
805
+ return createLintReport(context.issues);
806
+ }
807
+ checkMeta(dsl, context);
808
+ var entries = walkLayers(dsl['layers'], context);
809
+ for(var _iterator = _create_for_of_iterator_helper_loose(entries), _step; !(_step = _iterator()).done;){
810
+ var entry = _step.value;
811
+ checkLayerBase(entry, context);
812
+ checkProperties(entry, context);
813
+ checkLayerContent(entry, context);
814
+ }
815
+ checkLayerRelationships(entries, context);
816
+ return createLintReport(context.issues);
817
+ }
818
+ /**
819
+ * Validate DSL and return the public validation result.
820
+ * Strings are interpreted as raw JSON. File-system paths are intentionally not
821
+ * accepted so the same validator works unchanged in Node.js and browsers.
822
+ */ function validateDSL(dsl, options) {
823
+ if (options === void 0) options = {};
824
+ var coerced = coerceInput(dsl);
825
+ if ('error' in coerced) {
826
+ return createInputErrorResult(coerced.error);
827
+ }
828
+ var report = lintDSL(coerced.value);
829
+ var errors = report.issues.filter(function(issue) {
830
+ return issue.severity === 'ERROR';
831
+ }).map(convertToValidationIssue);
832
+ var warnings = report.issues.filter(function(issue) {
833
+ return issue.severity === 'WARNING';
834
+ }).map(convertToValidationIssue);
835
+ var hasFailed = errors.length > 0 || options.strict === true && warnings.length > 0;
836
+ return {
837
+ result: hasFailed ? 'fail' : 'pass',
838
+ summary: errors.length + " errors, " + warnings.length + " warnings",
839
+ errors: errors,
840
+ warnings: warnings
841
+ };
842
+ }
843
+ /** Error thrown when a value cannot be used as a valid DSL composition. */ var DSLValidationError = /*#__PURE__*/ function(TypeError1) {
844
+ _inherits(DSLValidationError, TypeError1);
845
+ function DSLValidationError(issues) {
846
+ var _this;
847
+ _this = TypeError1.call(this, issues.map(function(issue) {
848
+ return issue.code + ": " + issue.message;
849
+ }).join('; ')) || this;
850
+ _this.name = 'DSLValidationError';
851
+ _this.issues = issues;
852
+ return _this;
853
+ }
854
+ DSLValidationError.fromValidationResult = function fromValidationResult(validationResult) {
855
+ return new DSLValidationError([].concat(validationResult.errors, validationResult.warnings));
856
+ };
857
+ return DSLValidationError;
858
+ }(_wrap_native_super(TypeError));
859
+ function coerceInput(dsl) {
860
+ if (typeof dsl !== 'string') {
861
+ if (isRecord$1(dsl)) {
862
+ if (containsCircularReference(dsl)) {
863
+ return {
864
+ error: 'DSL value contains circular references and cannot be represented as JSON'
865
+ };
866
+ }
867
+ return {
868
+ value: dsl
869
+ };
870
+ }
871
+ return {
872
+ error: "expected a DSL object or raw JSON string, got " + describeValueType(dsl)
873
+ };
874
+ }
875
+ var firstCharacter = dsl.trimStart()[0];
876
+ if (firstCharacter !== '{' && firstCharacter !== '[') {
877
+ return {
878
+ error: 'expected raw DSL JSON text beginning with { or ['
879
+ };
880
+ }
881
+ try {
882
+ return {
883
+ value: JSON.parse(dsl)
884
+ };
885
+ } catch (error) {
886
+ return {
887
+ error: "invalid JSON: " + (_instanceof(error, Error) ? error.message : String(error))
888
+ };
889
+ }
890
+ }
891
+ function createInputErrorResult(message) {
892
+ return {
893
+ result: 'fail',
894
+ summary: 'input cannot be read as DSL JSON',
895
+ errors: [
896
+ {
897
+ code: 'INPUT_ERROR',
898
+ label: '输入无法解析为 DSL JSON',
899
+ message: message,
900
+ path: '',
901
+ layerId: null
902
+ }
903
+ ],
904
+ warnings: []
905
+ };
906
+ }
907
+ function createLintReport(issues) {
908
+ var errorCount = issues.filter(function(issue) {
909
+ return issue.severity === 'ERROR';
910
+ }).length;
911
+ var warningCount = issues.length - errorCount;
912
+ return {
913
+ ok: issues.length === 0,
914
+ hasErrors: errorCount > 0,
915
+ counts: {
916
+ ERROR: errorCount,
917
+ WARNING: warningCount
918
+ },
919
+ issues: issues
920
+ };
921
+ }
922
+ function convertToValidationIssue(issue) {
923
+ var _DSL_CODE_LABELS_issue_code;
924
+ return {
925
+ code: issue.code,
926
+ label: (_DSL_CODE_LABELS_issue_code = DSL_CODE_LABELS[issue.code]) != null ? _DSL_CODE_LABELS_issue_code : '',
927
+ message: issue.message,
928
+ path: issue.path,
929
+ layerId: issue.layerId
930
+ };
931
+ }
932
+ function addIssue(context, severity, code, message, path, layerId) {
933
+ if (layerId === void 0) layerId = null;
934
+ context.issues.push({
935
+ severity: severity,
936
+ code: code,
937
+ message: message,
938
+ path: path,
939
+ layerId: layerId
940
+ });
941
+ }
942
+ function checkRoot(dsl, context) {
943
+ if (!isRecord$1(dsl)) {
944
+ addIssue(context, 'ERROR', 'R001', "DSL root is " + describeValueType(dsl) + ", expected an object", '');
945
+ return false;
946
+ }
947
+ if (!hasValue(dsl, 'meta')) {
948
+ addIssue(context, 'ERROR', 'R002', "missing 'meta' object", 'meta');
949
+ }
950
+ if (!hasValue(dsl, 'layers')) {
951
+ addIssue(context, 'ERROR', 'R003', "missing 'layers' array", 'layers');
952
+ } else if (!Array.isArray(dsl['layers'])) {
953
+ addIssue(context, 'ERROR', 'R004', "layers is " + describeValueType(dsl['layers']) + ", expected an array", 'layers');
954
+ }
955
+ return true;
956
+ }
957
+ function checkMeta(dsl, context) {
958
+ var meta = dsl['meta'];
959
+ if (!isRecord$1(meta)) {
960
+ return;
961
+ }
962
+ var required = [
963
+ [
964
+ 'name',
965
+ 'string',
966
+ function(value) {
967
+ return typeof value === 'string';
968
+ },
969
+ 'M002a'
970
+ ],
971
+ [
972
+ 'duration',
973
+ 'number',
974
+ isNumber,
975
+ 'M002b'
976
+ ],
977
+ [
978
+ 'fps',
979
+ 'integer',
980
+ isIntLike,
981
+ 'M002c'
982
+ ],
983
+ [
984
+ 'width',
985
+ 'integer',
986
+ isIntLike,
987
+ 'M002d'
988
+ ],
989
+ [
990
+ 'height',
991
+ 'integer',
992
+ isIntLike,
993
+ 'M002e'
994
+ ],
995
+ [
996
+ 'loop',
997
+ 'boolean',
998
+ function(value) {
999
+ return typeof value === 'boolean';
1000
+ },
1001
+ 'M002f'
1002
+ ]
1003
+ ];
1004
+ for(var _iterator = _create_for_of_iterator_helper_loose(required), _step; !(_step = _iterator()).done;){
1005
+ var _step_value = _step.value, field = _step_value[0], expected = _step_value[1], accepts = _step_value[2], code = _step_value[3];
1006
+ if (!hasValue(meta, field)) {
1007
+ addIssue(context, 'ERROR', 'M001', "meta." + field + " is missing", "meta." + field);
1008
+ } else if (!accepts(meta[field])) {
1009
+ addIssue(context, 'ERROR', code, "meta." + field + " is " + describeValueType(meta[field]) + ", expected " + expected, "meta." + field);
1010
+ }
1011
+ }
1012
+ if (meta['background_color'] != null) {
1013
+ var background = meta['background_color'];
1014
+ if (typeof background !== 'string') {
1015
+ addIssue(context, 'ERROR', 'M003', "meta.background_color is " + describeValueType(background) + ", expected a string", 'meta.background_color');
1016
+ } else if (!isValidHexColor(background)) {
1017
+ addIssue(context, 'ERROR', 'M004', "meta.background_color " + formatValue(background) + " is not a supported hex color", 'meta.background_color');
1018
+ }
1019
+ }
1020
+ var fps = meta['fps'];
1021
+ var width = meta['width'];
1022
+ var height = meta['height'];
1023
+ var duration = meta['duration'];
1024
+ if (isIntLike(fps) && fps <= 0) {
1025
+ addIssue(context, 'ERROR', 'M005', "meta.fps is " + formatNumber(fps) + ", must be > 0", 'meta.fps');
1026
+ }
1027
+ if (isIntLike(width) && width <= 0) {
1028
+ addIssue(context, 'ERROR', 'M006', "meta.width is " + formatNumber(width) + ", must be > 0", 'meta.width');
1029
+ }
1030
+ if (isIntLike(height) && height <= 0) {
1031
+ addIssue(context, 'ERROR', 'M006', "meta.height is " + formatNumber(height) + ", must be > 0", 'meta.height');
1032
+ }
1033
+ if (isNumber(duration)) {
1034
+ if (duration <= 0) {
1035
+ addIssue(context, 'ERROR', 'M007', "meta.duration is " + formatNumber(duration) + ", must be > 0", 'meta.duration');
1036
+ } else {
1037
+ context.duration = duration;
1038
+ }
1039
+ }
1040
+ }
1041
+ function walkLayers(layers, context) {
1042
+ var entries = [];
1043
+ if (!Array.isArray(layers)) {
1044
+ return entries;
1045
+ }
1046
+ var visitLayer = function visitLayer1(layer, path, physicalParentId) {
1047
+ if (!isRecord$1(layer)) {
1048
+ addIssue(context, 'ERROR', 'L021', "layer entry is " + describeValueType(layer) + ", expected an object", path, physicalParentId);
1049
+ return;
1050
+ }
1051
+ var layerId = readLayerId(layer);
1052
+ entries.push({
1053
+ layer: layer,
1054
+ path: path,
1055
+ layerId: layerId,
1056
+ physicalParentId: physicalParentId
1057
+ });
1058
+ var children = layer['children'];
1059
+ if (children == null) {
1060
+ return;
1061
+ }
1062
+ if (!Array.isArray(children)) {
1063
+ addIssue(context, 'ERROR', 'L022', "children is " + describeValueType(children) + ", expected an array", "" + path + ".children", layerId);
1064
+ return;
1065
+ }
1066
+ children.forEach(function(child, index) {
1067
+ return visitLayer(child, path + ".children[" + index + "]", layerId);
1068
+ });
1069
+ };
1070
+ layers.forEach(function(layer, index) {
1071
+ return visitLayer(layer, "layers[" + index + "]", null);
1072
+ });
1073
+ return entries;
1074
+ }
1075
+ function checkLayerBase(entry, context) {
1076
+ var layer = entry.layer, path = entry.path, layerId = entry.layerId;
1077
+ if (!hasValue(layer, 'id')) {
1078
+ addIssue(context, 'ERROR', 'L001', 'id is missing', "" + path + ".id");
1079
+ } else if (typeof layer['id'] !== 'string') {
1080
+ addIssue(context, 'ERROR', 'L002', "id is " + describeValueType(layer['id']) + ", expected a string", "" + path + ".id");
1081
+ } else if (layer['id'] === '') {
1082
+ addIssue(context, 'ERROR', 'L003', 'id is an empty string', "" + path + ".id");
1083
+ }
1084
+ if (!hasValue(layer, 'name')) {
1085
+ addIssue(context, 'ERROR', 'L004', 'name is missing', "" + path + ".name");
1086
+ } else if (typeof layer['name'] !== 'string') {
1087
+ addIssue(context, 'ERROR', 'L005', "name is " + describeValueType(layer['name']) + ", expected a string", "" + path + ".name");
1088
+ }
1089
+ if (!hasValue(layer, 'type')) {
1090
+ addIssue(context, 'ERROR', 'L006', 'type is missing', "" + path + ".type");
1091
+ } else if (!VALID_LAYER_TYPE_SET.has(String(layer['type']))) {
1092
+ addIssue(context, 'ERROR', 'L007', "type " + formatValue(layer['type']) + " not in {null, layer, text, particle}", "" + path + ".type");
1093
+ }
1094
+ for(var _i = 0, _iter = [
1095
+ [
1096
+ 'width',
1097
+ 'L008',
1098
+ 'L009'
1099
+ ],
1100
+ [
1101
+ 'height',
1102
+ 'L010',
1103
+ 'L011'
1104
+ ]
1105
+ ]; _i < _iter.length; _i++){
1106
+ var _iter__i = _iter[_i], field = _iter__i[0], missingCode = _iter__i[1], typeCode = _iter__i[2];
1107
+ if (!hasValue(layer, field)) {
1108
+ addIssue(context, 'ERROR', missingCode, "" + field + " is missing", path + "." + field);
1109
+ } else if (!isNumber(layer[field])) {
1110
+ addIssue(context, 'ERROR', typeCode, field + " is " + describeValueType(layer[field]) + ", expected a number", path + "." + field);
1111
+ } else if (layer[field] < 0) {
1112
+ addIssue(context, 'ERROR', typeCode, field + " is " + formatNumber(layer[field]) + ", expected a number greater than or equal to 0", path + "." + field);
1113
+ }
1114
+ }
1115
+ var description = layer['description'];
1116
+ if (!hasValue(layer, 'description')) {
1117
+ addIssue(context, 'ERROR', 'L012', 'description is missing', "" + path + ".description");
1118
+ } else if (!isRecord$1(description)) {
1119
+ addIssue(context, 'ERROR', 'L013', "description is " + describeValueType(description) + ", expected an object", "" + path + ".description");
1120
+ } else {
1121
+ for(var _i1 = 0, _iter1 = [
1122
+ [
1123
+ 'self',
1124
+ 'L014'
1125
+ ],
1126
+ [
1127
+ 'composite',
1128
+ 'L015'
1129
+ ]
1130
+ ]; _i1 < _iter1.length; _i1++){
1131
+ var _iter__i1 = _iter1[_i1], field1 = _iter__i1[0], code = _iter__i1[1];
1132
+ if (!hasValue(description, field1)) {
1133
+ addIssue(context, 'ERROR', code, "description." + field1 + " is missing", path + ".description." + field1);
1134
+ } else if (typeof description[field1] !== 'string') {
1135
+ addIssue(context, 'ERROR', 'L016', "description." + field1 + " is " + describeValueType(description[field1]) + ", expected a string", path + ".description." + field1);
1136
+ }
1137
+ }
1138
+ }
1139
+ var timeRange = layer['time_range'];
1140
+ var hasNumericTimeRange = false;
1141
+ if (timeRange === undefined) {
1142
+ return;
1143
+ }
1144
+ if (!Array.isArray(timeRange) || timeRange.length !== 2) {
1145
+ var got = Array.isArray(timeRange) ? "array of length " + timeRange.length : describeValueType(timeRange);
1146
+ addIssue(context, 'ERROR', 'L018', "time_range is " + got + ", expected [number, number]", "" + path + ".time_range");
1147
+ } else if (!timeRange.every(isNumber)) {
1148
+ addIssue(context, 'ERROR', 'L019', 'time_range elements must be numbers', "" + path + ".time_range");
1149
+ } else {
1150
+ hasNumericTimeRange = true;
1151
+ }
1152
+ if (hasNumericTimeRange && Array.isArray(timeRange)) {
1153
+ var start = timeRange[0];
1154
+ var end = timeRange[1];
1155
+ if (start > end) {
1156
+ addIssue(context, 'ERROR', 'L020', "time_range [" + formatNumber(start) + ", " + formatNumber(end) + "] — start must be <= end", "" + path + ".time_range", layerId);
1157
+ } else if (start === end) {
1158
+ addIssue(context, 'WARNING', 'L020', "time_range [" + formatNumber(start) + ", " + formatNumber(end) + "] has zero duration", "" + path + ".time_range", layerId);
1159
+ }
1160
+ if (context.duration != null && (start < -EPSILON || end > context.duration + EPSILON)) {
1161
+ addIssue(context, 'WARNING', 'L023', "time_range [" + formatNumber(start) + ", " + formatNumber(end) + "] falls outside [0, " + formatNumber(context.duration) + "]", "" + path + ".time_range", layerId);
1162
+ }
1163
+ }
1164
+ }
1165
+ function checkProperties(entry, context) {
1166
+ var _loop = function() {
1167
+ var propertyName = _step.value;
1168
+ var dimension = propertyName === 'opacity' ? 'scalar' : 3;
1169
+ var propertyPath = path + "." + propertyName;
1170
+ var property = layer[propertyName];
1171
+ if (propertyName !== 'position' && property === undefined) {
1172
+ return "continue";
1173
+ }
1174
+ if (property == null) {
1175
+ addIssue(context, 'ERROR', 'P001', "" + propertyName + " is missing", propertyPath, layerId);
1176
+ return "continue";
1177
+ }
1178
+ if (!isRecord$1(property)) {
1179
+ addIssue(context, 'ERROR', 'P002', propertyName + " is " + describeValueType(property) + ", expected an object", propertyPath, layerId);
1180
+ return "continue";
1181
+ }
1182
+ var animated = property['a'];
1183
+ if (!hasValue(property, 'a')) {
1184
+ addIssue(context, 'ERROR', 'P003', "" + propertyName + ".a is missing", "" + propertyPath + ".a", layerId);
1185
+ return "continue";
1186
+ }
1187
+ if (typeof animated !== 'boolean') {
1188
+ addIssue(context, 'ERROR', 'P004', propertyName + ".a is " + describeValueType(animated) + ", expected a boolean", "" + propertyPath + ".a", layerId);
1189
+ return "continue";
1190
+ }
1191
+ var hasAnimation = hasValue(property, 'animation');
1192
+ var hasValueField = hasValue(property, 'value');
1193
+ if (!animated) {
1194
+ checkStaticValue(propertyName, dimension, property, propertyPath, layerId, context);
1195
+ if (hasAnimation) {
1196
+ addIssue(context, 'ERROR', 'P006', "" + propertyName + ".animation present while a=false", "" + propertyPath + ".animation", layerId);
1197
+ }
1198
+ return "continue";
1199
+ }
1200
+ if (propertyName === 'anchor') {
1201
+ addIssue(context, 'ERROR', 'P015', 'anchor animation is unsupported; anchor must use a static value', propertyPath, layerId);
1202
+ }
1203
+ if (!hasAnimation) {
1204
+ addIssue(context, 'ERROR', 'P007', "" + propertyName + ".animation missing while a=true", "" + propertyPath + ".animation", layerId);
1205
+ return "continue";
1206
+ }
1207
+ var animation = property['animation'];
1208
+ if (!Array.isArray(animation)) {
1209
+ addIssue(context, 'ERROR', 'P008', propertyName + ".animation is " + describeValueType(animation) + ", expected an array", "" + propertyPath + ".animation", layerId);
1210
+ return "continue";
1211
+ }
1212
+ if (hasValueField) {
1213
+ addIssue(context, 'ERROR', 'P009', "" + propertyName + ".value present while a=true", "" + propertyPath + ".value", layerId);
1214
+ }
1215
+ if (animation.length === 0) {
1216
+ addIssue(context, 'WARNING', 'P010', "" + propertyName + ".animation is empty (no segments)", "" + propertyPath + ".animation", layerId);
1217
+ return "continue";
1218
+ }
1219
+ var animationPath = "" + propertyPath + ".animation";
1220
+ var curves = animation.map(function(curve, index) {
1221
+ return checkCurve(propertyName, dimension, curve, animationPath + "[" + index + "]", layerId, context);
1222
+ });
1223
+ checkContinuity(propertyName, curves, animationPath, layerId, context);
1224
+ };
1225
+ var layer = entry.layer, path = entry.path, layerId = entry.layerId;
1226
+ for(var _iterator = _create_for_of_iterator_helper_loose([].concat(SPATIAL_PROPERTIES, [
1227
+ 'opacity'
1228
+ ])), _step; !(_step = _iterator()).done;)_loop();
1229
+ }
1230
+ function checkStaticValue(propertyName, dimension, property, propertyPath, layerId, context) {
1231
+ var value = property['value'];
1232
+ if (!hasValue(property, 'value')) {
1233
+ addIssue(context, 'ERROR', 'P005', "" + propertyName + ".value missing while a=false", "" + propertyPath + ".value", layerId);
1234
+ return;
1235
+ }
1236
+ if (dimension === 3) {
1237
+ if (!Array.isArray(value) || value.length !== 3) {
1238
+ var got = Array.isArray(value) ? "array length " + value.length : describeValueType(value);
1239
+ addIssue(context, 'ERROR', 'P011', propertyName + ".value must be a 3-element array, got " + got, "" + propertyPath + ".value", layerId);
1240
+ return;
1241
+ }
1242
+ if (!value.every(isNumber)) {
1243
+ addIssue(context, 'WARNING', 'P013', "" + propertyName + ".value has non-numeric elements", "" + propertyPath + ".value", layerId);
1244
+ }
1245
+ } else if (!isNumber(value)) {
1246
+ addIssue(context, 'ERROR', 'P012', "opacity.value is " + describeValueType(value) + ", expected a number", "" + propertyPath + ".value", layerId);
1247
+ } else if (value < -EPSILON || value > 1 + EPSILON) {
1248
+ addIssue(context, 'ERROR', 'P014', "opacity.value " + formatNumber(value) + " out of [0, 1]", "" + propertyPath + ".value", layerId);
1249
+ }
1250
+ }
1251
+ function checkCurve(propertyName, dimension, curve, segmentPath, layerId, context) {
1252
+ if (!isRecord$1(curve)) {
1253
+ addIssue(context, 'ERROR', 'C001', "animation segment is " + describeValueType(curve) + ", expected an object", segmentPath, layerId);
1254
+ return null;
1255
+ }
1256
+ var timeRange = curve['t'];
1257
+ var isTimeRangeValid = false;
1258
+ if (!hasValue(curve, 't')) {
1259
+ addIssue(context, 'ERROR', 'C002', 't is missing', "" + segmentPath + ".t", layerId);
1260
+ } else if (!Array.isArray(timeRange) || timeRange.length !== 2) {
1261
+ var got = Array.isArray(timeRange) ? "array length " + timeRange.length : describeValueType(timeRange);
1262
+ addIssue(context, 'ERROR', 'C003', "t must be a 2-element array, got " + got, "" + segmentPath + ".t", layerId);
1263
+ } else if (!timeRange.every(isNumber)) {
1264
+ addIssue(context, 'ERROR', 'C005', 't elements must be numbers', "" + segmentPath + ".t", layerId);
1265
+ } else {
1266
+ isTimeRangeValid = true;
1267
+ }
1268
+ if (isTimeRangeValid && Array.isArray(timeRange)) {
1269
+ var start = timeRange[0];
1270
+ var end = timeRange[1];
1271
+ if (start >= end) {
1272
+ addIssue(context, 'ERROR', 'C004', "t [" + formatNumber(start) + ", " + formatNumber(end) + "] — start >= end", "" + segmentPath + ".t", layerId);
1273
+ }
1274
+ if (context.duration != null && (start < -EPSILON || end > context.duration + EPSILON)) {
1275
+ addIssue(context, 'WARNING', 'C016', "t [" + formatNumber(start) + ", " + formatNumber(end) + "] falls outside [0, " + formatNumber(context.duration) + "]", "" + segmentPath + ".t", layerId);
1276
+ }
1277
+ }
1278
+ var isStartValid = checkCurveEndpoint(dimension, curve, 'start', 'C006', segmentPath, layerId, context);
1279
+ var isEndValid = checkCurveEndpoint(dimension, curve, 'end', 'C007', segmentPath, layerId, context);
1280
+ var easing = curve['easing'];
1281
+ if (!hasValue(curve, 'easing')) {
1282
+ addIssue(context, 'ERROR', 'C011', 'easing is missing', "" + segmentPath + ".easing", layerId);
1283
+ } else if (!Array.isArray(easing) || easing.length !== 4) {
1284
+ var got1 = Array.isArray(easing) ? "array length " + easing.length : describeValueType(easing);
1285
+ addIssue(context, 'ERROR', 'C011', "easing must be a 4-element array [x1,y1,x2,y2], got " + got1, "" + segmentPath + ".easing", layerId);
1286
+ } else if (!easing.every(isNumber)) {
1287
+ addIssue(context, 'ERROR', 'C012', 'easing elements must be numbers', "" + segmentPath + ".easing", layerId);
1288
+ } else if (easing[0] < 0 || easing[0] > 1 || easing[2] < 0 || easing[2] > 1) {
1289
+ addIssue(context, 'ERROR', 'C012', 'easing x control points must be in the [0, 1] range', "" + segmentPath + ".easing", layerId);
1290
+ }
1291
+ for(var _i = 0, _iter = [
1292
+ 'in',
1293
+ 'out'
1294
+ ]; _i < _iter.length; _i++){
1295
+ var key = _iter[_i];
1296
+ if (!hasValue(curve, key)) {
1297
+ continue;
1298
+ }
1299
+ if (propertyName !== 'position') {
1300
+ addIssue(context, 'ERROR', 'C013', "'" + key + "' tangent only allowed on position, not " + propertyName, segmentPath + "." + key, layerId);
1301
+ } else {
1302
+ var tangent = curve[key];
1303
+ if (!Array.isArray(tangent) || tangent.length !== 3 || !tangent.every(isNumber)) {
1304
+ var got2 = Array.isArray(tangent) ? "array length " + tangent.length : describeValueType(tangent);
1305
+ addIssue(context, 'ERROR', 'C014', "'" + key + "' must be a finite 3-element array, got " + got2, segmentPath + "." + key, layerId);
1306
+ }
1307
+ }
1308
+ }
1309
+ if (!isTimeRangeValid || !isStartValid || !isEndValid || !Array.isArray(timeRange)) {
1310
+ return null;
1311
+ }
1312
+ return {
1313
+ t: [
1314
+ timeRange[0],
1315
+ timeRange[1]
1316
+ ],
1317
+ start: curve['start'],
1318
+ end: curve['end']
1319
+ };
1320
+ }
1321
+ function checkCurveEndpoint(dimension, curve, key, missingCode, segmentPath, layerId, context) {
1322
+ var value = curve[key];
1323
+ if (!hasValue(curve, key)) {
1324
+ addIssue(context, 'ERROR', missingCode, "" + key + " is missing", segmentPath + "." + key, layerId);
1325
+ return false;
1326
+ }
1327
+ if (dimension === 3) {
1328
+ if (!Array.isArray(value) || value.length !== 3) {
1329
+ var got = Array.isArray(value) ? "array length " + value.length : describeValueType(value);
1330
+ addIssue(context, 'ERROR', 'C008', key + " must be a 3-element array, got " + got, segmentPath + "." + key, layerId);
1331
+ return false;
1332
+ }
1333
+ if (!value.every(isNumber)) {
1334
+ addIssue(context, 'ERROR', 'C008', "" + key + " must contain finite numbers", segmentPath + "." + key, layerId);
1335
+ return false;
1336
+ }
1337
+ return true;
1338
+ }
1339
+ if (isNumber(value)) {
1340
+ if (value < -EPSILON || value > 1 + EPSILON) {
1341
+ addIssue(context, 'ERROR', 'C009', "" + key + " must be in the [0, 1] range", segmentPath + "." + key, layerId);
1342
+ return false;
1343
+ }
1344
+ addIssue(context, 'WARNING', 'C010', key + " is a scalar " + formatNumber(value) + "; expected a 1-element array (accepted and normalized)", segmentPath + "." + key, layerId);
1345
+ return true;
1346
+ }
1347
+ if (Array.isArray(value)) {
1348
+ if (value.length === 1) {
1349
+ if (!isNumber(value[0]) || value[0] < -EPSILON || value[0] > 1 + EPSILON) {
1350
+ addIssue(context, 'ERROR', 'C009', "" + key + " must contain one finite number in the [0, 1] range", segmentPath + "." + key, layerId);
1351
+ return false;
1352
+ }
1353
+ return true;
1354
+ }
1355
+ addIssue(context, 'ERROR', 'C009', key + " must be a 1-element array, got array length " + value.length, segmentPath + "." + key, layerId);
1356
+ return false;
1357
+ }
1358
+ addIssue(context, 'ERROR', 'C009', key + " is " + describeValueType(value) + ", expected a 1-element array", segmentPath + "." + key, layerId);
1359
+ return false;
1360
+ }
1361
+ function checkContinuity(propertyName, curves, animationPath, layerId, context) {
1362
+ var validCurves = curves.filter(function(curve) {
1363
+ return curve != null;
1364
+ });
1365
+ for(var index = 0; index < validCurves.length - 1; index++){
1366
+ var left = validCurves[index];
1367
+ var right = validCurves[index + 1];
1368
+ var path = animationPath + "[segments " + index + "->" + (index + 1) + "]";
1369
+ if (left.t[1] > right.t[0] + EPSILON) {
1370
+ addIssue(context, 'WARNING', 'S002', propertyName + ": segments " + index + "/" + (index + 1) + " overlap (t " + formatValue(left.t) + " / " + formatValue(right.t) + ")", path, layerId);
1371
+ } else if (left.t[1] < right.t[0] - EPSILON) {
1372
+ addIssue(context, 'WARNING', 'S003', propertyName + ": gap between segments " + index + "/" + (index + 1) + " (t " + formatValue(left.t) + " / " + formatValue(right.t) + ")", path, layerId);
1373
+ }
1374
+ if (right.t[0] < left.t[0] - EPSILON) {
1375
+ addIssue(context, 'WARNING', 'S004', propertyName + ": segments not monotonic at " + index + "/" + (index + 1) + " (t " + formatValue(left.t) + " / " + formatValue(right.t) + ")", path, layerId);
1376
+ }
1377
+ }
1378
+ }
1379
+ function checkLayerContent(entry, context) {
1380
+ var layer = entry.layer, path = entry.path, layerId = entry.layerId;
1381
+ var layerType = layer['type'];
1382
+ if (typeof layerType !== 'string' || !VALID_LAYER_TYPE_SET.has(layerType)) {
1383
+ return;
1384
+ }
1385
+ var asset = layer['asset'];
1386
+ var hasAsset = hasValue(layer, 'asset');
1387
+ var particle = layer['particle'];
1388
+ var hasParticle = hasValue(layer, 'particle');
1389
+ if (layerType !== 'particle' && hasParticle) {
1390
+ addIssue(context, 'WARNING', 'A024', "type=" + layerType + " has a particle block (ignored)", "" + path + ".particle", layerId);
1391
+ }
1392
+ if (layerType === 'null') {
1393
+ if (hasAsset) {
1394
+ addIssue(context, 'WARNING', 'A010', 'null layer has an asset (ignored)', "" + path + ".asset", layerId);
1395
+ }
1396
+ return;
1397
+ }
1398
+ if (layerType === 'layer') {
1399
+ if (!hasAsset) {
1400
+ addIssue(context, 'ERROR', 'A001', 'type=layer requires an asset', "" + path + ".asset", layerId);
1401
+ } else if (!isRecord$1(asset)) {
1402
+ addIssue(context, 'ERROR', 'A002', "asset is " + describeValueType(asset) + ", expected an object", "" + path + ".asset", layerId);
1403
+ } else {
1404
+ checkAssetFields(asset, "" + path + ".asset", layerId, context);
1405
+ }
1406
+ if (hasValue(layer, 'text')) {
1407
+ addIssue(context, 'WARNING', 'A016', 'type=layer has a text block (ignored)', "" + path + ".text", layerId);
1408
+ }
1409
+ if (isNumber(layer['width']) && layer['width'] <= 0 || isNumber(layer['height']) && layer['height'] <= 0) {
1410
+ addIssue(context, 'ERROR', 'L024', 'image layers require width and height greater than 0', path, layerId);
1411
+ }
1412
+ return;
1413
+ }
1414
+ if (layerType === 'particle') {
1415
+ if (isNumber(layer['width']) && layer['width'] <= 0 || isNumber(layer['height']) && layer['height'] <= 0) {
1416
+ addIssue(context, 'ERROR', 'L024', 'particle layers require width and height greater than 0', path, layerId);
1417
+ }
1418
+ if (!hasParticle) {
1419
+ addIssue(context, 'ERROR', 'A022', 'type=particle requires a particle block', "" + path + ".particle", layerId);
1420
+ } else if (!isRecord$1(particle)) {
1421
+ addIssue(context, 'ERROR', 'A023', "particle is " + describeValueType(particle) + ", expected an object", "" + path + ".particle", layerId);
1422
+ } else {
1423
+ for(var _iterator = _create_for_of_iterator_helper_loose(lintParticle(particle, layer, "" + path + ".particle")), _step; !(_step = _iterator()).done;){
1424
+ var issue = _step.value;
1425
+ addIssue(context, 'ERROR', issue.code, issue.message, issue.path, layerId);
1426
+ }
1427
+ }
1428
+ if (hasAsset) {
1429
+ addIssue(context, 'WARNING', 'A025', 'type=particle has an asset (ignored)', "" + path + ".asset", layerId);
1430
+ }
1431
+ if (hasValue(layer, 'text')) {
1432
+ addIssue(context, 'WARNING', 'A026', 'type=particle has a text block (ignored)', "" + path + ".text", layerId);
1433
+ }
1434
+ return;
1435
+ }
1436
+ var text = layer['text'];
1437
+ if (!hasValue(layer, 'text')) {
1438
+ addIssue(context, 'ERROR', 'A011', 'type=text requires a text block', "" + path + ".text", layerId);
1439
+ } else if (!isRecord$1(text)) {
1440
+ addIssue(context, 'ERROR', 'A012', "text is " + describeValueType(text) + ", expected an object", "" + path + ".text", layerId);
1441
+ } else {
1442
+ for(var _i = 0, _iter = [
1443
+ [
1444
+ 'content',
1445
+ 'A013',
1446
+ 'string'
1447
+ ],
1448
+ [
1449
+ 'size',
1450
+ 'A014',
1451
+ 'number'
1452
+ ],
1453
+ [
1454
+ 'color',
1455
+ 'A015',
1456
+ 'string'
1457
+ ]
1458
+ ]; _i < _iter.length; _i++){
1459
+ var _iter__i = _iter[_i], field = _iter__i[0], code = _iter__i[1], expected = _iter__i[2];
1460
+ var value = text[field];
1461
+ if (!hasValue(text, field)) {
1462
+ addIssue(context, 'ERROR', code, "text." + field + " is missing", path + ".text." + field, layerId);
1463
+ } else if (expected === 'number' && !isNumber(value)) {
1464
+ addIssue(context, 'ERROR', code, "text." + field + " is " + describeValueType(value) + ", expected a number", path + ".text." + field, layerId);
1465
+ } else if (expected === 'string' && typeof value !== 'string') {
1466
+ addIssue(context, 'ERROR', code, "text." + field + " is " + describeValueType(value) + ", expected a string", path + ".text." + field, layerId);
1467
+ }
1468
+ }
1469
+ if (isNumber(text['size']) && text['size'] < 0) {
1470
+ addIssue(context, 'ERROR', 'A014', "text.size is " + formatNumber(text['size']) + ", expected a number greater than or equal to 0", "" + path + ".text.size", layerId);
1471
+ }
1472
+ if (typeof text['color'] === 'string' && !isValidHexColor(text['color'])) {
1473
+ addIssue(context, 'ERROR', 'A015', "text.color " + formatValue(text['color']) + " is not a supported hex color", "" + path + ".text.color", layerId);
1474
+ }
1475
+ if (hasValue(text, 'font') && typeof text['font'] !== 'string') {
1476
+ addIssue(context, 'ERROR', 'A018', 'text.font must be a string', "" + path + ".text.font", layerId);
1477
+ }
1478
+ if (hasValue(text, 'align') && text['align'] !== 'left' && text['align'] !== 'center' && text['align'] !== 'right') {
1479
+ addIssue(context, 'ERROR', 'A019', 'text.align must be left, center, or right', "" + path + ".text.align", layerId);
1480
+ }
1481
+ for(var _i1 = 0, _iter1 = [
1482
+ 'line_height',
1483
+ 'letter_spacing'
1484
+ ]; _i1 < _iter1.length; _i1++){
1485
+ var field1 = _iter1[_i1];
1486
+ if (hasValue(text, field1) && !isNumber(text[field1])) {
1487
+ addIssue(context, 'ERROR', 'A020', "text." + field1 + " must be a finite number", path + ".text." + field1, layerId);
1488
+ }
1489
+ }
1490
+ }
1491
+ if (hasAsset) {
1492
+ addIssue(context, 'WARNING', 'A017', 'type=text has an asset (ignored)', "" + path + ".asset", layerId);
1493
+ }
1494
+ }
1495
+ function checkAssetFields(asset, assetPath, layerId, context) {
1496
+ var source = asset['source'];
1497
+ if (!hasValue(asset, 'source')) {
1498
+ addIssue(context, 'ERROR', 'A003', 'asset.source is missing', "" + assetPath + ".source", layerId);
1499
+ return;
1500
+ }
1501
+ if (typeof source !== 'string' || !VALID_ASSET_SOURCE_SET.has(source)) {
1502
+ addIssue(context, 'ERROR', 'A004', "asset.source " + formatValue(source) + " not in {user, llm_svg}", "" + assetPath + ".source", layerId);
1503
+ return;
1504
+ }
1505
+ if (source === 'llm_svg') {
1506
+ if (asset['format'] !== 'svg') {
1507
+ addIssue(context, 'ERROR', 'A005', "asset.format is " + formatValue(asset['format']) + ", must be 'svg' for llm_svg", "" + assetPath + ".format", layerId);
1508
+ }
1509
+ if (typeof asset['svg'] !== 'string') {
1510
+ addIssue(context, 'ERROR', 'A006', 'asset.svg must be a string', "" + assetPath + ".svg", layerId);
1511
+ }
1512
+ if (typeof asset['prompt'] !== 'string') {
1513
+ addIssue(context, 'ERROR', 'A007', 'asset.prompt must be a string', "" + assetPath + ".prompt", layerId);
1514
+ }
1515
+ if (asset['url'] !== undefined && typeof asset['url'] !== 'string') {
1516
+ addIssue(context, 'ERROR', 'A021', 'asset.url must be a string when present', "" + assetPath + ".url", layerId);
1517
+ } else if (typeof asset['url'] === 'string' && asset['url'] !== '' && !isAbsoluteResourceUrl(asset['url'])) {
1518
+ addIssue(context, 'ERROR', 'A021', 'asset.url must be absolute or a Data URL when non-empty', "" + assetPath + ".url", layerId);
1519
+ }
1520
+ } else {
1521
+ if (typeof asset['url'] !== 'string') {
1522
+ addIssue(context, 'ERROR', 'A008', 'asset.url must be a string', "" + assetPath + ".url", layerId);
1523
+ } else if (!isAbsoluteResourceUrl(asset['url'])) {
1524
+ addIssue(context, 'ERROR', 'A008', 'asset.url must be absolute or a Data URL', "" + assetPath + ".url", layerId);
1525
+ }
1526
+ if (asset['prompt'] !== '') {
1527
+ addIssue(context, 'ERROR', 'A009', "asset.prompt must be '' for source=user, got " + formatValue(asset['prompt']), "" + assetPath + ".prompt", layerId);
1528
+ }
1529
+ }
1530
+ }
1531
+ function checkLayerRelationships(entries, context) {
1532
+ var firstLayerById = new Map();
1533
+ var layerCountById = new Map();
1534
+ for(var _iterator = _create_for_of_iterator_helper_loose(entries), _step; !(_step = _iterator()).done;){
1535
+ var entry = _step.value;
1536
+ var _layerCountById_get;
1537
+ if (entry.layerId == null) {
1538
+ continue;
1539
+ }
1540
+ layerCountById.set(entry.layerId, ((_layerCountById_get = layerCountById.get(entry.layerId)) != null ? _layerCountById_get : 0) + 1);
1541
+ if (!firstLayerById.has(entry.layerId)) {
1542
+ firstLayerById.set(entry.layerId, entry);
1543
+ }
1544
+ }
1545
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(entries), _step1; !(_step1 = _iterator1()).done;){
1546
+ var entry1 = _step1.value;
1547
+ var _layerCountById_get1;
1548
+ if (entry1.layerId == null || ((_layerCountById_get1 = layerCountById.get(entry1.layerId)) != null ? _layerCountById_get1 : 0) <= 1) {
1549
+ continue;
1550
+ }
1551
+ addIssue(context, 'ERROR', 'X001', "id " + formatValue(entry1.layerId) + " is not globally unique (" + layerCountById.get(entry1.layerId) + " occurrences)", "" + entry1.path + ".id", entry1.layerId);
1552
+ }
1553
+ var logicalParentIdByLayer = new Map();
1554
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(entries), _step2; !(_step2 = _iterator2()).done;){
1555
+ var entry2 = _step2.value;
1556
+ var parent = entry2.layer['parent'];
1557
+ var resolvedParentId = null;
1558
+ if (parent == null) {
1559
+ resolvedParentId = null;
1560
+ } else if (typeof parent !== 'string') {
1561
+ addIssue(context, 'ERROR', 'X003', "parent is " + describeValueType(parent) + ", expected a string or null", "" + entry2.path + ".parent", entry2.layerId);
1562
+ } else if (entry2.layerId != null && parent === entry2.layerId) {
1563
+ addIssue(context, 'ERROR', 'X002', "parent " + formatValue(parent) + " references own id (self-reference)", "" + entry2.path + ".parent", entry2.layerId);
1564
+ } else if (!firstLayerById.has(parent)) {
1565
+ addIssue(context, 'ERROR', 'X004', "parent " + formatValue(parent) + " not found (dangling reference)", "" + entry2.path + ".parent", entry2.layerId);
1566
+ } else {
1567
+ resolvedParentId = parent;
1568
+ }
1569
+ logicalParentIdByLayer.set(entry2, resolvedParentId);
1570
+ if (resolvedParentId != null && entry2.physicalParentId !== resolvedParentId) {
1571
+ addIssue(context, 'WARNING', 'X005', "parent=" + formatValue(resolvedParentId) + " but physical nesting under " + formatValue(entry2.physicalParentId) + " (parent wins)", "" + entry2.path + ".parent", entry2.layerId);
1572
+ } else if (resolvedParentId == null && parent == null && entry2.physicalParentId != null) {
1573
+ addIssue(context, 'WARNING', 'X005', "layer nested under " + formatValue(entry2.physicalParentId) + " but parent is null/absent", "" + entry2.path + ".parent", entry2.layerId);
1574
+ }
1575
+ }
1576
+ checkParentCycles(entries, firstLayerById, logicalParentIdByLayer, context);
1577
+ }
1578
+ function checkParentCycles(entries, firstLayerById, logicalParentIdByLayer, context) {
1579
+ var resolvedLayerSet = new Set();
1580
+ var cycleEntries = [];
1581
+ for(var _iterator = _create_for_of_iterator_helper_loose(entries), _step; !(_step = _iterator()).done;){
1582
+ var _loop = function() {
1583
+ var currentId = current.layerId;
1584
+ if (currentId == null) {
1585
+ return "break";
1586
+ }
1587
+ if (visitedLayerIdSet.has(currentId)) {
1588
+ var cycleStartIndex = pathEntries.findIndex(function(entry) {
1589
+ return entry.layerId === currentId;
1590
+ });
1591
+ if (cycleStartIndex >= 0) {
1592
+ var _cycleEntries;
1593
+ (_cycleEntries = cycleEntries).push.apply(_cycleEntries, [].concat(pathEntries.slice(cycleStartIndex)));
1594
+ }
1595
+ return "break";
1596
+ }
1597
+ if (resolvedLayerSet.has(current)) {
1598
+ return "break";
1599
+ }
1600
+ pathEntries.push(current);
1601
+ visitedLayerIdSet.add(currentId);
1602
+ var parentId = logicalParentIdByLayer.get(current);
1603
+ current = parentId == null ? undefined : firstLayerById.get(parentId);
1604
+ };
1605
+ var start = _step.value;
1606
+ if (resolvedLayerSet.has(start)) {
1607
+ continue;
1608
+ }
1609
+ var pathEntries = [];
1610
+ var visitedLayerIdSet = new Set();
1611
+ var current = start;
1612
+ while(current != null){
1613
+ var _ret = _loop();
1614
+ if (_ret === "break") break;
1615
+ }
1616
+ pathEntries.forEach(function(entry) {
1617
+ return resolvedLayerSet.add(entry);
1618
+ });
1619
+ }
1620
+ var reportedCycleLayerSet = new Set();
1621
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(cycleEntries), _step1; !(_step1 = _iterator1()).done;){
1622
+ var entry = _step1.value;
1623
+ if (reportedCycleLayerSet.has(entry)) {
1624
+ continue;
1625
+ }
1626
+ reportedCycleLayerSet.add(entry);
1627
+ addIssue(context, 'ERROR', 'X006', "layer " + formatValue(entry.layerId) + " is part of a parent-pointer cycle", "" + entry.path + ".parent", entry.layerId);
1628
+ }
1629
+ }
1630
+ function readLayerId(layer) {
1631
+ var id = layer['id'];
1632
+ return typeof id === 'string' && id.length > 0 ? id : null;
1633
+ }
1634
+ function containsCircularReference(value, ancestorSet) {
1635
+ if (ancestorSet === void 0) ancestorSet = new WeakSet();
1636
+ if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null) {
1637
+ return false;
1638
+ }
1639
+ if (ancestorSet.has(value)) {
1640
+ return true;
1641
+ }
1642
+ ancestorSet.add(value);
1643
+ var hasCircularChild = Object.values(value).some(function(child) {
1644
+ return containsCircularReference(child, ancestorSet);
1645
+ });
1646
+ ancestorSet.delete(value);
1647
+ return hasCircularChild;
1648
+ }
1649
+ function hasValue(object, key) {
1650
+ return Object.prototype.hasOwnProperty.call(object, key) && object[key] != null;
1651
+ }
1652
+ function isNumber(value) {
1653
+ return typeof value === 'number' && Number.isFinite(value);
1654
+ }
1655
+ function isIntLike(value) {
1656
+ return isNumber(value) && Number.isInteger(value);
1657
+ }
1658
+ function isAbsoluteResourceUrl(value) {
1659
+ try {
1660
+ new URL(value);
1661
+ return true;
1662
+ } catch (unused) {
1663
+ return false;
1664
+ }
1665
+ }
1666
+ function describeValueType(value) {
1667
+ if (value === null) {
1668
+ return 'null';
1669
+ }
1670
+ if (value === undefined) {
1671
+ return 'undefined';
1672
+ }
1673
+ if (Array.isArray(value)) {
1674
+ return 'array';
1675
+ }
1676
+ if (isRecord$1(value)) {
1677
+ return 'object';
1678
+ }
1679
+ return typeof value === "undefined" ? "undefined" : _type_of(value);
1680
+ }
1681
+ function formatValue(value) {
1682
+ if (value === null) {
1683
+ return 'null';
1684
+ }
1685
+ if (value === undefined) {
1686
+ return 'undefined';
1687
+ }
1688
+ if (typeof value === 'boolean') {
1689
+ return String(value);
1690
+ }
1691
+ if (typeof value === 'number') {
1692
+ return formatNumber(value);
1693
+ }
1694
+ if (typeof value === 'string') {
1695
+ return JSON.stringify(value);
1696
+ }
1697
+ if (Array.isArray(value)) {
1698
+ return "[" + value.map(formatValue).join(', ') + "]";
1699
+ }
1700
+ if (isRecord$1(value)) {
1701
+ return "{" + Object.entries(value).map(function(param) {
1702
+ var key = param[0], item = param[1];
1703
+ return formatValue(key) + ": " + formatValue(item);
1704
+ }).join(', ') + "}";
1705
+ }
1706
+ return String(value);
1707
+ }
1708
+ function formatNumber(value) {
1709
+ if (Number.isNaN(value)) {
1710
+ return 'NaN';
1711
+ }
1712
+ if (value === Infinity) {
1713
+ return 'Infinity';
1714
+ }
1715
+ if (value === -Infinity) {
1716
+ return '-Infinity';
1717
+ }
1718
+ return String(value);
1719
+ }
1720
+
1721
+ function assembleDSLResult(baselineScene, baselineComposition, dslLayerByIRId, layerMapping, diagnostics) {
1722
+ var _baselineComposition_name;
1723
+ var layers = assembleDSLHierarchy(baselineComposition.layers, dslLayerByIRId);
1724
+ var frameRate = baselineComposition.frameRate;
1725
+ return {
1726
+ dsl: {
1727
+ meta: {
1728
+ name: (_baselineComposition_name = baselineComposition.name) != null ? _baselineComposition_name : baselineComposition.id,
1729
+ duration: Math.max(0, (baselineComposition.outPoint - baselineComposition.inPoint) / frameRate),
1730
+ fps: frameRate,
1731
+ width: baselineComposition.width,
1732
+ height: baselineComposition.height,
1733
+ loop: baselineComposition.endBehavior === IREndBehavior.Loop,
1734
+ background_color: baselineComposition.backgroundColor != null ? colorToHex(baselineComposition.backgroundColor) : null
1735
+ },
1736
+ layers: layers
1737
+ },
1738
+ preservedData: {
1739
+ baselineScene: baselineScene,
1740
+ layerMapping: layerMapping
1741
+ },
1742
+ diagnostics: diagnostics
1743
+ };
1744
+ }
1745
+ function assembleDSLHierarchy(sourceLayers, dslLayerByIRId) {
1746
+ var rootLayers = [];
1747
+ // IR is bottom-to-top while each DSL sibling array is top-to-bottom.
1748
+ for(var _iterator = _create_for_of_iterator_helper_loose(sourceLayers), _step; !(_step = _iterator()).done;){
1749
+ var sourceLayer = _step.value;
1750
+ var convertedLayer = dslLayerByIRId.get(sourceLayer.id);
1751
+ if (convertedLayer == null) {
1752
+ continue;
1753
+ }
1754
+ var parentLayerId = sourceLayer.parentId;
1755
+ var parentLayer = parentLayerId != null ? dslLayerByIRId.get(parentLayerId) : undefined;
1756
+ if (parentLayer != null) {
1757
+ var _parentLayer, _children;
1758
+ (_children = (_parentLayer = parentLayer).children) != null ? _children : _parentLayer.children = [];
1759
+ parentLayer.children.unshift(convertedLayer);
1760
+ } else {
1761
+ rootLayers.unshift(convertedLayer);
1762
+ }
1763
+ }
1764
+ return rootLayers;
1765
+ }
1766
+
1767
+ function mapDSLParticleExpressionToIR(expression) {
1768
+ if (expression[0] === ValueType.RANDOM) {
1769
+ return {
1770
+ type: 'randomBetweenConstants',
1771
+ min: expression[1][0],
1772
+ max: expression[1][1]
1773
+ };
1774
+ }
1775
+ return {
1776
+ type: 'constant',
1777
+ value: expression[1]
1778
+ };
1779
+ }
1780
+ function mapIRParticleExpressionToDSL(expression) {
1781
+ switch(expression.type){
1782
+ case 'constant':
1783
+ return [
1784
+ ValueType.CONSTANT,
1785
+ expression.value
1786
+ ];
1787
+ case 'randomBetweenConstants':
1788
+ return [
1789
+ ValueType.RANDOM,
1790
+ [
1791
+ expression.min,
1792
+ expression.max
1793
+ ]
1794
+ ];
1795
+ case 'curve':
1796
+ var _ref;
1797
+ var _expression_keyframes_;
1798
+ return [
1799
+ ValueType.CONSTANT,
1800
+ (_ref = (_expression_keyframes_ = expression.keyframes[0]) == null ? void 0 : _expression_keyframes_.value) != null ? _ref : 0
1801
+ ];
1802
+ }
1803
+ }
1804
+ function isDSLCompatibleParticleExpression(expression) {
1805
+ return expression.type === 'constant' || expression.type === 'randomBetweenConstants';
1806
+ }
1807
+ function isDSLNumberExpressionEqual(left, right) {
1808
+ if (left[0] !== right[0]) {
1809
+ return false;
1810
+ }
1811
+ if (left[0] === ValueType.CONSTANT && right[0] === ValueType.CONSTANT) {
1812
+ return Object.is(left[1], right[1]);
1813
+ }
1814
+ if (left[0] === ValueType.RANDOM && right[0] === ValueType.RANDOM) {
1815
+ return Object.is(left[1][0], right[1][0]) && Object.is(left[1][1], right[1][1]);
1816
+ }
1817
+ return false;
1818
+ }
1819
+
1820
+ /** Static defaults for absent transform channels. */ var TRANSFORM_FALLBACK = {
1821
+ position: [
1822
+ 0,
1823
+ 0,
1824
+ 0
1825
+ ],
1826
+ rotation: [
1827
+ 0,
1828
+ 0,
1829
+ 0
1830
+ ],
1831
+ scale: [
1832
+ 1,
1833
+ 1,
1834
+ 1
1835
+ ],
1836
+ anchor: [
1837
+ 0,
1838
+ 0,
1839
+ 0
1840
+ ],
1841
+ opacity: 1
1842
+ };
1843
+ function getLayerStackingOrder(layer) {
1844
+ var _value_;
1845
+ var _layer_position_animation_;
1846
+ var value = layer.position.a ? (_layer_position_animation_ = layer.position.animation[0]) == null ? void 0 : _layer_position_animation_.start : layer.position.value;
1847
+ return Array.isArray(value) ? (_value_ = value[2]) != null ? _value_ : 0 : 0;
1848
+ }
1849
+ function withPositionZ(position, depth) {
1850
+ var result = structuredClone(position);
1851
+ if (result.a) {
1852
+ for(var _iterator = _create_for_of_iterator_helper_loose(result.animation), _step; !(_step = _iterator()).done;){
1853
+ var segment = _step.value;
1854
+ segment.start[2] = depth;
1855
+ segment.end[2] = depth;
1856
+ }
1857
+ } else if (Array.isArray(result.value)) {
1858
+ result.value[2] = depth;
1859
+ }
1860
+ return result;
1861
+ }
1862
+
1863
+ function convertIRParticleToDSL(layer, frameRate, layerPath, diagnostics) {
1864
+ var convertExpression = function convertExpression(expression, fieldPath) {
1865
+ if (!isDSLCompatibleParticleExpression(expression)) {
1866
+ diagnostics.push({
1867
+ code: 'PARTICLE_EXPRESSION_PROJECTED',
1868
+ severity: 'warning',
1869
+ action: 'approximated',
1870
+ path: layerPath + ".content." + fieldPath,
1871
+ sourceId: layer.id,
1872
+ feature: fieldPath,
1873
+ message: "Particle " + fieldPath + " uses an IR " + expression.type + " expression and was projected to a representative editable DSL value; the baseline IR preserves the original expression until this field is edited."
1874
+ });
1875
+ }
1876
+ return mapIRParticleExpressionToDSL(expression);
1877
+ };
1878
+ return {
1879
+ options: {
1880
+ maxCount: layer.content.maxParticles,
1881
+ startLifetime: convertExpression(layer.content.startLifetime, 'startLifetime')
1882
+ },
1883
+ emission: _extends({
1884
+ rateOverTime: convertExpression(layer.content.emission.rateOverTime, 'emission.rateOverTime')
1885
+ }, layer.content.emission.bursts != null && {
1886
+ bursts: layer.content.emission.bursts.map(function(burst) {
1887
+ return {
1888
+ time: burst.frameOffset / frameRate,
1889
+ count: burst.count,
1890
+ cycles: burst.cycleCount === 'infinite' ? 0 : burst.cycleCount,
1891
+ interval: burst.repeatIntervalFrames / frameRate
1892
+ };
1893
+ })
1894
+ })
1895
+ };
1896
+ }
1897
+
1898
+ var LINEAR_EASING = [
1899
+ 0,
1900
+ 0,
1901
+ 1,
1902
+ 1
1903
+ ];
1904
+ function convertIRLayersToDSL(baselineComposition, assets, frameRate) {
1905
+ var layerMapping = {
1906
+ layers: {}
1907
+ };
1908
+ var diagnostics = [];
1909
+ var dslLayerByIRId = new Map();
1910
+ var imageAssetById = new Map(assets.filter(function(asset) {
1911
+ return asset.type === 'image';
1912
+ }).map(function(asset) {
1913
+ return [
1914
+ asset.id,
1915
+ asset
1916
+ ];
1917
+ }));
1918
+ var fontAssetById = new Map(assets.filter(function(asset) {
1919
+ return asset.type === 'font';
1920
+ }).map(function(asset) {
1921
+ return [
1922
+ asset.id,
1923
+ asset
1924
+ ];
1925
+ }));
1926
+ for(var _iterator = _create_for_of_iterator_helper_loose(baselineComposition.layers.entries()), _step; !(_step = _iterator()).done;){
1927
+ var _step_value = _step.value, layerIndex = _step_value[0], layer = _step_value[1];
1928
+ var layerId = layer.id;
1929
+ var layerPath = "$.compositions[id=" + JSON.stringify(baselineComposition.id) + "].layers[" + layerIndex + "]";
1930
+ var convertedLayer = convertIRLayerToDSL(layer, layerId, imageAssetById, fontAssetById, frameRate, layerPath, diagnostics);
1931
+ convertedLayer.position = withPositionZ(convertedLayer.position, layerIndex);
1932
+ layerMapping.layers[layerId] = {
1933
+ irCompositionId: baselineComposition.id,
1934
+ irLayerId: layer.id
1935
+ };
1936
+ dslLayerByIRId.set(layer.id, convertedLayer);
1937
+ collectDiagnostics(layer, layerId, layerPath, diagnostics);
1938
+ if (convertedLayer.type === 'null' && isVisualLayerWithoutAsset(layer, convertedLayer.asset)) {
1939
+ diagnostics.push({
1940
+ code: 'LAYER_ASSET_NOT_MATERIALIZED',
1941
+ severity: 'warning',
1942
+ action: 'approximated',
1943
+ path: "" + layerPath + ".content.assetId",
1944
+ sourceId: layerId,
1945
+ feature: 'asset',
1946
+ message: "Visual layer type '" + layer.type + "' has no materialized URL asset and was projected to DSL type=null; the baseline scene preserves the original visual data."
1947
+ });
1948
+ }
1949
+ }
1950
+ return {
1951
+ dslLayerByIRId: dslLayerByIRId,
1952
+ layerMapping: layerMapping,
1953
+ diagnostics: diagnostics
1954
+ };
1955
+ }
1956
+ function convertIRLayerToDSL(layer, layerId, imageAssetById, fontAssetById, frameRate, layerPath, diagnostics) {
1957
+ var _layer_parentId, _layer_name, _layer_name1;
1958
+ var _layer_transform, _layer_transform1, _layer_transform2, _layer_transform3;
1959
+ var size = resolveLayerSize(layer);
1960
+ var asset = convertIRAssetToDSL(layer, imageAssetById);
1961
+ var layerType = mapLayerType$1(layer, asset);
1962
+ var parentId = (_layer_parentId = layer.parentId) != null ? _layer_parentId : null;
1963
+ var convertedLayer = {
1964
+ id: layerId,
1965
+ name: (_layer_name = layer.name) != null ? _layer_name : layer.id,
1966
+ type: layerType,
1967
+ width: size.width,
1968
+ height: size.height,
1969
+ description: {
1970
+ self: (_layer_name1 = layer.name) != null ? _layer_name1 : layer.id,
1971
+ composite: ''
1972
+ },
1973
+ parent: parentId,
1974
+ time_range: [
1975
+ layer.time.inFrame / frameRate,
1976
+ layer.time.outFrame / frameRate
1977
+ ],
1978
+ position: convertIRVec3PropertyToDSL((_layer_transform = layer.transform) == null ? void 0 : _layer_transform.position, TRANSFORM_FALLBACK.position, frameRate, true),
1979
+ rotation: convertIRLayerRotationToDSL(layer, frameRate),
1980
+ scale: convertIRVec3PropertyToDSL((_layer_transform1 = layer.transform) == null ? void 0 : _layer_transform1.scale, TRANSFORM_FALLBACK.scale, frameRate, false),
1981
+ anchor: convertIRVec3PropertyToDSL((_layer_transform2 = layer.transform) == null ? void 0 : _layer_transform2.anchor, TRANSFORM_FALLBACK.anchor, frameRate, false),
1982
+ opacity: convertIRNumberPropertyToDSL((_layer_transform3 = layer.transform) == null ? void 0 : _layer_transform3.opacity, TRANSFORM_FALLBACK.opacity, frameRate),
1983
+ children: []
1984
+ };
1985
+ if (layerType === 'layer' && asset != null) {
1986
+ convertedLayer.asset = asset;
1987
+ }
1988
+ if (layer.type === 'text') {
1989
+ convertedLayer.text = convertIRTextToDSL(layer, fontAssetById);
1990
+ }
1991
+ if (layer.type === 'particle') {
1992
+ convertedLayer.particle = convertIRParticleToDSL(layer, frameRate, layerPath, diagnostics);
1993
+ }
1994
+ return convertedLayer;
1995
+ }
1996
+ function mapLayerType$1(layer, asset) {
1997
+ if (layer.type === 'particle') {
1998
+ return 'particle';
1999
+ }
2000
+ if (layer.type === 'text') {
2001
+ return 'text';
2002
+ }
2003
+ if (layer.type === 'null' || layer.type === 'precomp') {
2004
+ return 'null';
2005
+ }
2006
+ return asset != null ? 'layer' : 'null';
2007
+ }
2008
+ function isVisualLayerWithoutAsset(layer, asset) {
2009
+ return layer.type !== 'null' && layer.type !== 'precomp' && layer.type !== 'text' && layer.type !== 'particle' && asset == null;
2010
+ }
2011
+ function resolveLayerSize(layer) {
2012
+ if (layer.localBounds != null) {
2013
+ var _layer_localBounds = layer.localBounds, width = _layer_localBounds.width, height = _layer_localBounds.height;
2014
+ return {
2015
+ width: width,
2016
+ height: height
2017
+ };
2018
+ }
2019
+ return {
2020
+ width: 0,
2021
+ height: 0
2022
+ };
2023
+ }
2024
+ function convertIRAssetToDSL(layer, imageAssetById) {
2025
+ if (layer.type !== 'image') {
2026
+ return undefined;
2027
+ }
2028
+ var imageAsset = imageAssetById.get(layer.content.assetId);
2029
+ if (imageAsset == null) {
2030
+ return undefined;
2031
+ }
2032
+ return {
2033
+ url: getIRResourceSourceUrl(imageAsset.source),
2034
+ source: 'user',
2035
+ prompt: ''
2036
+ };
2037
+ }
2038
+ function convertIRTextToDSL(layer, fontAssetById) {
2039
+ var text = layer.content;
2040
+ var fontAsset = fontAssetById.get(text.fontAssetId);
2041
+ if (fontAsset == null) {
2042
+ throw new TypeError("[dsl-ir] Text layer '" + layer.id + "' references a missing Font Asset: " + text.fontAssetId);
2043
+ }
2044
+ return _extends({
2045
+ content: text.text,
2046
+ font: fontAsset.family,
2047
+ size: text.fontSize,
2048
+ color: colorToHex(text.color)
2049
+ }, text.textAlign != null && {
2050
+ align: text.textAlign
2051
+ }, {
2052
+ line_height: text.lineHeight
2053
+ }, text.letterSpacing != null && {
2054
+ letter_spacing: text.letterSpacing
2055
+ });
2056
+ }
2057
+ function convertIRLayerRotationToDSL(layer, frameRate) {
2058
+ var _layer_transform;
2059
+ var rotation = (_layer_transform = layer.transform) == null ? void 0 : _layer_transform.rotation;
2060
+ if (rotation == null) {
2061
+ return convertIRVec3PropertyToDSL(undefined, TRANSFORM_FALLBACK.rotation, frameRate, false);
2062
+ }
2063
+ return convertIRRotationToDSL(rotation, frameRate);
2064
+ }
2065
+ /**
2066
+ * Merge per-axis rotation into the DSL's 3D vector track.
2067
+ *
2068
+ * Aligned channels retain their shared easing. Independent axes fall back to
2069
+ * a union-of-keyframe-times projection.
2070
+ */ function convertIRRotationToDSL(rotation, frameRate) {
2071
+ var rotationChannels = [
2072
+ rotation.x,
2073
+ rotation.y,
2074
+ rotation.z
2075
+ ];
2076
+ var animatedChannels = rotationChannels.filter(function(channel) {
2077
+ return (channel == null ? void 0 : channel.type) === 'keyframed';
2078
+ });
2079
+ if (animatedChannels.length === 0) {
2080
+ return {
2081
+ a: false,
2082
+ value: [
2083
+ readNumberStatic(rotation.x, 0),
2084
+ readNumberStatic(rotation.y, 0),
2085
+ readNumberStatic(rotation.z, 0)
2086
+ ]
2087
+ };
2088
+ }
2089
+ if (isRotationChannelSetAligned(animatedChannels)) {
2090
+ var templateChannel = animatedChannels[0];
2091
+ var keyframes = templateChannel.keyframes.map(function(keyframe, index) {
2092
+ var hasEndValue = animatedChannels.some(function(channel) {
2093
+ var _channel_keyframes_index;
2094
+ return ((_channel_keyframes_index = channel.keyframes[index]) == null ? void 0 : _channel_keyframes_index.endValue) != null;
2095
+ });
2096
+ return _extends({
2097
+ frame: keyframe.frame,
2098
+ value: readAlignedRotationValue(rotation, index)
2099
+ }, hasEndValue && {
2100
+ endValue: readAlignedRotationEndValue(rotation, index)
2101
+ }, keyframe.hold != null && {
2102
+ hold: keyframe.hold
2103
+ }, keyframe.inTangent != null && {
2104
+ inTangent: keyframe.inTangent
2105
+ }, keyframe.outTangent != null && {
2106
+ outTangent: keyframe.outTangent
2107
+ });
2108
+ });
2109
+ return convertIRKeyframesToDSLProperty(keyframes, TRANSFORM_FALLBACK.rotation, frameRate, false);
2110
+ }
2111
+ var keyframeFrameSet = new Set();
2112
+ for(var _iterator = _create_for_of_iterator_helper_loose(rotationChannels), _step; !(_step = _iterator()).done;){
2113
+ var channel = _step.value;
2114
+ if ((channel == null ? void 0 : channel.type) === 'keyframed' && channel.keyframes != null) {
2115
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(channel.keyframes), _step1; !(_step1 = _iterator1()).done;){
2116
+ var keyframe = _step1.value;
2117
+ keyframeFrameSet.add(keyframe.frame);
2118
+ }
2119
+ }
2120
+ }
2121
+ // Keep Array.from: loose SWC array-spread lowering does not expand Set in dist.
2122
+ var sortedFrames = Array.from(keyframeFrameSet).sort(function(leftFrame, rightFrame) {
2123
+ return leftFrame - rightFrame;
2124
+ });
2125
+ var keyframes1 = sortedFrames.map(function(frame) {
2126
+ return {
2127
+ frame: frame,
2128
+ value: [
2129
+ readNumberAtFrame(rotation.x, frame, 0),
2130
+ readNumberAtFrame(rotation.y, frame, 0),
2131
+ readNumberAtFrame(rotation.z, frame, 0)
2132
+ ]
2133
+ };
2134
+ });
2135
+ return convertIRKeyframesToDSLProperty(keyframes1, TRANSFORM_FALLBACK.rotation, frameRate, false);
2136
+ }
2137
+ function isRotationChannelSetAligned(rotationChannels) {
2138
+ var templateChannel = rotationChannels[0];
2139
+ return rotationChannels.every(function(channel) {
2140
+ return channel.keyframes.length === templateChannel.keyframes.length && channel.keyframes.every(function(keyframe, index) {
2141
+ return isRotationKeyframeAligned(keyframe, templateChannel.keyframes[index]);
2142
+ });
2143
+ });
2144
+ }
2145
+ function isRotationKeyframeAligned(left, right) {
2146
+ return Math.abs(left.frame - right.frame) < EPSILON$1 && left.hold === right.hold && isBezierHandleEqual(left.inTangent, right.inTangent) && isBezierHandleEqual(left.outTangent, right.outTangent);
2147
+ }
2148
+ function isBezierHandleEqual(left, right) {
2149
+ if (left == null || right == null) {
2150
+ return left === right;
2151
+ }
2152
+ return Math.abs(left.x - right.x) < EPSILON$1 && Math.abs(left.y - right.y) < EPSILON$1;
2153
+ }
2154
+ function readAlignedRotationValue(rotation, index) {
2155
+ return [
2156
+ readAlignedAxisValue(rotation.x, index),
2157
+ readAlignedAxisValue(rotation.y, index),
2158
+ readAlignedAxisValue(rotation.z, index)
2159
+ ];
2160
+ }
2161
+ function readAlignedRotationEndValue(rotation, index) {
2162
+ return [
2163
+ readAlignedAxisEndValue(rotation.x, index),
2164
+ readAlignedAxisEndValue(rotation.y, index),
2165
+ readAlignedAxisEndValue(rotation.z, index)
2166
+ ];
2167
+ }
2168
+ function readAlignedAxisValue(channel, index) {
2169
+ var _ref, _ref1;
2170
+ var _channel_keyframes_index;
2171
+ return (channel == null ? void 0 : channel.type) === 'keyframed' ? (_ref = (_channel_keyframes_index = channel.keyframes[index]) == null ? void 0 : _channel_keyframes_index.value) != null ? _ref : 0 : (_ref1 = channel == null ? void 0 : channel.value) != null ? _ref1 : 0;
2172
+ }
2173
+ function readAlignedAxisEndValue(channel, index) {
2174
+ var _ref, _ref1, _ref2;
2175
+ var _channel_keyframes_index, _channel_keyframes_, _channel_keyframes_index1;
2176
+ if ((channel == null ? void 0 : channel.type) !== 'keyframed') {
2177
+ var _ref3;
2178
+ return (_ref3 = channel == null ? void 0 : channel.value) != null ? _ref3 : 0;
2179
+ }
2180
+ return (_ref = (_ref1 = (_ref2 = (_channel_keyframes_index = channel.keyframes[index]) == null ? void 0 : _channel_keyframes_index.endValue) != null ? _ref2 : (_channel_keyframes_ = channel.keyframes[index + 1]) == null ? void 0 : _channel_keyframes_.value) != null ? _ref1 : (_channel_keyframes_index1 = channel.keyframes[index]) == null ? void 0 : _channel_keyframes_index1.value) != null ? _ref : 0;
2181
+ }
2182
+ function convertIRVec3PropertyToDSL(property, fallback, frameRate, includeSpatialTangents) {
2183
+ if ((property == null ? void 0 : property.type) === 'keyframed') {
2184
+ return convertIRKeyframesToDSLProperty(property.keyframes, fallback, frameRate, includeSpatialTangents);
2185
+ }
2186
+ return {
2187
+ a: false,
2188
+ value: (property == null ? void 0 : property.value) != null ? [].concat(property.value) : [].concat(fallback)
2189
+ };
2190
+ }
2191
+ function convertIRNumberPropertyToDSL(property, fallback, frameRate) {
2192
+ var _ref;
2193
+ if ((property == null ? void 0 : property.type) === 'keyframed') {
2194
+ return convertIRKeyframesToDSLProperty(property.keyframes, fallback, frameRate, false);
2195
+ }
2196
+ return {
2197
+ a: false,
2198
+ value: (_ref = property == null ? void 0 : property.value) != null ? _ref : fallback
2199
+ };
2200
+ }
2201
+ function convertIRKeyframesToDSLProperty(keyframes, fallback, frameRate, includeSpatialTangents) {
2202
+ if (keyframes.length < 2) {
2203
+ var _ref;
2204
+ var _keyframes_;
2205
+ return {
2206
+ a: false,
2207
+ value: (_ref = (_keyframes_ = keyframes[0]) == null ? void 0 : _keyframes_.value) != null ? _ref : fallback
2208
+ };
2209
+ }
2210
+ var animation = [];
2211
+ for(var keyframeIndex = 0; keyframeIndex < keyframes.length - 1; keyframeIndex++){
2212
+ var _currentKeyframe_endValue, _ref1, _ref2, _ref3, _ref4;
2213
+ var _currentKeyframe_outTangent, _currentKeyframe_outTangent1, _nextKeyframe_inTangent, _nextKeyframe_inTangent1;
2214
+ var currentKeyframe = keyframes[keyframeIndex];
2215
+ var nextKeyframe = keyframes[keyframeIndex + 1];
2216
+ var endValue = (_currentKeyframe_endValue = currentKeyframe.endValue) != null ? _currentKeyframe_endValue : nextKeyframe.value;
2217
+ var easing = [
2218
+ (_ref1 = (_currentKeyframe_outTangent = currentKeyframe.outTangent) == null ? void 0 : _currentKeyframe_outTangent.x) != null ? _ref1 : LINEAR_EASING[0],
2219
+ (_ref2 = (_currentKeyframe_outTangent1 = currentKeyframe.outTangent) == null ? void 0 : _currentKeyframe_outTangent1.y) != null ? _ref2 : LINEAR_EASING[1],
2220
+ (_ref3 = (_nextKeyframe_inTangent = nextKeyframe.inTangent) == null ? void 0 : _nextKeyframe_inTangent.x) != null ? _ref3 : LINEAR_EASING[2],
2221
+ (_ref4 = (_nextKeyframe_inTangent1 = nextKeyframe.inTangent) == null ? void 0 : _nextKeyframe_inTangent1.y) != null ? _ref4 : LINEAR_EASING[3]
2222
+ ];
2223
+ animation.push(_extends({
2224
+ t: [
2225
+ currentKeyframe.frame / frameRate,
2226
+ nextKeyframe.frame / frameRate
2227
+ ],
2228
+ start: convertIRPropertyValueToArray(currentKeyframe.value),
2229
+ end: convertIRPropertyValueToArray(currentKeyframe.hold === true ? currentKeyframe.value : endValue),
2230
+ easing: easing
2231
+ }, includeSpatialTangents && currentKeyframe.spatialOut != null && {
2232
+ out: convertIRSpatialTangentToDSL(currentKeyframe.spatialOut)
2233
+ }, includeSpatialTangents && nextKeyframe.spatialIn != null && {
2234
+ in: convertIRSpatialTangentToDSL(nextKeyframe.spatialIn)
2235
+ }));
2236
+ }
2237
+ return {
2238
+ a: true,
2239
+ animation: animation
2240
+ };
2241
+ }
2242
+ function convertIRSpatialTangentToDSL(value) {
2243
+ var _value_, _value_1, _value_2;
2244
+ return [
2245
+ (_value_ = value[0]) != null ? _value_ : 0,
2246
+ (_value_1 = value[1]) != null ? _value_1 : 0,
2247
+ (_value_2 = value[2]) != null ? _value_2 : 0
2248
+ ];
2249
+ }
2250
+ function convertIRPropertyValueToArray(value) {
2251
+ return Array.isArray(value) ? [].concat(value) : [
2252
+ value
2253
+ ];
2254
+ }
2255
+ function readNumberStatic(property, fallback) {
2256
+ var _property_value;
2257
+ if (property == null || property.type === 'keyframed') {
2258
+ return fallback;
2259
+ }
2260
+ return (_property_value = property.value) != null ? _property_value : fallback;
2261
+ }
2262
+ function readNumberAtFrame(property, frame, fallback) {
2263
+ var _ref;
2264
+ var _property_keyframes;
2265
+ if (property == null) {
2266
+ return fallback;
2267
+ }
2268
+ if (property.type === 'static') {
2269
+ var _property_value;
2270
+ return (_property_value = property.value) != null ? _property_value : fallback;
2271
+ }
2272
+ var keyframe = (_property_keyframes = property.keyframes) == null ? void 0 : _property_keyframes.find(function(candidate) {
2273
+ return Math.abs(candidate.frame - frame) < EPSILON$1;
2274
+ });
2275
+ return (_ref = keyframe == null ? void 0 : keyframe.value) != null ? _ref : fallback;
2276
+ }
2277
+ function collectDiagnostics(layer, layerId, layerPath, diagnostics) {
2278
+ var _layer_content;
2279
+ var preservedFields = [];
2280
+ var unsupportedFeatures = [];
2281
+ collectPreservedField(preservedFields, layer.visible === false ? layer.visible : undefined, 'visible');
2282
+ collectPreservedField(preservedFields, layer.endBehavior != null && layer.endBehavior !== 'destroy' ? layer.endBehavior : undefined, 'endBehavior');
2283
+ collectPreservedField(preservedFields, layer.blendMode, 'blendMode');
2284
+ collectPreservedField(preservedFields, layer.mask, 'mask');
2285
+ collectPreservedField(preservedFields, layer.matte, 'matte');
2286
+ collectPreservedField(preservedFields, layer.localBounds != null && layer.localBounds.x !== 0 ? layer.localBounds.x : undefined, 'localBounds.x');
2287
+ collectPreservedField(preservedFields, layer.localBounds != null && layer.localBounds.y !== 0 ? layer.localBounds.y : undefined, 'localBounds.y');
2288
+ collectPreservedField(preservedFields, layer.type === 'shape' ? (_layer_content = layer.content) == null ? void 0 : _layer_content.shapes : undefined, 'shapes');
2289
+ collectPreservedField(preservedFields, layer.type === 'solid' ? layer.content.color : undefined, 'content.color');
2290
+ if (layer.type === 'particle') {
2291
+ collectPreservedField(preservedFields, isDSLCompatibleParticleExpression(layer.content.startLifetime) ? undefined : layer.content.startLifetime, 'content.startLifetime');
2292
+ collectPreservedField(preservedFields, isDSLCompatibleParticleExpression(layer.content.emission.rateOverTime) ? undefined : layer.content.emission.rateOverTime, 'content.emission.rateOverTime');
2293
+ }
2294
+ if (layer.type === 'shape') {
2295
+ unsupportedFeatures.push('shape');
2296
+ }
2297
+ if (layer.type === 'solid') {
2298
+ unsupportedFeatures.push('solid');
2299
+ }
2300
+ if (layer.type === 'precomp') {
2301
+ unsupportedFeatures.push(layer.type);
2302
+ }
2303
+ if (layer.mask != null || layer.matte != null) {
2304
+ unsupportedFeatures.push('mask');
2305
+ }
2306
+ var uniquePreservedFields = Array.from(new Set(preservedFields));
2307
+ var uniqueUnsupportedFeatures = Array.from(new Set(unsupportedFeatures));
2308
+ if (uniqueUnsupportedFeatures.length > 0) {
2309
+ diagnostics.push({
2310
+ code: 'LAYER_HAS_UNSUPPORTED_FEATURES',
2311
+ severity: 'warning',
2312
+ action: 'unsupported',
2313
+ path: layerPath,
2314
+ sourceId: layerId,
2315
+ feature: uniqueUnsupportedFeatures.join(','),
2316
+ message: "Layer contains features outside the editable DSL surface: " + uniqueUnsupportedFeatures.join(', ')
2317
+ });
2318
+ }
2319
+ if (uniquePreservedFields.length > 0) {
2320
+ diagnostics.push({
2321
+ code: 'LAYER_FIELDS_PRESERVED_IN_BASE_IR',
2322
+ severity: 'info',
2323
+ action: 'normalized',
2324
+ path: layerPath,
2325
+ sourceId: layerId,
2326
+ feature: uniquePreservedFields.join(','),
2327
+ message: "Fields preserved in baseline scene: " + uniquePreservedFields.join(', ')
2328
+ });
2329
+ }
2330
+ }
2331
+ function collectPreservedField(preservedFields, value, fieldName) {
2332
+ if (value == null) {
2333
+ return;
2334
+ }
2335
+ if (Array.isArray(value) && value.length === 0) {
2336
+ return;
2337
+ }
2338
+ preservedFields.push(fieldName);
2339
+ }
2340
+
2341
+ /** Expand referenced IR Compositions into the editable DSL tree. */ function expandDSLPrecompositions(dslResult, convertIRSceneEntryToDSL) {
2342
+ var irScene = dslResult.preservedData.baselineScene;
2343
+ var context = {
2344
+ irScene: irScene,
2345
+ compositionById: new Map(irScene.compositions.map(function(composition) {
2346
+ return [
2347
+ composition.id,
2348
+ composition
2349
+ ];
2350
+ })),
2351
+ layerMapping: dslResult.preservedData.layerMapping,
2352
+ diagnostics: dslResult.diagnostics,
2353
+ visitedCompositionIdSet: new Set([
2354
+ irScene.entryCompositionId
2355
+ ]),
2356
+ convertIRSceneEntryToDSL: convertIRSceneEntryToDSL
2357
+ };
2358
+ expandPrecompLayerTree(dslResult.dsl.layers, getIRSceneEntryComposition(irScene), context);
2359
+ }
2360
+ function expandPrecompLayerTree(layers, sourceComposition, context) {
2361
+ var layerById = new Map(sourceComposition.layers.map(function(layer) {
2362
+ return [
2363
+ layer.id,
2364
+ layer
2365
+ ];
2366
+ }));
2367
+ for(var _iterator = _create_for_of_iterator_helper_loose(layers), _step; !(_step = _iterator()).done;){
2368
+ var layer = _step.value;
2369
+ var _layer_children;
2370
+ var referencedComposition = resolveReferencedComposition(layer.id, context.layerMapping, layerById, context);
2371
+ var children = (_layer_children = layer.children) != null ? _layer_children : [];
2372
+ if (referencedComposition != null && children.length === 0) {
2373
+ expandPrecompChildren(layer, referencedComposition, context);
2374
+ continue;
2375
+ }
2376
+ if (children.length > 0) {
2377
+ expandPrecompLayerTree(children, sourceComposition, context);
2378
+ }
2379
+ }
2380
+ }
2381
+ function expandPrecompChildren(parentLayer, referencedComposition, context) {
2382
+ if (context.visitedCompositionIdSet.has(referencedComposition.id)) {
2383
+ context.diagnostics.push({
2384
+ code: 'PRECOMP_EXPAND_CYCLE_SKIPPED',
2385
+ severity: 'warning',
2386
+ action: 'unsupported',
2387
+ path: '$.layers',
2388
+ sourceId: parentLayer.id,
2389
+ feature: 'precomp-cycle',
2390
+ message: "Precomp '" + referencedComposition.id + "' was not expanded because it would create a cycle."
2391
+ });
2392
+ return;
2393
+ }
2394
+ context.visitedCompositionIdSet.add(referencedComposition.id);
2395
+ try {
2396
+ var _context_diagnostics, _parentLayer_children;
2397
+ var _parentLayer, _children;
2398
+ var childScene = _extends({}, context.irScene, {
2399
+ entryCompositionId: referencedComposition.id
2400
+ });
2401
+ var childResult = context.convertIRSceneEntryToDSL(childScene);
2402
+ var prefix = parentLayer.id + "__precomp_" + sanitizeIdPart(referencedComposition.id) + "__";
2403
+ var children = cloneExpandedLayers(childResult.dsl.layers, {
2404
+ prefix: prefix,
2405
+ parentLayerId: parentLayer.id,
2406
+ irCompositionId: referencedComposition.id,
2407
+ childLayerMapping: childResult.preservedData.layerMapping,
2408
+ targetLayerMapping: context.layerMapping
2409
+ });
2410
+ (_context_diagnostics = context.diagnostics).push.apply(_context_diagnostics, [].concat(childResult.diagnostics));
2411
+ (_children = (_parentLayer = parentLayer).children) != null ? _children : _parentLayer.children = [];
2412
+ (_parentLayer_children = parentLayer.children).push.apply(_parentLayer_children, [].concat(children));
2413
+ expandPrecompLayerTree(children, referencedComposition, context);
2414
+ } finally{
2415
+ context.visitedCompositionIdSet.delete(referencedComposition.id);
2416
+ }
2417
+ }
2418
+ function cloneExpandedLayers(layers, options) {
2419
+ var expandedLayerIdBySourceId = buildExpandedLayerIdBySourceId(layers, options.prefix);
2420
+ var cloneExpandedLayer = function cloneExpandedLayer1(layer, fallbackParentId) {
2421
+ var _expandedLayerIdBySourceId_get, _expandedLayerIdBySourceId_get1, _layer_children;
2422
+ var clonedLayer = structuredClone(layer);
2423
+ var expandedLayerId = (_expandedLayerIdBySourceId_get = expandedLayerIdBySourceId.get(layer.id)) != null ? _expandedLayerIdBySourceId_get : "" + options.prefix + layer.id;
2424
+ clonedLayer.id = expandedLayerId;
2425
+ clonedLayer.parent = layer.parent != null ? (_expandedLayerIdBySourceId_get1 = expandedLayerIdBySourceId.get(layer.parent)) != null ? _expandedLayerIdBySourceId_get1 : fallbackParentId : fallbackParentId;
2426
+ clonedLayer.children = ((_layer_children = layer.children) != null ? _layer_children : []).map(function(childLayer) {
2427
+ return cloneExpandedLayer(childLayer, expandedLayerId);
2428
+ });
2429
+ registerExpandedLayer(layer.id, clonedLayer, options);
2430
+ return clonedLayer;
2431
+ };
2432
+ return layers.map(function(layer) {
2433
+ return cloneExpandedLayer(layer, options.parentLayerId);
2434
+ });
2435
+ }
2436
+ function buildExpandedLayerIdBySourceId(layers, prefix, expandedLayerIdBySourceId) {
2437
+ if (expandedLayerIdBySourceId === void 0) expandedLayerIdBySourceId = new Map();
2438
+ for(var _iterator = _create_for_of_iterator_helper_loose(layers), _step; !(_step = _iterator()).done;){
2439
+ var layer = _step.value;
2440
+ var _layer_children;
2441
+ expandedLayerIdBySourceId.set(layer.id, "" + prefix + layer.id);
2442
+ buildExpandedLayerIdBySourceId((_layer_children = layer.children) != null ? _layer_children : [], prefix, expandedLayerIdBySourceId);
2443
+ }
2444
+ return expandedLayerIdBySourceId;
2445
+ }
2446
+ function registerExpandedLayer(sourceLayerId, expandedLayer, options) {
2447
+ var childMapping = options.childLayerMapping.layers[sourceLayerId];
2448
+ if (childMapping == null) {
2449
+ return;
2450
+ }
2451
+ var expandedSource = {
2452
+ irCompositionId: options.irCompositionId,
2453
+ parentLayerId: options.parentLayerId,
2454
+ baselineTransform: {
2455
+ position: structuredClone(expandedLayer.position),
2456
+ scale: structuredClone(expandedLayer.scale),
2457
+ rotation: structuredClone(expandedLayer.rotation),
2458
+ anchor: structuredClone(expandedLayer.anchor),
2459
+ opacity: structuredClone(expandedLayer.opacity)
2460
+ },
2461
+ baselineLayer: _extends({
2462
+ name: expandedLayer.name,
2463
+ type: expandedLayer.type,
2464
+ width: expandedLayer.width,
2465
+ height: expandedLayer.height,
2466
+ description: structuredClone(expandedLayer.description),
2467
+ parent: expandedLayer.parent,
2468
+ timeRange: structuredClone(expandedLayer.time_range)
2469
+ }, expandedLayer.text != null && {
2470
+ text: structuredClone(expandedLayer.text)
2471
+ }, expandedLayer.asset != null && {
2472
+ asset: structuredClone(expandedLayer.asset)
2473
+ }, expandedLayer.particle != null && {
2474
+ particle: structuredClone(expandedLayer.particle)
2475
+ })
2476
+ };
2477
+ options.targetLayerMapping.layers[expandedLayer.id] = {
2478
+ irCompositionId: options.irCompositionId,
2479
+ irLayerId: childMapping.irLayerId,
2480
+ expandedSource: expandedSource
2481
+ };
2482
+ }
2483
+ function resolveReferencedComposition(dslLayerId, layerMapping, layerById, context) {
2484
+ var mapping = layerMapping.layers[dslLayerId];
2485
+ var sourceLayer = mapping != null ? layerById.get(mapping.irLayerId) : undefined;
2486
+ return (sourceLayer == null ? void 0 : sourceLayer.type) === 'precomp' ? context.compositionById.get(sourceLayer.content.compositionId) : undefined;
2487
+ }
2488
+ function sanitizeIdPart(value) {
2489
+ return value.replace(/[^a-zA-Z0-9_-]/g, '_');
2490
+ }
2491
+
2492
+ /** Convert Animation IR to editable DSL and retain source-neutral data for the reverse conversion. */ function convertIRToDSL(baselineScene) {
2493
+ assertIRScene(baselineScene);
2494
+ var baselineSnapshot = structuredClone(baselineScene);
2495
+ var result = convertIRSceneEntryToDSL(baselineSnapshot);
2496
+ expandDSLPrecompositions(result, convertIRSceneEntryToDSL);
2497
+ validateConvertedDSL(result);
2498
+ return result;
2499
+ }
2500
+ function validateConvertedDSL(result) {
2501
+ var _result_diagnostics;
2502
+ var validationResult = validateDSL(result.dsl);
2503
+ if (validationResult.result === 'fail') {
2504
+ throw DSLValidationError.fromValidationResult(validationResult);
2505
+ }
2506
+ (_result_diagnostics = result.diagnostics).push.apply(_result_diagnostics, [].concat(validationResult.warnings.map(function(warning) {
2507
+ return _extends({
2508
+ code: warning.code,
2509
+ severity: 'warning',
2510
+ action: 'unsupported',
2511
+ path: toJSONPath(warning.path)
2512
+ }, warning.layerId != null && {
2513
+ sourceId: warning.layerId
2514
+ }, {
2515
+ message: warning.message
2516
+ });
2517
+ })));
2518
+ }
2519
+ function convertIRSceneEntryToDSL(baselineScene) {
2520
+ var baselineComposition = getIRSceneEntryComposition(baselineScene);
2521
+ var convertedLayers = convertIRLayersToDSL(baselineComposition, baselineScene.assets, baselineComposition.frameRate);
2522
+ return assembleDSLResult(baselineScene, baselineComposition, convertedLayers.dslLayerByIRId, convertedLayers.layerMapping, convertedLayers.diagnostics);
2523
+ }
2524
+
2525
+ function convertDSLPropertyToIRVec3(property, frameRate, fallback, includeSpatialTangents) {
2526
+ if (includeSpatialTangents === void 0) includeSpatialTangents = false;
2527
+ var _ref;
2528
+ if ((property == null ? void 0 : property.a) === true) {
2529
+ if (property.animation.length > 0) {
2530
+ return {
2531
+ type: 'keyframed',
2532
+ keyframes: convertDSLCurvesToIRKeyframes(property.animation, frameRate, function(value) {
2533
+ return convertDSLValueToIRVec3(value, fallback);
2534
+ }, includeSpatialTangents)
2535
+ };
2536
+ }
2537
+ return {
2538
+ type: 'static',
2539
+ value: [].concat(fallback)
2540
+ };
2541
+ }
2542
+ return {
2543
+ type: 'static',
2544
+ value: convertDSLValueToIRVec3((_ref = property == null ? void 0 : property.value) != null ? _ref : fallback, fallback)
2545
+ };
2546
+ }
2547
+ function convertDSLPropertyToStaticIRVec3(property, fallback) {
2548
+ var _ref;
2549
+ var _property_animation_;
2550
+ if ((property == null ? void 0 : property.a) !== true) {
2551
+ var _ref1;
2552
+ return {
2553
+ type: 'static',
2554
+ value: convertDSLValueToIRVec3((_ref1 = property == null ? void 0 : property.value) != null ? _ref1 : fallback, fallback)
2555
+ };
2556
+ }
2557
+ return {
2558
+ type: 'static',
2559
+ value: convertDSLValueToIRVec3((_ref = (_property_animation_ = property.animation[0]) == null ? void 0 : _property_animation_.start) != null ? _ref : fallback, fallback)
2560
+ };
2561
+ }
2562
+ function convertDSLPropertyToIRNumber(property, frameRate, fallback) {
2563
+ var _ref;
2564
+ if ((property == null ? void 0 : property.a) === true) {
2565
+ if (property.animation.length > 0) {
2566
+ return {
2567
+ type: 'keyframed',
2568
+ keyframes: convertDSLCurvesToIRKeyframes(property.animation, frameRate, function(value) {
2569
+ return convertDSLValueToIRNumber(value, fallback);
2570
+ }, false)
2571
+ };
2572
+ }
2573
+ return {
2574
+ type: 'static',
2575
+ value: fallback
2576
+ };
2577
+ }
2578
+ return {
2579
+ type: 'static',
2580
+ value: convertDSLValueToIRNumber((_ref = property == null ? void 0 : property.value) != null ? _ref : fallback, fallback)
2581
+ };
2582
+ }
2583
+ function convertDSLPropertyToIRRotation(property, frameRate, fallback) {
2584
+ var rotationVector = convertDSLPropertyToIRVec3(property, frameRate, fallback, false);
2585
+ return {
2586
+ x: projectVectorAxis(rotationVector, 0),
2587
+ y: projectVectorAxis(rotationVector, 1),
2588
+ z: projectVectorAxis(rotationVector, 2)
2589
+ };
2590
+ }
2591
+ function projectVectorAxis(property, axisIndex) {
2592
+ if (property.type === 'static') {
2593
+ var _property_value_axisIndex;
2594
+ return {
2595
+ type: 'static',
2596
+ value: (_property_value_axisIndex = property.value[axisIndex]) != null ? _property_value_axisIndex : 0
2597
+ };
2598
+ }
2599
+ return {
2600
+ type: 'keyframed',
2601
+ keyframes: property.keyframes.map(function(keyframe) {
2602
+ var _keyframe_value_axisIndex, _keyframe_endValue_axisIndex;
2603
+ return _extends({
2604
+ frame: keyframe.frame,
2605
+ value: (_keyframe_value_axisIndex = keyframe.value[axisIndex]) != null ? _keyframe_value_axisIndex : 0
2606
+ }, keyframe.endValue != null && {
2607
+ endValue: (_keyframe_endValue_axisIndex = keyframe.endValue[axisIndex]) != null ? _keyframe_endValue_axisIndex : 0
2608
+ }, keyframe.hold != null && {
2609
+ hold: keyframe.hold
2610
+ }, keyframe.inTangent != null && {
2611
+ inTangent: keyframe.inTangent
2612
+ }, keyframe.outTangent != null && {
2613
+ outTangent: keyframe.outTangent
2614
+ });
2615
+ })
2616
+ };
2617
+ }
2618
+ function convertDSLCurvesToIRKeyframes(animationCurves, frameRate, convertValue, includeSpatialTangents) {
2619
+ var keyframes = [];
2620
+ for(var _iterator = _create_for_of_iterator_helper_loose(animationCurves), _step; !(_step = _iterator()).done;){
2621
+ var curve = _step.value;
2622
+ var startValue = convertValue(curve.start);
2623
+ var endValue = convertValue(curve.end);
2624
+ var spatialOut = includeSpatialTangents ? convertDSLSpatialTangentToIR(curve.out) : undefined;
2625
+ var spatialIn = includeSpatialTangents ? convertDSLSpatialTangentToIR(curve.in) : undefined;
2626
+ var startKeyframe = _extends({
2627
+ frame: secondsToFrames(curve.t[0], frameRate),
2628
+ value: startValue,
2629
+ endValue: endValue,
2630
+ outTangent: {
2631
+ x: curve.easing[0],
2632
+ y: curve.easing[1]
2633
+ }
2634
+ }, spatialOut != null && {
2635
+ spatialOut: spatialOut
2636
+ });
2637
+ var endKeyframe = _extends({
2638
+ frame: secondsToFrames(curve.t[1], frameRate),
2639
+ value: endValue,
2640
+ inTangent: {
2641
+ x: curve.easing[2],
2642
+ y: curve.easing[3]
2643
+ }
2644
+ }, spatialIn != null && {
2645
+ spatialIn: spatialIn
2646
+ });
2647
+ appendOrMergeKeyframe(keyframes, startKeyframe);
2648
+ appendOrMergeKeyframe(keyframes, endKeyframe);
2649
+ }
2650
+ return normalizeKeyframeOrder(keyframes);
2651
+ }
2652
+ function normalizeKeyframeOrder(keyframes) {
2653
+ var sortedKeyframes = [].concat(keyframes).sort(function(left, right) {
2654
+ return left.frame - right.frame;
2655
+ });
2656
+ var normalizedKeyframes = [];
2657
+ for(var _iterator = _create_for_of_iterator_helper_loose(sortedKeyframes), _step; !(_step = _iterator()).done;){
2658
+ var keyframe = _step.value;
2659
+ appendOrMergeKeyframe(normalizedKeyframes, keyframe);
2660
+ }
2661
+ return normalizedKeyframes;
2662
+ }
2663
+ function convertDSLSpatialTangentToIR(value) {
2664
+ if ((value == null ? void 0 : value.length) === 2) {
2665
+ return [
2666
+ value[0],
2667
+ value[1]
2668
+ ];
2669
+ }
2670
+ if ((value == null ? void 0 : value.length) === 3) {
2671
+ return [
2672
+ value[0],
2673
+ value[1],
2674
+ value[2]
2675
+ ];
2676
+ }
2677
+ return undefined;
2678
+ }
2679
+ function appendOrMergeKeyframe(keyframes, keyframe) {
2680
+ var previousKeyframe = keyframes[keyframes.length - 1];
2681
+ if (previousKeyframe == null || previousKeyframe.frame !== keyframe.frame) {
2682
+ keyframes.push(keyframe);
2683
+ return;
2684
+ }
2685
+ previousKeyframe.value = keyframe.value;
2686
+ if (keyframe.endValue != null) {
2687
+ previousKeyframe.endValue = keyframe.endValue;
2688
+ }
2689
+ if (keyframe.inTangent != null) {
2690
+ previousKeyframe.inTangent = keyframe.inTangent;
2691
+ }
2692
+ if (keyframe.outTangent != null) {
2693
+ previousKeyframe.outTangent = keyframe.outTangent;
2694
+ }
2695
+ if (keyframe.spatialIn != null) {
2696
+ previousKeyframe.spatialIn = keyframe.spatialIn;
2697
+ }
2698
+ if (keyframe.spatialOut != null) {
2699
+ previousKeyframe.spatialOut = keyframe.spatialOut;
2700
+ }
2701
+ }
2702
+ function convertDSLValueToIRVec3(value, fallback) {
2703
+ if (Array.isArray(value)) {
2704
+ return [
2705
+ resolveFiniteNumber(value[0], fallback[0]),
2706
+ resolveFiniteNumber(value[1], fallback[1]),
2707
+ resolveFiniteNumber(value[2], fallback[2])
2708
+ ];
2709
+ }
2710
+ return [
2711
+ resolveFiniteNumber(value, fallback[0]),
2712
+ fallback[1],
2713
+ fallback[2]
2714
+ ];
2715
+ }
2716
+ function convertDSLValueToIRNumber(value, fallback) {
2717
+ return resolveFiniteNumber(Array.isArray(value) ? value[0] : value, fallback);
2718
+ }
2719
+
2720
+ var DEFAULT_FONT_FAMILY = 'sans-serif';
2721
+ function normalizeDSLFontFamily(family) {
2722
+ var normalizedFamily = family == null ? void 0 : family.trim();
2723
+ return normalizedFamily != null && normalizedFamily !== '' ? normalizedFamily : DEFAULT_FONT_FAMILY;
2724
+ }
2725
+ function ensureSystemFontAsset(assets, family, style, weight) {
2726
+ var normalizedFamily = normalizeDSLFontFamily(family);
2727
+ var existingAsset = assets.find(function(asset) {
2728
+ return asset.type === 'font' && asset.family === normalizedFamily && asset.style === style && asset.weight === weight && asset.source.kind === 'system';
2729
+ });
2730
+ if (existingAsset != null) {
2731
+ return existingAsset.id;
2732
+ }
2733
+ var assetId = createId();
2734
+ assets.push({
2735
+ id: assetId,
2736
+ type: 'font',
2737
+ family: normalizedFamily,
2738
+ style: style,
2739
+ weight: weight,
2740
+ source: {
2741
+ kind: 'system'
2742
+ }
2743
+ });
2744
+ return assetId;
2745
+ }
2746
+ function estimateTextBounds(text) {
2747
+ var width = text.text.length * text.fontSize * 0.6 + text.letterSpacing * Math.max(text.text.length - 1, 0);
2748
+ return {
2749
+ width: Math.max(width, 1),
2750
+ height: Math.max(text.fontSize * 1.2, 1)
2751
+ };
2752
+ }
2753
+ function resolveAssetUrl(asset) {
2754
+ if (asset.source === 'user') {
2755
+ return asset.url;
2756
+ }
2757
+ if (asset.url != null && asset.url !== '') {
2758
+ return asset.url;
2759
+ }
2760
+ return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(asset.svg);
2761
+ }
2762
+
2763
+ var TEXT_PROPERTY_FIELDS = [
2764
+ 'content',
2765
+ 'font',
2766
+ 'size',
2767
+ 'color',
2768
+ 'align',
2769
+ 'line_height',
2770
+ 'letter_spacing'
2771
+ ];
2772
+ /**
2773
+ * Structural, epsilon-tolerant equality between two editable-DSL properties.
2774
+ *
2775
+ * Used for preserved-data change detection so writeback replaces only edited
2776
+ * fields in the IR snapshot.
2777
+ */ function isAnimatedPropertyEqual(leftProperty, rightProperty) {
2778
+ if (leftProperty === undefined || rightProperty === undefined) {
2779
+ return leftProperty === rightProperty;
2780
+ }
2781
+ if (leftProperty.a !== rightProperty.a) {
2782
+ return false;
2783
+ }
2784
+ if (!leftProperty.a) {
2785
+ return !rightProperty.a && isNumberArrayEqual(toNumberArray(leftProperty.value), toNumberArray(rightProperty.value));
2786
+ }
2787
+ if (!rightProperty.a) {
2788
+ return false;
2789
+ }
2790
+ if (leftProperty.animation.length !== rightProperty.animation.length) {
2791
+ return false;
2792
+ }
2793
+ return leftProperty.animation.every(function(curve, curveIndex) {
2794
+ return isAnimationCurveEqual(curve, rightProperty.animation[curveIndex]);
2795
+ });
2796
+ }
2797
+ function collectTextPropertyChanges(baselineText, editedText) {
2798
+ var changes = [];
2799
+ for(var _iterator = _create_for_of_iterator_helper_loose(TEXT_PROPERTY_FIELDS), _step; !(_step = _iterator()).done;){
2800
+ var field = _step.value;
2801
+ var oldValue = baselineText[field];
2802
+ var newValue = editedText[field];
2803
+ var isEqual = field === 'color' ? isHexEqual(oldValue, newValue) : Object.is(oldValue, newValue);
2804
+ if (!isEqual) {
2805
+ changes.push({
2806
+ field: field,
2807
+ oldValue: oldValue,
2808
+ newValue: newValue
2809
+ });
2810
+ }
2811
+ }
2812
+ return changes;
2813
+ }
2814
+ function readTextProperties(layer) {
2815
+ return layer.type === 'text' && layer.text != null ? layer.text : undefined;
2816
+ }
2817
+ function isAssetEqual(leftAsset, rightAsset) {
2818
+ if (leftAsset.source !== rightAsset.source) {
2819
+ return false;
2820
+ }
2821
+ if (leftAsset.source === 'user' && rightAsset.source === 'user') {
2822
+ return leftAsset.url === rightAsset.url;
2823
+ }
2824
+ return leftAsset.source === 'llm_svg' && rightAsset.source === 'llm_svg' && leftAsset.url === rightAsset.url && leftAsset.svg === rightAsset.svg && leftAsset.prompt === rightAsset.prompt;
2825
+ }
2826
+ function isAnimationCurveEqual(leftCurve, rightCurve) {
2827
+ return isNumberArrayEqual(leftCurve.t, rightCurve.t) && isNumberArrayEqual(leftCurve.start, rightCurve.start) && isNumberArrayEqual(leftCurve.end, rightCurve.end) && isNumberArrayEqual(leftCurve.easing, rightCurve.easing) && isNumberArrayEqual(toNumberArray(leftCurve.out), toNumberArray(rightCurve.out)) && isNumberArrayEqual(toNumberArray(leftCurve.in), toNumberArray(rightCurve.in));
2828
+ }
2829
+ function toNumberArray(value) {
2830
+ if (value == null) {
2831
+ return [];
2832
+ }
2833
+ return Array.isArray(value) ? value : [
2834
+ value
2835
+ ];
2836
+ }
2837
+
2838
+ function convertDSLParticleToIRContent(particle, frameRate) {
2839
+ return {
2840
+ maxParticles: particle.options.maxCount,
2841
+ startLifetime: mapDSLParticleExpressionToIR(particle.options.startLifetime),
2842
+ emission: _extends({
2843
+ rateOverTime: mapDSLParticleExpressionToIR(particle.emission.rateOverTime)
2844
+ }, particle.emission.bursts != null && {
2845
+ bursts: mapDSLParticleBurstsToIR(particle.emission.bursts, frameRate)
2846
+ })
2847
+ };
2848
+ }
2849
+ function mapDSLParticleBurstsToIR(bursts, frameRate) {
2850
+ return bursts.map(function(burst) {
2851
+ var _burst_cycles, _burst_interval;
2852
+ return {
2853
+ frameOffset: secondsToFrames(burst.time, frameRate),
2854
+ count: burst.count,
2855
+ cycleCount: burst.cycles === 0 ? 'infinite' : (_burst_cycles = burst.cycles) != null ? _burst_cycles : 1,
2856
+ repeatIntervalFrames: secondsToFrames((_burst_interval = burst.interval) != null ? _burst_interval : 0, frameRate)
2857
+ };
2858
+ });
2859
+ }
2860
+
2861
+ function updateIRParticle(irLayer, editedLayer, baselineLayer, frameRate, reportChange) {
2862
+ var editedParticle = editedLayer.particle;
2863
+ var baselineParticle = baselineLayer.particle;
2864
+ if (irLayer.type !== 'particle' || editedParticle == null || baselineParticle == null) {
2865
+ return;
2866
+ }
2867
+ if (editedParticle.options.maxCount !== baselineParticle.options.maxCount) {
2868
+ var previousValue = irLayer.content.maxParticles;
2869
+ irLayer.content.maxParticles = editedParticle.options.maxCount;
2870
+ reportChange({
2871
+ kind: 'layer',
2872
+ op: 'set',
2873
+ field: 'particle.options.maxCount',
2874
+ layerId: editedLayer.id,
2875
+ oldValue: previousValue,
2876
+ newValue: editedParticle.options.maxCount
2877
+ });
2878
+ }
2879
+ if (!isDSLNumberExpressionEqual(editedParticle.options.startLifetime, baselineParticle.options.startLifetime)) {
2880
+ var previousValue1 = irLayer.content.startLifetime;
2881
+ irLayer.content.startLifetime = mapDSLParticleExpressionToIR(editedParticle.options.startLifetime);
2882
+ reportChange({
2883
+ kind: 'layer',
2884
+ op: 'set',
2885
+ field: 'particle.options.startLifetime',
2886
+ layerId: editedLayer.id,
2887
+ oldValue: previousValue1,
2888
+ newValue: irLayer.content.startLifetime
2889
+ });
2890
+ }
2891
+ if (!isDSLNumberExpressionEqual(editedParticle.emission.rateOverTime, baselineParticle.emission.rateOverTime)) {
2892
+ var previousValue2 = irLayer.content.emission.rateOverTime;
2893
+ irLayer.content.emission.rateOverTime = mapDSLParticleExpressionToIR(editedParticle.emission.rateOverTime);
2894
+ reportChange({
2895
+ kind: 'layer',
2896
+ op: 'set',
2897
+ field: 'particle.emission.rateOverTime',
2898
+ layerId: editedLayer.id,
2899
+ oldValue: previousValue2,
2900
+ newValue: irLayer.content.emission.rateOverTime
2901
+ });
2902
+ }
2903
+ if (!areParticleBurstsEqual(editedParticle.emission.bursts, baselineParticle.emission.bursts)) {
2904
+ var previousValue3 = irLayer.content.emission.bursts;
2905
+ var updatedBursts = editedParticle.emission.bursts == null ? undefined : mapDSLParticleBurstsToIR(editedParticle.emission.bursts, frameRate);
2906
+ if (updatedBursts == null) {
2907
+ delete irLayer.content.emission.bursts;
2908
+ } else {
2909
+ irLayer.content.emission.bursts = updatedBursts;
2910
+ }
2911
+ reportChange({
2912
+ kind: 'layer',
2913
+ op: updatedBursts == null ? 'delete' : 'set',
2914
+ field: 'particle.emission.bursts',
2915
+ layerId: editedLayer.id,
2916
+ oldValue: previousValue3,
2917
+ newValue: updatedBursts
2918
+ });
2919
+ }
2920
+ }
2921
+ function areParticleBurstsEqual(left, right) {
2922
+ if (left == null || right == null) {
2923
+ return left === right;
2924
+ }
2925
+ if (left.length !== right.length) {
2926
+ return false;
2927
+ }
2928
+ return left.every(function(burst, index) {
2929
+ var other = right[index];
2930
+ return other != null && Object.is(burst.time, other.time) && Object.is(burst.count, other.count) && Object.is(burst.cycles, other.cycles) && Object.is(burst.interval, other.interval);
2931
+ });
2932
+ }
2933
+
2934
+ function updateIRLayer(irLayer, irScene, editedLayer, baselineLayer, dslPath, frameRate, strict, reportWarning, reportChange) {
2935
+ var _editedLayer_parent, _baselineLayer_parent;
2936
+ if (editedLayer.name !== baselineLayer.name) {
2937
+ var previousName = irLayer.name;
2938
+ irLayer.name = editedLayer.name;
2939
+ reportChange({
2940
+ kind: 'layer',
2941
+ op: 'set',
2942
+ field: 'name',
2943
+ layerId: editedLayer.id,
2944
+ oldValue: previousName,
2945
+ newValue: editedLayer.name
2946
+ });
2947
+ }
2948
+ if (editedLayer.type !== baselineLayer.type) {
2949
+ reportUnsupportedLayerEdit(strict, reportWarning, 'LAYER_TYPE_CHANGE_IGNORED', "type change on layer '" + editedLayer.id + "' ('" + baselineLayer.type + "' -> '" + editedLayer.type + "') is ignored.", editedLayer.id, "" + dslPath + ".type");
2950
+ }
2951
+ if (editedLayer.description.self !== baselineLayer.description.self || editedLayer.description.composite !== baselineLayer.description.composite) {
2952
+ reportUnsupportedLayerEdit(strict, reportWarning, 'LAYER_DESCRIPTION_CHANGE_IGNORED', "description change on layer '" + editedLayer.id + "' is not represented in Animation IR and is ignored.", editedLayer.id, "" + dslPath + ".description");
2953
+ }
2954
+ if (((_editedLayer_parent = editedLayer.parent) != null ? _editedLayer_parent : null) !== ((_baselineLayer_parent = baselineLayer.parent) != null ? _baselineLayer_parent : null)) {
2955
+ reportUnsupportedLayerEdit(strict, reportWarning, 'PARENT_CHANGE_IGNORED', "parent change on layer '" + editedLayer.id + "' " + ("('" + baselineLayer.parent + "' -> '" + editedLayer.parent + "') is ignored in this mode."), editedLayer.id, "" + dslPath + ".parent");
2956
+ }
2957
+ updateIRTransform(irLayer, editedLayer, baselineLayer, frameRate, reportChange);
2958
+ updateIRTiming(irLayer, editedLayer, baselineLayer, frameRate, reportChange);
2959
+ updateIRText(irLayer, irScene, editedLayer, baselineLayer, reportChange);
2960
+ updateIRParticle(irLayer, editedLayer, baselineLayer, frameRate, reportChange);
2961
+ updateIRLocalBounds(irLayer, editedLayer, reportChange);
2962
+ updateIRAsset(irLayer, irScene, editedLayer, baselineLayer, reportChange);
2963
+ }
2964
+ function updateIRLocalBounds(irLayer, editedLayer, reportChange) {
2965
+ var _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
2966
+ if (irLayer.type !== 'text' && irLayer.type !== 'image' && irLayer.type !== 'particle') {
2967
+ return;
2968
+ }
2969
+ var previousBounds = irLayer.localBounds;
2970
+ var estimatedBounds = irLayer.type === 'text' ? estimateTextBounds(irLayer.content) : undefined;
2971
+ var fallbackWidth = (_ref = (_ref1 = previousBounds == null ? void 0 : previousBounds.width) != null ? _ref1 : estimatedBounds == null ? void 0 : estimatedBounds.width) != null ? _ref : editedLayer.width;
2972
+ var fallbackHeight = (_ref2 = (_ref3 = previousBounds == null ? void 0 : previousBounds.height) != null ? _ref3 : estimatedBounds == null ? void 0 : estimatedBounds.height) != null ? _ref2 : editedLayer.height;
2973
+ var updatedBounds = {
2974
+ x: (_ref4 = previousBounds == null ? void 0 : previousBounds.x) != null ? _ref4 : 0,
2975
+ y: (_ref5 = previousBounds == null ? void 0 : previousBounds.y) != null ? _ref5 : 0,
2976
+ width: Number.isFinite(editedLayer.width) && editedLayer.width > 0 ? editedLayer.width : fallbackWidth,
2977
+ height: Number.isFinite(editedLayer.height) && editedLayer.height > 0 ? editedLayer.height : fallbackHeight
2978
+ };
2979
+ if (previousBounds != null && isScalarEqual(updatedBounds.x, previousBounds.x) && isScalarEqual(updatedBounds.y, previousBounds.y) && isScalarEqual(updatedBounds.width, previousBounds.width) && isScalarEqual(updatedBounds.height, previousBounds.height)) {
2980
+ return;
2981
+ }
2982
+ irLayer.localBounds = updatedBounds;
2983
+ reportChange({
2984
+ kind: 'layer',
2985
+ op: 'set',
2986
+ field: 'localBounds',
2987
+ layerId: editedLayer.id,
2988
+ oldValue: previousBounds,
2989
+ newValue: updatedBounds
2990
+ });
2991
+ }
2992
+ function reportUnsupportedLayerEdit(strict, reportWarning, code, message, layerId, path) {
2993
+ var formattedMessage = "[dsl-ir:preserved-data] " + message;
2994
+ if (strict) {
2995
+ throw new Error(formattedMessage);
2996
+ }
2997
+ reportWarning({
2998
+ code: code,
2999
+ message: formattedMessage,
3000
+ path: path,
3001
+ layerId: layerId
3002
+ });
3003
+ }
3004
+ function updateIRTransform(irLayer, editedLayer, baselineLayer, frameRate, reportChange) {
3005
+ // Create the transform lazily so no-op updates preserve the baseline shape.
3006
+ var ensureTransform = function ensureTransform() {
3007
+ var _irLayer, _transform;
3008
+ return (_transform = (_irLayer = irLayer).transform) != null ? _transform : _irLayer.transform = {};
3009
+ };
3010
+ if (!isAnimatedPropertyEqual(withPositionZ(editedLayer.position, 0), withPositionZ(baselineLayer.position, 0))) {
3011
+ var _irLayer_transform;
3012
+ var sourcePosition = (_irLayer_transform = irLayer.transform) == null ? void 0 : _irLayer_transform.position;
3013
+ var position = convertDSLPropertyToIRVec3(withPositionZ(editedLayer.position, 0), frameRate, TRANSFORM_FALLBACK.position, true);
3014
+ if ((sourcePosition == null ? void 0 : sourcePosition.type) === 'static') {
3015
+ if (position.type === 'static') {
3016
+ position.value[2] = sourcePosition.value[2];
3017
+ } else {
3018
+ for(var _iterator = _create_for_of_iterator_helper_loose(position.keyframes), _step; !(_step = _iterator()).done;){
3019
+ var keyframe = _step.value;
3020
+ keyframe.value[2] = sourcePosition.value[2];
3021
+ if (keyframe.endValue != null) {
3022
+ keyframe.endValue[2] = sourcePosition.value[2];
3023
+ }
3024
+ }
3025
+ }
3026
+ }
3027
+ if ((sourcePosition == null ? void 0 : sourcePosition.type) === 'keyframed') {
3028
+ var depths = sourcePosition.keyframes.flatMap(function(keyframe) {
3029
+ var _keyframe_endValue;
3030
+ return [
3031
+ keyframe.value[2],
3032
+ ((_keyframe_endValue = keyframe.endValue) != null ? _keyframe_endValue : keyframe.value)[2]
3033
+ ];
3034
+ });
3035
+ var constantDepth = depths.every(function(depth) {
3036
+ return depth === depths[0];
3037
+ });
3038
+ if (position.type === 'static' && constantDepth) {
3039
+ var _depths_;
3040
+ position.value[2] = (_depths_ = depths[0]) != null ? _depths_ : 0;
3041
+ } else if (position.type === 'keyframed') {
3042
+ var _loop = function() {
3043
+ var keyframe = _step1.value;
3044
+ var _ref, _ref1;
3045
+ var source = sourcePosition.keyframes.find(function(candidate) {
3046
+ return candidate.frame === keyframe.frame;
3047
+ });
3048
+ if (source == null && !constantDepth) {
3049
+ throw new Error('[dsl-ir] Position timing edits on layers with animated source depth are unsupported.');
3050
+ }
3051
+ keyframe.value[2] = (_ref = (_ref1 = source == null ? void 0 : source.value[2]) != null ? _ref1 : depths[0]) != null ? _ref : 0;
3052
+ if (keyframe.endValue != null) {
3053
+ var _ref2, _ref3, _ref4;
3054
+ var _this;
3055
+ keyframe.endValue[2] = (_ref2 = (_ref3 = (_this = (_ref4 = source == null ? void 0 : source.endValue) != null ? _ref4 : source == null ? void 0 : source.value) == null ? void 0 : _this[2]) != null ? _ref3 : depths[0]) != null ? _ref2 : 0;
3056
+ }
3057
+ };
3058
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(position.keyframes), _step1; !(_step1 = _iterator1()).done;)_loop();
3059
+ } else {
3060
+ throw new Error('[dsl-ir] Replacing animated source depth with static position is unsupported.');
3061
+ }
3062
+ }
3063
+ ensureTransform().position = position;
3064
+ reportChange({
3065
+ kind: 'transform',
3066
+ op: 'set',
3067
+ field: 'position',
3068
+ layerId: editedLayer.id,
3069
+ oldValue: baselineLayer.position,
3070
+ newValue: editedLayer.position
3071
+ });
3072
+ }
3073
+ if (editedLayer.rotation !== undefined && !isAnimatedPropertyEqual(editedLayer.rotation, baselineLayer.rotation)) {
3074
+ var transform = ensureTransform();
3075
+ transform.rotation = convertDSLPropertyToIRRotation(editedLayer.rotation, frameRate, TRANSFORM_FALLBACK.rotation);
3076
+ reportChange({
3077
+ kind: 'transform',
3078
+ op: 'set',
3079
+ field: 'rotation',
3080
+ layerId: editedLayer.id,
3081
+ oldValue: baselineLayer.rotation,
3082
+ newValue: editedLayer.rotation
3083
+ });
3084
+ }
3085
+ if (editedLayer.scale !== undefined && !isAnimatedPropertyEqual(editedLayer.scale, baselineLayer.scale)) {
3086
+ ensureTransform().scale = convertDSLPropertyToIRVec3(editedLayer.scale, frameRate, TRANSFORM_FALLBACK.scale, false);
3087
+ reportChange({
3088
+ kind: 'transform',
3089
+ op: 'set',
3090
+ field: 'scale',
3091
+ layerId: editedLayer.id,
3092
+ oldValue: baselineLayer.scale,
3093
+ newValue: editedLayer.scale
3094
+ });
3095
+ }
3096
+ if (editedLayer.anchor !== undefined && !isAnimatedPropertyEqual(editedLayer.anchor, baselineLayer.anchor)) {
3097
+ ensureTransform().anchor = convertDSLPropertyToStaticIRVec3(editedLayer.anchor, TRANSFORM_FALLBACK.anchor);
3098
+ reportChange({
3099
+ kind: 'transform',
3100
+ op: 'set',
3101
+ field: 'anchor',
3102
+ layerId: editedLayer.id,
3103
+ oldValue: baselineLayer.anchor,
3104
+ newValue: editedLayer.anchor
3105
+ });
3106
+ }
3107
+ if (editedLayer.opacity !== undefined && !isAnimatedPropertyEqual(editedLayer.opacity, baselineLayer.opacity)) {
3108
+ ensureTransform().opacity = convertDSLPropertyToIRNumber(editedLayer.opacity, frameRate, TRANSFORM_FALLBACK.opacity);
3109
+ reportChange({
3110
+ kind: 'transform',
3111
+ op: 'set',
3112
+ field: 'opacity',
3113
+ layerId: editedLayer.id,
3114
+ oldValue: baselineLayer.opacity,
3115
+ newValue: editedLayer.opacity
3116
+ });
3117
+ }
3118
+ }
3119
+ function updateIRTiming(irLayer, editedLayer, baselineLayer, frameRate, reportChange) {
3120
+ if (editedLayer.time_range === undefined || baselineLayer.time_range !== undefined && isScalarEqual(editedLayer.time_range[0], baselineLayer.time_range[0]) && isScalarEqual(editedLayer.time_range[1], baselineLayer.time_range[1])) {
3121
+ return;
3122
+ }
3123
+ var previousTime = irLayer.time;
3124
+ irLayer.time = _extends({}, irLayer.time, {
3125
+ inFrame: editedLayer.time_range[0] * frameRate,
3126
+ outFrame: editedLayer.time_range[1] * frameRate
3127
+ });
3128
+ reportChange({
3129
+ kind: 'timing',
3130
+ op: 'set',
3131
+ field: 'time_range',
3132
+ layerId: editedLayer.id,
3133
+ oldValue: previousTime,
3134
+ newValue: editedLayer.time_range
3135
+ });
3136
+ }
3137
+ function updateIRText(irLayer, irScene, editedLayer, baselineLayer, reportChange) {
3138
+ var _normalizedEditedText_font;
3139
+ var editedText = readTextProperties(editedLayer);
3140
+ var baselineText = readTextProperties(baselineLayer);
3141
+ if (irLayer.type !== 'text' || editedText == null) {
3142
+ return;
3143
+ }
3144
+ var normalizedEditedText = normalizeTextPropertiesForIR(editedText, irLayer.content);
3145
+ var textChanges = baselineText != null ? collectTextPropertyChanges(baselineText, normalizedEditedText) : [];
3146
+ if (baselineText != null && textChanges.length === 0) {
3147
+ return;
3148
+ }
3149
+ var previousText = irLayer.content;
3150
+ var currentFontAsset = resolveFontAsset(irScene, irLayer.content.fontAssetId);
3151
+ var fontAssetId = baselineText == null || textChanges.some(function(change) {
3152
+ return change.field === 'font';
3153
+ }) ? ensureSystemFontAsset(irScene.assets, (_normalizedEditedText_font = normalizedEditedText.font) != null ? _normalizedEditedText_font : currentFontAsset.family, currentFontAsset.style, currentFontAsset.weight) : irLayer.content.fontAssetId;
3154
+ irLayer.content = buildUpdatedTextData(irLayer.content, normalizedEditedText, fontAssetId);
3155
+ if (baselineText == null) {
3156
+ reportChange({
3157
+ kind: 'text',
3158
+ op: 'set',
3159
+ field: 'text',
3160
+ layerId: editedLayer.id,
3161
+ oldValue: previousText,
3162
+ newValue: normalizedEditedText
3163
+ });
3164
+ } else {
3165
+ for(var _iterator = _create_for_of_iterator_helper_loose(textChanges), _step; !(_step = _iterator()).done;){
3166
+ var _step_value = _step.value, field = _step_value.field, oldValue = _step_value.oldValue, newValue = _step_value.newValue;
3167
+ reportChange({
3168
+ kind: 'text',
3169
+ op: 'set',
3170
+ field: "text." + field,
3171
+ layerId: editedLayer.id,
3172
+ oldValue: oldValue,
3173
+ newValue: newValue
3174
+ });
3175
+ }
3176
+ }
3177
+ }
3178
+ function normalizeTextPropertiesForIR(text, currentText) {
3179
+ var currentFontSize = Number.isFinite(currentText.fontSize) && currentText.fontSize > 0 ? currentText.fontSize : 16;
3180
+ var fontSize = Number.isFinite(text.size) && text.size > 0 ? text.size : currentFontSize;
3181
+ var lineHeight = text.line_height != null && Number.isFinite(text.line_height) && text.line_height > 0 ? text.line_height : fontSize;
3182
+ var fontFamily = text.font != null ? normalizeDSLFontFamily(text.font) : undefined;
3183
+ return _extends({}, text, {
3184
+ size: fontSize,
3185
+ line_height: lineHeight
3186
+ }, fontFamily != null && {
3187
+ font: fontFamily
3188
+ });
3189
+ }
3190
+ function buildUpdatedTextData(currentText, editedText, fontAssetId) {
3191
+ var _editedText_align, _editedText_letter_spacing, _editedText_line_height;
3192
+ return {
3193
+ text: editedText.content,
3194
+ fontAssetId: fontAssetId,
3195
+ fontSize: editedText.size,
3196
+ color: hexToIRColor(editedText.color),
3197
+ textAlign: (_editedText_align = editedText.align) != null ? _editedText_align : currentText.textAlign,
3198
+ letterSpacing: (_editedText_letter_spacing = editedText.letter_spacing) != null ? _editedText_letter_spacing : currentText.letterSpacing,
3199
+ lineHeight: (_editedText_line_height = editedText.line_height) != null ? _editedText_line_height : currentText.lineHeight
3200
+ };
3201
+ }
3202
+ function resolveFontAsset(irScene, fontAssetId) {
3203
+ var fontAsset = irScene.assets.find(function(asset) {
3204
+ return asset.type === 'font' && asset.id === fontAssetId;
3205
+ });
3206
+ if (fontAsset == null) {
3207
+ throw new TypeError("[dsl-ir] Text references a missing Font Asset: " + fontAssetId);
3208
+ }
3209
+ return fontAsset;
3210
+ }
3211
+ function updateIRAsset(irLayer, irScene, editedLayer, baselineLayer, reportChange) {
3212
+ if (irLayer.type !== 'image' || editedLayer.asset == null) {
3213
+ return;
3214
+ }
3215
+ var imageAsset = irScene.assets.find(function(asset) {
3216
+ return asset.type === 'image' && asset.id === irLayer.content.assetId;
3217
+ });
3218
+ if (imageAsset == null) {
3219
+ return;
3220
+ }
3221
+ if (baselineLayer.asset != null && isAssetEqual(editedLayer.asset, baselineLayer.asset)) {
3222
+ return;
3223
+ }
3224
+ var editedUrl = resolveAssetUrl(editedLayer.asset);
3225
+ var baselineUrl = baselineLayer.asset != null ? resolveAssetUrl(baselineLayer.asset) : undefined;
3226
+ if (editedUrl !== '' && editedUrl !== baselineUrl) {
3227
+ var previousUrl = getIRResourceSourceUrl(imageAsset.source);
3228
+ if (countImageAssetReferences(irScene, imageAsset.id) > 1) {
3229
+ var clonedAssetId = createAvailableRecombineAssetId(irScene);
3230
+ imageAsset = _extends({}, imageAsset, {
3231
+ id: clonedAssetId
3232
+ });
3233
+ irScene.assets.push(imageAsset);
3234
+ irLayer.content.assetId = clonedAssetId;
3235
+ }
3236
+ imageAsset.source = createIRResourceSource(editedUrl);
3237
+ reportChange({
3238
+ kind: 'asset',
3239
+ op: 'set',
3240
+ field: 'asset.url',
3241
+ layerId: editedLayer.id,
3242
+ oldValue: previousUrl,
3243
+ newValue: editedUrl
3244
+ });
3245
+ }
3246
+ }
3247
+ function countImageAssetReferences(irScene, assetId) {
3248
+ return irScene.compositions.reduce(function(count, composition) {
3249
+ return count + composition.layers.filter(function(layer) {
3250
+ return layer.type === 'image' && layer.content.assetId === assetId;
3251
+ }).length;
3252
+ }, 0);
3253
+ }
3254
+ function createAvailableRecombineAssetId(irScene) {
3255
+ var existingAssetIdSet = new Set(irScene.assets.map(function(asset) {
3256
+ return asset.id;
3257
+ }));
3258
+ while(true){
3259
+ var candidate = createId();
3260
+ if (!existingAssetIdSet.has(candidate)) {
3261
+ return candidate;
3262
+ }
3263
+ }
3264
+ }
3265
+
3266
+ /** Apply edited sibling order without changing parent relationships. */ function updateLayerOrder(updatedIR, editedLayers, irLayerIdByEditedLayer, reportChange, rootDSLParentId) {
3267
+ var irLayerById = new Map(updatedIR.layers.map(function(layer) {
3268
+ return [
3269
+ layer.id,
3270
+ layer
3271
+ ];
3272
+ }));
3273
+ var childIRLayerIdsByParentIRLayerId = new Map();
3274
+ for(var _iterator = _create_for_of_iterator_helper_loose(updatedIR.layers), _step; !(_step = _iterator()).done;){
3275
+ var layer = _step.value;
3276
+ var parentLayerId = layer.parentId;
3277
+ if (parentLayerId != null) {
3278
+ var _childIRLayerIdsByParentIRLayerId_get;
3279
+ var childLayerIds = (_childIRLayerIdsByParentIRLayerId_get = childIRLayerIdsByParentIRLayerId.get(parentLayerId)) != null ? _childIRLayerIdsByParentIRLayerId_get : [];
3280
+ childLayerIds.push(layer.id);
3281
+ childIRLayerIdsByParentIRLayerId.set(parentLayerId, childLayerIds);
3282
+ }
3283
+ }
3284
+ updateSiblingGroups(editedLayers, undefined, {
3285
+ updatedIR: updatedIR,
3286
+ irLayerIdByEditedLayer: irLayerIdByEditedLayer,
3287
+ irLayerById: irLayerById,
3288
+ childIRLayerIdsByParentIRLayerId: childIRLayerIdsByParentIRLayerId,
3289
+ reportChange: reportChange,
3290
+ rootDSLParentId: rootDSLParentId
3291
+ });
3292
+ }
3293
+ function updateSiblingGroups(siblingLayers, parentLayer, context) {
3294
+ updateIRSiblingOrder(siblingLayers, parentLayer, context);
3295
+ for(var _iterator = _create_for_of_iterator_helper_loose(siblingLayers), _step; !(_step = _iterator()).done;){
3296
+ var sibling = _step.value;
3297
+ var _sibling_children;
3298
+ updateSiblingGroups((_sibling_children = sibling.children) != null ? _sibling_children : [], sibling, context);
3299
+ }
3300
+ }
3301
+ function updateIRSiblingOrder(siblingLayers, parentLayer, context) {
3302
+ var _ref, _ref1, _ref2;
3303
+ var parentIRLayerId = parentLayer != null ? context.irLayerIdByEditedLayer.get(parentLayer) : undefined;
3304
+ if (parentLayer != null && parentIRLayerId == null) {
3305
+ return;
3306
+ }
3307
+ var expectedParentId = (_ref = (_ref1 = parentLayer == null ? void 0 : parentLayer.id) != null ? _ref1 : context.rootDSLParentId) != null ? _ref : null;
3308
+ var orderedSiblings = [];
3309
+ for(var _iterator = _create_for_of_iterator_helper_loose(siblingLayers), _step; !(_step = _iterator()).done;){
3310
+ var layer = _step.value;
3311
+ var _layer_parent;
3312
+ var irLayerId = context.irLayerIdByEditedLayer.get(layer);
3313
+ if (irLayerId == null) {
3314
+ continue;
3315
+ }
3316
+ var irLayer = context.irLayerById.get(irLayerId);
3317
+ if (irLayer == null || ((_layer_parent = layer.parent) != null ? _layer_parent : null) !== expectedParentId || irLayer.parentId !== parentIRLayerId) {
3318
+ continue;
3319
+ }
3320
+ orderedSiblings.push({
3321
+ layer: layer,
3322
+ subtreeLayerIdSet: collectIRSubtreeLayerIds(irLayerId, context.childIRLayerIdsByParentIRLayerId)
3323
+ });
3324
+ }
3325
+ if (orderedSiblings.length < 2) {
3326
+ return;
3327
+ }
3328
+ var ownerByIRLayerId = new Map();
3329
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(orderedSiblings), _step1; !(_step1 = _iterator1()).done;){
3330
+ var sibling = _step1.value;
3331
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(sibling.subtreeLayerIdSet), _step2; !(_step2 = _iterator2()).done;){
3332
+ var irLayerId1 = _step2.value;
3333
+ ownerByIRLayerId.set(irLayerId1, sibling);
3334
+ }
3335
+ }
3336
+ var currentIROrder = collectOwnerOrder(context.updatedIR.layers, function(layer) {
3337
+ return ownerByIRLayerId.get(layer.id);
3338
+ });
3339
+ var currentDSLOrder = [].concat(currentIROrder).reverse();
3340
+ orderedSiblings.sort(function(left, right) {
3341
+ return getLayerStackingOrder(right.layer) - getLayerStackingOrder(left.layer) || currentDSLOrder.indexOf(left) - currentDSLOrder.indexOf(right);
3342
+ });
3343
+ if (currentDSLOrder.length !== orderedSiblings.length || isOwnerOrderEqual(currentDSLOrder, orderedSiblings)) {
3344
+ return;
3345
+ }
3346
+ var reorderedLayers = reorderOwnedEntries(context.updatedIR.layers, [].concat(orderedSiblings).reverse(), function(layer) {
3347
+ return ownerByIRLayerId.get(layer.id);
3348
+ });
3349
+ if (reorderedLayers == null) {
3350
+ return;
3351
+ }
3352
+ context.updatedIR.layers = reorderedLayers;
3353
+ var changedParentLayerId = (_ref2 = parentLayer == null ? void 0 : parentLayer.id) != null ? _ref2 : context.rootDSLParentId;
3354
+ context.reportChange(_extends({
3355
+ kind: 'layer',
3356
+ op: 'set',
3357
+ field: 'order'
3358
+ }, changedParentLayerId != null && {
3359
+ layerId: changedParentLayerId
3360
+ }, {
3361
+ oldValue: currentDSLOrder.map(function(sibling) {
3362
+ return sibling.layer.id;
3363
+ }),
3364
+ newValue: orderedSiblings.map(function(sibling) {
3365
+ return sibling.layer.id;
3366
+ })
3367
+ }));
3368
+ }
3369
+ function collectIRSubtreeLayerIds(rootLayerId, childIRLayerIdsByParentIRLayerId, subtreeLayerIdSet) {
3370
+ if (subtreeLayerIdSet === void 0) subtreeLayerIdSet = new Set();
3371
+ var _childIRLayerIdsByParentIRLayerId_get;
3372
+ if (subtreeLayerIdSet.has(rootLayerId)) {
3373
+ return subtreeLayerIdSet;
3374
+ }
3375
+ subtreeLayerIdSet.add(rootLayerId);
3376
+ for(var _iterator = _create_for_of_iterator_helper_loose((_childIRLayerIdsByParentIRLayerId_get = childIRLayerIdsByParentIRLayerId.get(rootLayerId)) != null ? _childIRLayerIdsByParentIRLayerId_get : []), _step; !(_step = _iterator()).done;){
3377
+ var childLayerId = _step.value;
3378
+ collectIRSubtreeLayerIds(childLayerId, childIRLayerIdsByParentIRLayerId, subtreeLayerIdSet);
3379
+ }
3380
+ return subtreeLayerIdSet;
3381
+ }
3382
+ function collectOwnerOrder(entries, resolveOwner) {
3383
+ var owners = [];
3384
+ for(var _iterator = _create_for_of_iterator_helper_loose(entries), _step; !(_step = _iterator()).done;){
3385
+ var entry = _step.value;
3386
+ var owner = resolveOwner(entry);
3387
+ if (owner != null && !owners.includes(owner)) {
3388
+ owners.push(owner);
3389
+ }
3390
+ }
3391
+ return owners;
3392
+ }
3393
+ function isOwnerOrderEqual(left, right) {
3394
+ return left.length === right.length && left.every(function(owner, index) {
3395
+ return owner === right[index];
3396
+ });
3397
+ }
3398
+ function reorderOwnedEntries(entries, orderedOwners, resolveOwner) {
3399
+ var entriesByOwner = new Map();
3400
+ for(var _iterator = _create_for_of_iterator_helper_loose(orderedOwners), _step; !(_step = _iterator()).done;){
3401
+ var owner = _step.value;
3402
+ entriesByOwner.set(owner, []);
3403
+ }
3404
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(entries), _step1; !(_step1 = _iterator1()).done;){
3405
+ var entry = _step1.value;
3406
+ var owner1 = resolveOwner(entry);
3407
+ if (owner1 != null) {
3408
+ var _entriesByOwner_get;
3409
+ (_entriesByOwner_get = entriesByOwner.get(owner1)) == null ? void 0 : _entriesByOwner_get.push(entry);
3410
+ }
3411
+ }
3412
+ if (orderedOwners.some(function(owner) {
3413
+ var _ref;
3414
+ var _entriesByOwner_get;
3415
+ return ((_ref = (_entriesByOwner_get = entriesByOwner.get(owner)) == null ? void 0 : _entriesByOwner_get.length) != null ? _ref : 0) === 0;
3416
+ })) {
3417
+ return undefined;
3418
+ }
3419
+ var reorderedOwnedEntries = orderedOwners.flatMap(function(owner) {
3420
+ var _entriesByOwner_get;
3421
+ return (_entriesByOwner_get = entriesByOwner.get(owner)) != null ? _entriesByOwner_get : [];
3422
+ });
3423
+ var reorderedIndex = 0;
3424
+ return entries.map(function(entry) {
3425
+ if (resolveOwner(entry) == null) {
3426
+ return entry;
3427
+ }
3428
+ return reorderedOwnedEntries[reorderedIndex++];
3429
+ });
3430
+ }
3431
+
3432
+ /** Apply previously validated DSL to a clone of the baseline IR. */ function updateValidatedIRFromDSL(baselineScene, editedDocument, layerMapping, options) {
3433
+ var _loop = function() {
3434
+ var _step_value = _step3.value, baselineLayer = _step_value.layer, path = _step_value.path;
3435
+ var _layerMapping_layers_baselineLayer_id;
3436
+ var irLayerId = (_layerMapping_layers_baselineLayer_id = layerMapping.layers[baselineLayer.id]) == null ? void 0 : _layerMapping_layers_baselineLayer_id.irLayerId;
3437
+ if (irLayerId == null) {
3438
+ return "continue";
3439
+ }
3440
+ var editedLayer = matchEditedLayer(baselineLayer, path, {
3441
+ editedLayerById: editedLayerById,
3442
+ editedLayerByPath: editedLayerByPath,
3443
+ matchedEditedLayerSet: matchedEditedLayerSet
3444
+ });
3445
+ if (editedLayer == null) {
3446
+ var _layerMapping_layers_baselineLayer_id1;
3447
+ var expandedSource = (_layerMapping_layers_baselineLayer_id1 = layerMapping.layers[baselineLayer.id]) == null ? void 0 : _layerMapping_layers_baselineLayer_id1.expandedSource;
3448
+ var expandedComposition = expandedSource != null ? compositionById.get(expandedSource.irCompositionId) : undefined;
3449
+ if (expandedSource != null && (expandedComposition == null ? void 0 : expandedComposition.layers.some(function(layer) {
3450
+ return layer.id === irLayerId;
3451
+ })) === true) {
3452
+ var _deletedExpandedIRLayerIdsByCompositionId_get;
3453
+ var deletedIds = (_deletedExpandedIRLayerIdsByCompositionId_get = deletedExpandedIRLayerIdsByCompositionId.get(expandedSource.irCompositionId)) != null ? _deletedExpandedIRLayerIdsByCompositionId_get : new Set();
3454
+ deletedIds.add(irLayerId);
3455
+ deletedExpandedIRLayerIdsByCompositionId.set(expandedSource.irCompositionId, deletedIds);
3456
+ semanticallyDeletedExpandedDSLIds.add(baselineLayer.id);
3457
+ } else {
3458
+ deletedIRLayerIdSet.add(irLayerId);
3459
+ }
3460
+ reportChange({
3461
+ kind: 'layer',
3462
+ op: 'delete',
3463
+ layerId: baselineLayer.id
3464
+ });
3465
+ return "continue";
3466
+ }
3467
+ var irLayer = clonedLayerByIRId.get(irLayerId);
3468
+ if (irLayer == null) {
3469
+ return "continue";
3470
+ }
3471
+ matchedEditedLayerSet.add(editedLayer);
3472
+ irLayerIdByEditedLayer.set(editedLayer, irLayerId);
3473
+ updateIRLayer(irLayer, updatedScene, editedLayer, baselineLayer, path, targetFrameRate, strict, reportWarning, reportChange);
3474
+ }, _loop1 = function() {
3475
+ var editedLayer = _step4.value;
3476
+ var _editedPathByLayer_get;
3477
+ var _layerMapping_layers_editedLayer_id;
3478
+ if (matchedEditedLayerSet.has(editedLayer)) {
3479
+ return "continue";
3480
+ }
3481
+ var expandedSource = (_layerMapping_layers_editedLayer_id = layerMapping.layers[editedLayer.id]) == null ? void 0 : _layerMapping_layers_editedLayer_id.expandedSource;
3482
+ if (expandedSource != null) {
3483
+ var mappingEntry = layerMapping.layers[editedLayer.id];
3484
+ var targetComposition = compositionById.get(expandedSource.irCompositionId);
3485
+ var targetLayer = (mappingEntry == null ? void 0 : mappingEntry.irLayerId) != null ? targetComposition == null ? void 0 : targetComposition.layers.find(function(layer) {
3486
+ return layer.id === mappingEntry.irLayerId;
3487
+ }) : undefined;
3488
+ if (targetComposition != null && targetLayer != null && (mappingEntry == null ? void 0 : mappingEntry.irLayerId) != null) {
3489
+ var _editedPathByLayer_get1;
3490
+ updateIRLayer(targetLayer, updatedScene, editedLayer, buildExpandedBaselineLayer(editedLayer, expandedSource), (_editedPathByLayer_get1 = editedPathByLayer.get(editedLayer)) != null ? _editedPathByLayer_get1 : '$.layers', targetFrameRate, strict, reportWarning, reportChange);
3491
+ expandedIRLayerIdByEditedLayer.set(editedLayer, mappingEntry.irLayerId);
3492
+ editedExpandedCompositionById.set(expandedSource.irCompositionId, targetComposition);
3493
+ }
3494
+ return "continue";
3495
+ }
3496
+ var message = "[dsl-ir:preserved-data] edited layer '" + editedLayer.id + "' matches no baseline scene layer; new layers are not supported in this mode.";
3497
+ if (strict) {
3498
+ throw new Error(message);
3499
+ }
3500
+ reportWarning({
3501
+ code: 'INVENTED_LAYER',
3502
+ message: message,
3503
+ path: (_editedPathByLayer_get = editedPathByLayer.get(editedLayer)) != null ? _editedPathByLayer_get : '$.layers',
3504
+ layerId: editedLayer.id
3505
+ });
3506
+ }, _loop2 = function() {
3507
+ var _step_value = _step5.value, dslLayerId = _step_value[0], mappingEntry = _step_value[1];
3508
+ var _deletedExpandedIRLayerIdsByCompositionId_get;
3509
+ var expandedSource = mappingEntry.expandedSource;
3510
+ var irLayerId = mappingEntry.irLayerId;
3511
+ if (expandedSource == null || irLayerId == null || editedLayerById.has(dslLayerId) || !editedLayerById.has(expandedSource.parentLayerId) || semanticallyDeletedExpandedDSLIds.has(dslLayerId)) {
3512
+ return "continue";
3513
+ }
3514
+ var composition = compositionById.get(expandedSource.irCompositionId);
3515
+ if ((composition == null ? void 0 : composition.layers.some(function(layer) {
3516
+ return layer.id === irLayerId;
3517
+ })) !== true) {
3518
+ return "continue";
3519
+ }
3520
+ var deletedIds = (_deletedExpandedIRLayerIdsByCompositionId_get = deletedExpandedIRLayerIdsByCompositionId.get(expandedSource.irCompositionId)) != null ? _deletedExpandedIRLayerIdsByCompositionId_get : new Set();
3521
+ deletedIds.add(irLayerId);
3522
+ deletedExpandedIRLayerIdsByCompositionId.set(expandedSource.irCompositionId, deletedIds);
3523
+ semanticallyDeletedExpandedDSLIds.add(dslLayerId);
3524
+ reportChange({
3525
+ kind: 'layer',
3526
+ op: 'delete',
3527
+ layerId: dslLayerId
3528
+ });
3529
+ };
3530
+ if (options === void 0) options = {};
3531
+ var strict = options.strict === true;
3532
+ var reportWarning = createWarningReporter(options.onWarning);
3533
+ var reportChange = createChangeReporter(options.onChange);
3534
+ var baselineDSLResult = convertIRToDSL(baselineScene);
3535
+ var baselineDSL = baselineDSLResult.dsl;
3536
+ var editedDSL = structuredClone(editedDocument);
3537
+ var updatedScene = structuredClone(baselineScene);
3538
+ var updatedIR = getIRSceneEntryComposition(updatedScene);
3539
+ var compositionById = new Map(updatedScene.compositions.map(function(composition) {
3540
+ return [
3541
+ composition.id,
3542
+ composition
3543
+ ];
3544
+ }));
3545
+ var targetFrameRate = editedDSL.meta.fps;
3546
+ // Reframe the clone first; comparisons still use the untouched baseline DSL in seconds.
3547
+ for(var _iterator = _create_for_of_iterator_helper_loose(updatedScene.compositions), _step; !(_step = _iterator()).done;){
3548
+ var composition = _step.value;
3549
+ updateIRFrameRate(composition, targetFrameRate, reportChange, composition.id === updatedIR.id);
3550
+ }
3551
+ updateIRComposition(updatedIR, editedDSL, baselineDSL, targetFrameRate, reportChange);
3552
+ var baselineLayers = collectLayersWithPaths(baselineDSL.layers);
3553
+ var editedLayerEntries = collectLayersWithPaths(editedDSL.layers);
3554
+ var editedLayers = editedLayerEntries.map(function(entry) {
3555
+ return entry.layer;
3556
+ });
3557
+ var editedPathByLayer = new Map(editedLayerEntries.map(function(entry) {
3558
+ return [
3559
+ entry.layer,
3560
+ entry.path
3561
+ ];
3562
+ }));
3563
+ var editedLayerById = new Map();
3564
+ var editedLayerByPath = new Map();
3565
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(editedLayerEntries), _step1; !(_step1 = _iterator1()).done;){
3566
+ var _step_value = _step1.value, layer = _step_value.layer, path = _step_value.path;
3567
+ var previousEntry = editedLayerById.get(layer.id);
3568
+ if (previousEntry != null) {
3569
+ throw new Error("[dsl-ir:preserved-data] Duplicate layer id '" + layer.id + "'; earlier occurrence at path '" + previousEntry.path + "'.");
3570
+ }
3571
+ editedLayerById.set(layer.id, {
3572
+ layer: layer,
3573
+ path: path
3574
+ });
3575
+ editedLayerByPath.set(path, layer);
3576
+ }
3577
+ var clonedLayerByIRId = new Map();
3578
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(updatedIR.layers), _step2; !(_step2 = _iterator2()).done;){
3579
+ var layer1 = _step2.value;
3580
+ clonedLayerByIRId.set(layer1.id, layer1);
3581
+ }
3582
+ // Track object identity because edited IDs may have changed.
3583
+ var matchedEditedLayerSet = new Set();
3584
+ var irLayerIdByEditedLayer = new Map();
3585
+ var deletedIRLayerIdSet = new Set();
3586
+ var deletedExpandedIRLayerIdsByCompositionId = new Map();
3587
+ var semanticallyDeletedExpandedDSLIds = new Set();
3588
+ for(var _iterator3 = _create_for_of_iterator_helper_loose(baselineLayers), _step3; !(_step3 = _iterator3()).done;)_loop();
3589
+ var expandedIRLayerIdByEditedLayer = new Map();
3590
+ var editedExpandedCompositionById = new Map();
3591
+ for(var _iterator4 = _create_for_of_iterator_helper_loose(editedLayers), _step4; !(_step4 = _iterator4()).done;)_loop1();
3592
+ for(var _iterator5 = _create_for_of_iterator_helper_loose(Object.entries(layerMapping.layers)), _step5; !(_step5 = _iterator5()).done;)_loop2();
3593
+ removeIRLayers(updatedIR, deletedIRLayerIdSet, reportChange);
3594
+ for(var _iterator6 = _create_for_of_iterator_helper_loose(deletedExpandedIRLayerIdsByCompositionId), _step6; !(_step6 = _iterator6()).done;){
3595
+ var _step_value1 = _step6.value, compositionId = _step_value1[0], deletedLayerIds = _step_value1[1];
3596
+ var composition1 = compositionById.get(compositionId);
3597
+ if (composition1 != null) {
3598
+ removeIRLayers(composition1, deletedLayerIds, reportChange);
3599
+ }
3600
+ }
3601
+ updateLayerOrder(updatedIR, editedDSL.layers, irLayerIdByEditedLayer, reportChange);
3602
+ updateExpandedCompositionLayerOrder(editedDSL.layers, editedExpandedCompositionById, layerMapping, expandedIRLayerIdByEditedLayer, reportChange);
3603
+ assertIRScene(updatedScene);
3604
+ return updatedScene;
3605
+ }
3606
+ function buildExpandedBaselineLayer(editedLayer, expandedSource) {
3607
+ var baseline = expandedSource.baselineLayer;
3608
+ var transform = expandedSource.baselineTransform;
3609
+ if (baseline == null || transform == null) {
3610
+ return structuredClone(editedLayer);
3611
+ }
3612
+ return _extends({}, structuredClone(editedLayer), {
3613
+ name: baseline.name,
3614
+ type: baseline.type,
3615
+ width: baseline.width,
3616
+ height: baseline.height,
3617
+ description: structuredClone(baseline.description),
3618
+ parent: baseline.parent,
3619
+ time_range: structuredClone(baseline.timeRange),
3620
+ position: structuredClone(transform.position),
3621
+ scale: structuredClone(transform.scale),
3622
+ rotation: structuredClone(transform.rotation),
3623
+ anchor: structuredClone(transform.anchor),
3624
+ opacity: structuredClone(transform.opacity)
3625
+ }, baseline.text != null && {
3626
+ text: structuredClone(baseline.text)
3627
+ }, baseline.asset != null && {
3628
+ asset: structuredClone(baseline.asset)
3629
+ }, baseline.particle != null && {
3630
+ particle: structuredClone(baseline.particle)
3631
+ });
3632
+ }
3633
+ function updateExpandedCompositionLayerOrder(layers, compositionById, layerMapping, irLayerIdByEditedLayer, reportChange) {
3634
+ for(var _iterator = _create_for_of_iterator_helper_loose(layers), _step; !(_step = _iterator()).done;){
3635
+ var layer = _step.value;
3636
+ var _layer_children;
3637
+ var children = (_layer_children = layer.children) != null ? _layer_children : [];
3638
+ var firstExpandedSource = children.map(function(child) {
3639
+ var _layerMapping_layers_child_id;
3640
+ return (_layerMapping_layers_child_id = layerMapping.layers[child.id]) == null ? void 0 : _layerMapping_layers_child_id.expandedSource;
3641
+ }).find(function(source) {
3642
+ return source != null;
3643
+ });
3644
+ var targetComposition = firstExpandedSource != null ? compositionById.get(firstExpandedSource.irCompositionId) : undefined;
3645
+ if (targetComposition != null) {
3646
+ updateLayerOrder(targetComposition, children, irLayerIdByEditedLayer, reportChange, layer.id);
3647
+ }
3648
+ updateExpandedCompositionLayerOrder(children, compositionById, layerMapping, irLayerIdByEditedLayer, reportChange);
3649
+ }
3650
+ }
3651
+ function matchEditedLayer(baselineLayer, path, context) {
3652
+ var _context_editedLayerById_get;
3653
+ var layerById = (_context_editedLayerById_get = context.editedLayerById.get(baselineLayer.id)) == null ? void 0 : _context_editedLayerById_get.layer;
3654
+ if (layerById != null) {
3655
+ return layerById;
3656
+ }
3657
+ var layerByPath = context.editedLayerByPath.get(path);
3658
+ if (layerByPath != null && !context.matchedEditedLayerSet.has(layerByPath) && layerByPath.name === baselineLayer.name) {
3659
+ return layerByPath;
3660
+ }
3661
+ return undefined;
3662
+ }
3663
+ function collectLayersWithPaths(layers, prefix, entries) {
3664
+ if (prefix === void 0) prefix = '$.layers';
3665
+ if (entries === void 0) entries = [];
3666
+ layers.forEach(function(layer, index) {
3667
+ var _layer_children;
3668
+ var path = prefix + "[" + index + "]";
3669
+ entries.push({
3670
+ layer: layer,
3671
+ path: path
3672
+ });
3673
+ collectLayersWithPaths((_layer_children = layer.children) != null ? _layer_children : [], "" + path + ".children", entries);
3674
+ });
3675
+ return entries;
3676
+ }
3677
+ function createWarningReporter(onWarning) {
3678
+ if (onWarning == null) {
3679
+ return function() {};
3680
+ }
3681
+ return function(param) {
3682
+ var code = param.code, message = param.message, path = param.path, layerId = param.layerId;
3683
+ var warning = {
3684
+ level: 'warning',
3685
+ code: code,
3686
+ message: message
3687
+ };
3688
+ if (path != null) {
3689
+ warning.path = path;
3690
+ }
3691
+ if (layerId != null) {
3692
+ warning.layerId = layerId;
3693
+ }
3694
+ onWarning(warning);
3695
+ };
3696
+ }
3697
+ function createChangeReporter(onChange) {
3698
+ if (onChange == null) {
3699
+ return function() {};
3700
+ }
3701
+ return function(change) {
3702
+ var normalizedChange = _extends({
3703
+ kind: change.kind,
3704
+ op: change.op
3705
+ }, change.field != null && {
3706
+ field: change.field
3707
+ }, change.layerId != null && {
3708
+ layerId: change.layerId
3709
+ }, change.oldValue !== undefined && {
3710
+ oldValue: structuredClone(change.oldValue)
3711
+ }, change.newValue !== undefined && {
3712
+ newValue: structuredClone(change.newValue)
3713
+ }, change.note != null && {
3714
+ note: change.note
3715
+ });
3716
+ onChange(normalizedChange);
3717
+ };
3718
+ }
3719
+ function removeIRLayers(updatedIR, deletedIRLayerIdSet, reportChange) {
3720
+ if (deletedIRLayerIdSet.size === 0) {
3721
+ return;
3722
+ }
3723
+ updatedIR.layers = updatedIR.layers.filter(function(layer) {
3724
+ return !deletedIRLayerIdSet.has(layer.id);
3725
+ });
3726
+ for(var _iterator = _create_for_of_iterator_helper_loose(updatedIR.layers), _step; !(_step = _iterator()).done;){
3727
+ var layer = _step.value;
3728
+ if (layer.parentId != null && deletedIRLayerIdSet.has(layer.parentId)) {
3729
+ delete layer.parentId;
3730
+ reportChange({
3731
+ kind: 'layer',
3732
+ op: 'delete',
3733
+ field: 'parentId',
3734
+ layerId: layer.id
3735
+ });
3736
+ }
3737
+ if (layer.matte != null && deletedIRLayerIdSet.has(layer.matte.sourceLayerId)) {
3738
+ var previousMatte = layer.matte;
3739
+ delete layer.matte;
3740
+ reportChange({
3741
+ kind: 'layer',
3742
+ op: 'delete',
3743
+ field: 'matte',
3744
+ layerId: layer.id,
3745
+ oldValue: previousMatte
3746
+ });
3747
+ }
3748
+ }
3749
+ }
3750
+ /** Scale frame-based IR timing so a frame-rate change preserves playback duration. */ function updateIRFrameRate(updatedIR, targetFrameRate, reportChange, reportCompositionChange) {
3751
+ if (reportCompositionChange === void 0) reportCompositionChange = true;
3752
+ var previousFrameRate = updatedIR.frameRate;
3753
+ if (isScalarEqual(targetFrameRate, previousFrameRate)) {
3754
+ return;
3755
+ }
3756
+ var frameRateScale = targetFrameRate / previousFrameRate;
3757
+ updatedIR.frameRate = targetFrameRate;
3758
+ updatedIR.inPoint *= frameRateScale;
3759
+ updatedIR.outPoint *= frameRateScale;
3760
+ for(var _iterator = _create_for_of_iterator_helper_loose(updatedIR.layers), _step; !(_step = _iterator()).done;){
3761
+ var layer = _step.value;
3762
+ var _layer_transform, _layer_transform1, _layer_transform_rotation, _layer_transform2, _layer_transform_rotation1, _layer_transform3, _layer_transform_rotation2, _layer_transform4, _layer_transform5;
3763
+ layer.time.inFrame *= frameRateScale;
3764
+ layer.time.outFrame *= frameRateScale;
3765
+ if (layer.type === 'precomp' && layer.time.sourceStartFrame != null) {
3766
+ layer.time.sourceStartFrame *= frameRateScale;
3767
+ }
3768
+ reframeAnimatedProperty((_layer_transform = layer.transform) == null ? void 0 : _layer_transform.position, frameRateScale);
3769
+ reframeAnimatedProperty((_layer_transform1 = layer.transform) == null ? void 0 : _layer_transform1.scale, frameRateScale);
3770
+ reframeAnimatedProperty((_layer_transform2 = layer.transform) == null ? void 0 : (_layer_transform_rotation = _layer_transform2.rotation) == null ? void 0 : _layer_transform_rotation.x, frameRateScale);
3771
+ reframeAnimatedProperty((_layer_transform3 = layer.transform) == null ? void 0 : (_layer_transform_rotation1 = _layer_transform3.rotation) == null ? void 0 : _layer_transform_rotation1.y, frameRateScale);
3772
+ reframeAnimatedProperty((_layer_transform4 = layer.transform) == null ? void 0 : (_layer_transform_rotation2 = _layer_transform4.rotation) == null ? void 0 : _layer_transform_rotation2.z, frameRateScale);
3773
+ reframeAnimatedProperty((_layer_transform5 = layer.transform) == null ? void 0 : _layer_transform5.opacity, frameRateScale);
3774
+ if (layer.type === 'particle') {
3775
+ var _layer_content_emission_bursts;
3776
+ for(var _iterator1 = _create_for_of_iterator_helper_loose((_layer_content_emission_bursts = layer.content.emission.bursts) != null ? _layer_content_emission_bursts : []), _step1; !(_step1 = _iterator1()).done;){
3777
+ var burst = _step1.value;
3778
+ burst.frameOffset *= frameRateScale;
3779
+ burst.repeatIntervalFrames *= frameRateScale;
3780
+ }
3781
+ }
3782
+ }
3783
+ if (reportCompositionChange) {
3784
+ reportChange({
3785
+ kind: 'composition',
3786
+ op: 'set',
3787
+ field: 'fps',
3788
+ oldValue: previousFrameRate,
3789
+ newValue: targetFrameRate
3790
+ });
3791
+ }
3792
+ }
3793
+ function reframeAnimatedProperty(property, frameRateScale) {
3794
+ if ((property == null ? void 0 : property.type) !== 'keyframed') {
3795
+ return;
3796
+ }
3797
+ for(var _iterator = _create_for_of_iterator_helper_loose(property.keyframes), _step; !(_step = _iterator()).done;){
3798
+ var keyframe = _step.value;
3799
+ keyframe.frame *= frameRateScale;
3800
+ }
3801
+ }
3802
+ function updateIRComposition(updatedIR, editedDSL, baselineDSL, frameRate, reportChange) {
3803
+ var _editedDSL_meta_background_color;
3804
+ var baselineMeta = baselineDSL.meta;
3805
+ if (editedDSL.meta.name !== baselineMeta.name) {
3806
+ var previousName = updatedIR.name;
3807
+ updatedIR.name = editedDSL.meta.name;
3808
+ reportChange({
3809
+ kind: 'composition',
3810
+ op: 'set',
3811
+ field: 'name',
3812
+ oldValue: previousName,
3813
+ newValue: editedDSL.meta.name
3814
+ });
3815
+ }
3816
+ if (!isScalarEqual(editedDSL.meta.duration, baselineMeta.duration)) {
3817
+ updatedIR.outPoint = updatedIR.inPoint + editedDSL.meta.duration * frameRate;
3818
+ reportChange({
3819
+ kind: 'composition',
3820
+ op: 'set',
3821
+ field: 'duration',
3822
+ oldValue: baselineMeta.duration,
3823
+ newValue: editedDSL.meta.duration
3824
+ });
3825
+ }
3826
+ if (Number.isFinite(editedDSL.meta.width) && editedDSL.meta.width > 0 && editedDSL.meta.width !== baselineMeta.width) {
3827
+ var previousWidth = updatedIR.width;
3828
+ updatedIR.width = editedDSL.meta.width;
3829
+ reportChange({
3830
+ kind: 'composition',
3831
+ op: 'set',
3832
+ field: 'width',
3833
+ oldValue: previousWidth,
3834
+ newValue: editedDSL.meta.width
3835
+ });
3836
+ }
3837
+ if (Number.isFinite(editedDSL.meta.height) && editedDSL.meta.height > 0 && editedDSL.meta.height !== baselineMeta.height) {
3838
+ var previousHeight = updatedIR.height;
3839
+ updatedIR.height = editedDSL.meta.height;
3840
+ reportChange({
3841
+ kind: 'composition',
3842
+ op: 'set',
3843
+ field: 'height',
3844
+ oldValue: previousHeight,
3845
+ newValue: editedDSL.meta.height
3846
+ });
3847
+ }
3848
+ var baselineLoop = baselineMeta.loop;
3849
+ if (editedDSL.meta.loop !== baselineLoop) {
3850
+ updatedIR.endBehavior = editedDSL.meta.loop ? IREndBehavior.Loop : IREndBehavior.Destroy;
3851
+ reportChange({
3852
+ kind: 'composition',
3853
+ op: 'set',
3854
+ field: 'loop',
3855
+ oldValue: baselineLoop,
3856
+ newValue: editedDSL.meta.loop
3857
+ });
3858
+ }
3859
+ var baselineBackgroundColor = baselineMeta.background_color;
3860
+ var editedBackgroundColor = (_editedDSL_meta_background_color = editedDSL.meta.background_color) != null ? _editedDSL_meta_background_color : null;
3861
+ if (!isHexEqual(editedBackgroundColor, baselineBackgroundColor)) {
3862
+ updatedIR.backgroundColor = editedBackgroundColor != null ? hexToIRColor(editedBackgroundColor) : undefined;
3863
+ reportChange({
3864
+ kind: 'composition',
3865
+ op: 'set',
3866
+ field: 'background_color',
3867
+ oldValue: baselineBackgroundColor,
3868
+ newValue: editedBackgroundColor
3869
+ });
3870
+ }
3871
+ }
3872
+
3873
+ /** Convert DSL to a clone of the baseline IR carried by the adapter-owned preserved data. */ function convertDSLToIRWithPreservedData(composition, preservedData, options) {
3874
+ if (options === void 0) options = {};
3875
+ assertIRToDSLPreservedData(preservedData);
3876
+ var diagnostics = [];
3877
+ var scene = updateValidatedIRFromDSL(preservedData.baselineScene, composition, preservedData.layerMapping, _extends({}, options, {
3878
+ onWarning: function onWarning(warning) {
3879
+ var _warning_path;
3880
+ diagnostics.push(_extends({
3881
+ code: warning.code,
3882
+ severity: 'warning',
3883
+ action: 'unsupported',
3884
+ path: (_warning_path = warning.path) != null ? _warning_path : warning.layerId != null ? '$.layers' : '$'
3885
+ }, warning.layerId != null && {
3886
+ sourceId: warning.layerId
3887
+ }, {
3888
+ message: warning.message
3889
+ }));
3890
+ options.onWarning == null ? void 0 : options.onWarning.call(options, warning);
3891
+ }
3892
+ }));
3893
+ return {
3894
+ scene: scene,
3895
+ diagnostics: diagnostics
3896
+ };
3897
+ }
3898
+ function assertIRToDSLPreservedData(preservedData) {
3899
+ if (preservedData == null || (typeof preservedData === "undefined" ? "undefined" : _type_of(preservedData)) !== 'object') {
3900
+ throw new TypeError('[dsl-ir:preserved-data] Expected an IR-to-DSL preserved data object.');
3901
+ }
3902
+ if (!isRecord$1(preservedData.layerMapping)) {
3903
+ throw new TypeError('[dsl-ir:preserved-data] Invalid IR-to-DSL layer mapping.');
3904
+ }
3905
+ assertIRScene(preservedData.baselineScene);
3906
+ assertLayerMapping(preservedData.layerMapping, preservedData.baselineScene);
3907
+ }
3908
+ function assertLayerMapping(layerMapping, baselineScene) {
3909
+ var _loop = function() {
3910
+ var _step_value = _step.value, dslLayerId = _step_value[0], entry = _step_value[1];
3911
+ if (dslLayerId === '' || !isRecord$1(entry)) {
3912
+ throw new TypeError("[dsl-ir:preserved-data] Invalid mapping entry for DSL layer '" + dslLayerId + "'.");
3913
+ }
3914
+ var irCompositionId = entry['irCompositionId'];
3915
+ var irLayerId = entry['irLayerId'];
3916
+ var composition = typeof irCompositionId === 'string' ? compositionById.get(irCompositionId) : undefined;
3917
+ if (composition == null || typeof irLayerId !== 'string' || !composition.layers.some(function(layer) {
3918
+ return layer.id === irLayerId;
3919
+ })) {
3920
+ throw new TypeError("[dsl-ir:preserved-data] Invalid mapping entry for DSL layer '" + dslLayerId + "'.");
3921
+ }
3922
+ if (entry['expandedSource'] !== undefined && !isExpandedLayerSource(entry['expandedSource'], layers)) {
3923
+ throw new TypeError("[dsl-ir:preserved-data] Invalid expanded mapping for DSL layer '" + dslLayerId + "'.");
3924
+ }
3925
+ };
3926
+ var layers = layerMapping['layers'];
3927
+ if (!isRecord$1(layers)) {
3928
+ throw new TypeError('[dsl-ir:preserved-data] Layer mapping entries must be an object.');
3929
+ }
3930
+ var compositionById = new Map(baselineScene.compositions.map(function(composition) {
3931
+ return [
3932
+ composition.id,
3933
+ composition
3934
+ ];
3935
+ }));
3936
+ for(var _iterator = _create_for_of_iterator_helper_loose(Object.entries(layers)), _step; !(_step = _iterator()).done;)_loop();
3937
+ }
3938
+ function isExpandedLayerSource(value, layerEntries) {
3939
+ if (!isRecord$1(value) || typeof value['irCompositionId'] !== 'string' || typeof value['parentLayerId'] !== 'string' || !Object.hasOwn(layerEntries, value['parentLayerId']) || !isRecord$1(value['baselineTransform']) || !isRecord$1(value['baselineLayer'])) {
3940
+ return false;
3941
+ }
3942
+ var transform = value['baselineTransform'];
3943
+ var layer = value['baselineLayer'];
3944
+ return [
3945
+ 'position',
3946
+ 'scale',
3947
+ 'rotation',
3948
+ 'anchor',
3949
+ 'opacity'
3950
+ ].every(function(field) {
3951
+ return isRecord$1(transform[field]);
3952
+ }) && typeof layer['name'] === 'string' && (layer['type'] === 'null' || layer['type'] === 'layer' || layer['type'] === 'text' || layer['type'] === 'particle') && (layer['type'] !== 'particle' || isRecord$1(layer['particle'])) && typeof layer['width'] === 'number' && Number.isFinite(layer['width']) && typeof layer['height'] === 'number' && Number.isFinite(layer['height']) && isRecord$1(layer['description']) && Array.isArray(layer['timeRange']) && layer['timeRange'].length === 2;
3953
+ }
3954
+
3955
+ function assembleIRComposition(composition, layers) {
3956
+ var frameRate = composition.meta.fps;
3957
+ var durationFrames = secondsToFrames(composition.meta.duration, frameRate);
3958
+ return _extends({
3959
+ id: createId(),
3960
+ name: composition.meta.name,
3961
+ width: composition.meta.width,
3962
+ height: composition.meta.height,
3963
+ frameRate: frameRate,
3964
+ inPoint: 0,
3965
+ outPoint: durationFrames
3966
+ }, composition.meta.background_color != null && {
3967
+ backgroundColor: hexToIRColor(composition.meta.background_color)
3968
+ }, {
3969
+ endBehavior: composition.meta.loop ? IREndBehavior.Loop : IREndBehavior.Destroy,
3970
+ layers: layers
3971
+ });
3972
+ }
3973
+
3974
+ /** Convert authored 2D DSL sibling groups to flat IR layers in bottom-to-top painter order. */ function convertDSLLayersToIR(composition, imageAssets, fontAssets) {
3975
+ if (imageAssets === void 0) imageAssets = [];
3976
+ if (fontAssets === void 0) fontAssets = [];
3977
+ var flattenedLayers = flattenLayersInRenderOrder(composition.layers);
3978
+ var irLayerIdByDSLId = new Map();
3979
+ for(var _iterator = _create_for_of_iterator_helper_loose(flattenedLayers), _step; !(_step = _iterator()).done;){
3980
+ var layer = _step.value.layer;
3981
+ if (!irLayerIdByDSLId.has(layer.id)) {
3982
+ irLayerIdByDSLId.set(layer.id, convertLayerIdToIR(layer.id));
3983
+ }
3984
+ }
3985
+ return flattenedLayers.map(function(param) {
3986
+ var layer = param.layer, nestedParentId = param.nestedParentId;
3987
+ var _layer_parent, _irLayerIdByDSLId_get;
3988
+ var parentId = (_layer_parent = layer.parent) != null ? _layer_parent : nestedParentId;
3989
+ return convertLayerToIR(layer, {
3990
+ layerId: (_irLayerIdByDSLId_get = irLayerIdByDSLId.get(layer.id)) != null ? _irLayerIdByDSLId_get : convertLayerIdToIR(layer.id),
3991
+ parentLayerId: parentId != null ? irLayerIdByDSLId.get(parentId) : undefined,
3992
+ compositionDurationSeconds: composition.meta.duration,
3993
+ frameRate: composition.meta.fps
3994
+ }, imageAssets, fontAssets);
3995
+ });
3996
+ }
3997
+ function convertLayerToIR(layer, context, imageAssets, fontAssets) {
3998
+ var layerType = mapLayerType(layer.type);
3999
+ var imageAssetId = layerType === 'image' && layer.asset != null ? createId() : undefined;
4000
+ var textContent = layer.type === 'text' && layer.text != null ? convertTextData(layer.text, fontAssets) : undefined;
4001
+ var particleContent = layer.type === 'particle' ? convertDSLParticleToIRContent(requireParticleProperties(layer), context.frameRate) : undefined;
4002
+ if (imageAssetId != null && layer.asset != null) {
4003
+ imageAssets.push({
4004
+ id: imageAssetId,
4005
+ type: 'image',
4006
+ source: createIRResourceSource(resolveAssetUrl(layer.asset))
4007
+ });
4008
+ }
4009
+ var convertedLayer = _extends({
4010
+ id: context.layerId,
4011
+ name: layer.name,
4012
+ type: layerType,
4013
+ time: convertLayerTime(layer, context.compositionDurationSeconds, context.frameRate)
4014
+ }, context.parentLayerId != null && {
4015
+ parentId: context.parentLayerId
4016
+ }, {
4017
+ visible: true
4018
+ }, imageAssetId != null && {
4019
+ content: {
4020
+ assetId: imageAssetId
4021
+ }
4022
+ }, textContent != null && {
4023
+ content: textContent
4024
+ }, particleContent != null && {
4025
+ content: particleContent
4026
+ }, {
4027
+ transform: {
4028
+ position: convertDSLPositionToIR(layer.position, context.frameRate),
4029
+ rotation: convertDSLPropertyToIRRotation(layer.rotation, context.frameRate, [
4030
+ 0,
4031
+ 0,
4032
+ 0
4033
+ ]),
4034
+ scale: convertDSLPropertyToIRVec3(layer.scale, context.frameRate, [
4035
+ 1,
4036
+ 1,
4037
+ 1
4038
+ ]),
4039
+ anchor: convertDSLPropertyToStaticIRVec3(layer.anchor, [
4040
+ 0,
4041
+ 0,
4042
+ 0
4043
+ ]),
4044
+ opacity: convertDSLPropertyToIRNumber(layer.opacity, context.frameRate, 1)
4045
+ }
4046
+ });
4047
+ if (textContent != null) {
4048
+ convertedLayer.localBounds = resolveTextLocalBounds(layer, textContent);
4049
+ } else if (layer.width > 0 && layer.height > 0) {
4050
+ convertedLayer.localBounds = {
4051
+ x: 0,
4052
+ y: 0,
4053
+ width: layer.width,
4054
+ height: layer.height
4055
+ };
4056
+ }
4057
+ return convertedLayer;
4058
+ }
4059
+ function convertDSLPositionToIR(position, frameRate) {
4060
+ var result = convertDSLPropertyToIRVec3(position, frameRate, [
4061
+ 0,
4062
+ 0,
4063
+ 0
4064
+ ], true);
4065
+ // Authored DSL uses Z for stacking; its pixel coordinates stay on the 2D plane.
4066
+ if (result.type === 'static') {
4067
+ result.value[2] = 0;
4068
+ } else {
4069
+ for(var _iterator = _create_for_of_iterator_helper_loose(result.keyframes), _step; !(_step = _iterator()).done;){
4070
+ var keyframe = _step.value;
4071
+ keyframe.value[2] = 0;
4072
+ if (keyframe.endValue != null) {
4073
+ keyframe.endValue[2] = 0;
4074
+ }
4075
+ }
4076
+ }
4077
+ return result;
4078
+ }
4079
+ function requireParticleProperties(layer) {
4080
+ if (layer.particle == null) {
4081
+ throw new TypeError("[dsl-ir] Particle layer '" + layer.id + "' requires particle data.");
4082
+ }
4083
+ return layer.particle;
4084
+ }
4085
+ function resolveTextLocalBounds(layer, text) {
4086
+ var estimatedBounds = estimateTextBounds(text);
4087
+ return {
4088
+ x: 0,
4089
+ y: 0,
4090
+ width: Number.isFinite(layer.width) && layer.width > 0 ? layer.width : estimatedBounds.width,
4091
+ height: Number.isFinite(layer.height) && layer.height > 0 ? layer.height : estimatedBounds.height
4092
+ };
4093
+ }
4094
+ function convertLayerIdToIR(layerId) {
4095
+ return isIRId(layerId) ? layerId : createId();
4096
+ }
4097
+ function flattenLayersInRenderOrder(layers, nestedParentId, flattenedLayers) {
4098
+ if (nestedParentId === void 0) nestedParentId = null;
4099
+ if (flattenedLayers === void 0) flattenedLayers = [];
4100
+ var orderedLayers = [].concat(layers).sort(function(left, right) {
4101
+ return getLayerStackingOrder(left) - getLayerStackingOrder(right) || left.id.localeCompare(right.id);
4102
+ });
4103
+ for(var _iterator = _create_for_of_iterator_helper_loose(orderedLayers), _step; !(_step = _iterator()).done;){
4104
+ var layer = _step.value;
4105
+ var _layer_children;
4106
+ flattenedLayers.push({
4107
+ layer: layer,
4108
+ nestedParentId: nestedParentId
4109
+ });
4110
+ flattenLayersInRenderOrder((_layer_children = layer.children) != null ? _layer_children : [], layer.id, flattenedLayers);
4111
+ }
4112
+ return flattenedLayers;
4113
+ }
4114
+ function mapLayerType(type) {
4115
+ switch(type){
4116
+ case 'layer':
4117
+ return 'image';
4118
+ case 'text':
4119
+ return 'text';
4120
+ case 'null':
4121
+ return 'null';
4122
+ case 'particle':
4123
+ return 'particle';
4124
+ }
4125
+ }
4126
+ function convertLayerTime(layer, compositionDurationSeconds, frameRate) {
4127
+ var _layer_time_range, _layer_time_range1;
4128
+ var startSeconds = resolveFiniteNumber((_layer_time_range = layer.time_range) == null ? void 0 : _layer_time_range[0], 0);
4129
+ var endSeconds = resolveFiniteNumber((_layer_time_range1 = layer.time_range) == null ? void 0 : _layer_time_range1[1], compositionDurationSeconds);
4130
+ return {
4131
+ inFrame: secondsToFrames(startSeconds, frameRate),
4132
+ outFrame: secondsToFrames(endSeconds, frameRate)
4133
+ };
4134
+ }
4135
+ function convertTextData(text, fontAssets) {
4136
+ var _text_align;
4137
+ var fontFamily = normalizeDSLFontFamily(text.font);
4138
+ // DSL text cannot express style or weight, so new IR fonts use the canonical normal/400 defaults.
4139
+ var fontAssetId = ensureSystemFontAsset(fontAssets, fontFamily, 'normal', 400);
4140
+ var fontSize = Number.isFinite(text.size) && text.size > 0 ? text.size : 16;
4141
+ return {
4142
+ text: text.content,
4143
+ fontAssetId: fontAssetId,
4144
+ fontSize: fontSize,
4145
+ color: hexToIRColor(text.color !== '' ? text.color : '#000000'),
4146
+ letterSpacing: resolveFiniteNumber(text.letter_spacing, 0),
4147
+ lineHeight: text.line_height != null && Number.isFinite(text.line_height) && text.line_height > 0 ? text.line_height : fontSize,
4148
+ textAlign: (_text_align = text.align) != null ? _text_align : 'left'
4149
+ };
4150
+ }
4151
+
4152
+ /** Convert an editable DSL composition into a shared Animation IR scene. */ function convertDSLToIR(composition, options) {
4153
+ if (options === void 0) options = {};
4154
+ var validationResult = validateDSL(composition, {
4155
+ strict: options.strict
4156
+ });
4157
+ if (validationResult.result === 'fail') {
4158
+ throw DSLValidationError.fromValidationResult(validationResult);
4159
+ }
4160
+ var diagnostics = reportDSLValidationWarnings(validationResult.warnings, options);
4161
+ if (options.preservedData != null) {
4162
+ var preservedResult = convertDSLToIRWithPreservedData(composition, options.preservedData, options);
4163
+ assertIRScene(preservedResult.scene);
4164
+ return {
4165
+ scene: preservedResult.scene,
4166
+ diagnostics: [].concat(diagnostics, preservedResult.diagnostics)
4167
+ };
4168
+ }
4169
+ var imageAssets = [];
4170
+ var fontAssets = [];
4171
+ var convertedLayers = convertDSLLayersToIR(composition, imageAssets, fontAssets);
4172
+ var scene = createIRScene(assembleIRComposition(composition, convertedLayers), [].concat(imageAssets, fontAssets));
4173
+ assertIRScene(scene);
4174
+ return {
4175
+ scene: scene,
4176
+ diagnostics: diagnostics
4177
+ };
4178
+ }
4179
+ function reportDSLValidationWarnings(warnings, options) {
4180
+ return warnings.map(function(warning) {
4181
+ var path = toJSONPath(warning.path);
4182
+ options.onWarning == null ? void 0 : options.onWarning.call(options, _extends({
4183
+ level: 'warning',
4184
+ code: warning.code,
4185
+ message: warning.message,
4186
+ path: path
4187
+ }, warning.layerId != null && {
4188
+ layerId: warning.layerId
4189
+ }));
4190
+ return _extends({
4191
+ code: warning.code,
4192
+ severity: 'warning',
4193
+ action: 'unsupported',
4194
+ path: path
4195
+ }, warning.layerId != null && {
4196
+ sourceId: warning.layerId
4197
+ }, {
4198
+ message: warning.message
4199
+ });
4200
+ });
4201
+ }
4202
+
4203
+ function parseParticleShape(value) {
4204
+ if (!isRecord(value) || !isIntegerInRange(value['type'], 0, 9)) {
4205
+ return undefined;
4206
+ }
4207
+ var type = value['type'];
4208
+ if (type === 0) {
4209
+ return _extends({
4210
+ type: 0,
4211
+ shape: 'None'
4212
+ }, projectDirectionExpressions(value), isFiniteNumberArray(value['upDirection']) && {
4213
+ upDirection: [].concat(value['upDirection'])
4214
+ });
4215
+ }
4216
+ var base = projectShapeBase(value);
4217
+ if (base == null) {
4218
+ return undefined;
4219
+ }
4220
+ switch(type){
4221
+ case 1:
4222
+ {
4223
+ var radial = projectRadialFields(value);
4224
+ return radial == null ? undefined : _extends({
4225
+ type: 1,
4226
+ shape: 'Sphere'
4227
+ }, base, radial);
4228
+ }
4229
+ case 2:
4230
+ {
4231
+ var radial1 = projectRadialFields(value);
4232
+ var angle = readFiniteNumber(value['angle']);
4233
+ return radial1 == null || angle == null ? undefined : _extends({
4234
+ type: 2,
4235
+ shape: 'Cone'
4236
+ }, base, {
4237
+ angle: angle
4238
+ }, radial1);
4239
+ }
4240
+ case 3:
4241
+ {
4242
+ var radial2 = projectRadialFields(value);
4243
+ return radial2 == null ? undefined : _extends({
4244
+ type: 3,
4245
+ shape: 'Hemisphere'
4246
+ }, base, radial2);
4247
+ }
4248
+ case 4:
4249
+ {
4250
+ var radial3 = projectRadialFields(value);
4251
+ return radial3 == null ? undefined : _extends({
4252
+ type: 4,
4253
+ shape: 'Circle'
4254
+ }, base, radial3);
4255
+ }
4256
+ case 5:
4257
+ {
4258
+ var radial4 = projectRadialFields(value);
4259
+ var donutRadius = readFiniteNumber(value['donutRadius']);
4260
+ return radial4 == null || donutRadius == null ? undefined : _extends({
4261
+ type: 5,
4262
+ shape: 'Donut'
4263
+ }, base, radial4, {
4264
+ donutRadius: donutRadius
4265
+ });
4266
+ }
4267
+ case 6:
4268
+ {
4269
+ var rectangle = projectRectangleFields(value);
4270
+ return rectangle == null ? undefined : _extends({
4271
+ type: 6,
4272
+ shape: 'Rectangle'
4273
+ }, base, rectangle);
4274
+ }
4275
+ case 7:
4276
+ {
4277
+ var rectangle1 = projectRectangleFields(value);
4278
+ return rectangle1 == null ? undefined : _extends({
4279
+ type: 7,
4280
+ shape: 'RectangleEdge'
4281
+ }, base, rectangle1);
4282
+ }
4283
+ case 8:
4284
+ {
4285
+ var width = readFiniteNumber(value['width']);
4286
+ return width == null ? undefined : _extends({
4287
+ type: 8,
4288
+ shape: 'Edge'
4289
+ }, base, {
4290
+ width: width
4291
+ });
4292
+ }
4293
+ case 9:
4294
+ return projectTextureShape(value, base);
4295
+ }
4296
+ }
4297
+ function projectRadialFields(value) {
4298
+ var radius = readFiniteNumber(value['radius']);
4299
+ var arc = readFiniteNumber(value['arc']);
4300
+ if (radius == null || arc == null) {
4301
+ return undefined;
4302
+ }
4303
+ return {
4304
+ radius: radius,
4305
+ arc: arc
4306
+ };
4307
+ }
4308
+ function projectRectangleFields(value) {
4309
+ var width = readFiniteNumber(value['width']);
4310
+ var height = readFiniteNumber(value['height']);
4311
+ if (width == null || height == null) {
4312
+ return undefined;
4313
+ }
4314
+ return {
4315
+ width: width,
4316
+ height: height
4317
+ };
4318
+ }
4319
+ function projectTextureShape(value, base) {
4320
+ var detail = projectTextureShapeDetail(value['detail']);
4321
+ var random = readFiniteNumber(value['random']);
4322
+ var width = readFiniteNumber(value['width']);
4323
+ var height = readFiniteNumber(value['height']);
4324
+ if (detail == null || random == null || width == null || height == null) {
4325
+ return undefined;
4326
+ }
4327
+ return _extends({
4328
+ type: 9,
4329
+ shape: 'Texture'
4330
+ }, base, {
4331
+ detail: detail,
4332
+ random: random,
4333
+ width: width,
4334
+ height: height
4335
+ });
4336
+ }
4337
+ function projectTextureShapeDetail(value) {
4338
+ if (!isRecord(value)) {
4339
+ return undefined;
4340
+ }
4341
+ var width = readFiniteNumber(value['width']);
4342
+ var height = readFiniteNumber(value['height']);
4343
+ var block = value['block'];
4344
+ var anchors = value['anchors'];
4345
+ if (width == null || height == null || !isFiniteNumberTuple(block, 2) || !isFiniteNumberArray(anchors)) {
4346
+ return undefined;
4347
+ }
4348
+ return {
4349
+ width: width,
4350
+ height: height,
4351
+ block: [
4352
+ block[0],
4353
+ block[1]
4354
+ ],
4355
+ anchors: [].concat(anchors)
4356
+ };
4357
+ }
4358
+ function projectShapeBase(value) {
4359
+ var arcMode = value['arcMode'] === undefined ? 0 : value['arcMode'];
4360
+ if (!isParticleShapeArcMode(arcMode)) {
4361
+ return undefined;
4362
+ }
4363
+ return _extends({
4364
+ arcMode: arcMode
4365
+ }, typeof value['alignSpeedDirection'] === 'boolean' && {
4366
+ alignSpeedDirection: value['alignSpeedDirection']
4367
+ }, isFiniteNumberTuple(value['upDirection'], 3) && {
4368
+ upDirection: [
4369
+ value['upDirection'][0],
4370
+ value['upDirection'][1],
4371
+ value['upDirection'][2]
4372
+ ]
4373
+ }, projectDirectionExpressions(value));
4374
+ }
4375
+ function projectDirectionExpressions(value) {
4376
+ var result = {};
4377
+ for(var _i = 0, _iter = [
4378
+ 'turbulenceX',
4379
+ 'turbulenceY',
4380
+ 'turbulenceZ'
4381
+ ]; _i < _iter.length; _i++){
4382
+ var field = _iter[_i];
4383
+ var expression = value[field];
4384
+ if (isTaggedExpression(expression)) {
4385
+ result[field] = [
4386
+ expression[0],
4387
+ structuredClone(expression[1])
4388
+ ];
4389
+ }
4390
+ }
4391
+ return result;
4392
+ }
4393
+ function readFiniteNumber(value) {
4394
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
4395
+ }
4396
+ function isFiniteNumberArray(value) {
4397
+ return Array.isArray(value) && value.every(function(entry) {
4398
+ return readFiniteNumber(entry) != null;
4399
+ });
4400
+ }
4401
+ function isFiniteNumberTuple(value, length) {
4402
+ return isFiniteNumberArray(value) && value.length === length;
4403
+ }
4404
+ function isTaggedExpression(value) {
4405
+ return Array.isArray(value) && value.length === 2 && Number.isInteger(value[0]);
4406
+ }
4407
+ function isIntegerInRange(value, minimum, maximum) {
4408
+ return typeof value === 'number' && Number.isInteger(value) && value >= minimum && value <= maximum;
4409
+ }
4410
+ function isParticleShapeArcMode(value) {
4411
+ return isIntegerInRange(value, 0, 3);
4412
+ }
4413
+ function isRecord(value) {
4414
+ return value != null && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && !Array.isArray(value);
4415
+ }
4416
+
4417
+ export { DSLValidationError, convertDSLToIR, convertIRToDSL, parseParticleShape, validateDSL };
4418
+ //# sourceMappingURL=index.mjs.map