playcanvas
Version: 
PlayCanvas WebGL game engine
175 lines (172 loc) • 6.74 kB
JavaScript
import { path } from '../../core/path.js';
import { Vec2 } from '../../core/math/vec2.js';
import { Vec4 } from '../../core/math/vec4.js';
import { TEXTURETYPE_RGBM, TEXTURETYPE_DEFAULT, ADDRESS_REPEAT, ADDRESS_CLAMP_TO_EDGE, ADDRESS_MIRRORED_REPEAT, FILTER_NEAREST, FILTER_LINEAR, FILTER_NEAREST_MIPMAP_NEAREST, FILTER_LINEAR_MIPMAP_NEAREST, FILTER_NEAREST_MIPMAP_LINEAR, FILTER_LINEAR_MIPMAP_LINEAR } from '../../platform/graphics/constants.js';
import { http } from '../../platform/net/http.js';
import { TextureAtlas } from '../../scene/texture-atlas.js';
import { ResourceHandler } from './handler.js';
var JSON_ADDRESS_MODE = {
		'repeat': ADDRESS_REPEAT,
		'clamp': ADDRESS_CLAMP_TO_EDGE,
		'mirror': ADDRESS_MIRRORED_REPEAT
};
var JSON_FILTER_MODE = {
		'nearest': FILTER_NEAREST,
		'linear': FILTER_LINEAR,
		'nearest_mip_nearest': FILTER_NEAREST_MIPMAP_NEAREST,
		'linear_mip_nearest': FILTER_LINEAR_MIPMAP_NEAREST,
		'nearest_mip_linear': FILTER_NEAREST_MIPMAP_LINEAR,
		'linear_mip_linear': FILTER_LINEAR_MIPMAP_LINEAR
};
var regexFrame = /^data\.frames\.(\d+)$/;
class TextureAtlasHandler extends ResourceHandler {
		load(url, callback) {
				if (typeof url === 'string') {
						url = {
								load: url,
								original: url
						};
				}
				var self = this;
				var handler = this._loader.getHandler('texture');
				if (path.getExtension(url.original) === '.json') {
						http.get(url.load, {
								retry: this.maxRetries > 0,
								maxRetries: this.maxRetries
						}, (err, response)=>{
								if (!err) {
										var textureUrl = url.original.replace('.json', '.png');
										self._loader.load(textureUrl, 'texture', (err, texture)=>{
												if (err) {
														callback(err);
												} else {
														callback(null, {
																data: response,
																texture: texture
														});
												}
										});
								} else {
										callback(err);
								}
						});
				} else {
						handler.load(url, callback);
				}
		}
		open(url, data, asset) {
				var resource = new TextureAtlas();
				if (data.texture && data.data) {
						resource.texture = data.texture;
						resource.__data = data.data;
				} else {
						var handler = this._loader.getHandler('texture');
						var texture = handler.open(url, data, asset);
						if (!texture) return null;
						resource.texture = texture;
				}
				return resource;
		}
		patch(asset, assets) {
				if (!asset.resource) {
						return;
				}
				if (asset.resource.__data) {
						if (asset.resource.__data.minfilter !== undefined) asset.data.minfilter = asset.resource.__data.minfilter;
						if (asset.resource.__data.magfilter !== undefined) asset.data.magfilter = asset.resource.__data.magfilter;
						if (asset.resource.__data.addressu !== undefined) asset.data.addressu = asset.resource.__data.addressu;
						if (asset.resource.__data.addressv !== undefined) asset.data.addressv = asset.resource.__data.addressv;
						if (asset.resource.__data.mipmaps !== undefined) asset.data.mipmaps = asset.resource.__data.mipmaps;
						if (asset.resource.__data.anisotropy !== undefined) asset.data.anisotropy = asset.resource.__data.anisotropy;
						if (asset.resource.__data.rgbm !== undefined) asset.data.rgbm = !!asset.resource.__data.rgbm;
						asset.data.frames = asset.resource.__data.frames;
						delete asset.resource.__data;
				}
				var texture = asset.resource.texture;
				if (texture) {
						texture.name = asset.name;
						if (asset.data.hasOwnProperty('minfilter') && texture.minFilter !== JSON_FILTER_MODE[asset.data.minfilter]) {
								texture.minFilter = JSON_FILTER_MODE[asset.data.minfilter];
						}
						if (asset.data.hasOwnProperty('magfilter') && texture.magFilter !== JSON_FILTER_MODE[asset.data.magfilter]) {
								texture.magFilter = JSON_FILTER_MODE[asset.data.magfilter];
						}
						if (asset.data.hasOwnProperty('addressu') && texture.addressU !== JSON_ADDRESS_MODE[asset.data.addressu]) {
								texture.addressU = JSON_ADDRESS_MODE[asset.data.addressu];
						}
						if (asset.data.hasOwnProperty('addressv') && texture.addressV !== JSON_ADDRESS_MODE[asset.data.addressv]) {
								texture.addressV = JSON_ADDRESS_MODE[asset.data.addressv];
						}
						if (asset.data.hasOwnProperty('mipmaps') && texture.mipmaps !== asset.data.mipmaps) {
								texture.mipmaps = asset.data.mipmaps;
						}
						if (asset.data.hasOwnProperty('anisotropy') && texture.anisotropy !== asset.data.anisotropy) {
								texture.anisotropy = asset.data.anisotropy;
						}
						if (asset.data.hasOwnProperty('rgbm')) {
								var type = asset.data.rgbm ? TEXTURETYPE_RGBM : TEXTURETYPE_DEFAULT;
								if (texture.type !== type) {
										texture.type = type;
								}
						}
				}
				asset.resource.texture = texture;
				var frames = {};
				for(var key in asset.data.frames){
						var frame = asset.data.frames[key];
						frames[key] = {
								rect: new Vec4(frame.rect),
								pivot: new Vec2(frame.pivot),
								border: new Vec4(frame.border)
						};
				}
				asset.resource.frames = frames;
				asset.off('change', this._onAssetChange, this);
				asset.on('change', this._onAssetChange, this);
		}
		_onAssetChange(asset, attribute, value) {
				var frame;
				if (attribute === 'data' || attribute === 'data.frames') {
						var frames = {};
						for(var key in value.frames){
								frame = value.frames[key];
								frames[key] = {
										rect: new Vec4(frame.rect),
										pivot: new Vec2(frame.pivot),
										border: new Vec4(frame.border)
								};
						}
						asset.resource.frames = frames;
				} else {
						var match = attribute.match(regexFrame);
						if (match) {
								var frameKey = match[1];
								if (value) {
										if (!asset.resource.frames[frameKey]) {
												asset.resource.frames[frameKey] = {
														rect: new Vec4(value.rect),
														pivot: new Vec2(value.pivot),
														border: new Vec4(value.border)
												};
										} else {
												frame = asset.resource.frames[frameKey];
												frame.rect.set(value.rect[0], value.rect[1], value.rect[2], value.rect[3]);
												frame.pivot.set(value.pivot[0], value.pivot[1]);
												frame.border.set(value.border[0], value.border[1], value.border[2], value.border[3]);
										}
										asset.resource.fire('set:frame', frameKey, asset.resource.frames[frameKey]);
								} else {
										if (asset.resource.frames[frameKey]) {
												delete asset.resource.frames[frameKey];
												asset.resource.fire('remove:frame', frameKey);
										}
								}
						}
				}
		}
		constructor(app){
				super(app, 'textureatlas');
				this._loader = app.loader;
		}
}
export { TextureAtlasHandler };