@babylonjs/addons 8.22.2 → 8.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lottie/index.d.ts +1 -0
- package/lottie/index.js +3 -0
- package/lottie/index.js.map +1 -0
- package/lottie/lottie/animationParser.d.ts +47 -0
- package/lottie/lottie/animationParser.js +368 -0
- package/lottie/lottie/animationParser.js.map +1 -0
- package/lottie/lottie/parsedTypes.d.ts +140 -0
- package/lottie/lottie/parsedTypes.js +2 -0
- package/lottie/lottie/parsedTypes.js.map +1 -0
- package/lottie/lottie/rawTypes.d.ts +152 -0
- package/lottie/lottie/rawTypes.js +4 -0
- package/lottie/lottie/rawTypes.js.map +1 -0
- package/lottie/lottiePlayer.d.ts +92 -0
- package/lottie/lottiePlayer.js +101 -0
- package/lottie/lottiePlayer.js.map +1 -0
- package/lottie/maths/bezier.d.ts +44 -0
- package/lottie/maths/bezier.js +53 -0
- package/lottie/maths/bezier.js.map +1 -0
- package/lottie/maths/boundingBox.d.ts +28 -0
- package/lottie/maths/boundingBox.js +155 -0
- package/lottie/maths/boundingBox.js.map +1 -0
- package/lottie/maths/matrix.d.ts +91 -0
- package/lottie/maths/matrix.js +174 -0
- package/lottie/maths/matrix.js.map +1 -0
- package/lottie/rendering/animationController.d.ts +72 -0
- package/lottie/rendering/animationController.js +210 -0
- package/lottie/rendering/animationController.js.map +1 -0
- package/lottie/rendering/controlNode.d.ts +32 -0
- package/lottie/rendering/controlNode.js +39 -0
- package/lottie/rendering/controlNode.js.map +1 -0
- package/lottie/rendering/node.d.ts +97 -0
- package/lottie/rendering/node.js +331 -0
- package/lottie/rendering/node.js.map +1 -0
- package/lottie/rendering/renderingManager.d.ts +45 -0
- package/lottie/rendering/renderingManager.js +61 -0
- package/lottie/rendering/renderingManager.js.map +1 -0
- package/lottie/sprites/spriteNode.d.ts +32 -0
- package/lottie/sprites/spriteNode.js +52 -0
- package/lottie/sprites/spriteNode.js.map +1 -0
- package/lottie/sprites/spritePacker.d.ts +101 -0
- package/lottie/sprites/spritePacker.js +237 -0
- package/lottie/sprites/spritePacker.js.map +1 -0
- package/lottie/worker.d.ts +1 -0
- package/lottie/worker.js +39 -0
- package/lottie/worker.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LottiePlayer, AnimationConfiguration } from "./lottiePlayer.js";
|
package/lottie/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../dev/addons/src/lottie/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAA0B,MAAM,gBAAgB,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-restricted-imports */\r\nexport { LottiePlayer, AnimationConfiguration } from \"./lottiePlayer\";\r\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AnimationInfo } from "./parsedTypes.js";
|
|
2
|
+
import type { SpritePacker } from "../sprites/spritePacker.js";
|
|
3
|
+
import type { RenderingManager } from "../rendering/renderingManager.js";
|
|
4
|
+
import type { AnimationConfiguration } from "../lottiePlayer.js";
|
|
5
|
+
/**
|
|
6
|
+
* Parses a lottie animation file and converts it into a format that can be rendered by Babylon.js
|
|
7
|
+
* Important: not all lottie features are supported, you can call .debug() after parsing an animation to see what features were not supported.
|
|
8
|
+
*/
|
|
9
|
+
export declare class AnimationParser {
|
|
10
|
+
private _packer;
|
|
11
|
+
private readonly _renderingManager;
|
|
12
|
+
private readonly _configuration;
|
|
13
|
+
private readonly _animationInfo;
|
|
14
|
+
private _unsupportedFeatures;
|
|
15
|
+
private _parentNodes;
|
|
16
|
+
private _rootNodes;
|
|
17
|
+
private _shape;
|
|
18
|
+
/**
|
|
19
|
+
* Get the animation information parsed from the Lottie file.
|
|
20
|
+
*/
|
|
21
|
+
get animationInfo(): AnimationInfo;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new instance of the Lottie animations parser.
|
|
24
|
+
* @param packer Object that packs the sprites from the animation into a texture atlas.
|
|
25
|
+
* @param fileContentAsJsonString The content of the lottie file as a JSON string.
|
|
26
|
+
* @param configuration Configuration options for the animation parser.
|
|
27
|
+
* @param renderingManager Object that manages the rendering of the sprites in the animation.
|
|
28
|
+
*/
|
|
29
|
+
constructor(packer: SpritePacker, fileContentAsJsonString: string, configuration: AnimationConfiguration, renderingManager: RenderingManager);
|
|
30
|
+
/**
|
|
31
|
+
* Logs to the console all issues that were encountered during parsing the file.
|
|
32
|
+
*/
|
|
33
|
+
debug(): void;
|
|
34
|
+
private _loadFromData;
|
|
35
|
+
private _parseLayer;
|
|
36
|
+
private _parseShapes;
|
|
37
|
+
private _parseGroupShape;
|
|
38
|
+
private _parseTransform;
|
|
39
|
+
private _fromLottieScalarToBabylonScalar;
|
|
40
|
+
private _fromLottieVector2ToBabylonVector2;
|
|
41
|
+
private _calculateFinalVector;
|
|
42
|
+
private _getScaleFactor;
|
|
43
|
+
private _validatePathShape;
|
|
44
|
+
private _validateRectangleShape;
|
|
45
|
+
private _validateFillShape;
|
|
46
|
+
private _validateGradientFillShape;
|
|
47
|
+
}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { ThinSprite } from "@babylonjs/core/Sprites/thinSprite.js";
|
|
2
|
+
import { SpriteNode } from "../sprites/spriteNode.js";
|
|
3
|
+
import { BezierCurve } from "../maths/bezier.js";
|
|
4
|
+
import { Node } from "../rendering/node.js";
|
|
5
|
+
import { ControlNode } from "../rendering/controlNode.js";
|
|
6
|
+
/**
|
|
7
|
+
* Default scale value for the scale property of a Lottie transform.
|
|
8
|
+
*/
|
|
9
|
+
const DefaultScale = { x: 1, y: 1 };
|
|
10
|
+
/**
|
|
11
|
+
* Default position value for the position property of a Lottie transform.
|
|
12
|
+
*/
|
|
13
|
+
const DefaultPosition = { x: 0, y: 0 };
|
|
14
|
+
/**
|
|
15
|
+
* Parses a lottie animation file and converts it into a format that can be rendered by Babylon.js
|
|
16
|
+
* Important: not all lottie features are supported, you can call .debug() after parsing an animation to see what features were not supported.
|
|
17
|
+
*/
|
|
18
|
+
export class AnimationParser {
|
|
19
|
+
/**
|
|
20
|
+
* Get the animation information parsed from the Lottie file.
|
|
21
|
+
*/
|
|
22
|
+
get animationInfo() {
|
|
23
|
+
return this._animationInfo;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new instance of the Lottie animations parser.
|
|
27
|
+
* @param packer Object that packs the sprites from the animation into a texture atlas.
|
|
28
|
+
* @param fileContentAsJsonString The content of the lottie file as a JSON string.
|
|
29
|
+
* @param configuration Configuration options for the animation parser.
|
|
30
|
+
* @param renderingManager Object that manages the rendering of the sprites in the animation.
|
|
31
|
+
*/
|
|
32
|
+
constructor(packer, fileContentAsJsonString, configuration, renderingManager) {
|
|
33
|
+
// Loop variables to save allocations
|
|
34
|
+
this._shape = undefined;
|
|
35
|
+
this._packer = packer;
|
|
36
|
+
this._renderingManager = renderingManager;
|
|
37
|
+
this._configuration = configuration;
|
|
38
|
+
this._unsupportedFeatures = [];
|
|
39
|
+
this._parentNodes = new Map();
|
|
40
|
+
this._rootNodes = [];
|
|
41
|
+
this._animationInfo = this._loadFromData(fileContentAsJsonString);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Logs to the console all issues that were encountered during parsing the file.
|
|
45
|
+
*/
|
|
46
|
+
debug() {
|
|
47
|
+
for (let i = 0; i < this._unsupportedFeatures.length; i++) {
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.log(this._unsupportedFeatures[i]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
_loadFromData(fileContentAsJsonString) {
|
|
53
|
+
this._unsupportedFeatures.length = 0; // Clear previous errors
|
|
54
|
+
const rawData = JSON.parse(fileContentAsJsonString);
|
|
55
|
+
for (let i = 0; i < rawData.layers.length; i++) {
|
|
56
|
+
this._parseLayer(rawData.layers[i]);
|
|
57
|
+
}
|
|
58
|
+
// Update the atlas texture after creating all sprites from the animation
|
|
59
|
+
this._packer.updateAtlasTexture();
|
|
60
|
+
// Reorder the sprites from back to front
|
|
61
|
+
this._renderingManager.ready();
|
|
62
|
+
// Release the canvas to avoid memory leaks
|
|
63
|
+
this._packer.releaseCanvas();
|
|
64
|
+
this._packer = undefined; // Clear the reference to the sprite packer to allow garbage collection
|
|
65
|
+
return {
|
|
66
|
+
startFrame: rawData.ip,
|
|
67
|
+
endFrame: rawData.op,
|
|
68
|
+
frameRate: rawData.fr,
|
|
69
|
+
widthPx: rawData.w,
|
|
70
|
+
heightPx: rawData.h,
|
|
71
|
+
nodes: this._rootNodes,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
_parseLayer(layer) {
|
|
75
|
+
if (layer.hd === true) {
|
|
76
|
+
return; // Ignore hidden layers
|
|
77
|
+
}
|
|
78
|
+
if (layer.ty !== 3 && layer.ty !== 4) {
|
|
79
|
+
this._unsupportedFeatures.push(`UnsupportedLayerType - Index: ${layer.ind} Name: ${layer.nm} Type: ${layer.ty}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (layer.ind === undefined || layer.ip === undefined || layer.op === undefined || layer.st === undefined) {
|
|
83
|
+
this._unsupportedFeatures.push(`Layer without required values - Name: ${layer.nm}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
let parentNode = undefined;
|
|
87
|
+
if (layer.parent) {
|
|
88
|
+
parentNode = this._parentNodes.get(layer.parent);
|
|
89
|
+
if (parentNode === undefined) {
|
|
90
|
+
this._unsupportedFeatures.push(`Parent node with index ${layer.parent} not found for layer ${layer.nm}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const transform = this._parseTransform(layer.ks);
|
|
94
|
+
const controlNode = new ControlNode(parentNode ? `${parentNode.id} - ${layer.nm} - ControlNode (TRS)` : `${layer.nm} - ControlNode (TRS)`, this._configuration.ignoreOpacityAnimations, layer.ip, layer.op, transform.position, transform.rotation, transform.scale, transform.opacity, parentNode);
|
|
95
|
+
// Nodes without a parent are top-level nodes in the scenegraph
|
|
96
|
+
if (!parentNode) {
|
|
97
|
+
this._rootNodes.push(controlNode);
|
|
98
|
+
}
|
|
99
|
+
const anchorNode = new Node(parentNode ? `${parentNode.id} - ${layer.nm} - Node (Anchor)` : `${layer.nm} - Node (Anchor)`, this._configuration.ignoreOpacityAnimations, transform.anchorPoint, undefined, // Rotation is not used for anchor point
|
|
100
|
+
undefined, // Scale is not used for anchor point
|
|
101
|
+
undefined, // Opacity is not used for anchor point
|
|
102
|
+
controlNode);
|
|
103
|
+
// Anchor nodes are always the parent of the control node of a child layer, build a map to build the scenegraph
|
|
104
|
+
this._parentNodes.set(layer.ind, anchorNode);
|
|
105
|
+
// Create the sprites for the layer if it has shapes
|
|
106
|
+
if (layer.shapes && layer.shapes.length > 0) {
|
|
107
|
+
const scalingFactor = this._getScaleFactor(anchorNode);
|
|
108
|
+
this._parseShapes(anchorNode, layer.shapes, scalingFactor);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
_parseShapes(parent, shapes, scalingFactor) {
|
|
112
|
+
for (let i = 0; i < shapes.length; i++) {
|
|
113
|
+
if (shapes[i].hd === true) {
|
|
114
|
+
continue; // Ignore hidden shapes
|
|
115
|
+
}
|
|
116
|
+
if (shapes[i].ty === "gr") {
|
|
117
|
+
this._parseGroupShape(parent, shapes[i], scalingFactor);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this._unsupportedFeatures.push(`Only group shapes are supported as children of layers - Name: ${shapes[i].nm} Type: ${shapes[i].ty}`);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
_parseGroupShape(parent, rawGroup, scalingFactor) {
|
|
126
|
+
if (!rawGroup.it || rawGroup.it.length === 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
let transform = undefined;
|
|
130
|
+
for (let i = 0; i < rawGroup.it.length; i++) {
|
|
131
|
+
this._shape = rawGroup.it[i];
|
|
132
|
+
if (this._shape.ty === "gr") {
|
|
133
|
+
this._unsupportedFeatures.push(`Nested group shapes are not supported. - Group ${rawGroup.nm} - Nested Group ${this._shape.nm}`);
|
|
134
|
+
}
|
|
135
|
+
else if (this._shape.ty === "tr") {
|
|
136
|
+
transform = this._parseTransform(this._shape);
|
|
137
|
+
}
|
|
138
|
+
else if (this._shape.ty === "sh") {
|
|
139
|
+
this._validatePathShape(this._shape);
|
|
140
|
+
}
|
|
141
|
+
else if (this._shape.ty === "rc") {
|
|
142
|
+
this._validateRectangleShape(this._shape);
|
|
143
|
+
}
|
|
144
|
+
else if (this._shape.ty === "fl") {
|
|
145
|
+
this._validateFillShape(this._shape);
|
|
146
|
+
}
|
|
147
|
+
else if (this._shape.ty === "gf") {
|
|
148
|
+
this._validateGradientFillShape(this._shape);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
this._unsupportedFeatures.push(`Unsupported shape type - Name: ${this._shape.nm} Type: ${this._shape.ty}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (transform === undefined) {
|
|
155
|
+
this._unsupportedFeatures.push(`Group ${rawGroup.nm} does not have a transform which is not supported`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const trsNode = new Node(`${parent.id} - ${rawGroup.nm} - ControlNode (TRS)`, this._configuration.ignoreOpacityAnimations, transform.position, transform.rotation, transform.scale, transform.opacity, parent);
|
|
159
|
+
const spriteInfo = this._packer.addLottieShape(rawGroup, scalingFactor);
|
|
160
|
+
const sprite = new ThinSprite();
|
|
161
|
+
// Set sprite UV coordinates
|
|
162
|
+
sprite._xOffset = spriteInfo.uOffset;
|
|
163
|
+
sprite._yOffset = spriteInfo.vOffset;
|
|
164
|
+
sprite._xSize = spriteInfo.cellWidth;
|
|
165
|
+
sprite._ySize = spriteInfo.cellHeight;
|
|
166
|
+
// Set sprite dimensions for rendering
|
|
167
|
+
sprite.width = spriteInfo.widthPx;
|
|
168
|
+
sprite.height = spriteInfo.heightPx;
|
|
169
|
+
sprite.invertV = true;
|
|
170
|
+
this._renderingManager.addSprite(sprite);
|
|
171
|
+
transform.anchorPoint.startValue.x += spriteInfo.centerX || 0;
|
|
172
|
+
transform.anchorPoint.startValue.y -= spriteInfo.centerY || 0;
|
|
173
|
+
new SpriteNode(`${parent.id} - ${rawGroup.nm} - SpriteNode (Anchor)`, this._configuration.ignoreOpacityAnimations, sprite, transform.anchorPoint, undefined, // Rotation is not used for anchor point
|
|
174
|
+
undefined, // Scale is not used for anchor point
|
|
175
|
+
undefined, // Opacity is not used for anchor point
|
|
176
|
+
trsNode);
|
|
177
|
+
}
|
|
178
|
+
_parseTransform(transform) {
|
|
179
|
+
return {
|
|
180
|
+
opacity: this._fromLottieScalarToBabylonScalar(transform.o, "Opacity", 1),
|
|
181
|
+
rotation: this._fromLottieScalarToBabylonScalar(transform.r, "Rotation", 0),
|
|
182
|
+
scale: this._fromLottieVector2ToBabylonVector2(transform.s, "Scale", DefaultScale),
|
|
183
|
+
position: this._fromLottieVector2ToBabylonVector2(transform.p, "Position", DefaultPosition),
|
|
184
|
+
anchorPoint: this._fromLottieVector2ToBabylonVector2(transform.a, "AnchorPoint", DefaultPosition),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
_fromLottieScalarToBabylonScalar(property, scalarType, defaultValue) {
|
|
188
|
+
if (!property) {
|
|
189
|
+
return {
|
|
190
|
+
startValue: defaultValue,
|
|
191
|
+
currentValue: defaultValue,
|
|
192
|
+
currentKeyframeIndex: 0,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (property.a === 0) {
|
|
196
|
+
return {
|
|
197
|
+
startValue: property.k,
|
|
198
|
+
currentValue: property.k,
|
|
199
|
+
currentKeyframeIndex: 0,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const keyframes = [];
|
|
203
|
+
const rawKeyFrames = property.k;
|
|
204
|
+
let i = 0;
|
|
205
|
+
for (i = 0; i < rawKeyFrames.length; i++) {
|
|
206
|
+
let easeFunction = undefined;
|
|
207
|
+
if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {
|
|
208
|
+
if (Array.isArray(rawKeyFrames[i].o.x)) {
|
|
209
|
+
// Value is an array
|
|
210
|
+
easeFunction = new BezierCurve(rawKeyFrames[i].o.x[0], rawKeyFrames[i].o.y[0], rawKeyFrames[i].i.x[0], rawKeyFrames[i].i.y[0], this._configuration.easingSteps);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Value is a number
|
|
214
|
+
easeFunction = new BezierCurve(rawKeyFrames[i].o.x, rawKeyFrames[i].o.y, rawKeyFrames[i].i.x, rawKeyFrames[i].i.y, this._configuration.easingSteps);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
let value = rawKeyFrames[i].s[0];
|
|
218
|
+
if (scalarType === "Rotation") {
|
|
219
|
+
value = (value * Math.PI) / 180; // Lottie uses degrees for rotation, convert to radians
|
|
220
|
+
}
|
|
221
|
+
keyframes.push({
|
|
222
|
+
value: value,
|
|
223
|
+
time: rawKeyFrames[i].t,
|
|
224
|
+
easeFunction: easeFunction, // We assume that the ease function is always defined if we have keyframes
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
let startValue = rawKeyFrames[0].s[0];
|
|
228
|
+
if (scalarType === "Rotation") {
|
|
229
|
+
startValue = (startValue * Math.PI) / 180; // Lottie uses degrees for rotation, convert to radians
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
startValue: startValue,
|
|
233
|
+
currentValue: startValue,
|
|
234
|
+
keyframes: keyframes,
|
|
235
|
+
currentKeyframeIndex: 0,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
_fromLottieVector2ToBabylonVector2(property, vectorType, defaultValue) {
|
|
239
|
+
if (!property) {
|
|
240
|
+
return {
|
|
241
|
+
startValue: defaultValue,
|
|
242
|
+
currentValue: defaultValue,
|
|
243
|
+
currentKeyframeIndex: 0,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
if (property.l !== undefined && property.l !== 2) {
|
|
247
|
+
this._unsupportedFeatures.push(`Invalid Vector2 Length - Length: ${property.l}`);
|
|
248
|
+
return {
|
|
249
|
+
startValue: defaultValue,
|
|
250
|
+
currentValue: defaultValue,
|
|
251
|
+
currentKeyframeIndex: 0,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (property.a === 0) {
|
|
255
|
+
const values = property.k;
|
|
256
|
+
const value = this._calculateFinalVector(values[0], values[1], vectorType);
|
|
257
|
+
return {
|
|
258
|
+
startValue: value,
|
|
259
|
+
currentValue: value,
|
|
260
|
+
currentKeyframeIndex: 0,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
const keyframes = [];
|
|
264
|
+
const rawKeyFrames = property.k;
|
|
265
|
+
let i = 0;
|
|
266
|
+
for (i = 0; i < rawKeyFrames.length; i++) {
|
|
267
|
+
let easeFunction1 = undefined;
|
|
268
|
+
if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {
|
|
269
|
+
if (Array.isArray(rawKeyFrames[i].o.x)) {
|
|
270
|
+
// Value is an array
|
|
271
|
+
easeFunction1 = new BezierCurve(rawKeyFrames[i].o.x[0], rawKeyFrames[i].o.y[0], rawKeyFrames[i].i.x[0], rawKeyFrames[i].i.y[0], this._configuration.easingSteps);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Value is a number
|
|
275
|
+
easeFunction1 = new BezierCurve(rawKeyFrames[i].o.x, rawKeyFrames[i].o.y, rawKeyFrames[i].i.x, rawKeyFrames[i].i.y, this._configuration.easingSteps);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
let easeFunction2 = undefined;
|
|
279
|
+
if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {
|
|
280
|
+
if (Array.isArray(rawKeyFrames[i].o.x)) {
|
|
281
|
+
// Value is an array
|
|
282
|
+
easeFunction2 = new BezierCurve(rawKeyFrames[i].o.x[1], rawKeyFrames[i].o.y[1], rawKeyFrames[i].i.x[1], rawKeyFrames[i].i.y[1], this._configuration.easingSteps);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
// Value is a number
|
|
286
|
+
easeFunction2 = new BezierCurve(rawKeyFrames[i].o.x, rawKeyFrames[i].o.y, rawKeyFrames[i].i.x, rawKeyFrames[i].i.y, this._configuration.easingSteps);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
keyframes.push({
|
|
290
|
+
value: this._calculateFinalVector(rawKeyFrames[i].s[0], rawKeyFrames[i].s[1], vectorType),
|
|
291
|
+
time: rawKeyFrames[i].t,
|
|
292
|
+
easeFunction1: easeFunction1, // We assume that the ease function is always defined if we have keyframes
|
|
293
|
+
easeFunction2: easeFunction2, // We assume that the ease function is always defined if we have keyframes
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
const startValue = this._calculateFinalVector(rawKeyFrames[0].s[0], rawKeyFrames[0].s[1], vectorType);
|
|
297
|
+
return {
|
|
298
|
+
startValue: startValue,
|
|
299
|
+
currentValue: { x: startValue.x, y: startValue.y }, // All vectors are passed by reference, so we need to create a copy to avoid modifying the start value
|
|
300
|
+
keyframes: keyframes,
|
|
301
|
+
currentKeyframeIndex: 0,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
_calculateFinalVector(x, y, vectorType) {
|
|
305
|
+
const result = { x, y };
|
|
306
|
+
if (vectorType === "Position") {
|
|
307
|
+
// Lottie uses a different coordinate system for position, so we need to invert the Y value
|
|
308
|
+
result.y = -result.y;
|
|
309
|
+
}
|
|
310
|
+
else if (vectorType === "AnchorPoint") {
|
|
311
|
+
// Lottie uses a different coordinate system for anchor point, so we need to invert the X value
|
|
312
|
+
result.x = -result.x;
|
|
313
|
+
}
|
|
314
|
+
else if (vectorType === "Scale") {
|
|
315
|
+
// Lottie uses a different coordinate system for scale, so we need to divide by 100
|
|
316
|
+
result.x = result.x / 100;
|
|
317
|
+
result.y = result.y / 100;
|
|
318
|
+
}
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
_getScaleFactor(node) {
|
|
322
|
+
const scale = { x: node.startScale.x, y: node.startScale.y };
|
|
323
|
+
while (node.parent) {
|
|
324
|
+
node = node.parent;
|
|
325
|
+
scale.x *= node.startScale.x;
|
|
326
|
+
scale.y *= node.startScale.y;
|
|
327
|
+
}
|
|
328
|
+
scale.x = scale.x * this._configuration.scaleMultiplier;
|
|
329
|
+
scale.y = scale.y * this._configuration.scaleMultiplier;
|
|
330
|
+
return scale;
|
|
331
|
+
}
|
|
332
|
+
_validatePathShape(shape) {
|
|
333
|
+
if (shape.ks.a === 1) {
|
|
334
|
+
this._unsupportedFeatures.push(`Path ${shape.nm} has animated properties which are not supported`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
_validateRectangleShape(shape) {
|
|
338
|
+
if (shape.p.a === 1) {
|
|
339
|
+
this._unsupportedFeatures.push(`Rectangle ${shape.nm} has an position property that is animated which is not supported`);
|
|
340
|
+
}
|
|
341
|
+
if (shape.s.a === 1) {
|
|
342
|
+
this._unsupportedFeatures.push(`Rectangle ${shape.nm} has a size property that is animated which is not supported`);
|
|
343
|
+
}
|
|
344
|
+
if (shape.r.a === 1) {
|
|
345
|
+
this._unsupportedFeatures.push(`Rectangle ${shape.nm} has a rounded corners property that is animated which is not supported`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
_validateFillShape(shape) {
|
|
349
|
+
if (shape.o.a === 1) {
|
|
350
|
+
this._unsupportedFeatures.push(`Fill ${shape.nm} has an opacity property that is animated which is not supported`);
|
|
351
|
+
}
|
|
352
|
+
if (shape.c.a === 1) {
|
|
353
|
+
this._unsupportedFeatures.push(`Fill ${shape.nm} has a color property that is animated which is not supported`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
_validateGradientFillShape(shape) {
|
|
357
|
+
if (shape.o.a === 1) {
|
|
358
|
+
this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has an opacity property that is animated which is not supported`);
|
|
359
|
+
}
|
|
360
|
+
if (shape.s.a === 1) {
|
|
361
|
+
this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has a start point property that is animated which is not supported`);
|
|
362
|
+
}
|
|
363
|
+
if (shape.e.a === 1) {
|
|
364
|
+
this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has an end point property that is animated which is not supported`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=animationParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animationParser.js","sourceRoot":"","sources":["../../../../../dev/addons/src/lottie/lottie/animationParser.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IVector2Like } from \"core/Maths/math.like\";\r\nimport { ThinSprite } from \"core/Sprites/thinSprite\";\r\n\r\nimport type {\r\n RawFillShape,\r\n RawGradientFillShape,\r\n RawGraphicElement,\r\n RawGroupShape,\r\n RawLottieAnimation,\r\n RawLottieLayer,\r\n RawPathShape,\r\n RawRectangleShape,\r\n RawScalarProperty,\r\n RawTransform,\r\n RawTransformShape,\r\n RawVectorKeyframe,\r\n RawVectorProperty,\r\n} from \"./rawTypes\";\r\nimport type { AnimationInfo, ScalarKeyframe, ScalarProperty, Transform, Vector2Keyframe, Vector2Property } from \"./parsedTypes\";\r\n\r\nimport type { SpritePacker } from \"../sprites/spritePacker\";\r\nimport { SpriteNode } from \"../sprites/spriteNode\";\r\n\r\nimport { BezierCurve } from \"../maths/bezier\";\r\n\r\nimport type { RenderingManager } from \"../rendering/renderingManager\";\r\nimport { Node } from \"../rendering/node\";\r\nimport { ControlNode } from \"../rendering/controlNode\";\r\n\r\nimport type { AnimationConfiguration } from \"../lottiePlayer\";\r\n\r\n/**\r\n * Type of the vector properties in the Lottie animation. It determines how the vector values are interpreted in Babylon.js.\r\n */\r\ntype VectorType = \"Scale\" | \"Position\" | \"AnchorPoint\";\r\n/**\r\n * Type of the scalar properties in the Lottie animation. It determines how the scalar values are interpreted in Babylon.js.\r\n */\r\ntype ScalarType = \"Rotation\" | \"Opacity\";\r\n\r\n/**\r\n * Default scale value for the scale property of a Lottie transform.\r\n */\r\nconst DefaultScale: IVector2Like = { x: 1, y: 1 };\r\n\r\n/**\r\n * Default position value for the position property of a Lottie transform.\r\n */\r\nconst DefaultPosition: IVector2Like = { x: 0, y: 0 };\r\n\r\n/**\r\n * Parses a lottie animation file and converts it into a format that can be rendered by Babylon.js\r\n * Important: not all lottie features are supported, you can call .debug() after parsing an animation to see what features were not supported.\r\n */\r\nexport class AnimationParser {\r\n private _packer: SpritePacker;\r\n private readonly _renderingManager: RenderingManager;\r\n private readonly _configuration: AnimationConfiguration;\r\n private readonly _animationInfo: AnimationInfo;\r\n\r\n private _unsupportedFeatures: string[];\r\n\r\n private _parentNodes: Map<number, Node>; // Map of nodes to build the scenegraph from the animation layers\r\n private _rootNodes: Node[]; // Array of root-level nodes in the animation, in top-down z order\r\n\r\n // Loop variables to save allocations\r\n private _shape: RawGraphicElement | undefined = undefined;\r\n\r\n /**\r\n * Get the animation information parsed from the Lottie file.\r\n */\r\n public get animationInfo(): AnimationInfo {\r\n return this._animationInfo;\r\n }\r\n\r\n /**\r\n * Creates a new instance of the Lottie animations parser.\r\n * @param packer Object that packs the sprites from the animation into a texture atlas.\r\n * @param fileContentAsJsonString The content of the lottie file as a JSON string.\r\n * @param configuration Configuration options for the animation parser.\r\n * @param renderingManager Object that manages the rendering of the sprites in the animation.\r\n */\r\n public constructor(packer: SpritePacker, fileContentAsJsonString: string, configuration: AnimationConfiguration, renderingManager: RenderingManager) {\r\n this._packer = packer;\r\n this._renderingManager = renderingManager;\r\n this._configuration = configuration;\r\n\r\n this._unsupportedFeatures = [];\r\n\r\n this._parentNodes = new Map<number, Node>();\r\n this._rootNodes = [];\r\n\r\n this._animationInfo = this._loadFromData(fileContentAsJsonString);\r\n }\r\n\r\n /**\r\n * Logs to the console all issues that were encountered during parsing the file.\r\n */\r\n public debug() {\r\n for (let i = 0; i < this._unsupportedFeatures.length; i++) {\r\n // eslint-disable-next-line no-console\r\n console.log(this._unsupportedFeatures[i]);\r\n }\r\n }\r\n\r\n private _loadFromData(fileContentAsJsonString: string): AnimationInfo {\r\n this._unsupportedFeatures.length = 0; // Clear previous errors\r\n const rawData = JSON.parse(fileContentAsJsonString) as RawLottieAnimation;\r\n\r\n for (let i = 0; i < rawData.layers.length; i++) {\r\n this._parseLayer(rawData.layers[i]);\r\n }\r\n\r\n // Update the atlas texture after creating all sprites from the animation\r\n this._packer.updateAtlasTexture();\r\n\r\n // Reorder the sprites from back to front\r\n this._renderingManager.ready();\r\n\r\n // Release the canvas to avoid memory leaks\r\n this._packer.releaseCanvas();\r\n this._packer = undefined as any; // Clear the reference to the sprite packer to allow garbage collection\r\n\r\n return {\r\n startFrame: rawData.ip,\r\n endFrame: rawData.op,\r\n frameRate: rawData.fr,\r\n widthPx: rawData.w,\r\n heightPx: rawData.h,\r\n nodes: this._rootNodes,\r\n };\r\n }\r\n\r\n private _parseLayer(layer: RawLottieLayer): void {\r\n if (layer.hd === true) {\r\n return; // Ignore hidden layers\r\n }\r\n\r\n if (layer.ty !== 3 && layer.ty !== 4) {\r\n this._unsupportedFeatures.push(`UnsupportedLayerType - Index: ${layer.ind} Name: ${layer.nm} Type: ${layer.ty}`);\r\n return;\r\n }\r\n\r\n if (layer.ind === undefined || layer.ip === undefined || layer.op === undefined || layer.st === undefined) {\r\n this._unsupportedFeatures.push(`Layer without required values - Name: ${layer.nm}`);\r\n return;\r\n }\r\n\r\n let parentNode: Node | undefined = undefined;\r\n if (layer.parent) {\r\n parentNode = this._parentNodes.get(layer.parent);\r\n if (parentNode === undefined) {\r\n this._unsupportedFeatures.push(`Parent node with index ${layer.parent} not found for layer ${layer.nm}`);\r\n }\r\n }\r\n\r\n const transform = this._parseTransform(layer.ks);\r\n\r\n const controlNode = new ControlNode(\r\n parentNode ? `${parentNode.id} - ${layer.nm} - ControlNode (TRS)` : `${layer.nm} - ControlNode (TRS)`,\r\n this._configuration.ignoreOpacityAnimations,\r\n layer.ip,\r\n layer.op,\r\n transform.position,\r\n transform.rotation,\r\n transform.scale,\r\n transform.opacity,\r\n parentNode\r\n );\r\n\r\n // Nodes without a parent are top-level nodes in the scenegraph\r\n if (!parentNode) {\r\n this._rootNodes.push(controlNode);\r\n }\r\n\r\n const anchorNode = new Node(\r\n parentNode ? `${parentNode.id} - ${layer.nm} - Node (Anchor)` : `${layer.nm} - Node (Anchor)`,\r\n this._configuration.ignoreOpacityAnimations,\r\n transform.anchorPoint,\r\n undefined, // Rotation is not used for anchor point\r\n undefined, // Scale is not used for anchor point\r\n undefined, // Opacity is not used for anchor point\r\n controlNode\r\n );\r\n\r\n // Anchor nodes are always the parent of the control node of a child layer, build a map to build the scenegraph\r\n this._parentNodes.set(layer.ind, anchorNode);\r\n\r\n // Create the sprites for the layer if it has shapes\r\n if (layer.shapes && layer.shapes.length > 0) {\r\n const scalingFactor = this._getScaleFactor(anchorNode);\r\n this._parseShapes(anchorNode, layer.shapes, scalingFactor);\r\n }\r\n }\r\n\r\n private _parseShapes(parent: Node, shapes: RawGraphicElement[], scalingFactor: IVector2Like): void {\r\n for (let i = 0; i < shapes.length; i++) {\r\n if (shapes[i].hd === true) {\r\n continue; // Ignore hidden shapes\r\n }\r\n\r\n if (shapes[i].ty === \"gr\") {\r\n this._parseGroupShape(parent, shapes[i] as RawGroupShape, scalingFactor);\r\n } else {\r\n this._unsupportedFeatures.push(`Only group shapes are supported as children of layers - Name: ${shapes[i].nm} Type: ${shapes[i].ty}`);\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n private _parseGroupShape(parent: Node, rawGroup: RawGroupShape, scalingFactor: IVector2Like): void {\r\n if (!rawGroup.it || rawGroup.it.length === 0) {\r\n return;\r\n }\r\n\r\n let transform: Transform | undefined = undefined;\r\n for (let i = 0; i < rawGroup.it.length; i++) {\r\n this._shape = rawGroup.it[i];\r\n if (this._shape.ty === \"gr\") {\r\n this._unsupportedFeatures.push(`Nested group shapes are not supported. - Group ${rawGroup.nm} - Nested Group ${this._shape.nm}`);\r\n } else if (this._shape.ty === \"tr\") {\r\n transform = this._parseTransform(this._shape as RawTransformShape);\r\n } else if (this._shape.ty === \"sh\") {\r\n this._validatePathShape(this._shape as RawPathShape);\r\n } else if (this._shape.ty === \"rc\") {\r\n this._validateRectangleShape(this._shape as RawRectangleShape);\r\n } else if (this._shape.ty === \"fl\") {\r\n this._validateFillShape(this._shape as RawFillShape);\r\n } else if (this._shape.ty === \"gf\") {\r\n this._validateGradientFillShape(this._shape as RawGradientFillShape);\r\n } else {\r\n this._unsupportedFeatures.push(`Unsupported shape type - Name: ${this._shape.nm} Type: ${this._shape.ty}`);\r\n }\r\n }\r\n\r\n if (transform === undefined) {\r\n this._unsupportedFeatures.push(`Group ${rawGroup.nm} does not have a transform which is not supported`);\r\n return;\r\n }\r\n\r\n const trsNode = new Node(\r\n `${parent.id} - ${rawGroup.nm} - ControlNode (TRS)`,\r\n this._configuration.ignoreOpacityAnimations,\r\n transform.position,\r\n transform.rotation,\r\n transform.scale,\r\n transform.opacity,\r\n parent\r\n );\r\n\r\n const spriteInfo = this._packer.addLottieShape(rawGroup, scalingFactor);\r\n\r\n const sprite = new ThinSprite();\r\n\r\n // Set sprite UV coordinates\r\n sprite._xOffset = spriteInfo.uOffset;\r\n sprite._yOffset = spriteInfo.vOffset;\r\n sprite._xSize = spriteInfo.cellWidth;\r\n sprite._ySize = spriteInfo.cellHeight;\r\n\r\n // Set sprite dimensions for rendering\r\n sprite.width = spriteInfo.widthPx;\r\n sprite.height = spriteInfo.heightPx;\r\n sprite.invertV = true;\r\n\r\n this._renderingManager.addSprite(sprite);\r\n\r\n transform.anchorPoint.startValue.x += spriteInfo.centerX || 0;\r\n transform.anchorPoint.startValue.y -= spriteInfo.centerY || 0;\r\n\r\n new SpriteNode(\r\n `${parent.id} - ${rawGroup.nm} - SpriteNode (Anchor)`,\r\n this._configuration.ignoreOpacityAnimations,\r\n sprite,\r\n transform.anchorPoint,\r\n undefined, // Rotation is not used for anchor point\r\n undefined, // Scale is not used for anchor point\r\n undefined, // Opacity is not used for anchor point\r\n trsNode\r\n );\r\n }\r\n\r\n private _parseTransform(transform: RawTransform): Transform {\r\n return {\r\n opacity: this._fromLottieScalarToBabylonScalar(transform.o, \"Opacity\", 1),\r\n rotation: this._fromLottieScalarToBabylonScalar(transform.r, \"Rotation\", 0),\r\n scale: this._fromLottieVector2ToBabylonVector2(transform.s, \"Scale\", DefaultScale),\r\n position: this._fromLottieVector2ToBabylonVector2(transform.p, \"Position\", DefaultPosition),\r\n anchorPoint: this._fromLottieVector2ToBabylonVector2(transform.a, \"AnchorPoint\", DefaultPosition),\r\n };\r\n }\r\n\r\n private _fromLottieScalarToBabylonScalar(property: RawScalarProperty | undefined, scalarType: ScalarType, defaultValue: number): ScalarProperty {\r\n if (!property) {\r\n return {\r\n startValue: defaultValue,\r\n currentValue: defaultValue,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n if (property.a === 0) {\r\n return {\r\n startValue: property.k as number,\r\n currentValue: property.k as number,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n const keyframes: ScalarKeyframe[] = [];\r\n const rawKeyFrames = property.k as RawVectorKeyframe[];\r\n let i = 0;\r\n for (i = 0; i < rawKeyFrames.length; i++) {\r\n let easeFunction: BezierCurve | undefined = undefined;\r\n if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {\r\n if (Array.isArray(rawKeyFrames[i].o!.x)) {\r\n // Value is an array\r\n easeFunction = new BezierCurve(\r\n (rawKeyFrames[i].o!.x as number[])[0],\r\n (rawKeyFrames[i].o!.y as number[])[0],\r\n (rawKeyFrames[i].i!.x as number[])[0],\r\n (rawKeyFrames[i].i!.y as number[])[0],\r\n this._configuration.easingSteps\r\n );\r\n } else {\r\n // Value is a number\r\n easeFunction = new BezierCurve(\r\n rawKeyFrames[i].o!.x as number,\r\n rawKeyFrames[i].o!.y as number,\r\n rawKeyFrames[i].i!.x as number,\r\n rawKeyFrames[i].i!.y as number,\r\n this._configuration.easingSteps\r\n );\r\n }\r\n }\r\n\r\n let value = rawKeyFrames[i].s[0];\r\n if (scalarType === \"Rotation\") {\r\n value = (value * Math.PI) / 180; // Lottie uses degrees for rotation, convert to radians\r\n }\r\n\r\n keyframes.push({\r\n value: value,\r\n time: rawKeyFrames[i].t,\r\n easeFunction: easeFunction!, // We assume that the ease function is always defined if we have keyframes\r\n });\r\n }\r\n\r\n let startValue = rawKeyFrames[0].s[0];\r\n if (scalarType === \"Rotation\") {\r\n startValue = (startValue * Math.PI) / 180; // Lottie uses degrees for rotation, convert to radians\r\n }\r\n\r\n return {\r\n startValue: startValue,\r\n currentValue: startValue,\r\n keyframes: keyframes,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n private _fromLottieVector2ToBabylonVector2(property: RawVectorProperty | undefined, vectorType: VectorType, defaultValue: IVector2Like): Vector2Property {\r\n if (!property) {\r\n return {\r\n startValue: defaultValue,\r\n currentValue: defaultValue,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n if (property.l !== undefined && property.l !== 2) {\r\n this._unsupportedFeatures.push(`Invalid Vector2 Length - Length: ${property.l}`);\r\n return {\r\n startValue: defaultValue,\r\n currentValue: defaultValue,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n if (property.a === 0) {\r\n const values = property.k as number[];\r\n const value = this._calculateFinalVector(values[0], values[1], vectorType);\r\n return {\r\n startValue: value,\r\n currentValue: value,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n const keyframes: Vector2Keyframe[] = [];\r\n const rawKeyFrames = property.k as RawVectorKeyframe[];\r\n let i = 0;\r\n for (i = 0; i < rawKeyFrames.length; i++) {\r\n let easeFunction1: BezierCurve | undefined = undefined;\r\n if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {\r\n if (Array.isArray(rawKeyFrames[i].o!.x)) {\r\n // Value is an array\r\n easeFunction1 = new BezierCurve(\r\n (rawKeyFrames[i].o!.x as number[])[0],\r\n (rawKeyFrames[i].o!.y as number[])[0],\r\n (rawKeyFrames[i].i!.x as number[])[0],\r\n (rawKeyFrames[i].i!.y as number[])[0],\r\n this._configuration.easingSteps\r\n );\r\n } else {\r\n // Value is a number\r\n easeFunction1 = new BezierCurve(\r\n rawKeyFrames[i].o!.x as number,\r\n rawKeyFrames[i].o!.y as number,\r\n rawKeyFrames[i].i!.x as number,\r\n rawKeyFrames[i].i!.y as number,\r\n this._configuration.easingSteps\r\n );\r\n }\r\n }\r\n\r\n let easeFunction2: BezierCurve | undefined = undefined;\r\n if (rawKeyFrames[i].o !== undefined && rawKeyFrames[i].i !== undefined) {\r\n if (Array.isArray(rawKeyFrames[i].o!.x)) {\r\n // Value is an array\r\n easeFunction2 = new BezierCurve(\r\n (rawKeyFrames[i].o!.x as number[])[1],\r\n (rawKeyFrames[i].o!.y as number[])[1],\r\n (rawKeyFrames[i].i!.x as number[])[1],\r\n (rawKeyFrames[i].i!.y as number[])[1],\r\n this._configuration.easingSteps\r\n );\r\n } else {\r\n // Value is a number\r\n easeFunction2 = new BezierCurve(\r\n rawKeyFrames[i].o!.x as number,\r\n rawKeyFrames[i].o!.y as number,\r\n rawKeyFrames[i].i!.x as number,\r\n rawKeyFrames[i].i!.y as number,\r\n this._configuration.easingSteps\r\n );\r\n }\r\n }\r\n\r\n keyframes.push({\r\n value: this._calculateFinalVector(rawKeyFrames[i].s[0], rawKeyFrames[i].s[1], vectorType),\r\n time: rawKeyFrames[i].t,\r\n easeFunction1: easeFunction1!, // We assume that the ease function is always defined if we have keyframes\r\n easeFunction2: easeFunction2!, // We assume that the ease function is always defined if we have keyframes\r\n });\r\n }\r\n\r\n const startValue = this._calculateFinalVector(rawKeyFrames[0].s[0], rawKeyFrames[0].s[1], vectorType);\r\n return {\r\n startValue: startValue,\r\n currentValue: { x: startValue.x, y: startValue.y }, // All vectors are passed by reference, so we need to create a copy to avoid modifying the start value\r\n keyframes: keyframes,\r\n currentKeyframeIndex: 0,\r\n };\r\n }\r\n\r\n private _calculateFinalVector(x: number, y: number, vectorType: VectorType): IVector2Like {\r\n const result = { x, y };\r\n\r\n if (vectorType === \"Position\") {\r\n // Lottie uses a different coordinate system for position, so we need to invert the Y value\r\n result.y = -result.y;\r\n } else if (vectorType === \"AnchorPoint\") {\r\n // Lottie uses a different coordinate system for anchor point, so we need to invert the X value\r\n result.x = -result.x;\r\n } else if (vectorType === \"Scale\") {\r\n // Lottie uses a different coordinate system for scale, so we need to divide by 100\r\n result.x = result.x / 100;\r\n result.y = result.y / 100;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private _getScaleFactor(node: Node): IVector2Like {\r\n const scale = { x: node.startScale.x, y: node.startScale.y };\r\n while (node.parent) {\r\n node = node.parent;\r\n scale.x *= node.startScale.x;\r\n scale.y *= node.startScale.y;\r\n }\r\n\r\n scale.x = scale.x * this._configuration.scaleMultiplier;\r\n scale.y = scale.y * this._configuration.scaleMultiplier;\r\n\r\n return scale;\r\n }\r\n\r\n private _validatePathShape(shape: RawPathShape): void {\r\n if (shape.ks.a === 1) {\r\n this._unsupportedFeatures.push(`Path ${shape.nm} has animated properties which are not supported`);\r\n }\r\n }\r\n\r\n private _validateRectangleShape(shape: RawRectangleShape): void {\r\n if (shape.p.a === 1) {\r\n this._unsupportedFeatures.push(`Rectangle ${shape.nm} has an position property that is animated which is not supported`);\r\n }\r\n\r\n if (shape.s.a === 1) {\r\n this._unsupportedFeatures.push(`Rectangle ${shape.nm} has a size property that is animated which is not supported`);\r\n }\r\n\r\n if (shape.r.a === 1) {\r\n this._unsupportedFeatures.push(`Rectangle ${shape.nm} has a rounded corners property that is animated which is not supported`);\r\n }\r\n }\r\n\r\n private _validateFillShape(shape: RawFillShape) {\r\n if (shape.o.a === 1) {\r\n this._unsupportedFeatures.push(`Fill ${shape.nm} has an opacity property that is animated which is not supported`);\r\n }\r\n\r\n if (shape.c.a === 1) {\r\n this._unsupportedFeatures.push(`Fill ${shape.nm} has a color property that is animated which is not supported`);\r\n }\r\n }\r\n\r\n private _validateGradientFillShape(shape: RawGradientFillShape) {\r\n if (shape.o.a === 1) {\r\n this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has an opacity property that is animated which is not supported`);\r\n }\r\n\r\n if (shape.s.a === 1) {\r\n this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has a start point property that is animated which is not supported`);\r\n }\r\n\r\n if (shape.e.a === 1) {\r\n this._unsupportedFeatures.push(`Gradient fill ${shape.nm} has an end point property that is animated which is not supported`);\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { IVector2Like } from "@babylonjs/core/Maths/math.like.js";
|
|
2
|
+
import type { BezierCurve } from "../maths/bezier.js";
|
|
3
|
+
import type { Node } from "../rendering/node.js";
|
|
4
|
+
/**
|
|
5
|
+
* Represents a Babylon.js thin version of a Lottie animation.
|
|
6
|
+
*/
|
|
7
|
+
export type AnimationInfo = {
|
|
8
|
+
/**
|
|
9
|
+
* Frame number where the animation starts.
|
|
10
|
+
*/
|
|
11
|
+
startFrame: number;
|
|
12
|
+
/**
|
|
13
|
+
* Frame number where the animation ends.
|
|
14
|
+
*/
|
|
15
|
+
endFrame: number;
|
|
16
|
+
/**
|
|
17
|
+
* Frame rate of the animation.
|
|
18
|
+
*/
|
|
19
|
+
frameRate: number;
|
|
20
|
+
/**
|
|
21
|
+
* Width of the animation in pixels
|
|
22
|
+
*/
|
|
23
|
+
widthPx: number;
|
|
24
|
+
/**
|
|
25
|
+
* Height of the animation in pixels
|
|
26
|
+
*/
|
|
27
|
+
heightPx: number;
|
|
28
|
+
/**
|
|
29
|
+
* Nodes representing the animation
|
|
30
|
+
*/
|
|
31
|
+
nodes: Node[];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Transform properties for a Lottie animation.
|
|
35
|
+
* Any of these properties may be animated.
|
|
36
|
+
*/
|
|
37
|
+
export type Transform = {
|
|
38
|
+
/**
|
|
39
|
+
* The anchor point of the layer, which is the point around which transformations are applied.
|
|
40
|
+
*/
|
|
41
|
+
anchorPoint: Vector2Property;
|
|
42
|
+
/**
|
|
43
|
+
* The position of the layer in the animation.
|
|
44
|
+
*/
|
|
45
|
+
position: Vector2Property;
|
|
46
|
+
/**
|
|
47
|
+
* The rotation of the layer in degrees.
|
|
48
|
+
*/
|
|
49
|
+
rotation: ScalarProperty;
|
|
50
|
+
/**
|
|
51
|
+
* The scale of the layer in the X and Y axis.
|
|
52
|
+
*/
|
|
53
|
+
scale: Vector2Property;
|
|
54
|
+
/**
|
|
55
|
+
* The opacity of the layer, represented as a scalar value.
|
|
56
|
+
*/
|
|
57
|
+
opacity: ScalarProperty;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Represents a scalar that can be animated.
|
|
61
|
+
*/
|
|
62
|
+
export type ScalarProperty = {
|
|
63
|
+
/**
|
|
64
|
+
* The initial value of the property at the start of the animation.
|
|
65
|
+
*/
|
|
66
|
+
startValue: number;
|
|
67
|
+
/**
|
|
68
|
+
* The current value of the property during the animation.
|
|
69
|
+
*/
|
|
70
|
+
currentValue: number;
|
|
71
|
+
/**
|
|
72
|
+
* An array of keyframes for the property.
|
|
73
|
+
*/
|
|
74
|
+
keyframes?: ScalarKeyframe[];
|
|
75
|
+
/**
|
|
76
|
+
* The index of the current keyframe being processed in the animation.
|
|
77
|
+
*/
|
|
78
|
+
currentKeyframeIndex: number;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Represents a keyframe for a scalar property.
|
|
82
|
+
*/
|
|
83
|
+
export type ScalarKeyframe = {
|
|
84
|
+
/**
|
|
85
|
+
* The value at this keyframe.
|
|
86
|
+
*/
|
|
87
|
+
value: number;
|
|
88
|
+
/**
|
|
89
|
+
* The time at which this keyframe occurs in the animation, in frames.
|
|
90
|
+
*/
|
|
91
|
+
time: number;
|
|
92
|
+
/**
|
|
93
|
+
* The easing function applied to the transition from this keyframe to the next one.
|
|
94
|
+
*/
|
|
95
|
+
easeFunction: BezierCurve;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Represents a 2D vector that can be animated.
|
|
99
|
+
*/
|
|
100
|
+
export type Vector2Property = {
|
|
101
|
+
/**
|
|
102
|
+
* The initial value at the start of the animation.
|
|
103
|
+
*/
|
|
104
|
+
startValue: IVector2Like;
|
|
105
|
+
/**
|
|
106
|
+
* The current value during the animation.
|
|
107
|
+
*/
|
|
108
|
+
currentValue: IVector2Like;
|
|
109
|
+
/**
|
|
110
|
+
* An array of keyframes for the property.
|
|
111
|
+
*/
|
|
112
|
+
keyframes?: Vector2Keyframe[];
|
|
113
|
+
/**
|
|
114
|
+
* The index of the current keyframe being processed in the animation.
|
|
115
|
+
*/
|
|
116
|
+
currentKeyframeIndex: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Represents a keyframe for a 2D vector property.
|
|
120
|
+
*/
|
|
121
|
+
export type Vector2Keyframe = {
|
|
122
|
+
/**
|
|
123
|
+
* The value at this keyframe.
|
|
124
|
+
*/
|
|
125
|
+
value: IVector2Like;
|
|
126
|
+
/**
|
|
127
|
+
* The time at which this keyframe occurs in the animation, in frames.
|
|
128
|
+
*/
|
|
129
|
+
time: number;
|
|
130
|
+
/**
|
|
131
|
+
* The easing function applied to the transition from this keyframe to the next one.
|
|
132
|
+
* This is used for the first dimension of the vector.
|
|
133
|
+
*/
|
|
134
|
+
easeFunction1: BezierCurve;
|
|
135
|
+
/**
|
|
136
|
+
* The easing function applied to the transition from this keyframe to the next one.
|
|
137
|
+
* This is used for the second dimension of the vector.
|
|
138
|
+
*/
|
|
139
|
+
easeFunction2: BezierCurve;
|
|
140
|
+
};
|