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