/** * @author Richard Davey * @copyright 2018 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var Class = require('../utils/Class'); var Frame = require('./Frame'); var TextureSource = require('./TextureSource'); /** * @classdesc * A Texture consists of a source, usually an Image from the Cache, or a Canvas, and a collection * of Frames. The Frames represent the different areas of the Texture. For example a texture atlas * may have many Frames, one for each element within the atlas. Where-as a single image would have * just one frame, that encompasses the whole image. * * Textures are managed by the global TextureManager. This is a singleton class that is * responsible for creating and delivering Textures and their corresponding Frames to Game Objects. * * Sprites and other Game Objects get the texture data they need from the TextureManager. * * @class Texture * @memberOf Phaser.Textures * @constructor * @since 3.0.0 * * @param {Phaser.Textures.TextureManager} manager - A reference to the Texture Manager this Texture belongs to. * @param {string} key - The unique string-based key of this Texture. * @param {Image|HTMLCanvasElement} source - The source that is used to create the texture. Usually an Image, but can also be a Canvas. * @param {number} [width] - The width of the Texture. This is optional and automatically derived from the source images. * @param {number} [height] - The height of the Texture. This is optional and automatically derived from the source images. */ var Texture = new Class({ initialize: function Texture (manager, key, source, width, height) { if (!Array.isArray(source)) { source = [ source ]; } /** * A reference to the Texture Manager this Texture belongs to. * * @name Phaser.Textures.Texture#manager * @type {Phaser.Textures.TextureManager} * @since 3.0.0 */ this.manager = manager; /** * The unique string-based key of this Texture. * * @name Phaser.Textures.Texture#key * @type {string} * @since 3.0.0 */ this.key = key; /** * An array of TextureSource instances. * These are unique to this Texture and contain the actual Image (or Canvas) data. * * @name Phaser.Textures.Texture#source * @type {Phaser.Textures.TextureSource[]} * @since 3.0.0 */ this.source = []; /** * An array of TextureSource data instances. * Used to store additional data images, such as normal maps or specular maps. * * @name Phaser.Textures.Texture#dataSource * @type {array} * @since 3.0.0 */ this.dataSource = []; /** * A key-value object pair associating the unique Frame keys with the Frames objects. * * @name Phaser.Textures.Texture#frames * @type {object} * @since 3.0.0 */ this.frames = {}; /** * Any additional data that was set in the source JSON (if any), * or any extra data you'd like to store relating to this texture * * @name Phaser.Textures.Texture#customData * @type {object} * @since 3.0.0 */ this.customData = {}; /** * The name of the first frame of the Texture. * * @name Phaser.Textures.Texture#firstFrame * @type {string} * @since 3.0.0 */ this.firstFrame = '__BASE'; /** * The total number of Frames in this Texture. * * @name Phaser.Textures.Texture#frameTotal * @type {integer} * @default 0 * @since 3.0.0 */ this.frameTotal = 0; // Load the Sources for (var i = 0; i < source.length; i++) { this.source.push(new TextureSource(this, source[i], width, height)); } }, /** * Adds a new Frame to this Texture. * * A Frame is a rectangular region of a TextureSource with a unique index or string-based key. * * @method Phaser.Textures.Texture#add * @since 3.0.0 * * @param {integer|string} name - The name of this Frame. The name is unique within the Texture. * @param {integer} sourceIndex - The index of the TextureSource that this Frame is a part of. * @param {number} x - The x coordinate of the top-left of this Frame. * @param {number} y - The y coordinate of the top-left of this Frame. * @param {number} width - The width of this Frame. * @param {number} height - The height of this Frame. * * @return {Phaser.Textures.Frame} The Frame that was added to this Texture. */ add: function (name, sourceIndex, x, y, width, height) { var frame = new Frame(this, name, sourceIndex, x, y, width, height); this.frames[name] = frame; // Set the first frame of the Texture (other than __BASE) // This is used to ensure we don't spam the display with entire // atlases of sprite sheets, but instead just the first frame of them // should the dev incorrectly specify the frame index if (this.frameTotal === 1) { this.firstFrame = name; } this.frameTotal++; return frame; }, /** * Checks to see if a Frame matching the given key exists within this Texture. * * @method Phaser.Textures.Texture#has * @since 3.0.0 * * @param {string} name - The key of the Frame to check for. * * @return {boolean} True if a Frame with the matching key exists in this Texture. */ has: function (name) { return (this.frames[name]); }, /** * Gets a Frame from this Texture based on either the key or the index of the Frame. * * In a Texture Atlas Frames are typically referenced by a key. * In a Sprite Sheet Frames are referenced by an index. * Passing no value for the name returns the base texture. * * @method Phaser.Textures.Texture#get * @since 3.0.0 * * @param {string|integer} [name] - The string-based name, or integer based index, of the Frame to get from this Texture. * * @return {Phaser.Textures.Frame} The Texture Frame. */ get: function (name) { // null, undefined, empty string, zero if (!name) { name = this.firstFrame; } var frame = this.frames[name]; if (!frame) { console.warn('No Texture.frame found with name ' + name); frame = this.frames[this.firstFrame]; } return frame; }, /** * Takes the given TextureSource and returns the index of it within this Texture. * If it's not in this Texture, it returns -1. * Unless this Texture has multiple TextureSources, such as with a multi-atlas, this * method will always return zero or -1. * * @method Phaser.Textures.Texture#getTextureSourceIndex * @since 3.0.0 * * @param {Phaser.Textures.TextureSource} source - The TextureSource to check. * * @return {integer} The index of the TextureSource within this Texture, or -1 if not in this Texture. */ getTextureSourceIndex: function (source) { for (var i = 0; i < this.source.length; i++) { if (this.source[i] === source) { return i; } } return -1; }, /** * Returns an array of all the Frames in the given TextureSource. * * @method Phaser.Textures.Texture#getFramesFromTextureSource * @since 3.0.0 * * @param {integer} sourceIndex - The index of the TextureSource to get the Frames from. * * @return {Phaser.Textures.Frame[]} An array of Texture Frames. */ getFramesFromTextureSource: function (sourceIndex) { var out = []; for (var frameName in this.frames) { if (frameName === '__BASE') { continue; } var frame = this.frames[frameName]; if (frame.sourceIndex === sourceIndex) { out.push(frame.name); } } return out; }, /** * Returns an array with all of the names of the Frames in this Texture. * * Useful if you want to randomly assign a Frame to a Game Object, as you can * pick a random element from the returned array. * * @method Phaser.Textures.Texture#getFrameNames * @since 3.0.0 * * @param {boolean} [includeBase=false] - Include the `__BASE` Frame in the output array? * * @return {string[]} An array of all Frame names in this Texture. */ getFrameNames: function (includeBase) { if (includeBase === undefined) { includeBase = false; } var out = Object.keys(this.frames); if (!includeBase) { var idx = out.indexOf('__BASE'); if (idx !== -1) { out.splice(idx, 1); } } return out; }, /** * Given a Frame name, return the source image it uses to render with. * * This will return the actual DOM Image or Canvas element. * * @method Phaser.Textures.Texture#getSourceImage * @since 3.0.0 * * @param {string|integer} [name] - The string-based name, or integer based index, of the Frame to get from this Texture. * * @return {HTMLImageElement|HTMLCanvasElement} The DOM Image or Canvas Element. */ getSourceImage: function (name) { if (name === undefined || name === null || this.frameTotal === 1) { name = '__BASE'; } var frame = this.frames[name]; if (!frame) { console.warn('No Texture.frame found with name ' + name); return this.frames['__BASE'].source.image; } else { return frame.source.image; } }, /** * Adds a data source image to this Texture. * * An example of a data source image would be a normal map, where all of the Frames for this Texture * equally apply to the normal map. * * @method Phaser.Textures.Texture#setDataSource * @since 3.0.0 * * @param {Image|HTMLCanvasElement} data - The source image. */ setDataSource: function (data) { if (!Array.isArray(data)) { data = [ data ]; } for (var i = 0; i < data.length; i++) { var source = this.source[i]; this.dataSource.push(new TextureSource(this, data[i], source.width, source.height)); } }, /** * Sets the Filter Mode for this Texture. * * The mode can be either Linear, the default, or Nearest. * * For pixel-art you should use Nearest. * * The mode applies to the entire Texture, not just a specific Frame of it. * * @method Phaser.Textures.Texture#setFilter * @since 3.0.0 * * @param {Phaser.Textures.FilterMode.LINEAR|Phaser.Textures.FilterMode.NEAREST} filterMode - The Filter Mode. */ setFilter: function (filterMode) { var i; for (i = 0; i < this.source.length; i++) { this.source[i].setFilter(filterMode); } for (i = 0; i < this.dataSource.length; i++) { this.dataSource[i].setFilter(filterMode); } }, /** * Destroys this Texture and releases references to its sources and frames. * * @method Phaser.Textures.Texture#destroy * @since 3.0.0 */ destroy: function () { var i; for (i = 0; i < this.source.length; i++) { this.source[i].destroy(); } for (i = 0; i < this.dataSource.length; i++) { this.dataSource[i].destroy(); } for (var frameName in this.frames) { var frame = this.frames[frameName]; frame.destroy(); } this.source = []; this.dataSource = []; this.frames = {}; } }); module.exports = Texture;