/** * @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 Extend = require('../utils/object/Extend'); /** * @classdesc * A Frame is a section of a Texture. * * @class Frame * @memberOf Phaser.Textures * @constructor * @since 3.0.0 * * @param {Phaser.Textures.Texture} texture - The Texture this Frame is a part of. * @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. */ var Frame = new Class({ initialize: function Frame (texture, name, sourceIndex, x, y, width, height) { /** * The Texture this Frame is a part of. * * @name Phaser.Textures.Frame#texture * @type {Phaser.Textures.Texture} * @since 3.0.0 */ this.texture = texture; /** * The name of this Frame. * The name is unique within the Texture. * * @name Phaser.Textures.Frame#name * @type {string} * @since 3.0.0 */ this.name = name; /** * The TextureSource this Frame is part of. * * @name Phaser.Textures.Frame#source * @type {Phaser.Textures.TextureSource} * @since 3.0.0 */ this.source = texture.source[sourceIndex]; /** * The index of the TextureSource in the Texture sources array. * * @name Phaser.Textures.Frame#sourceIndex * @type {integer} * @since 3.0.0 */ this.sourceIndex = sourceIndex; /** * X position within the source image to cut from. * * @name Phaser.Textures.Frame#cutX * @type {integer} * @since 3.0.0 */ this.cutX = x; /** * Y position within the source image to cut from. * * @name Phaser.Textures.Frame#cutY * @type {integer} * @since 3.0.0 */ this.cutY = y; /** * The width of the area in the source image to cut. * * @name Phaser.Textures.Frame#cutWidth * @type {integer} * @since 3.0.0 */ this.cutWidth = width; /** * The height of the area in the source image to cut. * * @name Phaser.Textures.Frame#cutHeight * @type {integer} * @since 3.0.0 */ this.cutHeight = height; /** * The X rendering offset of this Frame, taking trim into account. * * @name Phaser.Textures.Frame#x * @type {integer} * @default 0 * @since 3.0.0 */ this.x = 0; /** * The Y rendering offset of this Frame, taking trim into account. * * @name Phaser.Textures.Frame#y * @type {integer} * @default 0 * @since 3.0.0 */ this.y = 0; /** * The rendering width of this Frame, taking trim into account. * * @name Phaser.Textures.Frame#width * @type {integer} * @since 3.0.0 */ this.width = width; /** * The rendering height of this Frame, taking trim into account. * * @name Phaser.Textures.Frame#height * @type {integer} * @since 3.0.0 */ this.height = height; /** * Half the width, floored. * Precalculated for the renderer. * * @name Phaser.Textures.Frame#halfWidth * @type {integer} * @since 3.0.0 */ this.halfWidth = Math.floor(width * 0.5); /** * Half the height, floored. * Precalculated for the renderer. * * @name Phaser.Textures.Frame#halfHeight * @type {integer} * @since 3.0.0 */ this.halfHeight = Math.floor(height * 0.5); /** * The x center of this frame, floored. * * @name Phaser.Textures.Frame#centerX * @type {integer} * @since 3.0.0 */ this.centerX = Math.floor(width / 2); /** * The y center of this frame, floored. * * @name Phaser.Textures.Frame#centerY * @type {integer} * @since 3.0.0 */ this.centerY = Math.floor(height / 2); /** * The horizontal pivot point of this Frame. * * @name Phaser.Textures.Frame#pivotX * @type {number} * @default 0 * @since 3.0.0 */ this.pivotX = 0; /** * The vertical pivot point of this Frame. * * @name Phaser.Textures.Frame#pivotY * @type {number} * @default 0 * @since 3.0.0 */ this.pivotY = 0; /** * Does this Frame have a custom pivot point? * * @name Phaser.Textures.Frame#customPivot * @type {boolean} * @default false * @since 3.0.0 */ this.customPivot = false; /** * **CURRENTLY UNSUPPORTED** * * Is this frame is rotated or not in the Texture? * Rotation allows you to use rotated frames in texture atlas packing. * It has nothing to do with Sprite rotation. * * @name Phaser.Textures.Frame#rotated * @type {boolean} * @default false * @since 3.0.0 */ this.rotated = false; /** * Over-rides the Renderer setting. * -1 = use Renderer Setting * 0 = No rounding * 1 = Round * * @name Phaser.Textures.Frame#autoRound * @type {integer} * @default -1 * @since 3.0.0 */ this.autoRound = -1; /** * Any Frame specific custom data can be stored here. * * @name Phaser.Textures.Frame#customData * @type {object} * @since 3.0.0 */ this.customData = {}; /** * The un-modified source frame, trim and UV data. * * @name Phaser.Textures.Frame#data * @type {object} * @private * @since 3.0.0 */ this.data = { cut: { x: x, y: y, w: width, h: height, r: x + width, b: y + height }, trim: false, sourceSize: { w: width, h: height }, spriteSourceSize: { x: 0, y: 0, w: width, h: height }, uvs: { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 }, radius: 0.5 * Math.sqrt(width * width + height * height), drawImage: { sx: x, sy: y, sWidth: width, sHeight: height, dWidth: width, dHeight: height } }; this.updateUVs(); }, /** * If the frame was trimmed when added to the Texture Atlas, this records the trim and source data. * * @method Phaser.Textures.Frame#setTrim * @since 3.0.0 * * @param {number} actualWidth - The width of the frame before being trimmed. * @param {number} actualHeight - The height of the frame before being trimmed. * @param {number} destX - The destination X position of the trimmed frame for display. * @param {number} destY - The destination Y position of the trimmed frame for display. * @param {number} destWidth - The destination width of the trimmed frame for display. * @param {number} destHeight - The destination height of the trimmed frame for display. * * @return {Phaser.Textures.Frame} This Frame object. */ setTrim: function (actualWidth, actualHeight, destX, destY, destWidth, destHeight) { var data = this.data; var ss = data.spriteSourceSize; // Store actual values data.trim = true; data.sourceSize.w = actualWidth; data.sourceSize.h = actualHeight; ss.x = destX; ss.y = destY; ss.w = destWidth; ss.h = destHeight; // Adjust properties this.x = destX; this.y = destY; this.width = destWidth; this.height = destHeight; this.halfWidth = destWidth * 0.5; this.halfHeight = destHeight * 0.5; this.centerX = Math.floor(destWidth / 2); this.centerY = Math.floor(destHeight / 2); return this.updateUVs(); }, /** * Updates the internal WebGL UV cache and the drawImage cache. * * @method Phaser.Textures.Frame#updateUVs * @since 3.0.0 * * @return {Phaser.Textures.Frame} This Frame object. */ updateUVs: function () { var cx = this.cutX; var cy = this.cutY; var cw = this.cutWidth; var ch = this.cutHeight; // Canvas data var cd = this.data.drawImage; cd.sWidth = cw; cd.sHeight = ch; cd.dWidth = cw; cd.dHeight = ch; // WebGL data var tw = this.source.width; var th = this.source.height; var uvs = this.data.uvs; uvs.x0 = cx / tw; uvs.y0 = cy / th; uvs.x1 = cx / tw; uvs.y1 = (cy + ch) / th; uvs.x2 = (cx + cw) / tw; uvs.y2 = (cy + ch) / th; uvs.x3 = (cx + cw) / tw; uvs.y3 = cy / th; return this; }, /** * Updates the internal WebGL UV cache. * * @method Phaser.Textures.Frame#updateUVsInverted * @since 3.0.0 * * @return {Phaser.Textures.Frame} This Frame object. */ updateUVsInverted: function () { var tw = this.source.width; var th = this.source.height; var uvs = this.data.uvs; uvs.x3 = (this.cutX + this.cutHeight) / tw; uvs.y3 = (this.cutY + this.cutWidth) / th; uvs.x2 = this.cutX / tw; uvs.y2 = (this.cutY + this.cutWidth) / th; uvs.x1 = this.cutX / tw; uvs.y1 = this.cutY / th; uvs.x0 = (this.cutX + this.cutHeight) / tw; uvs.y0 = this.cutY / th; return this; }, /** * Clones this Frame into a new Frame object. * * @method Phaser.Textures.Frame#clone * @since 3.0.0 * * @return {Phaser.Textures.Frame} A clone of this Frame. */ clone: function () { var clone = new Frame(this.texture, this.name, this.sourceIndex); clone.cutX = this.cutX; clone.cutY = this.cutY; clone.cutWidth = this.cutWidth; clone.cutHeight = this.cutHeight; clone.x = this.x; clone.y = this.y; clone.width = this.width; clone.height = this.height; clone.halfWidth = this.halfWidth; clone.halfHeight = this.halfHeight; clone.centerX = this.centerX; clone.centerY = this.centerY; clone.rotated = this.rotated; clone.data = Extend(true, clone.data, this.data); clone.updateUVs(); return clone; }, /** * Destroys this Frames references. * * @method Phaser.Textures.Frame#destroy * @since 3.0.0 */ destroy: function () { this.texture = null; this.source = null; }, /** * The width of the Frame in its un-trimmed, un-padded state, as prepared in the art package, * before being packed. * * @name Phaser.Textures.Frame#realWidth * @type {number} * @readOnly * @since 3.0.0 */ realWidth: { get: function () { return this.data.sourceSize.w; } }, /** * The height of the Frame in its un-trimmed, un-padded state, as prepared in the art package, * before being packed. * * @name Phaser.Textures.Frame#realHeight * @type {number} * @readOnly * @since 3.0.0 */ realHeight: { get: function () { return this.data.sourceSize.h; } }, /** * The UV data for this Frame. * * @name Phaser.Textures.Frame#uvs * @type {object} * @readOnly * @since 3.0.0 */ uvs: { get: function () { return this.data.uvs; } }, /** * The radius of the Frame (derived from sqrt(w * w + h * h) / 2) * * @name Phaser.Textures.Frame#radius * @type {number} * @readOnly * @since 3.0.0 */ radius: { get: function () { return this.data.radius; } }, /** * Is the Frame trimmed or not? * * @name Phaser.Textures.Frame#trimmed * @type {boolean} * @readOnly * @since 3.0.0 */ trimmed: { get: function () { return this.data.trim; } }, /** * The Canvas drawImage data object. * * @name Phaser.Textures.Frame#canvasData * @type {object} * @readOnly * @since 3.0.0 */ canvasData: { get: function () { return this.data.drawImage; } } }); module.exports = Frame;