UNPKG

9.83 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var math = require('@pixi/math');
6var settings = require('@pixi/settings');
7var utils = require('@pixi/utils');
8var BaseTexture = require('./BaseTexture.js');
9var ImageResource = require('./resources/ImageResource.js');
10var TextureUvs = require('./TextureUvs.js');
11
12const DEFAULT_UVS = new TextureUvs.TextureUvs();
13function removeAllHandlers(tex) {
14 tex.destroy = function _emptyDestroy() {
15 };
16 tex.on = function _emptyOn() {
17 };
18 tex.once = function _emptyOnce() {
19 };
20 tex.emit = function _emptyEmit() {
21 };
22}
23class Texture extends utils.EventEmitter {
24 constructor(baseTexture, frame, orig, trim, rotate, anchor, borders) {
25 super();
26 this.noFrame = false;
27 if (!frame) {
28 this.noFrame = true;
29 frame = new math.Rectangle(0, 0, 1, 1);
30 }
31 if (baseTexture instanceof Texture) {
32 baseTexture = baseTexture.baseTexture;
33 }
34 this.baseTexture = baseTexture;
35 this._frame = frame;
36 this.trim = trim;
37 this.valid = false;
38 this._uvs = DEFAULT_UVS;
39 this.uvMatrix = null;
40 this.orig = orig || frame;
41 this._rotate = Number(rotate || 0);
42 if (rotate === true) {
43 this._rotate = 2;
44 } else if (this._rotate % 2 !== 0) {
45 throw new Error("attempt to use diamond-shaped UVs. If you are sure, set rotation manually");
46 }
47 this.defaultAnchor = anchor ? new math.Point(anchor.x, anchor.y) : new math.Point(0, 0);
48 this.defaultBorders = borders;
49 this._updateID = 0;
50 this.textureCacheIds = [];
51 if (!baseTexture.valid) {
52 baseTexture.once("loaded", this.onBaseTextureUpdated, this);
53 } else if (this.noFrame) {
54 if (baseTexture.valid) {
55 this.onBaseTextureUpdated(baseTexture);
56 }
57 } else {
58 this.frame = frame;
59 }
60 if (this.noFrame) {
61 baseTexture.on("update", this.onBaseTextureUpdated, this);
62 }
63 }
64 update() {
65 if (this.baseTexture.resource) {
66 this.baseTexture.resource.update();
67 }
68 }
69 onBaseTextureUpdated(baseTexture) {
70 if (this.noFrame) {
71 if (!this.baseTexture.valid) {
72 return;
73 }
74 this._frame.width = baseTexture.width;
75 this._frame.height = baseTexture.height;
76 this.valid = true;
77 this.updateUvs();
78 } else {
79 this.frame = this._frame;
80 }
81 this.emit("update", this);
82 }
83 destroy(destroyBase) {
84 if (this.baseTexture) {
85 if (destroyBase) {
86 const { resource } = this.baseTexture;
87 if (resource?.url && utils.TextureCache[resource.url]) {
88 Texture.removeFromCache(resource.url);
89 }
90 this.baseTexture.destroy();
91 }
92 this.baseTexture.off("loaded", this.onBaseTextureUpdated, this);
93 this.baseTexture.off("update", this.onBaseTextureUpdated, this);
94 this.baseTexture = null;
95 }
96 this._frame = null;
97 this._uvs = null;
98 this.trim = null;
99 this.orig = null;
100 this.valid = false;
101 Texture.removeFromCache(this);
102 this.textureCacheIds = null;
103 }
104 clone() {
105 const clonedFrame = this._frame.clone();
106 const clonedOrig = this._frame === this.orig ? clonedFrame : this.orig.clone();
107 const clonedTexture = new Texture(this.baseTexture, !this.noFrame && clonedFrame, clonedOrig, this.trim?.clone(), this.rotate, this.defaultAnchor, this.defaultBorders);
108 if (this.noFrame) {
109 clonedTexture._frame = clonedFrame;
110 }
111 return clonedTexture;
112 }
113 updateUvs() {
114 if (this._uvs === DEFAULT_UVS) {
115 this._uvs = new TextureUvs.TextureUvs();
116 }
117 this._uvs.set(this._frame, this.baseTexture, this.rotate);
118 this._updateID++;
119 }
120 static from(source, options = {}, strict = settings.settings.STRICT_TEXTURE_CACHE) {
121 const isFrame = typeof source === "string";
122 let cacheId = null;
123 if (isFrame) {
124 cacheId = source;
125 } else if (source instanceof BaseTexture.BaseTexture) {
126 if (!source.cacheId) {
127 const prefix = options?.pixiIdPrefix || "pixiid";
128 source.cacheId = `${prefix}-${utils.uid()}`;
129 BaseTexture.BaseTexture.addToCache(source, source.cacheId);
130 }
131 cacheId = source.cacheId;
132 } else {
133 if (!source._pixiId) {
134 const prefix = options?.pixiIdPrefix || "pixiid";
135 source._pixiId = `${prefix}_${utils.uid()}`;
136 }
137 cacheId = source._pixiId;
138 }
139 let texture = utils.TextureCache[cacheId];
140 if (isFrame && strict && !texture) {
141 throw new Error(`The cacheId "${cacheId}" does not exist in TextureCache.`);
142 }
143 if (!texture && !(source instanceof BaseTexture.BaseTexture)) {
144 if (!options.resolution) {
145 options.resolution = utils.getResolutionOfUrl(source);
146 }
147 texture = new Texture(new BaseTexture.BaseTexture(source, options));
148 texture.baseTexture.cacheId = cacheId;
149 BaseTexture.BaseTexture.addToCache(texture.baseTexture, cacheId);
150 Texture.addToCache(texture, cacheId);
151 } else if (!texture && source instanceof BaseTexture.BaseTexture) {
152 texture = new Texture(source);
153 Texture.addToCache(texture, cacheId);
154 }
155 return texture;
156 }
157 static fromURL(url, options) {
158 const resourceOptions = Object.assign({ autoLoad: false }, options?.resourceOptions);
159 const texture = Texture.from(url, Object.assign({ resourceOptions }, options), false);
160 const resource = texture.baseTexture.resource;
161 if (texture.baseTexture.valid) {
162 return Promise.resolve(texture);
163 }
164 return resource.load().then(() => Promise.resolve(texture));
165 }
166 static fromBuffer(buffer, width, height, options) {
167 return new Texture(BaseTexture.BaseTexture.fromBuffer(buffer, width, height, options));
168 }
169 static fromLoader(source, imageUrl, name, options) {
170 const baseTexture = new BaseTexture.BaseTexture(source, Object.assign({
171 scaleMode: BaseTexture.BaseTexture.defaultOptions.scaleMode,
172 resolution: utils.getResolutionOfUrl(imageUrl)
173 }, options));
174 const { resource } = baseTexture;
175 if (resource instanceof ImageResource.ImageResource) {
176 resource.url = imageUrl;
177 }
178 const texture = new Texture(baseTexture);
179 if (!name) {
180 name = imageUrl;
181 }
182 BaseTexture.BaseTexture.addToCache(texture.baseTexture, name);
183 Texture.addToCache(texture, name);
184 if (name !== imageUrl) {
185 BaseTexture.BaseTexture.addToCache(texture.baseTexture, imageUrl);
186 Texture.addToCache(texture, imageUrl);
187 }
188 if (texture.baseTexture.valid) {
189 return Promise.resolve(texture);
190 }
191 return new Promise((resolve) => {
192 texture.baseTexture.once("loaded", () => resolve(texture));
193 });
194 }
195 static addToCache(texture, id) {
196 if (id) {
197 if (!texture.textureCacheIds.includes(id)) {
198 texture.textureCacheIds.push(id);
199 }
200 if (utils.TextureCache[id] && utils.TextureCache[id] !== texture) {
201 console.warn(`Texture added to the cache with an id [${id}] that already had an entry`);
202 }
203 utils.TextureCache[id] = texture;
204 }
205 }
206 static removeFromCache(texture) {
207 if (typeof texture === "string") {
208 const textureFromCache = utils.TextureCache[texture];
209 if (textureFromCache) {
210 const index = textureFromCache.textureCacheIds.indexOf(texture);
211 if (index > -1) {
212 textureFromCache.textureCacheIds.splice(index, 1);
213 }
214 delete utils.TextureCache[texture];
215 return textureFromCache;
216 }
217 } else if (texture?.textureCacheIds) {
218 for (let i = 0; i < texture.textureCacheIds.length; ++i) {
219 if (utils.TextureCache[texture.textureCacheIds[i]] === texture) {
220 delete utils.TextureCache[texture.textureCacheIds[i]];
221 }
222 }
223 texture.textureCacheIds.length = 0;
224 return texture;
225 }
226 return null;
227 }
228 get resolution() {
229 return this.baseTexture.resolution;
230 }
231 get frame() {
232 return this._frame;
233 }
234 set frame(frame) {
235 this._frame = frame;
236 this.noFrame = false;
237 const { x, y, width, height } = frame;
238 const xNotFit = x + width > this.baseTexture.width;
239 const yNotFit = y + height > this.baseTexture.height;
240 if (xNotFit || yNotFit) {
241 const relationship = xNotFit && yNotFit ? "and" : "or";
242 const errorX = `X: ${x} + ${width} = ${x + width} > ${this.baseTexture.width}`;
243 const errorY = `Y: ${y} + ${height} = ${y + height} > ${this.baseTexture.height}`;
244 throw new Error(`Texture Error: frame does not fit inside the base Texture dimensions: ${errorX} ${relationship} ${errorY}`);
245 }
246 this.valid = width && height && this.baseTexture.valid;
247 if (!this.trim && !this.rotate) {
248 this.orig = frame;
249 }
250 if (this.valid) {
251 this.updateUvs();
252 }
253 }
254 get rotate() {
255 return this._rotate;
256 }
257 set rotate(rotate) {
258 this._rotate = rotate;
259 if (this.valid) {
260 this.updateUvs();
261 }
262 }
263 get width() {
264 return this.orig.width;
265 }
266 get height() {
267 return this.orig.height;
268 }
269 castToBaseTexture() {
270 return this.baseTexture;
271 }
272 static get EMPTY() {
273 if (!Texture._EMPTY) {
274 Texture._EMPTY = new Texture(new BaseTexture.BaseTexture());
275 removeAllHandlers(Texture._EMPTY);
276 removeAllHandlers(Texture._EMPTY.baseTexture);
277 }
278 return Texture._EMPTY;
279 }
280 static get WHITE() {
281 if (!Texture._WHITE) {
282 const canvas = settings.settings.ADAPTER.createCanvas(16, 16);
283 const context = canvas.getContext("2d");
284 canvas.width = 16;
285 canvas.height = 16;
286 context.fillStyle = "white";
287 context.fillRect(0, 0, 16, 16);
288 Texture._WHITE = new Texture(BaseTexture.BaseTexture.from(canvas));
289 removeAllHandlers(Texture._WHITE);
290 removeAllHandlers(Texture._WHITE.baseTexture);
291 }
292 return Texture._WHITE;
293 }
294}
295
296exports.Texture = Texture;
297//# sourceMappingURL=Texture.js.map