Files
nothoughts/node_modules/pixi.js/lib/rendering/renderers/shared/texture/Texture.js
2025-08-04 18:57:35 +02:00

195 lines
6.1 KiB
JavaScript

'use strict';
var EventEmitter = require('eventemitter3');
var groupD8 = require('../../../../maths/matrix/groupD8.js');
var Rectangle = require('../../../../maths/shapes/Rectangle.js');
var uid = require('../../../../utils/data/uid.js');
var deprecation = require('../../../../utils/logging/deprecation.js');
var NOOP = require('../../../../utils/misc/NOOP.js');
var BufferImageSource = require('./sources/BufferImageSource.js');
var TextureSource = require('./sources/TextureSource.js');
var TextureMatrix = require('./TextureMatrix.js');
"use strict";
class Texture extends EventEmitter {
/**
* @param {rendering.TextureOptions} options - Options for the texture
*/
constructor({
source,
label,
frame,
orig,
trim,
defaultAnchor,
defaultBorders,
rotate,
dynamic
} = {}) {
super();
/** unique id for this texture */
this.uid = uid.uid("texture");
/** A uvs object based on the given frame and the texture source */
this.uvs = { x0: 0, y0: 0, x1: 0, y1: 0, x2: 0, y2: 0, x3: 0, y3: 0 };
/**
* This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
* irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
*/
this.frame = new Rectangle.Rectangle();
/**
* Does this Texture have any frame data assigned to it?
*
* This mode is enabled automatically if no frame was passed inside constructor.
*
* In this mode texture is subscribed to baseTexture events, and fires `update` on any change.
*
* Beware, after loading or resize of baseTexture event can fired two times!
* If you want more control, subscribe on baseTexture itself.
* @example
* texture.on('update', () => {});
*/
this.noFrame = false;
/**
* Set to true if you plan on modifying the uvs of this texture.
* When this is the case, sprites and other objects using the texture will
* make sure to listen for changes to the uvs and update their vertices accordingly.
*/
this.dynamic = false;
/** is it a texture? yes! used for type checking */
this.isTexture = true;
this.label = label;
this.source = source?.source ?? new TextureSource.TextureSource();
this.noFrame = !frame;
if (frame) {
this.frame.copyFrom(frame);
} else {
const { width, height } = this._source;
this.frame.width = width;
this.frame.height = height;
}
this.orig = orig || this.frame;
this.trim = trim;
this.rotate = rotate ?? 0;
this.defaultAnchor = defaultAnchor;
this.defaultBorders = defaultBorders;
this.destroyed = false;
this.dynamic = dynamic || false;
this.updateUvs();
}
set source(value) {
if (this._source) {
this._source.off("resize", this.update, this);
}
this._source = value;
value.on("resize", this.update, this);
this.emit("update", this);
}
/** the underlying source of the texture (equivalent of baseTexture in v7) */
get source() {
return this._source;
}
/** returns a TextureMatrix instance for this texture. By default, that object is not created because its heavy. */
get textureMatrix() {
if (!this._textureMatrix) {
this._textureMatrix = new TextureMatrix.TextureMatrix(this);
}
return this._textureMatrix;
}
/** The width of the Texture in pixels. */
get width() {
return this.orig.width;
}
/** The height of the Texture in pixels. */
get height() {
return this.orig.height;
}
/** Call this function when you have modified the frame of this texture. */
updateUvs() {
const { uvs, frame } = this;
const { width, height } = this._source;
const nX = frame.x / width;
const nY = frame.y / height;
const nW = frame.width / width;
const nH = frame.height / height;
let rotate = this.rotate;
if (rotate) {
const w2 = nW / 2;
const h2 = nH / 2;
const cX = nX + w2;
const cY = nY + h2;
rotate = groupD8.groupD8.add(rotate, groupD8.groupD8.NW);
uvs.x0 = cX + w2 * groupD8.groupD8.uX(rotate);
uvs.y0 = cY + h2 * groupD8.groupD8.uY(rotate);
rotate = groupD8.groupD8.add(rotate, 2);
uvs.x1 = cX + w2 * groupD8.groupD8.uX(rotate);
uvs.y1 = cY + h2 * groupD8.groupD8.uY(rotate);
rotate = groupD8.groupD8.add(rotate, 2);
uvs.x2 = cX + w2 * groupD8.groupD8.uX(rotate);
uvs.y2 = cY + h2 * groupD8.groupD8.uY(rotate);
rotate = groupD8.groupD8.add(rotate, 2);
uvs.x3 = cX + w2 * groupD8.groupD8.uX(rotate);
uvs.y3 = cY + h2 * groupD8.groupD8.uY(rotate);
} else {
uvs.x0 = nX;
uvs.y0 = nY;
uvs.x1 = nX + nW;
uvs.y1 = nY;
uvs.x2 = nX + nW;
uvs.y2 = nY + nH;
uvs.x3 = nX;
uvs.y3 = nY + nH;
}
}
/**
* Destroys this texture
* @param destroySource - Destroy the source when the texture is destroyed.
*/
destroy(destroySource = false) {
if (this._source) {
if (destroySource) {
this._source.destroy();
this._source = null;
}
}
this._textureMatrix = null;
this.destroyed = true;
this.emit("destroy", this);
this.removeAllListeners();
}
/** call this if you have modified the `texture outside` of the constructor */
update() {
if (this.noFrame) {
this.frame.width = this._source.width;
this.frame.height = this._source.height;
}
this.updateUvs();
this.emit("update", this);
}
/** @deprecated since 8.0.0 */
get baseTexture() {
deprecation.deprecation(deprecation.v8_0_0, "Texture.baseTexture is now Texture.source");
return this._source;
}
}
Texture.EMPTY = new Texture({
label: "EMPTY",
source: new TextureSource.TextureSource({
label: "EMPTY"
})
});
Texture.EMPTY.destroy = NOOP.NOOP;
Texture.WHITE = new Texture({
source: new BufferImageSource.BufferImageSource({
resource: new Uint8Array([255, 255, 255, 255]),
width: 1,
height: 1,
alphaMode: "premultiply-alpha-on-upload",
label: "WHITE"
}),
label: "WHITE"
});
Texture.WHITE.destroy = NOOP.NOOP;
exports.Texture = Texture;
//# sourceMappingURL=Texture.js.map