etro 0.8.0 → 0.8.1
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/.github/workflows/nodejs.yml +3 -1
- package/CHANGELOG.md +9 -1
- package/CODE_OF_CONDUCT.md +5 -5
- package/CONTRIBUTING.md +22 -72
- package/README.md +1 -1
- package/dist/effect/base.d.ts +14 -1
- package/dist/etro-cjs.js +156 -213
- package/dist/etro-iife.js +156 -213
- package/dist/layer/base.d.ts +13 -0
- package/eslint.conf.js +2 -1
- package/eslint.test-conf.js +1 -0
- package/examples/application/readme-screenshot.html +4 -8
- package/examples/application/video-player.html +3 -4
- package/examples/introduction/effects.html +23 -4
- package/karma.conf.js +4 -2
- package/package.json +4 -1
- package/scripts/gen-effect-samples.html +0 -3
- package/src/effect/base.ts +29 -10
- package/src/effect/gaussian-blur.ts +10 -10
- package/src/effect/pixelate.ts +1 -2
- package/src/effect/shader.ts +18 -22
- package/src/effect/stack.ts +5 -2
- package/src/effect/transform.ts +13 -14
- package/src/event.ts +8 -14
- package/src/layer/audio-source.ts +16 -14
- package/src/layer/audio.ts +1 -2
- package/src/layer/base.ts +26 -7
- package/src/layer/visual.ts +5 -6
- package/src/movie.ts +41 -49
- package/src/util.ts +50 -57
- package/docs/effect.js.html +0 -1215
- package/docs/event.js.html +0 -145
- package/docs/index.html +0 -81
- package/docs/index.js.html +0 -92
- package/docs/layer.js.html +0 -888
- package/docs/module-effect-GaussianBlurComponent.html +0 -345
- package/docs/module-effect.Brightness.html +0 -339
- package/docs/module-effect.Channels.html +0 -319
- package/docs/module-effect.ChromaKey.html +0 -611
- package/docs/module-effect.Contrast.html +0 -339
- package/docs/module-effect.EllipticalMask.html +0 -200
- package/docs/module-effect.GaussianBlur.html +0 -202
- package/docs/module-effect.GaussianBlurHorizontal.html +0 -242
- package/docs/module-effect.GaussianBlurVertical.html +0 -242
- package/docs/module-effect.Pixelate.html +0 -330
- package/docs/module-effect.Shader.html +0 -1227
- package/docs/module-effect.Stack.html +0 -406
- package/docs/module-effect.Transform.Matrix.html +0 -193
- package/docs/module-effect.Transform.html +0 -1174
- package/docs/module-effect.html +0 -148
- package/docs/module-event.html +0 -473
- package/docs/module-index.html +0 -186
- package/docs/module-layer-Media.html +0 -1116
- package/docs/module-layer-MediaMixin.html +0 -164
- package/docs/module-layer.Audio.html +0 -1188
- package/docs/module-layer.Base.html +0 -629
- package/docs/module-layer.Image.html +0 -1421
- package/docs/module-layer.Text.html +0 -1731
- package/docs/module-layer.Video.html +0 -1938
- package/docs/module-layer.Visual.html +0 -1698
- package/docs/module-layer.html +0 -137
- package/docs/module-movie.html +0 -3118
- package/docs/module-util.Color.html +0 -702
- package/docs/module-util.Font.html +0 -395
- package/docs/module-util.html +0 -845
- package/docs/movie.js.html +0 -689
- package/docs/scripts/collapse.js +0 -20
- package/docs/scripts/linenumber.js +0 -25
- package/docs/scripts/nav.js +0 -12
- package/docs/scripts/polyfill.js +0 -4
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/scripts/prettify/lang-css.js +0 -2
- package/docs/scripts/prettify/prettify.js +0 -28
- package/docs/scripts/search.js +0 -83
- package/docs/styles/jsdoc.css +0 -671
- package/docs/styles/prettify.css +0 -79
- package/docs/util.js.html +0 -503
- package/spec/assets/effect/gaussian-blur-horizontal.png +0 -0
- package/spec/assets/effect/gaussian-blur-vertical.png +0 -0
- package/spec/assets/effect/grayscale.png +0 -0
- package/spec/assets/effect/original.png +0 -0
- package/spec/assets/effect/pixelate.png +0 -0
- package/spec/assets/effect/transform/multiply.png +0 -0
- package/spec/assets/effect/transform/rotate.png +0 -0
- package/spec/assets/effect/transform/scale-fraction.png +0 -0
- package/spec/assets/effect/transform/scale.png +0 -0
- package/spec/assets/effect/transform/translate-fraction.png +0 -0
- package/spec/assets/effect/transform/translate.png +0 -0
- package/spec/assets/layer/audio.wav +0 -0
- package/spec/assets/layer/image.jpg +0 -0
- package/spec/effect.spec.js +0 -421
- package/spec/event.spec.js +0 -39
- package/spec/layer.spec.js +0 -307
- package/spec/movie.spec.js +0 -346
- package/spec/util.spec.js +0 -294
package/dist/etro-cjs.js
CHANGED
|
@@ -52,14 +52,11 @@ var TypeId = /** @class */ (function () {
|
|
|
52
52
|
this._parts = id.split('.');
|
|
53
53
|
}
|
|
54
54
|
TypeId.prototype.contains = function (other) {
|
|
55
|
-
if (other._parts.length > this._parts.length)
|
|
55
|
+
if (other._parts.length > this._parts.length)
|
|
56
56
|
return false;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (other._parts[i] !== this._parts[i]) {
|
|
57
|
+
for (var i = 0; i < other._parts.length; i++)
|
|
58
|
+
if (other._parts[i] !== this._parts[i])
|
|
60
59
|
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
60
|
return true;
|
|
64
61
|
};
|
|
65
62
|
TypeId.prototype.toString = function () {
|
|
@@ -76,9 +73,8 @@ var TypeId = /** @class */ (function () {
|
|
|
76
73
|
* @param listener
|
|
77
74
|
*/
|
|
78
75
|
function subscribe(target, type, listener) {
|
|
79
|
-
if (!listeners.has(target))
|
|
76
|
+
if (!listeners.has(target))
|
|
80
77
|
listeners.set(target, []);
|
|
81
|
-
}
|
|
82
78
|
listeners.get(target).push({ type: new TypeId(type), listener: listener });
|
|
83
79
|
}
|
|
84
80
|
/**
|
|
@@ -92,9 +88,8 @@ function subscribe(target, type, listener) {
|
|
|
92
88
|
function unsubscribe(target, listener) {
|
|
93
89
|
// Make sure `listener` has been added with `subscribe`.
|
|
94
90
|
if (!listeners.has(target) ||
|
|
95
|
-
!listeners.get(target).map(function (pair) { return pair.listener; }).includes(listener))
|
|
91
|
+
!listeners.get(target).map(function (pair) { return pair.listener; }).includes(listener))
|
|
96
92
|
throw new Error('No matching event listener to remove');
|
|
97
|
-
}
|
|
98
93
|
var removed = listeners.get(target)
|
|
99
94
|
.filter(function (pair) { return pair.listener !== listener; });
|
|
100
95
|
listeners.set(target, removed);
|
|
@@ -111,17 +106,15 @@ function publish(target, type, event) {
|
|
|
111
106
|
event.target = target; // could be a proxy
|
|
112
107
|
event.type = type;
|
|
113
108
|
var t = new TypeId(type);
|
|
114
|
-
if (!listeners.has(target))
|
|
109
|
+
if (!listeners.has(target))
|
|
115
110
|
// No event fired
|
|
116
111
|
return null;
|
|
117
|
-
}
|
|
118
112
|
// Call event listeners for this event.
|
|
119
113
|
var listenersForType = [];
|
|
120
114
|
for (var i = 0; i < listeners.get(target).length; i++) {
|
|
121
115
|
var item = listeners.get(target)[i];
|
|
122
|
-
if (t.contains(item.type))
|
|
116
|
+
if (t.contains(item.type))
|
|
123
117
|
listenersForType.push(item.listener);
|
|
124
|
-
}
|
|
125
118
|
}
|
|
126
119
|
for (var i = 0; i < listenersForType.length; i++) {
|
|
127
120
|
var listener = listenersForType[i];
|
|
@@ -149,9 +142,8 @@ var event = /*#__PURE__*/Object.freeze({
|
|
|
149
142
|
function getPropertyDescriptor(obj, name) {
|
|
150
143
|
do {
|
|
151
144
|
var propDesc = Object.getOwnPropertyDescriptor(obj, name);
|
|
152
|
-
if (propDesc)
|
|
145
|
+
if (propDesc)
|
|
153
146
|
return propDesc;
|
|
154
|
-
}
|
|
155
147
|
obj = Object.getPrototypeOf(obj);
|
|
156
148
|
} while (obj);
|
|
157
149
|
return undefined;
|
|
@@ -166,35 +158,30 @@ function getPropertyDescriptor(obj, name) {
|
|
|
166
158
|
function applyOptions(options, destObj) {
|
|
167
159
|
var defaultOptions = destObj.getDefaultOptions();
|
|
168
160
|
// Validate; make sure `keys` doesn't have any extraneous items
|
|
169
|
-
for (var option in options)
|
|
161
|
+
for (var option in options)
|
|
170
162
|
// eslint-disable-next-line no-prototype-builtins
|
|
171
|
-
if (!defaultOptions.hasOwnProperty(option))
|
|
163
|
+
if (!defaultOptions.hasOwnProperty(option))
|
|
172
164
|
throw new Error("Invalid option: '" + option + "'");
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
165
|
// Merge options and defaultOptions
|
|
176
166
|
options = __assign(__assign({}, defaultOptions), options);
|
|
177
167
|
// Copy options
|
|
178
168
|
for (var option in options) {
|
|
179
169
|
var propDesc = getPropertyDescriptor(destObj, option);
|
|
180
170
|
// Update the property as long as the property has not been set (unless if it has a setter)
|
|
181
|
-
if (!propDesc || propDesc.set)
|
|
171
|
+
if (!propDesc || propDesc.set)
|
|
182
172
|
destObj[option] = options[option];
|
|
183
|
-
}
|
|
184
173
|
}
|
|
185
174
|
}
|
|
186
175
|
// This must be cleared at the start of each frame
|
|
187
176
|
var valCache = new WeakMap();
|
|
188
177
|
function cacheValue(element, path, value) {
|
|
189
178
|
// Initiate movie cache
|
|
190
|
-
if (!valCache.has(element.movie))
|
|
179
|
+
if (!valCache.has(element.movie))
|
|
191
180
|
valCache.set(element.movie, new WeakMap());
|
|
192
|
-
}
|
|
193
181
|
var movieCache = valCache.get(element.movie);
|
|
194
182
|
// Iniitate element cache
|
|
195
|
-
if (!movieCache.has(element))
|
|
183
|
+
if (!movieCache.has(element))
|
|
196
184
|
movieCache.set(element, {});
|
|
197
|
-
}
|
|
198
185
|
var elementCache = movieCache.get(element);
|
|
199
186
|
// Cache the value
|
|
200
187
|
elementCache[path] = value;
|
|
@@ -234,16 +221,13 @@ var KeyFrame = /** @class */ (function () {
|
|
|
234
221
|
return this;
|
|
235
222
|
};
|
|
236
223
|
KeyFrame.prototype.evaluate = function (time) {
|
|
237
|
-
if (this.value.length === 0)
|
|
224
|
+
if (this.value.length === 0)
|
|
238
225
|
throw new Error('Empty keyframe');
|
|
239
|
-
|
|
240
|
-
if (time === undefined) {
|
|
226
|
+
if (time === undefined)
|
|
241
227
|
throw new Error('|time| is undefined or null');
|
|
242
|
-
}
|
|
243
228
|
var firstTime = this.value[0][0];
|
|
244
|
-
if (time < firstTime)
|
|
229
|
+
if (time < firstTime)
|
|
245
230
|
throw new Error('No keyframe point before |time|');
|
|
246
|
-
}
|
|
247
231
|
// I think reduce are slow to do per-frame (or more)?
|
|
248
232
|
for (var i = 0; i < this.value.length; i++) {
|
|
249
233
|
var startTime = this.value[i][0];
|
|
@@ -252,7 +236,7 @@ var KeyFrame = /** @class */ (function () {
|
|
|
252
236
|
if (i + 1 < this.value.length) {
|
|
253
237
|
var endTime = this.value[i + 1][0];
|
|
254
238
|
var endValue = this.value[i + 1][1];
|
|
255
|
-
if (startTime <= time && time < endTime)
|
|
239
|
+
if (startTime <= time && time < endTime)
|
|
256
240
|
// No need for endValue if it is flat interpolation
|
|
257
241
|
// TODO: support custom interpolation for 'other' types?
|
|
258
242
|
if (!(typeof startValue === 'number' || typeof endValue === 'object')) {
|
|
@@ -268,7 +252,6 @@ var KeyFrame = /** @class */ (function () {
|
|
|
268
252
|
endValue, // eslint-disable-line @typescript-eslint/ban-types
|
|
269
253
|
percentProgress, this.interpolationKeys);
|
|
270
254
|
}
|
|
271
|
-
}
|
|
272
255
|
}
|
|
273
256
|
else {
|
|
274
257
|
// Repeat last value forever
|
|
@@ -294,28 +277,23 @@ var KeyFrame = /** @class */ (function () {
|
|
|
294
277
|
// TODO: Is this function efficient?
|
|
295
278
|
// TODO: Update doc @params to allow for keyframes
|
|
296
279
|
function val(element, path, time) {
|
|
297
|
-
if (hasCachedValue(element, path))
|
|
280
|
+
if (hasCachedValue(element, path))
|
|
298
281
|
return getCachedValue(element, path);
|
|
299
|
-
}
|
|
300
282
|
// Get property of element at path
|
|
301
283
|
var pathParts = path.split('.');
|
|
302
284
|
var property = element[pathParts.shift()];
|
|
303
|
-
while (pathParts.length > 0)
|
|
285
|
+
while (pathParts.length > 0)
|
|
304
286
|
property = property[pathParts.shift()];
|
|
305
|
-
}
|
|
306
287
|
// Property filter function
|
|
307
288
|
var process = element.propertyFilters[path];
|
|
308
289
|
var value;
|
|
309
|
-
if (property instanceof KeyFrame)
|
|
290
|
+
if (property instanceof KeyFrame)
|
|
310
291
|
value = property.evaluate(time);
|
|
311
|
-
|
|
312
|
-
else if (typeof property === 'function') {
|
|
292
|
+
else if (typeof property === 'function')
|
|
313
293
|
value = property(element, time); // TODO? add more args
|
|
314
|
-
|
|
315
|
-
else {
|
|
294
|
+
else
|
|
316
295
|
// Simple value
|
|
317
296
|
value = property;
|
|
318
|
-
}
|
|
319
297
|
return cacheValue(element, path, process ? process.call(element, value) : value);
|
|
320
298
|
}
|
|
321
299
|
/* export function floorInterp(x1, x2, t, objectKeys) {
|
|
@@ -326,18 +304,15 @@ function val(element, path, time) {
|
|
|
326
304
|
}, Object.create(Object.getPrototypeOf(x1)));
|
|
327
305
|
} */
|
|
328
306
|
function linearInterp(x1, x2, t, objectKeys) {
|
|
329
|
-
if (typeof x1 !== typeof x2)
|
|
307
|
+
if (typeof x1 !== typeof x2)
|
|
330
308
|
throw new Error('Type mismatch');
|
|
331
|
-
|
|
332
|
-
if (typeof x1 !== 'number' && typeof x1 !== 'object') {
|
|
309
|
+
if (typeof x1 !== 'number' && typeof x1 !== 'object')
|
|
333
310
|
// Flat interpolation (floor)
|
|
334
311
|
return x1;
|
|
335
|
-
}
|
|
336
312
|
if (typeof x1 === 'object') { // to work with objects (including arrays)
|
|
337
313
|
// TODO: make this code DRY
|
|
338
|
-
if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
|
|
314
|
+
if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
|
|
339
315
|
throw new Error('Prototype mismatch');
|
|
340
|
-
}
|
|
341
316
|
// Preserve prototype of objects
|
|
342
317
|
var int = Object.create(Object.getPrototypeOf(x1));
|
|
343
318
|
// Take the intersection of properties
|
|
@@ -345,9 +320,8 @@ function linearInterp(x1, x2, t, objectKeys) {
|
|
|
345
320
|
for (var i = 0; i < keys.length; i++) {
|
|
346
321
|
var key = keys[i];
|
|
347
322
|
// eslint-disable-next-line no-prototype-builtins
|
|
348
|
-
if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
|
|
323
|
+
if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
|
|
349
324
|
continue;
|
|
350
|
-
}
|
|
351
325
|
int[key] = linearInterp(x1[key], x2[key], t);
|
|
352
326
|
}
|
|
353
327
|
return int;
|
|
@@ -355,17 +329,14 @@ function linearInterp(x1, x2, t, objectKeys) {
|
|
|
355
329
|
return (1 - t) * x1 + t * x2;
|
|
356
330
|
}
|
|
357
331
|
function cosineInterp(x1, x2, t, objectKeys) {
|
|
358
|
-
if (typeof x1 !== typeof x2)
|
|
332
|
+
if (typeof x1 !== typeof x2)
|
|
359
333
|
throw new Error('Type mismatch');
|
|
360
|
-
|
|
361
|
-
if (typeof x1 !== 'number' && typeof x1 !== 'object') {
|
|
334
|
+
if (typeof x1 !== 'number' && typeof x1 !== 'object')
|
|
362
335
|
// Flat interpolation (floor)
|
|
363
336
|
return x1;
|
|
364
|
-
}
|
|
365
337
|
if (typeof x1 === 'object' && typeof x2 === 'object') { // to work with objects (including arrays)
|
|
366
|
-
if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
|
|
338
|
+
if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
|
|
367
339
|
throw new Error('Prototype mismatch');
|
|
368
|
-
}
|
|
369
340
|
// Preserve prototype of objects
|
|
370
341
|
var int = Object.create(Object.getPrototypeOf(x1));
|
|
371
342
|
// Take the intersection of properties
|
|
@@ -373,9 +344,8 @@ function cosineInterp(x1, x2, t, objectKeys) {
|
|
|
373
344
|
for (var i = 0; i < keys.length; i++) {
|
|
374
345
|
var key = keys[i];
|
|
375
346
|
// eslint-disable-next-line no-prototype-builtins
|
|
376
|
-
if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
|
|
347
|
+
if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
|
|
377
348
|
continue;
|
|
378
|
-
}
|
|
379
349
|
int[key] = cosineInterp(x1[key], x2[key], t);
|
|
380
350
|
}
|
|
381
351
|
return int;
|
|
@@ -505,12 +475,10 @@ function mapPixels(mapper, canvas, ctx, x, y, width, height, flush) {
|
|
|
505
475
|
width = width || canvas.width;
|
|
506
476
|
height = height || canvas.height;
|
|
507
477
|
var frame = ctx.getImageData(x, y, width, height);
|
|
508
|
-
for (var i = 0, l = frame.data.length; i < l; i += 4)
|
|
478
|
+
for (var i = 0, l = frame.data.length; i < l; i += 4)
|
|
509
479
|
mapper(frame.data, i);
|
|
510
|
-
|
|
511
|
-
if (flush) {
|
|
480
|
+
if (flush)
|
|
512
481
|
ctx.putImageData(frame, x, y);
|
|
513
|
-
}
|
|
514
482
|
}
|
|
515
483
|
/**
|
|
516
484
|
* <p>Emits "change" event when public properties updated, recursively.
|
|
@@ -527,17 +495,17 @@ function watchPublic(target) {
|
|
|
527
495
|
// Public API property updated, emit 'modify' event.
|
|
528
496
|
publish(proxy, target.type + ".change.modify", { property: getPath(receiver, prop), newValue: val });
|
|
529
497
|
};
|
|
530
|
-
var
|
|
498
|
+
var canWatch = function (receiver, prop) { return !prop.startsWith('_') &&
|
|
499
|
+
(target.publicExcludes === undefined || !target.publicExcludes.includes(prop)); };
|
|
531
500
|
// The path to each child property (each is a unique proxy)
|
|
532
501
|
var paths = new WeakMap();
|
|
533
502
|
var handler = {
|
|
534
503
|
set: function (obj, prop, val, receiver) {
|
|
535
504
|
// Recurse
|
|
536
|
-
if (typeof val === 'object' && val !== null && !paths.has(val) &&
|
|
505
|
+
if (typeof val === 'object' && val !== null && !paths.has(val) && canWatch(receiver, prop)) {
|
|
537
506
|
val = new Proxy(val, handler);
|
|
538
507
|
paths.set(val, getPath(receiver, prop));
|
|
539
508
|
}
|
|
540
|
-
var was = prop in obj;
|
|
541
509
|
// Set property or attribute
|
|
542
510
|
// Search prototype chain for the closest setter
|
|
543
511
|
var objProto = obj;
|
|
@@ -549,15 +517,12 @@ function watchPublic(target) {
|
|
|
549
517
|
break;
|
|
550
518
|
}
|
|
551
519
|
}
|
|
552
|
-
if (!objProto)
|
|
520
|
+
if (!objProto)
|
|
553
521
|
// Couldn't find setter; set value on instance
|
|
554
522
|
obj[prop] = val;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
// on root object.
|
|
558
|
-
if (obj !== target || (was && check(prop))) {
|
|
523
|
+
// Check if the property isn't blacklisted in publicExcludes.
|
|
524
|
+
if (canWatch(receiver, prop))
|
|
559
525
|
callback(prop, val, receiver);
|
|
560
|
-
}
|
|
561
526
|
return true;
|
|
562
527
|
}
|
|
563
528
|
};
|
|
@@ -597,23 +562,20 @@ function AudioSourceMixin(superclass) {
|
|
|
597
562
|
applyOptions(options, _this);
|
|
598
563
|
var load = function () {
|
|
599
564
|
// TODO: && ?
|
|
600
|
-
if ((options.duration || (_this.source.duration - _this.sourceStartTime)) < 0)
|
|
565
|
+
if ((options.duration || (_this.source.duration - _this.sourceStartTime)) < 0)
|
|
601
566
|
throw new Error('Invalid options.duration or options.sourceStartTime');
|
|
602
|
-
}
|
|
603
567
|
_this._unstretchedDuration = options.duration || (_this.source.duration - _this.sourceStartTime);
|
|
604
568
|
_this.duration = _this._unstretchedDuration / (_this.playbackRate);
|
|
605
569
|
// onload will use `this`, and can't bind itself because it's before
|
|
606
570
|
// super()
|
|
607
571
|
onload && onload.bind(_this)(_this.source, options);
|
|
608
572
|
};
|
|
609
|
-
if (_this.source.readyState >= 2)
|
|
573
|
+
if (_this.source.readyState >= 2)
|
|
610
574
|
// this frame's data is available now
|
|
611
575
|
load();
|
|
612
|
-
|
|
613
|
-
else {
|
|
576
|
+
else
|
|
614
577
|
// when this frame's data is available
|
|
615
578
|
_this.source.addEventListener('loadedmetadata', load);
|
|
616
|
-
}
|
|
617
579
|
_this.source.addEventListener('durationchange', function () {
|
|
618
580
|
_this.duration = options.duration || (_this.source.duration - _this.sourceStartTime);
|
|
619
581
|
});
|
|
@@ -623,11 +585,9 @@ function AudioSourceMixin(superclass) {
|
|
|
623
585
|
var _this = this;
|
|
624
586
|
_super.prototype.attach.call(this, movie);
|
|
625
587
|
subscribe(movie, 'movie.seek', function () {
|
|
626
|
-
|
|
627
|
-
if (time < _this.startTime || time >= _this.startTime + _this.duration) {
|
|
588
|
+
if (_this.currentTime < 0 || _this.currentTime >= _this.duration)
|
|
628
589
|
return;
|
|
629
|
-
|
|
630
|
-
_this.source.currentTime = time - _this.startTime;
|
|
590
|
+
_this.source.currentTime = _this.currentTime + _this.sourceStartTime;
|
|
631
591
|
});
|
|
632
592
|
// TODO: on unattach?
|
|
633
593
|
subscribe(movie, 'movie.audiodestinationupdate', function (event) {
|
|
@@ -639,7 +599,7 @@ function AudioSourceMixin(superclass) {
|
|
|
639
599
|
}
|
|
640
600
|
});
|
|
641
601
|
// connect to audiocontext
|
|
642
|
-
this._audioNode = movie.actx.createMediaElementSource(this.source);
|
|
602
|
+
this._audioNode = this.audioNode || movie.actx.createMediaElementSource(this.source);
|
|
643
603
|
// Spy on connect and disconnect to remember if it connected to
|
|
644
604
|
// actx.destination (for Movie#record).
|
|
645
605
|
var oldConnect = this._audioNode.connect.bind(this.audioNode);
|
|
@@ -650,14 +610,16 @@ function AudioSourceMixin(superclass) {
|
|
|
650
610
|
var oldDisconnect = this._audioNode.disconnect.bind(this.audioNode);
|
|
651
611
|
this._audioNode.disconnect = function (destination, output, input) {
|
|
652
612
|
if (_this._connectedToDestination &&
|
|
653
|
-
destination === movie.actx.destination)
|
|
613
|
+
destination === movie.actx.destination)
|
|
654
614
|
_this._connectedToDestination = false;
|
|
655
|
-
}
|
|
656
615
|
return oldDisconnect(destination, output, input);
|
|
657
616
|
};
|
|
658
617
|
// Connect to actx.destination by default (can be rewired by user)
|
|
659
618
|
this.audioNode.connect(movie.actx.destination);
|
|
660
619
|
};
|
|
620
|
+
MixedAudioSource.prototype.detach = function () {
|
|
621
|
+
this.audioNode.disconnect(this.movie.actx.destination);
|
|
622
|
+
};
|
|
661
623
|
MixedAudioSource.prototype.start = function () {
|
|
662
624
|
this.source.currentTime = this.currentTime + this.sourceStartTime;
|
|
663
625
|
this.source.play();
|
|
@@ -689,9 +651,8 @@ function AudioSourceMixin(superclass) {
|
|
|
689
651
|
},
|
|
690
652
|
set: function (value) {
|
|
691
653
|
this._playbackRate = value;
|
|
692
|
-
if (this._unstretchedDuration !== undefined)
|
|
654
|
+
if (this._unstretchedDuration !== undefined)
|
|
693
655
|
this.duration = this._unstretchedDuration / value;
|
|
694
|
-
}
|
|
695
656
|
},
|
|
696
657
|
enumerable: false,
|
|
697
658
|
configurable: true
|
|
@@ -771,20 +732,36 @@ var Base = /** @class */ (function () {
|
|
|
771
732
|
});
|
|
772
733
|
return newThis;
|
|
773
734
|
}
|
|
774
|
-
|
|
735
|
+
/**
|
|
736
|
+
* Attaches this layer to `movie` if not already attached.
|
|
737
|
+
* @ignore
|
|
738
|
+
*/
|
|
739
|
+
Base.prototype.tryAttach = function (movie) {
|
|
740
|
+
if (this._occurrenceCount === 0)
|
|
741
|
+
this.attach(movie);
|
|
775
742
|
this._occurrenceCount++;
|
|
743
|
+
};
|
|
744
|
+
Base.prototype.attach = function (movie) {
|
|
776
745
|
this._movie = movie;
|
|
777
746
|
};
|
|
778
|
-
|
|
779
|
-
|
|
747
|
+
/**
|
|
748
|
+
* Dettaches this layer from its movie if the number of times `tryDetach` has
|
|
749
|
+
* been called (including this call) equals the number of times `tryAttach`
|
|
750
|
+
* has been called.
|
|
751
|
+
*
|
|
752
|
+
* @ignore
|
|
753
|
+
*/
|
|
754
|
+
Base.prototype.tryDetach = function () {
|
|
755
|
+
if (this.movie === null)
|
|
780
756
|
throw new Error('No movie to detach from');
|
|
781
|
-
}
|
|
782
757
|
this._occurrenceCount--;
|
|
783
758
|
// If this layer occurs in another place in a `layers` array, do not unset
|
|
784
759
|
// _movie. (For calling `unshift` on the `layers` proxy)
|
|
785
|
-
if (this._occurrenceCount === 0)
|
|
786
|
-
this.
|
|
787
|
-
|
|
760
|
+
if (this._occurrenceCount === 0)
|
|
761
|
+
this.detach();
|
|
762
|
+
};
|
|
763
|
+
Base.prototype.detach = function () {
|
|
764
|
+
this._movie = null;
|
|
788
765
|
};
|
|
789
766
|
/**
|
|
790
767
|
* Called when the layer is activated
|
|
@@ -873,9 +850,8 @@ var Audio = /** @class */ (function (_super) {
|
|
|
873
850
|
*/
|
|
874
851
|
function Audio(options) {
|
|
875
852
|
var _this = _super.call(this, options) || this;
|
|
876
|
-
if (_this.duration === undefined)
|
|
853
|
+
if (_this.duration === undefined)
|
|
877
854
|
_this.duration = (_this).source.duration - _this.sourceStartTime;
|
|
878
|
-
}
|
|
879
855
|
return _this;
|
|
880
856
|
}
|
|
881
857
|
Audio.prototype.getDefaultOptions = function () {
|
|
@@ -913,9 +889,8 @@ var Visual = /** @class */ (function (_super) {
|
|
|
913
889
|
set: function (target, property, value) {
|
|
914
890
|
if (!isNaN(Number(property))) {
|
|
915
891
|
// The property is a number (index)
|
|
916
|
-
if (target[property])
|
|
892
|
+
if (target[property])
|
|
917
893
|
target[property].detach();
|
|
918
|
-
}
|
|
919
894
|
value.attach(_this);
|
|
920
895
|
}
|
|
921
896
|
target[property] = value;
|
|
@@ -958,18 +933,16 @@ var Visual = /** @class */ (function (_super) {
|
|
|
958
933
|
Visual.prototype.endRender = function () {
|
|
959
934
|
var w = val(this, 'width', this.currentTime) || val(this.movie, 'width', this.movie.currentTime);
|
|
960
935
|
var h = val(this, 'height', this.currentTime) || val(this.movie, 'height', this.movie.currentTime);
|
|
961
|
-
if (w * h > 0)
|
|
936
|
+
if (w * h > 0)
|
|
962
937
|
this._applyEffects();
|
|
963
|
-
}
|
|
964
938
|
// else InvalidStateError for drawing zero-area image in some effects, right?
|
|
965
939
|
};
|
|
966
940
|
Visual.prototype._applyEffects = function () {
|
|
967
941
|
for (var i = 0; i < this.effects.length; i++) {
|
|
968
942
|
var effect = this.effects[i];
|
|
969
|
-
if (effect.enabled)
|
|
943
|
+
if (effect.enabled)
|
|
970
944
|
// Pass relative time
|
|
971
945
|
effect.apply(this, this.movie.currentTime - this.startTime);
|
|
972
|
-
}
|
|
973
946
|
}
|
|
974
947
|
};
|
|
975
948
|
/**
|
|
@@ -1213,28 +1186,43 @@ var Base$1 = /** @class */ (function () {
|
|
|
1213
1186
|
newThis._target = null;
|
|
1214
1187
|
// Propogate up to target
|
|
1215
1188
|
subscribe(newThis, 'effect.change.modify', function (event) {
|
|
1216
|
-
if (!newThis._target)
|
|
1189
|
+
if (!newThis._target)
|
|
1217
1190
|
return;
|
|
1218
|
-
}
|
|
1219
1191
|
var type = newThis._target.type + ".change.effect.modify";
|
|
1220
1192
|
publish(newThis._target, type, __assign(__assign({}, event), { target: newThis._target, source: newThis, type: type }));
|
|
1221
1193
|
});
|
|
1222
1194
|
return newThis;
|
|
1223
1195
|
}
|
|
1224
|
-
|
|
1196
|
+
/**
|
|
1197
|
+
* Attaches this effect to `target` if not already attached.
|
|
1198
|
+
* @ignore
|
|
1199
|
+
*/
|
|
1200
|
+
Base.prototype.tryAttach = function (target) {
|
|
1201
|
+
if (this._occurrenceCount === 0)
|
|
1202
|
+
this.attach(target);
|
|
1225
1203
|
this._occurrenceCount++;
|
|
1226
|
-
this._target = target;
|
|
1227
1204
|
};
|
|
1228
|
-
Base.prototype.
|
|
1229
|
-
|
|
1205
|
+
Base.prototype.attach = function (movie) {
|
|
1206
|
+
this._target = movie;
|
|
1207
|
+
};
|
|
1208
|
+
/**
|
|
1209
|
+
* Dettaches this effect from its target if the number of times `tryDetach`
|
|
1210
|
+
* has been called (including this call) equals the number of times
|
|
1211
|
+
* `tryAttach` has been called.
|
|
1212
|
+
*
|
|
1213
|
+
* @ignore
|
|
1214
|
+
*/
|
|
1215
|
+
Base.prototype.tryDetach = function () {
|
|
1216
|
+
if (this._target === null)
|
|
1230
1217
|
throw new Error('No movie to detach from');
|
|
1231
|
-
}
|
|
1232
1218
|
this._occurrenceCount--;
|
|
1233
1219
|
// If this effect occurs in another place in the containing array, do not
|
|
1234
1220
|
// unset _target. (For calling `unshift` on the `layers` proxy)
|
|
1235
|
-
if (this._occurrenceCount === 0)
|
|
1236
|
-
this.
|
|
1237
|
-
|
|
1221
|
+
if (this._occurrenceCount === 0)
|
|
1222
|
+
this.detach();
|
|
1223
|
+
};
|
|
1224
|
+
Base.prototype.detach = function () {
|
|
1225
|
+
this._target = null;
|
|
1238
1226
|
};
|
|
1239
1227
|
// subclasses must implement apply
|
|
1240
1228
|
/**
|
|
@@ -1314,18 +1302,16 @@ var Shader = /** @class */ (function (_super) {
|
|
|
1314
1302
|
Shader.prototype._initGl = function () {
|
|
1315
1303
|
this._canvas = document.createElement('canvas');
|
|
1316
1304
|
var gl = this._canvas.getContext('webgl');
|
|
1317
|
-
if (gl === null)
|
|
1305
|
+
if (gl === null)
|
|
1318
1306
|
throw new Error('Unable to initialize WebGL. Your browser or machine may not support it.');
|
|
1319
|
-
}
|
|
1320
1307
|
this._gl = gl;
|
|
1321
1308
|
return gl;
|
|
1322
1309
|
};
|
|
1323
1310
|
Shader.prototype._initTextures = function (userUniforms, userTextures, sourceTextureOptions) {
|
|
1324
1311
|
var gl = this._gl;
|
|
1325
1312
|
var maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
1326
|
-
if (userTextures.length > maxTextures)
|
|
1313
|
+
if (userTextures.length > maxTextures)
|
|
1327
1314
|
console.warn('Too many textures!');
|
|
1328
|
-
}
|
|
1329
1315
|
this._userTextures = {};
|
|
1330
1316
|
for (var name_1 in userTextures) {
|
|
1331
1317
|
var userOptions = userTextures[name_1];
|
|
@@ -1338,9 +1324,8 @@ var Shader = /** @class */ (function (_super) {
|
|
|
1338
1324
|
* textures, without having to define multiple properties in the effect
|
|
1339
1325
|
* object.
|
|
1340
1326
|
*/
|
|
1341
|
-
if (userUniforms[name_1])
|
|
1327
|
+
if (userUniforms[name_1])
|
|
1342
1328
|
throw new Error("Texture - uniform naming conflict: " + name_1 + "!");
|
|
1343
|
-
}
|
|
1344
1329
|
// Add this as a "user uniform".
|
|
1345
1330
|
userUniforms[name_1] = '1i'; // texture pointer
|
|
1346
1331
|
}
|
|
@@ -1478,13 +1463,11 @@ var Shader = /** @class */ (function (_super) {
|
|
|
1478
1463
|
// Set the shader uniforms.
|
|
1479
1464
|
// Tell the shader we bound the texture to texture unit 0.
|
|
1480
1465
|
// All base (Shader class) uniforms are optional.
|
|
1481
|
-
if (this._uniformLocations.source)
|
|
1466
|
+
if (this._uniformLocations.source)
|
|
1482
1467
|
gl.uniform1i(this._uniformLocations.source, 0);
|
|
1483
|
-
}
|
|
1484
1468
|
// All base (Shader class) uniforms are optional.
|
|
1485
|
-
if (this._uniformLocations.size)
|
|
1469
|
+
if (this._uniformLocations.size)
|
|
1486
1470
|
gl.uniform2iv(this._uniformLocations.size, [target.canvas.width, target.canvas.height]);
|
|
1487
|
-
}
|
|
1488
1471
|
for (var unprefixed in this._userUniforms) {
|
|
1489
1472
|
var options = this._userUniforms[unprefixed];
|
|
1490
1473
|
var value = val(this, unprefixed, reltime);
|
|
@@ -1535,40 +1518,35 @@ var Shader = /** @class */ (function (_super) {
|
|
|
1535
1518
|
var i = 0;
|
|
1536
1519
|
for (var name_4 in this._userTextures) {
|
|
1537
1520
|
var testValue = val(this, name_4, reltime);
|
|
1538
|
-
if (value === testValue)
|
|
1521
|
+
if (value === testValue)
|
|
1539
1522
|
value = Shader.INTERNAL_TEXTURE_UNITS + i; // after the internal texture units
|
|
1540
|
-
}
|
|
1541
1523
|
i++;
|
|
1542
1524
|
}
|
|
1543
1525
|
}
|
|
1544
1526
|
if (outputType === '3fv') {
|
|
1545
1527
|
// allow 4-component vectors; TODO: why?
|
|
1546
|
-
if (Array.isArray(value) && (value.length === 3 || value.length === 4))
|
|
1528
|
+
if (Array.isArray(value) && (value.length === 3 || value.length === 4))
|
|
1547
1529
|
return value;
|
|
1548
|
-
}
|
|
1549
1530
|
// kind of loose so this can be changed if needed
|
|
1550
|
-
if (typeof value === 'object')
|
|
1531
|
+
if (typeof value === 'object')
|
|
1551
1532
|
return [
|
|
1552
1533
|
value.r !== undefined ? value.r : def,
|
|
1553
1534
|
value.g !== undefined ? value.g : def,
|
|
1554
1535
|
value.b !== undefined ? value.b : def
|
|
1555
1536
|
];
|
|
1556
|
-
}
|
|
1557
1537
|
throw new Error("Invalid type: " + outputType + " or value: " + value);
|
|
1558
1538
|
}
|
|
1559
1539
|
if (outputType === '4fv') {
|
|
1560
|
-
if (Array.isArray(value) && value.length === 4)
|
|
1540
|
+
if (Array.isArray(value) && value.length === 4)
|
|
1561
1541
|
return value;
|
|
1562
|
-
}
|
|
1563
1542
|
// kind of loose so this can be changed if needed
|
|
1564
|
-
if (typeof value === 'object')
|
|
1543
|
+
if (typeof value === 'object')
|
|
1565
1544
|
return [
|
|
1566
1545
|
value.r !== undefined ? value.r : def,
|
|
1567
1546
|
value.g !== undefined ? value.g : def,
|
|
1568
1547
|
value.b !== undefined ? value.b : def,
|
|
1569
1548
|
value.a !== undefined ? value.a : def
|
|
1570
1549
|
];
|
|
1571
|
-
}
|
|
1572
1550
|
throw new Error("Invalid type: " + outputType + " or value: " + value);
|
|
1573
1551
|
}
|
|
1574
1552
|
return value;
|
|
@@ -1662,9 +1640,8 @@ var Shader = /** @class */ (function (_super) {
|
|
|
1662
1640
|
else {
|
|
1663
1641
|
// No, it's not a power of 2. Turn off mips and set
|
|
1664
1642
|
// wrapping to clamp to edge
|
|
1665
|
-
if (wrapS !== gl.CLAMP_TO_EDGE || wrapT !== gl.CLAMP_TO_EDGE)
|
|
1643
|
+
if (wrapS !== gl.CLAMP_TO_EDGE || wrapT !== gl.CLAMP_TO_EDGE)
|
|
1666
1644
|
console.warn('Wrap mode is not CLAMP_TO_EDGE for a non-power-of-two texture. Defaulting to CLAMP_TO_EDGE');
|
|
1667
|
-
}
|
|
1668
1645
|
gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
1669
1646
|
gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1670
1647
|
}
|
|
@@ -1900,6 +1877,7 @@ var Stack = /** @class */ (function (_super) {
|
|
|
1900
1877
|
function Stack(options) {
|
|
1901
1878
|
var _this = _super.call(this) || this;
|
|
1902
1879
|
_this._effectsBack = [];
|
|
1880
|
+
// TODO: Throw 'change' events in handlers
|
|
1903
1881
|
_this.effects = new Proxy(_this._effectsBack, {
|
|
1904
1882
|
deleteProperty: function (target, property) {
|
|
1905
1883
|
var value = target[property];
|
|
@@ -1910,9 +1888,8 @@ var Stack = /** @class */ (function (_super) {
|
|
|
1910
1888
|
set: function (target, property, value) {
|
|
1911
1889
|
// TODO: make sure type check works
|
|
1912
1890
|
if (!isNaN(Number(property))) { // if property is a number (index)
|
|
1913
|
-
if (target[property])
|
|
1891
|
+
if (target[property])
|
|
1914
1892
|
target[property].detach(); // Detach old effect from movie
|
|
1915
|
-
}
|
|
1916
1893
|
value.attach(this._target); // Attach effect to movie
|
|
1917
1894
|
}
|
|
1918
1895
|
target[property] = value;
|
|
@@ -1921,6 +1898,7 @@ var Stack = /** @class */ (function (_super) {
|
|
|
1921
1898
|
});
|
|
1922
1899
|
options.effects.forEach(function (effect) { return _this.effects.push(effect); });
|
|
1923
1900
|
return _this;
|
|
1901
|
+
// TODO: Propogate 'change' events from children up
|
|
1924
1902
|
}
|
|
1925
1903
|
Stack.prototype.attach = function (movie) {
|
|
1926
1904
|
_super.prototype.attach.call(this, movie);
|
|
@@ -2001,10 +1979,9 @@ var GaussianBlurComponent = /** @class */ (function (_super) {
|
|
|
2001
1979
|
}
|
|
2002
1980
|
GaussianBlurComponent.prototype.apply = function (target, reltime) {
|
|
2003
1981
|
var radiusVal = val(this, 'radius', reltime);
|
|
2004
|
-
if (radiusVal !== this._radiusCache)
|
|
1982
|
+
if (radiusVal !== this._radiusCache)
|
|
2005
1983
|
// Regenerate gaussian distribution canvas.
|
|
2006
1984
|
this.shape = GaussianBlurComponent._render1DKernel(GaussianBlurComponent._gen1DKernel(radiusVal));
|
|
2007
|
-
}
|
|
2008
1985
|
this._radiusCache = radiusVal;
|
|
2009
1986
|
_super.prototype.apply.call(this, target, reltime);
|
|
2010
1987
|
};
|
|
@@ -2037,27 +2014,23 @@ var GaussianBlurComponent = /** @class */ (function (_super) {
|
|
|
2037
2014
|
var pascal = GaussianBlurComponent._genPascalRow(2 * radius + 1);
|
|
2038
2015
|
// don't use `reduce` and `map` (overhead?)
|
|
2039
2016
|
var sum = 0;
|
|
2040
|
-
for (var i = 0; i < pascal.length; i++)
|
|
2017
|
+
for (var i = 0; i < pascal.length; i++)
|
|
2041
2018
|
sum += pascal[i];
|
|
2042
|
-
|
|
2043
|
-
for (var i = 0; i < pascal.length; i++) {
|
|
2019
|
+
for (var i = 0; i < pascal.length; i++)
|
|
2044
2020
|
pascal[i] /= sum;
|
|
2045
|
-
}
|
|
2046
2021
|
return pascal;
|
|
2047
2022
|
};
|
|
2048
2023
|
GaussianBlurComponent._genPascalRow = function (index) {
|
|
2049
|
-
if (index < 0)
|
|
2024
|
+
if (index < 0)
|
|
2050
2025
|
throw new Error("Invalid index " + index);
|
|
2051
|
-
}
|
|
2052
2026
|
var currRow = [1];
|
|
2053
2027
|
for (var i = 1; i < index; i++) {
|
|
2054
2028
|
var nextRow = [];
|
|
2055
2029
|
nextRow.length = currRow.length + 1;
|
|
2056
2030
|
// edges are always 1's
|
|
2057
2031
|
nextRow[0] = nextRow[nextRow.length - 1] = 1;
|
|
2058
|
-
for (var j = 1; j < nextRow.length - 1; j++)
|
|
2032
|
+
for (var j = 1; j < nextRow.length - 1; j++)
|
|
2059
2033
|
nextRow[j] = currRow[j - 1] + currRow[j];
|
|
2060
|
-
}
|
|
2061
2034
|
currRow = nextRow;
|
|
2062
2035
|
}
|
|
2063
2036
|
return currRow;
|
|
@@ -2135,9 +2108,8 @@ var Pixelate = /** @class */ (function (_super) {
|
|
|
2135
2108
|
}
|
|
2136
2109
|
Pixelate.prototype.apply = function (target, reltime) {
|
|
2137
2110
|
var ps = val(this, 'pixelSize', reltime);
|
|
2138
|
-
if (ps % 1 !== 0 || ps < 0)
|
|
2111
|
+
if (ps % 1 !== 0 || ps < 0)
|
|
2139
2112
|
throw new Error('Pixel size must be a nonnegative integer');
|
|
2140
|
-
}
|
|
2141
2113
|
_super.prototype.apply.call(this, target, reltime);
|
|
2142
2114
|
};
|
|
2143
2115
|
return Pixelate;
|
|
@@ -2166,12 +2138,10 @@ var Transform = /** @class */ (function (_super) {
|
|
|
2166
2138
|
return _this;
|
|
2167
2139
|
}
|
|
2168
2140
|
Transform.prototype.apply = function (target, reltime) {
|
|
2169
|
-
if (target.canvas.width !== this._tmpCanvas.width)
|
|
2141
|
+
if (target.canvas.width !== this._tmpCanvas.width)
|
|
2170
2142
|
this._tmpCanvas.width = target.canvas.width;
|
|
2171
|
-
|
|
2172
|
-
if (target.canvas.height !== this._tmpCanvas.height) {
|
|
2143
|
+
if (target.canvas.height !== this._tmpCanvas.height)
|
|
2173
2144
|
this._tmpCanvas.height = target.canvas.height;
|
|
2174
|
-
}
|
|
2175
2145
|
// Use data, since that's the underlying storage
|
|
2176
2146
|
this._tmpMatrix.data = val(this, 'matrix.data', reltime);
|
|
2177
2147
|
this._tmpCtx.setTransform(this._tmpMatrix.a, this._tmpMatrix.b, this._tmpMatrix.c, this._tmpMatrix.d, this._tmpMatrix.e, this._tmpMatrix.f);
|
|
@@ -2197,9 +2167,8 @@ var Transform = /** @class */ (function (_super) {
|
|
|
2197
2167
|
];
|
|
2198
2168
|
}
|
|
2199
2169
|
Matrix.prototype.identity = function () {
|
|
2200
|
-
for (var i = 0; i < this.data.length; i++)
|
|
2170
|
+
for (var i = 0; i < this.data.length; i++)
|
|
2201
2171
|
this.data[i] = Matrix.IDENTITY.data[i];
|
|
2202
|
-
}
|
|
2203
2172
|
return this;
|
|
2204
2173
|
};
|
|
2205
2174
|
/**
|
|
@@ -2208,9 +2177,8 @@ var Transform = /** @class */ (function (_super) {
|
|
|
2208
2177
|
* @param [val]
|
|
2209
2178
|
*/
|
|
2210
2179
|
Matrix.prototype.cell = function (x, y, val) {
|
|
2211
|
-
if (val !== undefined)
|
|
2180
|
+
if (val !== undefined)
|
|
2212
2181
|
this.data[3 * y + x] = val;
|
|
2213
|
-
}
|
|
2214
2182
|
return this.data[3 * y + x];
|
|
2215
2183
|
};
|
|
2216
2184
|
Object.defineProperty(Matrix.prototype, "a", {
|
|
@@ -2262,19 +2230,16 @@ var Transform = /** @class */ (function (_super) {
|
|
|
2262
2230
|
*/
|
|
2263
2231
|
Matrix.prototype.multiply = function (other) {
|
|
2264
2232
|
// copy to temporary matrix to avoid modifying `this` while reading from it
|
|
2265
|
-
for (var x = 0; x < 3; x++)
|
|
2233
|
+
for (var x = 0; x < 3; x++)
|
|
2266
2234
|
for (var y = 0; y < 3; y++) {
|
|
2267
2235
|
var sum = 0;
|
|
2268
|
-
for (var i = 0; i < 3; i++)
|
|
2236
|
+
for (var i = 0; i < 3; i++)
|
|
2269
2237
|
sum += this.cell(x, i) * other.cell(i, y);
|
|
2270
|
-
}
|
|
2271
2238
|
Matrix._TMP_MATRIX.cell(x, y, sum);
|
|
2272
2239
|
}
|
|
2273
|
-
}
|
|
2274
2240
|
// copy data from TMP_MATRIX to this
|
|
2275
|
-
for (var i = 0; i < Matrix._TMP_MATRIX.data.length; i++)
|
|
2241
|
+
for (var i = 0; i < Matrix._TMP_MATRIX.data.length; i++)
|
|
2276
2242
|
this.data[i] = Matrix._TMP_MATRIX.data[i];
|
|
2277
|
-
}
|
|
2278
2243
|
return this;
|
|
2279
2244
|
};
|
|
2280
2245
|
/**
|
|
@@ -8804,7 +8769,7 @@ var Movie = /** @class */ (function () {
|
|
|
8804
8769
|
// Refresh screen when effect is removed, if the movie isn't playing
|
|
8805
8770
|
// already.
|
|
8806
8771
|
var value = target[property];
|
|
8807
|
-
value.
|
|
8772
|
+
value.tryDetach();
|
|
8808
8773
|
delete target[property];
|
|
8809
8774
|
publish(that, 'movie.change.effect.remove', { effect: value });
|
|
8810
8775
|
return true;
|
|
@@ -8816,10 +8781,10 @@ var Movie = /** @class */ (function () {
|
|
|
8816
8781
|
publish(that, 'movie.change.effect.remove', {
|
|
8817
8782
|
effect: target[property]
|
|
8818
8783
|
});
|
|
8819
|
-
target[property].
|
|
8784
|
+
target[property].tryDetach();
|
|
8820
8785
|
}
|
|
8821
8786
|
// Attach effect to movie
|
|
8822
|
-
value.
|
|
8787
|
+
value.tryAttach(that);
|
|
8823
8788
|
target[property] = value;
|
|
8824
8789
|
// Refresh screen when effect is set, if the movie isn't playing
|
|
8825
8790
|
// already.
|
|
@@ -8836,12 +8801,11 @@ var Movie = /** @class */ (function () {
|
|
|
8836
8801
|
deleteProperty: function (target, property) {
|
|
8837
8802
|
var oldDuration = this.duration;
|
|
8838
8803
|
var value = target[property];
|
|
8839
|
-
value.
|
|
8804
|
+
value.tryDetach(that);
|
|
8840
8805
|
delete target[property];
|
|
8841
8806
|
var current = that.currentTime >= value.startTime && that.currentTime < value.startTime + value.duration;
|
|
8842
|
-
if (current)
|
|
8807
|
+
if (current)
|
|
8843
8808
|
publish(that, 'movie.change.layer.remove', { layer: value });
|
|
8844
|
-
}
|
|
8845
8809
|
publish(that, 'movie.change.duration', { oldDuration: oldDuration });
|
|
8846
8810
|
return true;
|
|
8847
8811
|
},
|
|
@@ -8853,16 +8817,15 @@ var Movie = /** @class */ (function () {
|
|
|
8853
8817
|
publish(that, 'movie.change.layer.remove', {
|
|
8854
8818
|
layer: target[property]
|
|
8855
8819
|
});
|
|
8856
|
-
target[property].
|
|
8820
|
+
target[property].tryDetach();
|
|
8857
8821
|
}
|
|
8858
8822
|
// Attach layer to movie
|
|
8859
|
-
value.
|
|
8823
|
+
value.tryAttach(that);
|
|
8860
8824
|
target[property] = value;
|
|
8861
8825
|
// Refresh screen when a relevant layer is added or removed
|
|
8862
8826
|
var current = that.currentTime >= value.startTime && that.currentTime < value.startTime + value.duration;
|
|
8863
|
-
if (current)
|
|
8827
|
+
if (current)
|
|
8864
8828
|
publish(that, 'movie.change.layer.add', { layer: value });
|
|
8865
|
-
}
|
|
8866
8829
|
publish(that, 'movie.change.duration', { oldDuration: oldDuration });
|
|
8867
8830
|
}
|
|
8868
8831
|
else {
|
|
@@ -8886,14 +8849,12 @@ var Movie = /** @class */ (function () {
|
|
|
8886
8849
|
this._lastPlayedOffset = -1;
|
|
8887
8850
|
// newThis._updateInterval = 0.1; // time in seconds between each "timeupdate" event
|
|
8888
8851
|
// newThis._lastUpdate = -1;
|
|
8889
|
-
if (newThis.autoRefresh)
|
|
8852
|
+
if (newThis.autoRefresh)
|
|
8890
8853
|
newThis.refresh(); // render single frame on creation
|
|
8891
|
-
}
|
|
8892
8854
|
// Subscribe to own event "change" (child events propogate up)
|
|
8893
8855
|
subscribe(newThis, 'movie.change', function () {
|
|
8894
|
-
if (newThis.autoRefresh && !newThis.rendering)
|
|
8856
|
+
if (newThis.autoRefresh && !newThis.rendering)
|
|
8895
8857
|
newThis.refresh();
|
|
8896
|
-
}
|
|
8897
8858
|
});
|
|
8898
8859
|
// Subscribe to own event "ended"
|
|
8899
8860
|
subscribe(newThis, 'movie.recordended', function () {
|
|
@@ -8911,16 +8872,14 @@ var Movie = /** @class */ (function () {
|
|
|
8911
8872
|
Movie.prototype.play = function () {
|
|
8912
8873
|
var _this = this;
|
|
8913
8874
|
return new Promise(function (resolve) {
|
|
8914
|
-
if (!_this.paused)
|
|
8875
|
+
if (!_this.paused)
|
|
8915
8876
|
throw new Error('Already playing');
|
|
8916
|
-
}
|
|
8917
8877
|
_this._paused = _this._ended = false;
|
|
8918
8878
|
_this._lastPlayed = performance.now();
|
|
8919
8879
|
_this._lastPlayedOffset = _this.currentTime;
|
|
8920
|
-
if (!_this.renderingFrame)
|
|
8880
|
+
if (!_this.renderingFrame)
|
|
8921
8881
|
// Not rendering (and not playing), so play.
|
|
8922
8882
|
_this._render(true, undefined, resolve);
|
|
8923
|
-
}
|
|
8924
8883
|
// Stop rendering frame if currently doing so, because playing has higher
|
|
8925
8884
|
// priority. This will effect the next _render call.
|
|
8926
8885
|
_this._renderingFrame = false;
|
|
@@ -8944,12 +8903,10 @@ var Movie = /** @class */ (function () {
|
|
|
8944
8903
|
// TODO: improve recording performance to increase frame rate?
|
|
8945
8904
|
Movie.prototype.record = function (options) {
|
|
8946
8905
|
var _this = this;
|
|
8947
|
-
if (options.video === false && options.audio === false)
|
|
8906
|
+
if (options.video === false && options.audio === false)
|
|
8948
8907
|
throw new Error('Both video and audio cannot be disabled');
|
|
8949
|
-
|
|
8950
|
-
if (!this.paused) {
|
|
8908
|
+
if (!this.paused)
|
|
8951
8909
|
throw new Error('Cannot record movie while already playing or recording');
|
|
8952
|
-
}
|
|
8953
8910
|
return new Promise(function (resolve, reject) {
|
|
8954
8911
|
var canvasCache = _this.canvas;
|
|
8955
8912
|
// Record on a temporary canvas context
|
|
@@ -8980,9 +8937,8 @@ var Movie = /** @class */ (function () {
|
|
|
8980
8937
|
var mediaRecorder = new MediaRecorder(stream, options.mediaRecorderOptions);
|
|
8981
8938
|
mediaRecorder.ondataavailable = function (event) {
|
|
8982
8939
|
// if (this._paused) reject(new Error("Recording was interrupted"));
|
|
8983
|
-
if (event.data.size > 0)
|
|
8940
|
+
if (event.data.size > 0)
|
|
8984
8941
|
recordedChunks.push(event.data);
|
|
8985
|
-
}
|
|
8986
8942
|
};
|
|
8987
8943
|
// TODO: publish to movie, not layers
|
|
8988
8944
|
mediaRecorder.onstop = function () {
|
|
@@ -9041,17 +8997,15 @@ var Movie = /** @class */ (function () {
|
|
|
9041
8997
|
if (!this.rendering) {
|
|
9042
8998
|
// (!this.paused || this._renderingFrame) is true so it's playing or it's
|
|
9043
8999
|
// rendering a single frame.
|
|
9044
|
-
if (done)
|
|
9000
|
+
if (done)
|
|
9045
9001
|
done();
|
|
9046
|
-
}
|
|
9047
9002
|
return;
|
|
9048
9003
|
}
|
|
9049
9004
|
this._updateCurrentTime(timestamp);
|
|
9050
9005
|
var recordingEnd = this.recording ? this._recordEndTime : this.duration;
|
|
9051
9006
|
var recordingEnded = this.currentTime > recordingEnd;
|
|
9052
|
-
if (recordingEnded)
|
|
9007
|
+
if (recordingEnded)
|
|
9053
9008
|
publish(this, 'movie.recordended', { movie: this });
|
|
9054
|
-
}
|
|
9055
9009
|
// Bad for performance? (remember, it's calling Array.reduce)
|
|
9056
9010
|
var end = this.duration;
|
|
9057
9011
|
var ended = this.currentTime > end;
|
|
@@ -9070,9 +9024,8 @@ var Movie = /** @class */ (function () {
|
|
|
9070
9024
|
var layer = this.layers[i];
|
|
9071
9025
|
// A layer that has been deleted before layers.length has been updated
|
|
9072
9026
|
// (see the layers proxy in the constructor).
|
|
9073
|
-
if (!layer)
|
|
9027
|
+
if (!layer)
|
|
9074
9028
|
continue;
|
|
9075
|
-
}
|
|
9076
9029
|
layer.stop();
|
|
9077
9030
|
layer.active = false;
|
|
9078
9031
|
}
|
|
@@ -9080,27 +9033,24 @@ var Movie = /** @class */ (function () {
|
|
|
9080
9033
|
}
|
|
9081
9034
|
// Stop playback or recording if done
|
|
9082
9035
|
if (recordingEnded || (ended && !this.repeat)) {
|
|
9083
|
-
if (done)
|
|
9036
|
+
if (done)
|
|
9084
9037
|
done();
|
|
9085
|
-
}
|
|
9086
9038
|
return;
|
|
9087
9039
|
}
|
|
9088
9040
|
// Do render
|
|
9089
9041
|
this._renderBackground(timestamp);
|
|
9090
9042
|
var frameFullyLoaded = this._renderLayers();
|
|
9091
9043
|
this._applyEffects();
|
|
9092
|
-
if (frameFullyLoaded)
|
|
9044
|
+
if (frameFullyLoaded)
|
|
9093
9045
|
publish(this, 'movie.loadeddata', { movie: this });
|
|
9094
|
-
}
|
|
9095
9046
|
// If didn't load in this instant, repeatedly frame-render until frame is
|
|
9096
9047
|
// loaded.
|
|
9097
9048
|
// If the expression below is false, don't publish an event, just silently
|
|
9098
9049
|
// stop render loop.
|
|
9099
9050
|
if (!repeat || (this._renderingFrame && frameFullyLoaded)) {
|
|
9100
9051
|
this._renderingFrame = false;
|
|
9101
|
-
if (done)
|
|
9052
|
+
if (done)
|
|
9102
9053
|
done();
|
|
9103
|
-
}
|
|
9104
9054
|
return;
|
|
9105
9055
|
}
|
|
9106
9056
|
window.requestAnimationFrame(function (timestamp) {
|
|
@@ -9138,9 +9088,8 @@ var Movie = /** @class */ (function () {
|
|
|
9138
9088
|
var layer = this.layers[i];
|
|
9139
9089
|
// A layer that has been deleted before layers.length has been updated
|
|
9140
9090
|
// (see the layers proxy in the constructor).
|
|
9141
|
-
if (!layer)
|
|
9091
|
+
if (!layer)
|
|
9142
9092
|
continue;
|
|
9143
|
-
}
|
|
9144
9093
|
var reltime = this.currentTime - layer.startTime;
|
|
9145
9094
|
// Cancel operation if layer disabled or outside layer time interval
|
|
9146
9095
|
if (!val(layer, 'enabled', reltime) ||
|
|
@@ -9162,18 +9111,16 @@ var Movie = /** @class */ (function () {
|
|
|
9162
9111
|
layer.active = true;
|
|
9163
9112
|
}
|
|
9164
9113
|
// if the layer has an input file
|
|
9165
|
-
if ('source' in layer)
|
|
9114
|
+
if ('source' in layer)
|
|
9166
9115
|
frameFullyLoaded = frameFullyLoaded && layer.source.readyState >= 2;
|
|
9167
|
-
}
|
|
9168
9116
|
layer.render();
|
|
9169
9117
|
// if the layer has visual component
|
|
9170
9118
|
if (layer instanceof Visual) {
|
|
9171
9119
|
var canvas = layer.canvas;
|
|
9172
9120
|
// layer.canvas.width and layer.canvas.height should already be interpolated
|
|
9173
9121
|
// if the layer has an area (else InvalidStateError from canvas)
|
|
9174
|
-
if (canvas.width * canvas.height > 0)
|
|
9122
|
+
if (canvas.width * canvas.height > 0)
|
|
9175
9123
|
this.cctx.drawImage(canvas, val(layer, 'x', reltime), val(layer, 'y', reltime), canvas.width, canvas.height);
|
|
9176
|
-
}
|
|
9177
9124
|
}
|
|
9178
9125
|
}
|
|
9179
9126
|
return frameFullyLoaded;
|
|
@@ -9183,9 +9130,8 @@ var Movie = /** @class */ (function () {
|
|
|
9183
9130
|
var effect = this.effects[i];
|
|
9184
9131
|
// An effect that has been deleted before effects.length has been updated
|
|
9185
9132
|
// (see the effectsproxy in the constructor).
|
|
9186
|
-
if (!effect)
|
|
9133
|
+
if (!effect)
|
|
9187
9134
|
continue;
|
|
9188
|
-
}
|
|
9189
9135
|
effect.apply(this, this.currentTime);
|
|
9190
9136
|
}
|
|
9191
9137
|
};
|
|
@@ -9204,9 +9150,8 @@ var Movie = /** @class */ (function () {
|
|
|
9204
9150
|
* Convienence method
|
|
9205
9151
|
*/
|
|
9206
9152
|
Movie.prototype._publishToLayers = function (type, event) {
|
|
9207
|
-
for (var i = 0; i < this.layers.length; i++)
|
|
9153
|
+
for (var i = 0; i < this.layers.length; i++)
|
|
9208
9154
|
publish(this.layers[i], type, event);
|
|
9209
|
-
}
|
|
9210
9155
|
};
|
|
9211
9156
|
Object.defineProperty(Movie.prototype, "rendering", {
|
|
9212
9157
|
/**
|
|
@@ -9319,13 +9264,11 @@ var Movie = /** @class */ (function () {
|
|
|
9319
9264
|
return new Promise(function (resolve, reject) {
|
|
9320
9265
|
_this._currentTime = time;
|
|
9321
9266
|
publish(_this, 'movie.seek', {});
|
|
9322
|
-
if (refresh)
|
|
9267
|
+
if (refresh)
|
|
9323
9268
|
// Pass promise callbacks to `refresh`
|
|
9324
9269
|
_this.refresh().then(resolve).catch(reject);
|
|
9325
|
-
|
|
9326
|
-
else {
|
|
9270
|
+
else
|
|
9327
9271
|
resolve();
|
|
9328
|
-
}
|
|
9329
9272
|
});
|
|
9330
9273
|
};
|
|
9331
9274
|
Object.defineProperty(Movie.prototype, "canvas", {
|