2016-12-29 10:46:12 -08:00
|
|
|
const EventEmitter = require('events');
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
const twgl = require('twgl.js');
|
|
|
|
|
|
|
|
const RenderConstants = require('./RenderConstants');
|
2018-04-27 16:19:25 -04:00
|
|
|
const Silhouette = require('./Silhouette');
|
2016-12-28 12:17:45 -08:00
|
|
|
|
2017-11-07 17:18:23 -05:00
|
|
|
/**
|
|
|
|
* Truncate a number into what could be stored in a 32 bit floating point value.
|
|
|
|
* @param {number} num Number to truncate.
|
|
|
|
* @return {number} Truncated value.
|
|
|
|
*/
|
|
|
|
const toFloat32 = (function () {
|
|
|
|
const memory = new Float32Array(1);
|
|
|
|
return function (num) {
|
|
|
|
memory[0] = num;
|
|
|
|
return memory[0];
|
|
|
|
};
|
|
|
|
}());
|
|
|
|
|
2016-12-29 10:46:12 -08:00
|
|
|
class Skin extends EventEmitter {
|
2016-12-28 12:17:45 -08:00
|
|
|
/**
|
|
|
|
* Create a Skin, which stores and/or generates textures for use in rendering.
|
|
|
|
* @param {int} id - The unique ID for this Skin.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @constructor
|
2016-12-28 12:17:45 -08:00
|
|
|
*/
|
|
|
|
constructor (id) {
|
2016-12-29 10:46:12 -08:00
|
|
|
super();
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
/** @type {int} */
|
|
|
|
this._id = id;
|
|
|
|
|
|
|
|
/** @type {Vec3} */
|
|
|
|
this._rotationCenter = twgl.v3.create(0, 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The uniforms to be used by the vertex and pixel shaders.
|
|
|
|
* Some of these are used by other parts of the renderer as well.
|
|
|
|
* @type {Object.<string,*>}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._uniforms = {
|
|
|
|
/**
|
|
|
|
* The nominal (not necessarily current) size of the current skin.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @type {Array<number>}
|
2016-12-28 12:17:45 -08:00
|
|
|
*/
|
|
|
|
u_skinSize: [0, 0],
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The actual WebGL texture object for the skin.
|
|
|
|
* @type {WebGLTexture}
|
|
|
|
*/
|
|
|
|
u_skin: null
|
|
|
|
};
|
2016-12-29 13:42:58 -08:00
|
|
|
|
2018-04-27 16:19:25 -04:00
|
|
|
/**
|
|
|
|
* A silhouette to store touching data, skins are responsible for keeping it up to date.
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._silhouette = new Silhouette();
|
|
|
|
|
2016-12-29 13:42:58 -08:00
|
|
|
this.setMaxListeners(RenderConstants.SKIN_SHARE_SOFT_LIMIT);
|
2016-12-28 12:17:45 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dispose of this object. Do not use it after calling this method.
|
|
|
|
*/
|
|
|
|
dispose () {
|
|
|
|
this._id = RenderConstants.ID_NONE;
|
|
|
|
}
|
|
|
|
|
2017-11-29 20:51:19 -08:00
|
|
|
/**
|
|
|
|
* @returns {boolean} true for a raster-style skin (like a BitmapSkin), false for vector-style (like SVGSkin).
|
|
|
|
*/
|
|
|
|
get isRaster () {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-03 18:39:40 +01:00
|
|
|
/**
|
|
|
|
* @returns {boolean} true if alpha is premultiplied, false otherwise
|
|
|
|
*/
|
|
|
|
get hasPremultipliedAlpha () {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
/**
|
|
|
|
* @return {int} the unique ID for this Skin.
|
|
|
|
*/
|
|
|
|
get id () {
|
|
|
|
return this._id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {Vec3} the origin, in object space, about which this Skin should rotate.
|
|
|
|
*/
|
|
|
|
get rotationCenter () {
|
|
|
|
return this._rotationCenter;
|
|
|
|
}
|
|
|
|
|
2019-08-13 11:22:27 -04:00
|
|
|
/**
|
|
|
|
* @abstract
|
|
|
|
* @return {Array<number>} the "native" size, in texels, of this skin.
|
|
|
|
*/
|
|
|
|
get size () {
|
|
|
|
return [0, 0];
|
|
|
|
}
|
|
|
|
|
2016-12-28 13:53:20 -08:00
|
|
|
/**
|
|
|
|
* Set the origin, in object space, about which this Skin should rotate.
|
|
|
|
* @param {number} x - The x coordinate of the new rotation center.
|
|
|
|
* @param {number} y - The y coordinate of the new rotation center.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @fires Skin.event:WasAltered
|
2016-12-28 13:53:20 -08:00
|
|
|
*/
|
2016-12-28 12:17:45 -08:00
|
|
|
setRotationCenter (x, y) {
|
2017-08-09 23:01:09 -07:00
|
|
|
const emptySkin = this.size[0] === 0 && this.size[1] === 0;
|
2017-11-07 17:18:23 -05:00
|
|
|
// Compare a 32 bit x and y value against the stored 32 bit center
|
|
|
|
// values.
|
|
|
|
const changed = (
|
|
|
|
toFloat32(x) !== this._rotationCenter[0] ||
|
|
|
|
toFloat32(y) !== this._rotationCenter[1]);
|
2017-08-09 23:01:09 -07:00
|
|
|
if (!emptySkin && changed) {
|
2016-12-28 12:17:45 -08:00
|
|
|
this._rotationCenter[0] = x;
|
|
|
|
this._rotationCenter[1] = y;
|
2016-12-29 10:46:12 -08:00
|
|
|
this.emit(Skin.Events.WasAltered);
|
2016-12-28 12:17:45 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-13 13:10:20 -05:00
|
|
|
* Get the center of the current bounding box
|
2017-02-19 23:57:55 -05:00
|
|
|
* @return {Array<number>} the center of the current bounding box
|
2017-01-13 13:10:20 -05:00
|
|
|
*/
|
|
|
|
calculateRotationCenter () {
|
|
|
|
return [this.size[0] / 2, this.size[1] / 2];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-12-28 12:17:45 -08:00
|
|
|
* @abstract
|
2017-02-19 23:57:55 -05:00
|
|
|
* @param {Array<number>} scale - The scaling factors to be used.
|
2016-12-28 12:17:45 -08:00
|
|
|
* @return {WebGLTexture} The GL texture representation of this skin when drawing at the given size.
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
|
|
getTexture (scale) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-02-05 16:10:38 -05:00
|
|
|
/**
|
|
|
|
* Get the bounds of the drawable for determining its fenced position.
|
|
|
|
* @param {Array<number>} drawable - The Drawable instance this skin is using.
|
2019-08-13 11:41:11 -04:00
|
|
|
* @param {?Rectangle} result - Optional destination for bounds calculation.
|
2019-02-05 16:10:38 -05:00
|
|
|
* @return {!Rectangle} The drawable's bounds.
|
|
|
|
*/
|
2019-08-13 11:41:11 -04:00
|
|
|
getFenceBounds (drawable, result) {
|
|
|
|
return drawable.getFastBounds(result);
|
2019-02-05 16:10:38 -05:00
|
|
|
}
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
/**
|
|
|
|
* Update and returns the uniforms for this skin.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @param {Array<number>} scale - The scaling factors to be used.
|
2016-12-28 12:17:45 -08:00
|
|
|
* @returns {object.<string, *>} the shader uniforms to be used when rendering with this Skin.
|
|
|
|
*/
|
2016-12-28 13:53:20 -08:00
|
|
|
getUniforms (scale) {
|
|
|
|
this._uniforms.u_skin = this.getTexture(scale);
|
2016-12-28 12:17:45 -08:00
|
|
|
this._uniforms.u_skinSize = this.size;
|
|
|
|
return this._uniforms;
|
|
|
|
}
|
2017-11-15 17:29:32 -05:00
|
|
|
|
2018-04-27 16:19:25 -04:00
|
|
|
/**
|
|
|
|
* If the skin defers silhouette operations until the last possible minute,
|
|
|
|
* this will be called before isTouching uses the silhouette.
|
|
|
|
* @abstract
|
|
|
|
*/
|
|
|
|
updateSilhouette () {}
|
|
|
|
|
2017-11-15 17:29:32 -05:00
|
|
|
/**
|
|
|
|
* Does this point touch an opaque or translucent point on this skin?
|
2018-04-27 16:19:25 -04:00
|
|
|
* Nearest Neighbor version
|
2017-11-15 17:29:32 -05:00
|
|
|
* @param {twgl.v3} vec A texture coordinate.
|
|
|
|
* @return {boolean} Did it touch?
|
|
|
|
*/
|
2018-04-27 16:19:25 -04:00
|
|
|
isTouchingNearest (vec) {
|
|
|
|
return this._silhouette.isTouchingNearest(vec);
|
2017-11-15 17:29:32 -05:00
|
|
|
}
|
2018-04-27 16:19:25 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Does this point touch an opaque or translucent point on this skin?
|
|
|
|
* Linear Interpolation version
|
|
|
|
* @param {twgl.v3} vec A texture coordinate.
|
|
|
|
* @return {boolean} Did it touch?
|
|
|
|
*/
|
|
|
|
isTouchingLinear (vec) {
|
|
|
|
return this._silhouette.isTouchingLinear(vec);
|
|
|
|
}
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
}
|
|
|
|
|
2016-12-29 10:46:12 -08:00
|
|
|
/**
|
|
|
|
* These are the events which can be emitted by instances of this class.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @enum {string}
|
2016-12-29 10:46:12 -08:00
|
|
|
*/
|
|
|
|
Skin.Events = {
|
|
|
|
/**
|
|
|
|
* Emitted when anything about the Skin has been altered, such as the appearance or rotation center.
|
2017-02-19 23:57:55 -05:00
|
|
|
* @event Skin.event:WasAltered
|
2016-12-29 10:46:12 -08:00
|
|
|
*/
|
|
|
|
WasAltered: 'WasAltered'
|
|
|
|
};
|
|
|
|
|
2016-12-28 12:17:45 -08:00
|
|
|
module.exports = Skin;
|