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
|
@@ -70,22 +70,22 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
70
70
|
|
|
71
71
|
const load = () => {
|
|
72
72
|
// TODO: && ?
|
|
73
|
-
if ((options.duration || (this.source.duration - this.sourceStartTime)) < 0)
|
|
73
|
+
if ((options.duration || (this.source.duration - this.sourceStartTime)) < 0)
|
|
74
74
|
throw new Error('Invalid options.duration or options.sourceStartTime')
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
this._unstretchedDuration = options.duration || (this.source.duration - this.sourceStartTime)
|
|
77
77
|
this.duration = this._unstretchedDuration / (this.playbackRate)
|
|
78
78
|
// onload will use `this`, and can't bind itself because it's before
|
|
79
79
|
// super()
|
|
80
80
|
onload && onload.bind(this)(this.source, options)
|
|
81
81
|
}
|
|
82
|
-
if (this.source.readyState >= 2)
|
|
82
|
+
if (this.source.readyState >= 2)
|
|
83
83
|
// this frame's data is available now
|
|
84
84
|
load()
|
|
85
|
-
|
|
85
|
+
else
|
|
86
86
|
// when this frame's data is available
|
|
87
87
|
this.source.addEventListener('loadedmetadata', load)
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
this.source.addEventListener('durationchange', () => {
|
|
90
90
|
this.duration = options.duration || (this.source.duration - this.sourceStartTime)
|
|
91
91
|
})
|
|
@@ -95,11 +95,10 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
95
95
|
super.attach(movie)
|
|
96
96
|
|
|
97
97
|
subscribe(movie, 'movie.seek', () => {
|
|
98
|
-
|
|
99
|
-
if (time < this.startTime || time >= this.startTime + this.duration) {
|
|
98
|
+
if (this.currentTime < 0 || this.currentTime >= this.duration)
|
|
100
99
|
return
|
|
101
|
-
|
|
102
|
-
this.source.currentTime =
|
|
100
|
+
|
|
101
|
+
this.source.currentTime = this.currentTime + this.sourceStartTime
|
|
103
102
|
})
|
|
104
103
|
|
|
105
104
|
// TODO: on unattach?
|
|
@@ -113,7 +112,7 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
113
112
|
})
|
|
114
113
|
|
|
115
114
|
// connect to audiocontext
|
|
116
|
-
this._audioNode = movie.actx.createMediaElementSource(this.source)
|
|
115
|
+
this._audioNode = this.audioNode || movie.actx.createMediaElementSource(this.source)
|
|
117
116
|
|
|
118
117
|
// Spy on connect and disconnect to remember if it connected to
|
|
119
118
|
// actx.destination (for Movie#record).
|
|
@@ -125,9 +124,9 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
125
124
|
const oldDisconnect = this._audioNode.disconnect.bind(this.audioNode)
|
|
126
125
|
this._audioNode.disconnect = <T extends IAudioDestinationNode<AudioContext>>(destination?: T | number, output?: number, input?: number): AudioNode => {
|
|
127
126
|
if (this._connectedToDestination &&
|
|
128
|
-
destination === movie.actx.destination)
|
|
127
|
+
destination === movie.actx.destination)
|
|
129
128
|
this._connectedToDestination = false
|
|
130
|
-
|
|
129
|
+
|
|
131
130
|
return oldDisconnect(destination, output, input)
|
|
132
131
|
}
|
|
133
132
|
|
|
@@ -135,6 +134,10 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
135
134
|
this.audioNode.connect(movie.actx.destination)
|
|
136
135
|
}
|
|
137
136
|
|
|
137
|
+
detach () {
|
|
138
|
+
this.audioNode.disconnect(this.movie.actx.destination)
|
|
139
|
+
}
|
|
140
|
+
|
|
138
141
|
start () {
|
|
139
142
|
this.source.currentTime = this.currentTime + this.sourceStartTime
|
|
140
143
|
this.source.play()
|
|
@@ -166,9 +169,8 @@ function AudioSourceMixin<OptionsSuperclass extends BaseOptions> (superclass: Co
|
|
|
166
169
|
|
|
167
170
|
set playbackRate (value) {
|
|
168
171
|
this._playbackRate = value
|
|
169
|
-
if (this._unstretchedDuration !== undefined)
|
|
172
|
+
if (this._unstretchedDuration !== undefined)
|
|
170
173
|
this.duration = this._unstretchedDuration / value
|
|
171
|
-
}
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
get startTime () {
|
package/src/layer/audio.ts
CHANGED
|
@@ -14,9 +14,8 @@ class Audio extends AudioSourceMixin<BaseOptions>(Base) {
|
|
|
14
14
|
*/
|
|
15
15
|
constructor (options: AudioOptions) {
|
|
16
16
|
super(options)
|
|
17
|
-
if (this.duration === undefined)
|
|
17
|
+
if (this.duration === undefined)
|
|
18
18
|
this.duration = (this).source.duration - this.sourceStartTime
|
|
19
|
-
}
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
getDefaultOptions (): AudioOptions {
|
package/src/layer/base.ts
CHANGED
|
@@ -70,22 +70,41 @@ class Base implements EtroObject {
|
|
|
70
70
|
return newThis
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Attaches this layer to `movie` if not already attached.
|
|
75
|
+
* @ignore
|
|
76
|
+
*/
|
|
77
|
+
tryAttach (movie: Movie): void {
|
|
78
|
+
if (this._occurrenceCount === 0)
|
|
79
|
+
this.attach(movie)
|
|
80
|
+
|
|
74
81
|
this._occurrenceCount++
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
attach (movie: Movie): void {
|
|
75
85
|
this._movie = movie
|
|
76
86
|
}
|
|
77
87
|
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Dettaches this layer from its movie if the number of times `tryDetach` has
|
|
90
|
+
* been called (including this call) equals the number of times `tryAttach`
|
|
91
|
+
* has been called.
|
|
92
|
+
*
|
|
93
|
+
* @ignore
|
|
94
|
+
*/
|
|
95
|
+
tryDetach (): void {
|
|
96
|
+
if (this.movie === null)
|
|
80
97
|
throw new Error('No movie to detach from')
|
|
81
|
-
}
|
|
82
98
|
|
|
83
99
|
this._occurrenceCount--
|
|
84
100
|
// If this layer occurs in another place in a `layers` array, do not unset
|
|
85
101
|
// _movie. (For calling `unshift` on the `layers` proxy)
|
|
86
|
-
if (this._occurrenceCount === 0)
|
|
87
|
-
this.
|
|
88
|
-
|
|
102
|
+
if (this._occurrenceCount === 0)
|
|
103
|
+
this.detach()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
detach (): void {
|
|
107
|
+
this._movie = null
|
|
89
108
|
}
|
|
90
109
|
|
|
91
110
|
/**
|
package/src/layer/visual.ts
CHANGED
|
@@ -68,9 +68,9 @@ class Visual extends Base {
|
|
|
68
68
|
set: (target, property, value) => {
|
|
69
69
|
if (!isNaN(Number(property))) {
|
|
70
70
|
// The property is a number (index)
|
|
71
|
-
if (target[property])
|
|
71
|
+
if (target[property])
|
|
72
72
|
target[property].detach()
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
value.attach(this)
|
|
75
75
|
}
|
|
76
76
|
target[property] = value
|
|
@@ -116,19 +116,18 @@ class Visual extends Base {
|
|
|
116
116
|
endRender (): void {
|
|
117
117
|
const w = val(this, 'width', this.currentTime) || val(this.movie, 'width', this.movie.currentTime)
|
|
118
118
|
const h = val(this, 'height', this.currentTime) || val(this.movie, 'height', this.movie.currentTime)
|
|
119
|
-
if (w * h > 0)
|
|
119
|
+
if (w * h > 0)
|
|
120
120
|
this._applyEffects()
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
// else InvalidStateError for drawing zero-area image in some effects, right?
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
_applyEffects (): void {
|
|
126
126
|
for (let i = 0; i < this.effects.length; i++) {
|
|
127
127
|
const effect = this.effects[i]
|
|
128
|
-
if (effect.enabled)
|
|
128
|
+
if (effect.enabled)
|
|
129
129
|
// Pass relative time
|
|
130
130
|
effect.apply(this, this.movie.currentTime - this.startTime)
|
|
131
|
-
}
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
|
package/src/movie.ts
CHANGED
|
@@ -95,7 +95,7 @@ export class Movie {
|
|
|
95
95
|
// Refresh screen when effect is removed, if the movie isn't playing
|
|
96
96
|
// already.
|
|
97
97
|
const value = target[property]
|
|
98
|
-
value.
|
|
98
|
+
value.tryDetach()
|
|
99
99
|
delete target[property]
|
|
100
100
|
publish(that, 'movie.change.effect.remove', { effect: value })
|
|
101
101
|
return true
|
|
@@ -107,10 +107,10 @@ export class Movie {
|
|
|
107
107
|
publish(that, 'movie.change.effect.remove', {
|
|
108
108
|
effect: target[property]
|
|
109
109
|
})
|
|
110
|
-
target[property].
|
|
110
|
+
target[property].tryDetach()
|
|
111
111
|
}
|
|
112
112
|
// Attach effect to movie
|
|
113
|
-
value.
|
|
113
|
+
value.tryAttach(that)
|
|
114
114
|
target[property] = value
|
|
115
115
|
// Refresh screen when effect is set, if the movie isn't playing
|
|
116
116
|
// already.
|
|
@@ -118,6 +118,7 @@ export class Movie {
|
|
|
118
118
|
} else {
|
|
119
119
|
target[property] = value
|
|
120
120
|
}
|
|
121
|
+
|
|
121
122
|
return true
|
|
122
123
|
}
|
|
123
124
|
})
|
|
@@ -127,12 +128,12 @@ export class Movie {
|
|
|
127
128
|
deleteProperty (target, property): boolean {
|
|
128
129
|
const oldDuration = this.duration
|
|
129
130
|
const value = target[property]
|
|
130
|
-
value.
|
|
131
|
+
value.tryDetach(that)
|
|
131
132
|
delete target[property]
|
|
132
133
|
const current = that.currentTime >= value.startTime && that.currentTime < value.startTime + value.duration
|
|
133
|
-
if (current)
|
|
134
|
+
if (current)
|
|
134
135
|
publish(that, 'movie.change.layer.remove', { layer: value })
|
|
135
|
-
|
|
136
|
+
|
|
136
137
|
publish(that, 'movie.change.duration', { oldDuration })
|
|
137
138
|
return true
|
|
138
139
|
},
|
|
@@ -144,20 +145,21 @@ export class Movie {
|
|
|
144
145
|
publish(that, 'movie.change.layer.remove', {
|
|
145
146
|
layer: target[property]
|
|
146
147
|
})
|
|
147
|
-
target[property].
|
|
148
|
+
target[property].tryDetach()
|
|
148
149
|
}
|
|
149
150
|
// Attach layer to movie
|
|
150
|
-
value.
|
|
151
|
+
value.tryAttach(that)
|
|
151
152
|
target[property] = value
|
|
152
153
|
// Refresh screen when a relevant layer is added or removed
|
|
153
154
|
const current = that.currentTime >= value.startTime && that.currentTime < value.startTime + value.duration
|
|
154
|
-
if (current)
|
|
155
|
+
if (current)
|
|
155
156
|
publish(that, 'movie.change.layer.add', { layer: value })
|
|
156
|
-
|
|
157
|
+
|
|
157
158
|
publish(that, 'movie.change.duration', { oldDuration })
|
|
158
159
|
} else {
|
|
159
160
|
target[property] = value
|
|
160
161
|
}
|
|
162
|
+
|
|
161
163
|
return true
|
|
162
164
|
}
|
|
163
165
|
})
|
|
@@ -179,15 +181,13 @@ export class Movie {
|
|
|
179
181
|
// newThis._updateInterval = 0.1; // time in seconds between each "timeupdate" event
|
|
180
182
|
// newThis._lastUpdate = -1;
|
|
181
183
|
|
|
182
|
-
if (newThis.autoRefresh)
|
|
184
|
+
if (newThis.autoRefresh)
|
|
183
185
|
newThis.refresh() // render single frame on creation
|
|
184
|
-
}
|
|
185
186
|
|
|
186
187
|
// Subscribe to own event "change" (child events propogate up)
|
|
187
188
|
subscribe(newThis, 'movie.change', () => {
|
|
188
|
-
if (newThis.autoRefresh && !newThis.rendering)
|
|
189
|
+
if (newThis.autoRefresh && !newThis.rendering)
|
|
189
190
|
newThis.refresh()
|
|
190
|
-
}
|
|
191
191
|
})
|
|
192
192
|
|
|
193
193
|
// Subscribe to own event "ended"
|
|
@@ -207,18 +207,17 @@ export class Movie {
|
|
|
207
207
|
*/
|
|
208
208
|
play (): Promise<void> {
|
|
209
209
|
return new Promise(resolve => {
|
|
210
|
-
if (!this.paused)
|
|
210
|
+
if (!this.paused)
|
|
211
211
|
throw new Error('Already playing')
|
|
212
|
-
}
|
|
213
212
|
|
|
214
213
|
this._paused = this._ended = false
|
|
215
214
|
this._lastPlayed = performance.now()
|
|
216
215
|
this._lastPlayedOffset = this.currentTime
|
|
217
216
|
|
|
218
|
-
if (!this.renderingFrame)
|
|
217
|
+
if (!this.renderingFrame)
|
|
219
218
|
// Not rendering (and not playing), so play.
|
|
220
219
|
this._render(true, undefined, resolve)
|
|
221
|
-
|
|
220
|
+
|
|
222
221
|
// Stop rendering frame if currently doing so, because playing has higher
|
|
223
222
|
// priority. This will effect the next _render call.
|
|
224
223
|
this._renderingFrame = false
|
|
@@ -250,13 +249,12 @@ export class Movie {
|
|
|
250
249
|
audio?: boolean,
|
|
251
250
|
mediaRecorderOptions?: Record<string, unknown>
|
|
252
251
|
}): Promise<Blob> {
|
|
253
|
-
if (options.video === false && options.audio === false)
|
|
252
|
+
if (options.video === false && options.audio === false)
|
|
254
253
|
throw new Error('Both video and audio cannot be disabled')
|
|
255
|
-
}
|
|
256
254
|
|
|
257
|
-
if (!this.paused)
|
|
255
|
+
if (!this.paused)
|
|
258
256
|
throw new Error('Cannot record movie while already playing or recording')
|
|
259
|
-
|
|
257
|
+
|
|
260
258
|
return new Promise((resolve, reject) => {
|
|
261
259
|
const canvasCache = this.canvas
|
|
262
260
|
// Record on a temporary canvas context
|
|
@@ -290,9 +288,8 @@ export class Movie {
|
|
|
290
288
|
const mediaRecorder = new MediaRecorder(stream, options.mediaRecorderOptions)
|
|
291
289
|
mediaRecorder.ondataavailable = event => {
|
|
292
290
|
// if (this._paused) reject(new Error("Recording was interrupted"));
|
|
293
|
-
if (event.data.size > 0)
|
|
291
|
+
if (event.data.size > 0)
|
|
294
292
|
recordedChunks.push(event.data)
|
|
295
|
-
}
|
|
296
293
|
}
|
|
297
294
|
// TODO: publish to movie, not layers
|
|
298
295
|
mediaRecorder.onstop = () => {
|
|
@@ -357,18 +354,17 @@ export class Movie {
|
|
|
357
354
|
if (!this.rendering) {
|
|
358
355
|
// (!this.paused || this._renderingFrame) is true so it's playing or it's
|
|
359
356
|
// rendering a single frame.
|
|
360
|
-
if (done)
|
|
357
|
+
if (done)
|
|
361
358
|
done()
|
|
362
|
-
|
|
359
|
+
|
|
363
360
|
return
|
|
364
361
|
}
|
|
365
362
|
|
|
366
363
|
this._updateCurrentTime(timestamp)
|
|
367
364
|
const recordingEnd = this.recording ? this._recordEndTime : this.duration
|
|
368
365
|
const recordingEnded = this.currentTime > recordingEnd
|
|
369
|
-
if (recordingEnded)
|
|
366
|
+
if (recordingEnded)
|
|
370
367
|
publish(this, 'movie.recordended', { movie: this })
|
|
371
|
-
}
|
|
372
368
|
|
|
373
369
|
// Bad for performance? (remember, it's calling Array.reduce)
|
|
374
370
|
const end = this.duration
|
|
@@ -388,9 +384,9 @@ export class Movie {
|
|
|
388
384
|
const layer = this.layers[i]
|
|
389
385
|
// A layer that has been deleted before layers.length has been updated
|
|
390
386
|
// (see the layers proxy in the constructor).
|
|
391
|
-
if (!layer)
|
|
387
|
+
if (!layer)
|
|
392
388
|
continue
|
|
393
|
-
|
|
389
|
+
|
|
394
390
|
layer.stop()
|
|
395
391
|
layer.active = false
|
|
396
392
|
}
|
|
@@ -399,9 +395,9 @@ export class Movie {
|
|
|
399
395
|
|
|
400
396
|
// Stop playback or recording if done
|
|
401
397
|
if (recordingEnded || (ended && !this.repeat)) {
|
|
402
|
-
if (done)
|
|
398
|
+
if (done)
|
|
403
399
|
done()
|
|
404
|
-
|
|
400
|
+
|
|
405
401
|
return
|
|
406
402
|
}
|
|
407
403
|
|
|
@@ -410,9 +406,8 @@ export class Movie {
|
|
|
410
406
|
const frameFullyLoaded = this._renderLayers()
|
|
411
407
|
this._applyEffects()
|
|
412
408
|
|
|
413
|
-
if (frameFullyLoaded)
|
|
409
|
+
if (frameFullyLoaded)
|
|
414
410
|
publish(this, 'movie.loadeddata', { movie: this })
|
|
415
|
-
}
|
|
416
411
|
|
|
417
412
|
// If didn't load in this instant, repeatedly frame-render until frame is
|
|
418
413
|
// loaded.
|
|
@@ -420,9 +415,9 @@ export class Movie {
|
|
|
420
415
|
// stop render loop.
|
|
421
416
|
if (!repeat || (this._renderingFrame && frameFullyLoaded)) {
|
|
422
417
|
this._renderingFrame = false
|
|
423
|
-
if (done)
|
|
418
|
+
if (done)
|
|
424
419
|
done()
|
|
425
|
-
|
|
420
|
+
|
|
426
421
|
return
|
|
427
422
|
}
|
|
428
423
|
|
|
@@ -464,9 +459,9 @@ export class Movie {
|
|
|
464
459
|
const layer = this.layers[i]
|
|
465
460
|
// A layer that has been deleted before layers.length has been updated
|
|
466
461
|
// (see the layers proxy in the constructor).
|
|
467
|
-
if (!layer)
|
|
462
|
+
if (!layer)
|
|
468
463
|
continue
|
|
469
|
-
|
|
464
|
+
|
|
470
465
|
const reltime = this.currentTime - layer.startTime
|
|
471
466
|
// Cancel operation if layer disabled or outside layer time interval
|
|
472
467
|
if (!val(layer, 'enabled', reltime) ||
|
|
@@ -489,9 +484,9 @@ export class Movie {
|
|
|
489
484
|
}
|
|
490
485
|
|
|
491
486
|
// if the layer has an input file
|
|
492
|
-
if ('source' in layer)
|
|
487
|
+
if ('source' in layer)
|
|
493
488
|
frameFullyLoaded = frameFullyLoaded && (layer as unknown as AudioSource).source.readyState >= 2
|
|
494
|
-
|
|
489
|
+
|
|
495
490
|
layer.render()
|
|
496
491
|
|
|
497
492
|
// if the layer has visual component
|
|
@@ -499,11 +494,10 @@ export class Movie {
|
|
|
499
494
|
const canvas = (layer as Visual).canvas
|
|
500
495
|
// layer.canvas.width and layer.canvas.height should already be interpolated
|
|
501
496
|
// if the layer has an area (else InvalidStateError from canvas)
|
|
502
|
-
if (canvas.width * canvas.height > 0)
|
|
497
|
+
if (canvas.width * canvas.height > 0)
|
|
503
498
|
this.cctx.drawImage(canvas,
|
|
504
499
|
val(layer, 'x', reltime), val(layer, 'y', reltime), canvas.width, canvas.height
|
|
505
500
|
)
|
|
506
|
-
}
|
|
507
501
|
}
|
|
508
502
|
}
|
|
509
503
|
|
|
@@ -515,9 +509,9 @@ export class Movie {
|
|
|
515
509
|
const effect = this.effects[i]
|
|
516
510
|
// An effect that has been deleted before effects.length has been updated
|
|
517
511
|
// (see the effectsproxy in the constructor).
|
|
518
|
-
if (!effect)
|
|
512
|
+
if (!effect)
|
|
519
513
|
continue
|
|
520
|
-
|
|
514
|
+
|
|
521
515
|
effect.apply(this, this.currentTime)
|
|
522
516
|
}
|
|
523
517
|
}
|
|
@@ -537,9 +531,8 @@ export class Movie {
|
|
|
537
531
|
* Convienence method
|
|
538
532
|
*/
|
|
539
533
|
private _publishToLayers (type, event) {
|
|
540
|
-
for (let i = 0; i < this.layers.length; i++)
|
|
534
|
+
for (let i = 0; i < this.layers.length; i++)
|
|
541
535
|
publish(this.layers[i], type, event)
|
|
542
|
-
}
|
|
543
536
|
}
|
|
544
537
|
|
|
545
538
|
/**
|
|
@@ -631,12 +624,11 @@ export class Movie {
|
|
|
631
624
|
return new Promise((resolve, reject) => {
|
|
632
625
|
this._currentTime = time
|
|
633
626
|
publish(this, 'movie.seek', {})
|
|
634
|
-
if (refresh)
|
|
627
|
+
if (refresh)
|
|
635
628
|
// Pass promise callbacks to `refresh`
|
|
636
629
|
this.refresh().then(resolve).catch(reject)
|
|
637
|
-
|
|
630
|
+
else
|
|
638
631
|
resolve()
|
|
639
|
-
}
|
|
640
632
|
})
|
|
641
633
|
}
|
|
642
634
|
|