@next2d/media 1.14.20

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/dist/Video.js ADDED
@@ -0,0 +1,855 @@
1
+ import { SoundMixer } from "./SoundMixer";
2
+ import { DisplayObject } from "@next2d/display";
3
+ import { VideoEvent } from "@next2d/events";
4
+ import { Rectangle } from "@next2d/geom";
5
+ import { $document, $audioContext, $currentPlayer, $isTouch, $rendererWorker } from "@next2d/util";
6
+ import { $Math, $cancelAnimationFrame, $requestAnimationFrame, $getBoundsObject, $boundsMatrix, $clamp, $multiplicationMatrix, $poolFloat32Array6, $MATRIX_ARRAY_IDENTITY, $OffscreenCanvas, $multiplicationColor, $poolFloat32Array8, $Infinity, $poolBoundsObject, $getFloat32Array6, $getArray, $poolArray } from "@next2d/share";
7
+ /**
8
+ * サーバーまたはローカルに保存された録画済みビデオファイルを再生する Video オブジェクトです。
9
+ * ビデオストリームを再生するには、attachNetStream() を使用して、ビデオを Video オブジェクトに関連付けます。
10
+ * 次に、addChild() を使用して、Video オブジェクトを表示リストに追加します。
11
+ *
12
+ * A Video object that plays a recorded video file stored on a server or locally.
13
+ * To play a video stream, use attachNetStream() to attach the video to the Video object.
14
+ * Then, add the Video object to the display list using addChild().
15
+ *
16
+ * @class
17
+ * @memberOf next2d.media
18
+ * @extends DisplayObject
19
+ */
20
+ export class Video extends DisplayObject {
21
+ /**
22
+ * @param {number} [width = 0]
23
+ * @param {number} [height = 0]
24
+ *
25
+ * @constructor
26
+ * @public
27
+ */
28
+ constructor(width = 0, height = 0) {
29
+ super();
30
+ /**
31
+ * @type {boolean}
32
+ * @default true
33
+ * @private
34
+ */
35
+ this._$smoothing = true;
36
+ /**
37
+ * @type {boolean}
38
+ * @default false
39
+ * @private
40
+ */
41
+ this._$loop = false;
42
+ /**
43
+ * @type {boolean}
44
+ * @default true
45
+ * @private
46
+ */
47
+ this._$autoPlay = true;
48
+ /**
49
+ * @type {object}
50
+ * @private
51
+ */
52
+ this._$bounds = $getBoundsObject(0, width, 0, height);
53
+ /**
54
+ * @type {number}
55
+ * @default 0
56
+ * @private
57
+ */
58
+ this._$bytesLoaded = 0;
59
+ /**
60
+ * @type {number}
61
+ * @default 0
62
+ * @private
63
+ */
64
+ this._$bytesTotal = 0;
65
+ /**
66
+ * @type {number}
67
+ * @default -1
68
+ * @private
69
+ */
70
+ this._$timerId = -1;
71
+ /**
72
+ * @type {HTMLVideoElement}
73
+ * @default null
74
+ * @private
75
+ */
76
+ this._$video = null;
77
+ /**
78
+ * @type {boolean}
79
+ * @default true
80
+ * @private
81
+ */
82
+ this._$stop = true;
83
+ /**
84
+ * @type {boolean}
85
+ * @default false
86
+ * @private
87
+ */
88
+ this._$ready = false;
89
+ /**
90
+ * @type {number}
91
+ * @default 1
92
+ * @private
93
+ */
94
+ this._$volume = 1;
95
+ /**
96
+ * @type {CanvasRenderingContext2D}
97
+ * @default null
98
+ * @private
99
+ */
100
+ this._$context = null;
101
+ }
102
+ /**
103
+ * @description 指定されたクラスのストリングを返します。
104
+ * Returns the string representation of the specified class.
105
+ *
106
+ * @return {string}
107
+ * @default [class Video]
108
+ * @method
109
+ * @static
110
+ */
111
+ static toString() {
112
+ return "[class Video]";
113
+ }
114
+ /**
115
+ * @description 指定されたクラスの空間名を返します。
116
+ * Returns the space name of the specified class.
117
+ *
118
+ * @return {string}
119
+ * @default next2d.media.Video
120
+ * @const
121
+ * @static
122
+ */
123
+ static get namespace() {
124
+ return "next2d.media.Video";
125
+ }
126
+ /**
127
+ * @description 指定されたオブジェクトのストリングを返します。
128
+ * Returns the string representation of the specified object.
129
+ *
130
+ * @return {string}
131
+ * @default [object Video]
132
+ * @method
133
+ * @public
134
+ */
135
+ toString() {
136
+ return "[object Video]";
137
+ }
138
+ /**
139
+ * @description 指定されたオブジェクトの空間名を返します。
140
+ * Returns the space name of the specified object.
141
+ *
142
+ * @return {string}
143
+ * @default next2d.media.Video
144
+ * @const
145
+ * @public
146
+ */
147
+ get namespace() {
148
+ return "next2d.media.Video";
149
+ }
150
+ /**
151
+ * @description 既にアプリケーションにロードされているデータのバイト数です。
152
+ * The number of bytes of data that have been loaded into the application.
153
+ *
154
+ * @member {number}
155
+ * @default 0
156
+ * @readonly
157
+ * @public
158
+ */
159
+ get bytesLoaded() {
160
+ return this._$bytesLoaded;
161
+ }
162
+ /**
163
+ * @description アプリケーションにロードされるファイルの総バイト数。
164
+ * The total size in bytes of the file being loaded into the application.
165
+ *
166
+ * @member {number}
167
+ * @default 0
168
+ * @readonly
169
+ * @public
170
+ */
171
+ get bytesTotal() {
172
+ return this._$bytesTotal;
173
+ }
174
+ /**
175
+ * @description 現在のキーフレーム
176
+ * Current keyframe
177
+ *
178
+ *
179
+ * @member {number}
180
+ * @readonly
181
+ * @public
182
+ */
183
+ get currentTime() {
184
+ return this._$video ? this._$video.currentTime : 0;
185
+ }
186
+ /**
187
+ * @description キーフレーム総数
188
+ * Total number of keyframes
189
+ *
190
+ * @member {number}
191
+ * @readonly
192
+ * @public
193
+ */
194
+ get duration() {
195
+ return this._$video ? this._$video.duration : 0;
196
+ }
197
+ /**
198
+ * @description ビデオをループ生成するかどうかを指定します。
199
+ * Specifies whether to generate a video loop.
200
+ *
201
+ * @member {boolean}
202
+ * @default false
203
+ * @public
204
+ */
205
+ get loop() {
206
+ return this._$loop;
207
+ }
208
+ set loop(loop) {
209
+ this._$loop = !!loop;
210
+ }
211
+ /**
212
+ * @description ビデオの自動再生の設定。
213
+ * Setting up automatic video playback.
214
+ *
215
+ * @member {boolean}
216
+ * @default true
217
+ * @public
218
+ */
219
+ get autoPlay() {
220
+ return this._$autoPlay;
221
+ }
222
+ set autoPlay(auto_play) {
223
+ this._$autoPlay = !!auto_play;
224
+ }
225
+ /**
226
+ * @description ビデオを拡大 / 縮小する際にスムージング(補間)するかどうかを指定します。
227
+ * Specifies whether the video should be smoothed (interpolated)
228
+ * when it is scaled.
229
+ *
230
+ * @member {boolean}
231
+ * @default true
232
+ * @public
233
+ */
234
+ get smoothing() {
235
+ return this._$smoothing;
236
+ }
237
+ set smoothing(smoothing) {
238
+ this._$smoothing = !!smoothing;
239
+ }
240
+ /**
241
+ * @description 映像コンテンツへの URL を指定します。
242
+ * Specifies the URL to the video content.
243
+ *
244
+ * @member {string}
245
+ * @default ""
246
+ * @public
247
+ */
248
+ get src() {
249
+ return this._$video ? this._$video.src : "";
250
+ }
251
+ set src(src) {
252
+ if (!this._$video) {
253
+ this._$video = this._$initializeVideo();
254
+ }
255
+ this._$video.src = src;
256
+ this._$video.load();
257
+ }
258
+ /**
259
+ * @description ビデオストリームの高さをピクセル単位で指定する整数です。
260
+ * An integer specifying the height of the video stream, in pixels.
261
+ *
262
+ * @member {number}
263
+ * @default 320
264
+ * @readonly
265
+ * @public
266
+ */
267
+ get videoHeight() {
268
+ return this._$video ? this._$video.videoHeight : this._$bounds.yMax;
269
+ }
270
+ /**
271
+ * @description ビデオストリームの幅をピクセル単位で指定する整数です。
272
+ * An integer specifying the width of the video stream, in pixels.
273
+ *
274
+ * @member {number}
275
+ * @default 240
276
+ * @readonly
277
+ * @public
278
+ */
279
+ get videoWidth() {
280
+ return this._$video ? this._$video.videoWidth : this._$bounds.xMax;
281
+ }
282
+ /**
283
+ * @description ボリュームです。範囲は 0(無音)~ 1(フルボリューム)です。
284
+ * The volume, ranging from 0 (silent) to 1 (full volume).
285
+ *
286
+ * @member {number}
287
+ * @default 1
288
+ * @public
289
+ */
290
+ get volume() {
291
+ return this._$volume;
292
+ }
293
+ set volume(volume) {
294
+ this._$volume = $clamp($Math.min(SoundMixer.volume, volume), 0, 1, 1);
295
+ if (this._$video) {
296
+ this._$video.volume = this._$volume;
297
+ }
298
+ }
299
+ /**
300
+ * @description Video オブジェクトに現在表示されているイメージ(ビデオストリームではない)をクリアします。
301
+ * Clears the image currently displayed
302
+ * in the Video object (not the video stream).
303
+ *
304
+ * @return {void}
305
+ * @method
306
+ * @public
307
+ */
308
+ clear() {
309
+ if (this._$video) {
310
+ this._$video.pause();
311
+ }
312
+ // reset
313
+ this._$video = null;
314
+ this._$bounds.xMax = 0;
315
+ this._$bounds.yMax = 0;
316
+ this._$doChanged();
317
+ }
318
+ /**
319
+ * @description ビデオストリームの再生を一時停止します。
320
+ * Pauses playback of a video stream.
321
+ *
322
+ * @return {void}
323
+ * @method
324
+ * @public
325
+ */
326
+ pause() {
327
+ if (this._$video && !this._$stop) {
328
+ this._$stop = true;
329
+ this._$video.pause();
330
+ $cancelAnimationFrame(this._$timerId);
331
+ this._$timerId = -1;
332
+ if (this.hasEventListener(VideoEvent.PAUSE)) {
333
+ this.dispatchEvent(new VideoEvent(VideoEvent.PAUSE, false, false, this._$bytesLoaded, this._$bytesTotal));
334
+ }
335
+ const player = $currentPlayer();
336
+ player._$videos.splice(player._$videos.indexOf(this), 1);
337
+ }
338
+ }
339
+ /**
340
+ * @description ローカルディレクトリまたは Web サーバーからメディアファイルを再生します。
341
+ * Plays a media file from a local directory or a web server;
342
+ *
343
+ * @returns {void}
344
+ * @method
345
+ * @public
346
+ */
347
+ play() {
348
+ if (this._$video && this._$stop) {
349
+ this._$stop = false;
350
+ this._$video.volume = $Math.min(this._$volume, SoundMixer.volume);
351
+ this
352
+ ._$video
353
+ .play()
354
+ .then(() => {
355
+ this._$timerId = $requestAnimationFrame(() => {
356
+ this._$update();
357
+ });
358
+ if (this.hasEventListener(VideoEvent.PLAY)) {
359
+ this.dispatchEvent(new VideoEvent(VideoEvent.PLAY, false, false, this._$bytesLoaded, this._$bytesTotal));
360
+ }
361
+ const player = $currentPlayer();
362
+ if (player._$videos.indexOf(this) === -1) {
363
+ player._$videos.push(this);
364
+ }
365
+ this._$ready = true;
366
+ });
367
+ }
368
+ }
369
+ /**
370
+ * @description 指定された位置に最も近いキーフレームをシークします。
371
+ * Seeks the keyframe closest to the specified location.
372
+ *
373
+ * @param {number} offset
374
+ * @return {void}
375
+ * @method
376
+ * @public
377
+ */
378
+ seek(offset) {
379
+ if (this._$video) {
380
+ this._$video.currentTime = offset;
381
+ if (this.hasEventListener(VideoEvent.SEEK)) {
382
+ this.dispatchEvent(new VideoEvent(VideoEvent.SEEK, false, false, this._$bytesLoaded, this._$bytesTotal));
383
+ }
384
+ }
385
+ }
386
+ /**
387
+ * @return {void}
388
+ * @method
389
+ * @private
390
+ */
391
+ _$update() {
392
+ const player = $currentPlayer();
393
+ if (!this.stage || !this._$video) {
394
+ if (this._$video) {
395
+ this._$video.pause();
396
+ }
397
+ $cancelAnimationFrame(this._$timerId);
398
+ this._$timerId = -1;
399
+ player._$videos.splice(player._$videos.indexOf(this), 1);
400
+ return;
401
+ }
402
+ if ($rendererWorker) {
403
+ this._$postProperty();
404
+ }
405
+ // update
406
+ this._$bytesLoaded = this._$video.currentTime;
407
+ if (this._$video.currentTime) {
408
+ if (this.hasEventListener(VideoEvent.PROGRESS)) {
409
+ this.dispatchEvent(new VideoEvent(VideoEvent.PROGRESS, false, false, this._$bytesLoaded, this._$bytesTotal));
410
+ }
411
+ this._$doChanged();
412
+ }
413
+ this._$timerId = $requestAnimationFrame(() => {
414
+ this._$update();
415
+ });
416
+ }
417
+ /**
418
+ * @return {void}
419
+ * @method
420
+ * @private
421
+ */
422
+ _$start() {
423
+ if (!this._$video) {
424
+ return;
425
+ }
426
+ this._$bounds.xMax = this._$video.videoWidth;
427
+ this._$bounds.yMax = this._$video.videoHeight;
428
+ this._$bytesTotal = this._$video.duration;
429
+ const player = $currentPlayer();
430
+ if (this._$autoPlay) {
431
+ this._$stop = false;
432
+ this
433
+ ._$video
434
+ .play()
435
+ .then(() => {
436
+ if (player._$videos.indexOf(this) === -1) {
437
+ player._$videos.push(this);
438
+ }
439
+ if (this.hasEventListener(VideoEvent.PLAY_START)) {
440
+ this.dispatchEvent(new VideoEvent(VideoEvent.PLAY_START, false, false, this._$bytesLoaded, this._$bytesTotal));
441
+ }
442
+ this._$timerId = $requestAnimationFrame(() => {
443
+ this._$update();
444
+ });
445
+ this._$ready = true;
446
+ this._$doChanged();
447
+ });
448
+ }
449
+ this._$createContext();
450
+ }
451
+ /**
452
+ * @return {HTMLVideoElement}
453
+ * @method
454
+ * @private
455
+ */
456
+ _$initializeVideo() {
457
+ const video = $document.createElement("video");
458
+ video.autoplay = false;
459
+ video.crossOrigin = "anonymous";
460
+ if (!$audioContext) {
461
+ video.muted = true;
462
+ }
463
+ if ($isTouch) {
464
+ video.setAttribute("playsinline", "");
465
+ }
466
+ video.addEventListener("canplaythrough", () => {
467
+ this._$start();
468
+ });
469
+ video.addEventListener("ended", () => {
470
+ if (this._$loop) {
471
+ video.currentTime = 0;
472
+ return;
473
+ }
474
+ if (this.hasEventListener(VideoEvent.PLAY_END)) {
475
+ this.dispatchEvent(new VideoEvent(VideoEvent.PLAY_END, false, false, this._$bytesLoaded, this._$bytesTotal));
476
+ }
477
+ $cancelAnimationFrame(this._$timerId);
478
+ this._$timerId = -1;
479
+ });
480
+ return video;
481
+ }
482
+ /**
483
+ * @return {void}
484
+ * @method
485
+ * @private
486
+ */
487
+ _$createContext() {
488
+ if ($rendererWorker) {
489
+ const canvas = new $OffscreenCanvas(this._$bounds.xMax, this._$bounds.yMax);
490
+ this._$context = canvas.getContext("2d");
491
+ }
492
+ }
493
+ /**
494
+ * @param {object} character
495
+ * @return {void}
496
+ * @method
497
+ * @private
498
+ */
499
+ _$buildCharacter(character) {
500
+ if (character.buffer && !character._$buffer) {
501
+ character._$buffer = new Uint8Array(character.buffer);
502
+ character.buffer = null;
503
+ }
504
+ this._$loop = character.loop;
505
+ this._$autoPlay = character.autoPlay;
506
+ this._$bounds.xMin = character.bounds.xMin;
507
+ this._$bounds.yMin = character.bounds.yMin;
508
+ this._$bounds.xMax = character.bounds.xMax;
509
+ this._$bounds.yMax = character.bounds.yMax;
510
+ if (!this._$video) {
511
+ this._$video = this._$initializeVideo();
512
+ }
513
+ this._$video.src = URL.createObjectURL(new Blob([character._$buffer], { "type": "video/mp4" }));
514
+ // setup
515
+ this._$video.volume = $Math.min(character.volume, SoundMixer.volume);
516
+ this._$video.load();
517
+ if ($rendererWorker && this._$stage) {
518
+ this._$createWorkerInstance();
519
+ }
520
+ }
521
+ /**
522
+ * @param {object} character
523
+ * @return {void}
524
+ * @method
525
+ * @private
526
+ */
527
+ _$sync(character) {
528
+ this._$buildCharacter(character);
529
+ }
530
+ /**
531
+ * @param {object} tag
532
+ * @param {DisplayObjectContainer} parent
533
+ * @return {object}
534
+ * @method
535
+ * @private
536
+ */
537
+ _$build(tag, parent) {
538
+ const character = this._$baseBuild(tag, parent);
539
+ this._$buildCharacter(character);
540
+ return character;
541
+ }
542
+ /**
543
+ * @param {CanvasToWebGLContext} context
544
+ * @param {Float32Array} matrix
545
+ * @returns {void}
546
+ * @method
547
+ * @private
548
+ */
549
+ _$clip(context, matrix) {
550
+ const width = this._$bounds.xMax;
551
+ const height = this._$bounds.yMax;
552
+ if (!width || !height) {
553
+ return;
554
+ }
555
+ let multiMatrix = matrix;
556
+ const rawMatrix = this._$transform._$rawMatrix();
557
+ if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
558
+ || rawMatrix[2] !== 0 || rawMatrix[3] !== 1
559
+ || rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
560
+ multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
561
+ }
562
+ context.reset();
563
+ context.setTransform(multiMatrix[0], multiMatrix[1], multiMatrix[2], multiMatrix[3], multiMatrix[4], multiMatrix[5]);
564
+ context.beginPath();
565
+ context.moveTo(0, 0);
566
+ context.lineTo(width, 0);
567
+ context.lineTo(width, height);
568
+ context.lineTo(0, height);
569
+ context.lineTo(0, 0);
570
+ context.clip();
571
+ if (multiMatrix !== matrix) {
572
+ $poolFloat32Array6(multiMatrix);
573
+ }
574
+ }
575
+ /**
576
+ * @param {CanvasToWebGLContext} context
577
+ * @param {Float32Array} matrix
578
+ * @param {Float32Array} color_transform
579
+ * @return {void}
580
+ * @method
581
+ * @private
582
+ */
583
+ _$draw(context, matrix, color_transform) {
584
+ if (!this._$visible || !this._$video || !this._$ready) {
585
+ return;
586
+ }
587
+ let multiColor = color_transform;
588
+ const rawColor = this._$transform._$rawColorTransform();
589
+ if (rawColor[0] !== 1 || rawColor[1] !== 1
590
+ || rawColor[2] !== 1 || rawColor[3] !== 1
591
+ || rawColor[4] !== 0 || rawColor[5] !== 0
592
+ || rawColor[6] !== 0 || rawColor[7] !== 0) {
593
+ multiColor = $multiplicationColor(color_transform, rawColor);
594
+ }
595
+ const alpha = $clamp(multiColor[3] + multiColor[7] / 255, 0, 1, 0);
596
+ if (!alpha) {
597
+ if (multiColor !== color_transform) {
598
+ $poolFloat32Array8(multiColor);
599
+ }
600
+ return;
601
+ }
602
+ let multiMatrix = matrix;
603
+ const rawMatrix = this._$transform._$rawMatrix();
604
+ if (rawMatrix[0] !== 1 || rawMatrix[1] !== 0
605
+ || rawMatrix[2] !== 0 || rawMatrix[3] !== 1
606
+ || rawMatrix[4] !== 0 || rawMatrix[5] !== 0) {
607
+ multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
608
+ }
609
+ // default bounds
610
+ const bounds = $boundsMatrix(this._$bounds, multiMatrix);
611
+ const xMax = +bounds.xMax;
612
+ const xMin = +bounds.xMin;
613
+ const yMax = +bounds.yMax;
614
+ const yMin = +bounds.yMin;
615
+ $poolBoundsObject(bounds);
616
+ const width = $Math.ceil($Math.abs(xMax - xMin));
617
+ const height = $Math.ceil($Math.abs(yMax - yMin));
618
+ switch (true) {
619
+ case width === 0:
620
+ case height === 0:
621
+ case width === -$Infinity:
622
+ case height === -$Infinity:
623
+ case width === $Infinity:
624
+ case height === $Infinity:
625
+ return;
626
+ default:
627
+ break;
628
+ }
629
+ // cache current buffer
630
+ const manager = context.frameBuffer;
631
+ const currentAttachment = manager.currentAttachment;
632
+ if (!currentAttachment
633
+ || xMin > currentAttachment.width
634
+ || yMin > currentAttachment.height) {
635
+ return;
636
+ }
637
+ const filters = this._$filters || this.filters;
638
+ if (0 > xMin + width || 0 > yMin + height) {
639
+ if (filters && filters.length && this._$canApply(filters)) {
640
+ const xScale = +$Math.sqrt(multiMatrix[0] * multiMatrix[0]
641
+ + multiMatrix[1] * multiMatrix[1]);
642
+ const yScale = +$Math.sqrt(multiMatrix[2] * multiMatrix[2]
643
+ + multiMatrix[3] * multiMatrix[3]);
644
+ let rect = new Rectangle(0, 0, width, height);
645
+ for (let idx = 0; idx < filters.length; ++idx) {
646
+ // @ts-ignore
647
+ rect = filters[idx]._$generateFilterRect(rect, xScale, yScale);
648
+ }
649
+ if (0 > rect.x + rect.width || 0 > rect.y + rect.height) {
650
+ return;
651
+ }
652
+ }
653
+ else {
654
+ return;
655
+ }
656
+ }
657
+ const blendMode = this._$blendMode || this.blendMode;
658
+ let texture = manager.createTextureFromVideo(this._$video, this._$smoothing);
659
+ if (filters && filters.length
660
+ && this._$canApply(filters)) {
661
+ const xScale = +$Math.sqrt(multiMatrix[0] * multiMatrix[0]
662
+ + multiMatrix[1] * multiMatrix[1]);
663
+ const yScale = +$Math.sqrt(multiMatrix[2] * multiMatrix[2]
664
+ + multiMatrix[3] * multiMatrix[3]);
665
+ if (xScale !== 1 || yScale !== 1) {
666
+ const currentAttachment = manager.currentAttachment;
667
+ // create cache buffer
668
+ const attachment = manager
669
+ .createCacheAttachment(width, height, false);
670
+ context._$bind(attachment);
671
+ const parentMatrix = $getFloat32Array6(xScale, 0, 0, yScale, width / 2, height / 2);
672
+ const baseMatrix = $getFloat32Array6(1, 0, 0, 1, -texture.width / 2, -texture.height / 2);
673
+ const scaleMatrix = $multiplicationMatrix(parentMatrix, baseMatrix);
674
+ $poolFloat32Array6(parentMatrix);
675
+ $poolFloat32Array6(baseMatrix);
676
+ context.reset();
677
+ context.setTransform(scaleMatrix[0], scaleMatrix[1], scaleMatrix[2], scaleMatrix[3], scaleMatrix[4], scaleMatrix[5]);
678
+ context.drawImage(texture, 0, 0, texture.width, texture.height);
679
+ manager.releaseTexture(texture);
680
+ $poolFloat32Array6(scaleMatrix);
681
+ texture = manager.getTextureFromCurrentAttachment();
682
+ // release buffer
683
+ manager.releaseAttachment(attachment, false);
684
+ // end draw and reset current buffer
685
+ context._$bind(currentAttachment);
686
+ }
687
+ // draw filter
688
+ texture = this._$drawFilter(context, texture, multiMatrix, filters, width, height);
689
+ // reset
690
+ context.reset();
691
+ // draw
692
+ context.globalAlpha = alpha;
693
+ context.imageSmoothingEnabled = this._$smoothing;
694
+ context.globalCompositeOperation = blendMode;
695
+ // size
696
+ const bounds = $boundsMatrix(this._$bounds, multiMatrix);
697
+ context.setTransform(1, 0, 0, 1, bounds.xMin - texture._$offsetX, bounds.yMin - texture._$offsetY);
698
+ context.drawImage(texture, 0, 0, texture.width, texture.height, multiColor);
699
+ // pool
700
+ $poolBoundsObject(bounds);
701
+ }
702
+ else {
703
+ // reset
704
+ context.reset();
705
+ context.setTransform(multiMatrix[0], multiMatrix[1], multiMatrix[2], multiMatrix[3], multiMatrix[4], multiMatrix[5]);
706
+ // draw
707
+ context.globalAlpha = alpha;
708
+ context.imageSmoothingEnabled = this._$smoothing;
709
+ context.globalCompositeOperation = blendMode;
710
+ context.drawImage(texture, 0, 0, texture.width, texture.height, multiColor);
711
+ manager.releaseTexture(texture);
712
+ }
713
+ if (multiMatrix !== matrix) {
714
+ $poolFloat32Array6(multiMatrix);
715
+ }
716
+ if (multiColor !== color_transform) {
717
+ $poolFloat32Array8(multiColor);
718
+ }
719
+ }
720
+ /**
721
+ * @param {CanvasRenderingContext2D} context
722
+ * @param {Float32Array} matrix
723
+ * @param {object} options
724
+ * @return {boolean}
725
+ * @method
726
+ * @private
727
+ */
728
+ _$mouseHit(context, matrix, options) {
729
+ if (!this._$visible) {
730
+ return false;
731
+ }
732
+ return this._$hit(context, matrix, options);
733
+ }
734
+ /**
735
+ * @param {CanvasRenderingContext2D} context
736
+ * @param {array} matrix
737
+ * @param {object} options
738
+ * @return {boolean}
739
+ * @method
740
+ * @private
741
+ */
742
+ _$hit(context, matrix, options) {
743
+ let multiMatrix = matrix;
744
+ const rawMatrix = this._$transform._$rawMatrix();
745
+ if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) {
746
+ multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
747
+ }
748
+ const baseBounds = this._$getBounds(null);
749
+ const bounds = $boundsMatrix(baseBounds, multiMatrix);
750
+ const xMax = +bounds.xMax;
751
+ const xMin = +bounds.xMin;
752
+ const yMax = +bounds.yMax;
753
+ const yMin = +bounds.yMin;
754
+ $poolBoundsObject(bounds);
755
+ $poolBoundsObject(baseBounds);
756
+ const width = $Math.ceil($Math.abs(xMax - xMin));
757
+ const height = $Math.ceil($Math.abs(yMax - yMin));
758
+ context.setTransform(1, 0, 0, 1, xMin, yMin);
759
+ context.beginPath();
760
+ context.moveTo(0, 0);
761
+ context.lineTo(width, 0);
762
+ context.lineTo(width, height);
763
+ context.lineTo(0, height);
764
+ context.lineTo(0, 0);
765
+ if (multiMatrix !== matrix) {
766
+ $poolFloat32Array6(multiMatrix);
767
+ }
768
+ return context.isPointInPath(options.x, options.y);
769
+ }
770
+ /**
771
+ * @param {Float32Array} [matrix=null]
772
+ * @return {object}
773
+ * @method
774
+ * @private
775
+ */
776
+ _$getBounds(matrix = null) {
777
+ if (matrix) {
778
+ let multiMatrix = matrix;
779
+ const rawMatrix = this._$transform._$rawMatrix();
780
+ if (rawMatrix !== $MATRIX_ARRAY_IDENTITY) {
781
+ multiMatrix = $multiplicationMatrix(matrix, rawMatrix);
782
+ }
783
+ const bounds = $boundsMatrix(this._$bounds, multiMatrix);
784
+ if (multiMatrix !== matrix) {
785
+ $poolFloat32Array6(multiMatrix);
786
+ }
787
+ return bounds;
788
+ }
789
+ return $getBoundsObject(this._$bounds.xMin, this._$bounds.xMax, this._$bounds.yMin, this._$bounds.yMax);
790
+ }
791
+ /**
792
+ * @return {void}
793
+ * @method
794
+ * @private
795
+ */
796
+ _$createWorkerInstance() {
797
+ if (!$rendererWorker || this._$created) {
798
+ return;
799
+ }
800
+ this._$created = true;
801
+ const message = {
802
+ "command": "createVideo",
803
+ "instanceId": this._$instanceId,
804
+ "parentId": this._$parent ? this._$parent._$instanceId : -1,
805
+ "smoothing": this._$smoothing,
806
+ "xMin": this._$bounds.xMin,
807
+ "yMin": this._$bounds.yMin,
808
+ "xMax": this._$bounds.xMax,
809
+ "yMax": this._$bounds.yMax
810
+ };
811
+ if (this._$characterId > -1) {
812
+ message.characterId = this._$characterId;
813
+ }
814
+ if (this._$loaderInfo) {
815
+ message.loaderInfoId = this._$loaderInfo._$id;
816
+ }
817
+ if (this._$scale9Grid) {
818
+ message.grid = {
819
+ "x": this._$scale9Grid.x,
820
+ "y": this._$scale9Grid.y,
821
+ "w": this._$scale9Grid.width,
822
+ "h": this._$scale9Grid.height
823
+ };
824
+ }
825
+ $rendererWorker.postMessage(message);
826
+ }
827
+ /**
828
+ * @return {void}
829
+ * @method
830
+ * @private
831
+ */
832
+ _$postProperty() {
833
+ if (!$rendererWorker) {
834
+ return;
835
+ }
836
+ const message = this._$createMessage();
837
+ message.smoothing = this._$smoothing;
838
+ const options = $getArray();
839
+ const context = this._$context;
840
+ if (context && this._$video) {
841
+ message.xMin = this._$bounds.xMin;
842
+ message.yMin = this._$bounds.yMin;
843
+ message.xMax = this._$bounds.xMax;
844
+ message.yMax = this._$bounds.yMax;
845
+ context.drawImage(this._$video, 0, 0);
846
+ const imageBitmap = context.canvas.transferToImageBitmap();
847
+ message.imageBitmap = imageBitmap;
848
+ options.push(imageBitmap);
849
+ }
850
+ $rendererWorker.postMessage(message, options);
851
+ $poolArray(options);
852
+ this._$posted = true;
853
+ this._$updated = false;
854
+ }
855
+ }