UNPKG

4.3 kBJavaScriptView Raw
1const twgl = require('twgl.js');
2
3const Skin = require('./Skin');
4
5class BitmapSkin extends Skin {
6 /**
7 * Create a new Bitmap Skin.
8 * @extends Skin
9 * @param {!int} id - The ID for this Skin.
10 * @param {!RenderWebGL} renderer - The renderer which will use this skin.
11 */
12 constructor (id, renderer) {
13 super(id);
14
15 /** @type {!int} */
16 this._costumeResolution = 1;
17
18 /** @type {!RenderWebGL} */
19 this._renderer = renderer;
20
21 /** @type {Array<int>} */
22 this._textureSize = [0, 0];
23 }
24
25 /**
26 * Dispose of this object. Do not use it after calling this method.
27 */
28 dispose () {
29 if (this._texture) {
30 this._renderer.gl.deleteTexture(this._texture);
31 this._texture = null;
32 }
33 super.dispose();
34 }
35
36 /**
37 * @returns {boolean} true for a raster-style skin (like a BitmapSkin), false for vector-style (like SVGSkin).
38 */
39 get isRaster () {
40 return true;
41 }
42
43 /**
44 * @return {Array<number>} the "native" size, in texels, of this skin.
45 */
46 get size () {
47 return [this._textureSize[0] / this._costumeResolution, this._textureSize[1] / this._costumeResolution];
48 }
49
50 /**
51 * @param {Array<number>} scale - The scaling factors to be used.
52 * @return {WebGLTexture} The GL texture representation of this skin when drawing at the given scale.
53 */
54 // eslint-disable-next-line no-unused-vars
55 getTexture (scale) {
56 return this._texture || super.getTexture();
57 }
58
59 /**
60 * Set the contents of this skin to a snapshot of the provided bitmap data.
61 * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} bitmapData - new contents for this skin.
62 * @param {int} [costumeResolution=1] - The resolution to use for this bitmap.
63 * @param {Array<number>} [rotationCenter] - Optional rotation center for the bitmap. If not supplied, it will be
64 * calculated from the bounding box
65 * @fires Skin.event:WasAltered
66 */
67 setBitmap (bitmapData, costumeResolution, rotationCenter) {
68 if (!bitmapData.width || !bitmapData.height) {
69 super.setEmptyImageData();
70 return;
71 }
72 const gl = this._renderer.gl;
73
74 // Preferably bitmapData is ImageData. ImageData speeds up updating
75 // Silhouette and is better handled by more browsers in regards to
76 // memory.
77 let textureData = bitmapData;
78 if (bitmapData instanceof HTMLCanvasElement) {
79 // Given a HTMLCanvasElement get the image data to pass to webgl and
80 // Silhouette.
81 const context = bitmapData.getContext('2d');
82 textureData = context.getImageData(0, 0, bitmapData.width, bitmapData.height);
83 }
84
85 if (this._texture === null) {
86 const textureOptions = {
87 auto: false,
88 wrap: gl.CLAMP_TO_EDGE
89 };
90
91 this._texture = twgl.createTexture(gl, textureOptions);
92 }
93
94 this._setTexture(textureData);
95
96 // Do these last in case any of the above throws an exception
97 this._costumeResolution = costumeResolution || 2;
98 this._textureSize = BitmapSkin._getBitmapSize(bitmapData);
99
100 if (typeof rotationCenter === 'undefined') rotationCenter = this.calculateRotationCenter();
101 this._rotationCenter[0] = rotationCenter[0];
102 this._rotationCenter[1] = rotationCenter[1];
103
104 this.emit(Skin.Events.WasAltered);
105 }
106
107 /**
108 * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} bitmapData - bitmap data to inspect.
109 * @returns {Array<int>} the width and height of the bitmap data, in pixels.
110 * @private
111 */
112 static _getBitmapSize (bitmapData) {
113 if (bitmapData instanceof HTMLImageElement) {
114 return [bitmapData.naturalWidth || bitmapData.width, bitmapData.naturalHeight || bitmapData.height];
115 }
116
117 if (bitmapData instanceof HTMLVideoElement) {
118 return [bitmapData.videoWidth || bitmapData.width, bitmapData.videoHeight || bitmapData.height];
119 }
120
121 // ImageData or HTMLCanvasElement
122 return [bitmapData.width, bitmapData.height];
123 }
124
125}
126
127module.exports = BitmapSkin;