Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions src/BitmapSkin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const twgl = require('twgl.js');

const Skin = require('./Skin');

class BitmapSkin extends Skin {
/**
* Create a new Bitmap Skin.
* @param {!int} id - The ID for this Skin.
* @param {!RenderWebGL} renderer - The renderer which will use this skin.
*/
constructor (id, renderer) {
super(id);

/** @type {!int} */
this._costumeResolution = 1;

/** @type {!RenderWebGL} */
this._renderer = renderer;

/** @type {WebGLTexture} */
this._texture = null;

/** @type {[int, int]} */
this._textureSize = [0, 0];
}

/**
* Dispose of this object. Do not use it after calling this method.
*/
dispose () {
if (this._texture) {
this._renderer.gl.deleteTexture(this._texture);
this._texture = null;
}
super.dispose();
}

/**
* @return {[number,number]} the "native" size, in texels, of this skin.
*/
get size () {
return [this._textureSize[0] / this._costumeResolution, this._textureSize[1] / this._costumeResolution];
}

/**
* @param {[number,number]} scale - The scaling factors to be used.
* @return {WebGLTexture} The GL texture representation of this skin when drawing at the given scale.
*/
// eslint-disable-next-line no-unused-vars
getTexture (scale) {
return this._texture;
}

/**
* Set the contents of this skin to a snapshot of the provided bitmap data.
* @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} bitmapData - new contents for this skin.
* @param {int} [costumeResolution=1] - The resolution to use for this bitmap.
*/
setBitmap (bitmapData, costumeResolution) {
const gl = this._renderer.gl;

if (this._texture) {
gl.bindTexture(gl.TEXTURE_2D, this._texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmapData);
} else {
const textureOptions = {
auto: true,
mag: gl.NEAREST,
min: gl.NEAREST, // TODO: mipmaps, linear (except pixelate)
wrap: gl.CLAMP_TO_EDGE,
src: bitmapData
};

this._texture = twgl.createTexture(gl, textureOptions);
}

// Do these last in case any of the above throws an exception
this._costumeResolution = costumeResolution || 1;
this._textureSize = BitmapSkin._getBitmapSize(bitmapData);

this.emit(Skin.Events.WasAltered);
}

/**
* @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} bitmapData - bitmap data to inspect.
* @returns {[int,int]} the width and height of the bitmap data, in pixels.
* @private
*/
static _getBitmapSize (bitmapData) {
if (bitmapData instanceof HTMLImageElement) {
return [bitmapData.naturalWidth || bitmapData.width, bitmapData.naturalHeight || bitmapData.height];
}

if (bitmapData instanceof HTMLVideoElement) {
return [bitmapData.videoWidth || bitmapData.width, bitmapData.videoHeight || bitmapData.height];
}

// ImageData or HTMLCanvasElement
return [bitmapData.width, bitmapData.height];
}
}

module.exports = BitmapSkin;
Loading