UNPKG

7.92 kBJavaScriptView Raw
1import { SCALE_MODES, FORMATS, ALPHA_MODES, TYPES, MIPMAP_MODES, WRAP_MODES, TARGETS } from '@pixi/constants';
2import { settings } from '@pixi/settings';
3import { EventEmitter, uid, isPow2, BaseTextureCache, TextureCache } from '@pixi/utils';
4import { autoDetectResource } from './resources/autoDetectResource.mjs';
5import { BufferResource } from './resources/BufferResource.mjs';
6import { Resource } from './resources/Resource.mjs';
7
8const defaultBufferOptions = {
9 scaleMode: SCALE_MODES.NEAREST,
10 format: FORMATS.RGBA,
11 alphaMode: ALPHA_MODES.NPM
12};
13const _BaseTexture = class extends EventEmitter {
14 constructor(resource = null, options = null) {
15 super();
16 options = Object.assign({}, _BaseTexture.defaultOptions, options);
17 const {
18 alphaMode,
19 mipmap,
20 anisotropicLevel,
21 scaleMode,
22 width,
23 height,
24 wrapMode,
25 format,
26 type,
27 target,
28 resolution,
29 resourceOptions
30 } = options;
31 if (resource && !(resource instanceof Resource)) {
32 resource = autoDetectResource(resource, resourceOptions);
33 resource.internal = true;
34 }
35 this.resolution = resolution || settings.RESOLUTION;
36 this.width = Math.round((width || 0) * this.resolution) / this.resolution;
37 this.height = Math.round((height || 0) * this.resolution) / this.resolution;
38 this._mipmap = mipmap;
39 this.anisotropicLevel = anisotropicLevel;
40 this._wrapMode = wrapMode;
41 this._scaleMode = scaleMode;
42 this.format = format;
43 this.type = type;
44 this.target = target;
45 this.alphaMode = alphaMode;
46 this.uid = uid();
47 this.touched = 0;
48 this.isPowerOfTwo = false;
49 this._refreshPOT();
50 this._glTextures = {};
51 this.dirtyId = 0;
52 this.dirtyStyleId = 0;
53 this.cacheId = null;
54 this.valid = width > 0 && height > 0;
55 this.textureCacheIds = [];
56 this.destroyed = false;
57 this.resource = null;
58 this._batchEnabled = 0;
59 this._batchLocation = 0;
60 this.parentTextureArray = null;
61 this.setResource(resource);
62 }
63 get realWidth() {
64 return Math.round(this.width * this.resolution);
65 }
66 get realHeight() {
67 return Math.round(this.height * this.resolution);
68 }
69 get mipmap() {
70 return this._mipmap;
71 }
72 set mipmap(value) {
73 if (this._mipmap !== value) {
74 this._mipmap = value;
75 this.dirtyStyleId++;
76 }
77 }
78 get scaleMode() {
79 return this._scaleMode;
80 }
81 set scaleMode(value) {
82 if (this._scaleMode !== value) {
83 this._scaleMode = value;
84 this.dirtyStyleId++;
85 }
86 }
87 get wrapMode() {
88 return this._wrapMode;
89 }
90 set wrapMode(value) {
91 if (this._wrapMode !== value) {
92 this._wrapMode = value;
93 this.dirtyStyleId++;
94 }
95 }
96 setStyle(scaleMode, mipmap) {
97 let dirty;
98 if (scaleMode !== void 0 && scaleMode !== this.scaleMode) {
99 this.scaleMode = scaleMode;
100 dirty = true;
101 }
102 if (mipmap !== void 0 && mipmap !== this.mipmap) {
103 this.mipmap = mipmap;
104 dirty = true;
105 }
106 if (dirty) {
107 this.dirtyStyleId++;
108 }
109 return this;
110 }
111 setSize(desiredWidth, desiredHeight, resolution) {
112 resolution = resolution || this.resolution;
113 return this.setRealSize(desiredWidth * resolution, desiredHeight * resolution, resolution);
114 }
115 setRealSize(realWidth, realHeight, resolution) {
116 this.resolution = resolution || this.resolution;
117 this.width = Math.round(realWidth) / this.resolution;
118 this.height = Math.round(realHeight) / this.resolution;
119 this._refreshPOT();
120 this.update();
121 return this;
122 }
123 _refreshPOT() {
124 this.isPowerOfTwo = isPow2(this.realWidth) && isPow2(this.realHeight);
125 }
126 setResolution(resolution) {
127 const oldResolution = this.resolution;
128 if (oldResolution === resolution) {
129 return this;
130 }
131 this.resolution = resolution;
132 if (this.valid) {
133 this.width = Math.round(this.width * oldResolution) / resolution;
134 this.height = Math.round(this.height * oldResolution) / resolution;
135 this.emit("update", this);
136 }
137 this._refreshPOT();
138 return this;
139 }
140 setResource(resource) {
141 if (this.resource === resource) {
142 return this;
143 }
144 if (this.resource) {
145 throw new Error("Resource can be set only once");
146 }
147 resource.bind(this);
148 this.resource = resource;
149 return this;
150 }
151 update() {
152 if (!this.valid) {
153 if (this.width > 0 && this.height > 0) {
154 this.valid = true;
155 this.emit("loaded", this);
156 this.emit("update", this);
157 }
158 } else {
159 this.dirtyId++;
160 this.dirtyStyleId++;
161 this.emit("update", this);
162 }
163 }
164 onError(event) {
165 this.emit("error", this, event);
166 }
167 destroy() {
168 if (this.resource) {
169 this.resource.unbind(this);
170 if (this.resource.internal) {
171 this.resource.destroy();
172 }
173 this.resource = null;
174 }
175 if (this.cacheId) {
176 delete BaseTextureCache[this.cacheId];
177 delete TextureCache[this.cacheId];
178 this.cacheId = null;
179 }
180 this.dispose();
181 _BaseTexture.removeFromCache(this);
182 this.textureCacheIds = null;
183 this.destroyed = true;
184 }
185 dispose() {
186 this.emit("dispose", this);
187 }
188 castToBaseTexture() {
189 return this;
190 }
191 static from(source, options, strict = settings.STRICT_TEXTURE_CACHE) {
192 const isFrame = typeof source === "string";
193 let cacheId = null;
194 if (isFrame) {
195 cacheId = source;
196 } else {
197 if (!source._pixiId) {
198 const prefix = options?.pixiIdPrefix || "pixiid";
199 source._pixiId = `${prefix}_${uid()}`;
200 }
201 cacheId = source._pixiId;
202 }
203 let baseTexture = BaseTextureCache[cacheId];
204 if (isFrame && strict && !baseTexture) {
205 throw new Error(`The cacheId "${cacheId}" does not exist in BaseTextureCache.`);
206 }
207 if (!baseTexture) {
208 baseTexture = new _BaseTexture(source, options);
209 baseTexture.cacheId = cacheId;
210 _BaseTexture.addToCache(baseTexture, cacheId);
211 }
212 return baseTexture;
213 }
214 static fromBuffer(buffer, width, height, options) {
215 buffer = buffer || new Float32Array(width * height * 4);
216 const resource = new BufferResource(buffer, { width, height });
217 const type = buffer instanceof Float32Array ? TYPES.FLOAT : TYPES.UNSIGNED_BYTE;
218 return new _BaseTexture(resource, Object.assign({}, defaultBufferOptions, options || { width, height, type }));
219 }
220 static addToCache(baseTexture, id) {
221 if (id) {
222 if (!baseTexture.textureCacheIds.includes(id)) {
223 baseTexture.textureCacheIds.push(id);
224 }
225 if (BaseTextureCache[id] && BaseTextureCache[id] !== baseTexture) {
226 console.warn(`BaseTexture added to the cache with an id [${id}] that already had an entry`);
227 }
228 BaseTextureCache[id] = baseTexture;
229 }
230 }
231 static removeFromCache(baseTexture) {
232 if (typeof baseTexture === "string") {
233 const baseTextureFromCache = BaseTextureCache[baseTexture];
234 if (baseTextureFromCache) {
235 const index = baseTextureFromCache.textureCacheIds.indexOf(baseTexture);
236 if (index > -1) {
237 baseTextureFromCache.textureCacheIds.splice(index, 1);
238 }
239 delete BaseTextureCache[baseTexture];
240 return baseTextureFromCache;
241 }
242 } else if (baseTexture?.textureCacheIds) {
243 for (let i = 0; i < baseTexture.textureCacheIds.length; ++i) {
244 delete BaseTextureCache[baseTexture.textureCacheIds[i]];
245 }
246 baseTexture.textureCacheIds.length = 0;
247 return baseTexture;
248 }
249 return null;
250 }
251};
252let BaseTexture = _BaseTexture;
253BaseTexture.defaultOptions = {
254 mipmap: MIPMAP_MODES.POW2,
255 anisotropicLevel: 0,
256 scaleMode: SCALE_MODES.LINEAR,
257 wrapMode: WRAP_MODES.CLAMP,
258 alphaMode: ALPHA_MODES.UNPACK,
259 target: TARGETS.TEXTURE_2D,
260 format: FORMATS.RGBA,
261 type: TYPES.UNSIGNED_BYTE
262};
263BaseTexture._globalBatch = 0;
264
265export { BaseTexture };
266//# sourceMappingURL=BaseTexture.mjs.map