import { Utils } from '../common/Utils'
import { ImageWrapType, ImageMappingType } from '../const';
import { BaseImageTexture } from './BaseImageTexture';
/**
* @class CubeTexture
* The cube texture resource.
* @memberof THING
* @extends THING.BaseImageTexture
* @public
*/
class CubeTexture extends BaseImageTexture {
/**
* The cube texture that load image resource and use by style.
* @param {Object} param The initial parameters.
* @example
* // Create cube texture from cube map images
* let cubeTexture = new THING.CubeTexture([
* './skyboxes/bluesky/posx.jpg', './skyboxes/bluesky/negx.jpg',
* './skyboxes/bluesky/posy.jpg', './skyboxes/bluesky/negy.jpg',
* './skyboxes/bluesky/posz.jpg', './skyboxes/bluesky/negz.jpg'
* ]);
*
* // Create cube texture
* let cubeTexture = new THING.CubeTexture({
* url:{
* negx: './images/Night/negx.jpg', // 左
* negy: './images/Night/negy.jpg', // 下
* negz: './images/Night/negz.jpg', // 前
* posx: './images/Night/posx.jpg', // 右
* posy: './images/Night/posy.jpg', // 上
* posz: './images/Night/posz.jpg' // 后
* }
* });
*
* // Create cube texture from folder path
* let cubeTexture = new THING.CubeTexture({
* url: './images/Night/?png'
* }};
*/
constructor(param = {}) {
super(param);
}
onLoad(param) {
// Parse arguments
let onLoad = Utils.parseValue(param['onLoad'], null);
this._updateUrl();
// Some features do not support in compressed texture
this.flipY = Utils.parseValue(param['flipY'], false);
this.wrapType = Utils.parseValue(param['wrapType'], ImageWrapType.ClampToEdge);
this.mappingType = Utils.parseValue(param['mappingType'], ImageMappingType.CubeReflection);
const data = Utils.parseValue(param['data'], null);
if (data) {
this._loadImages(data, onLoad);
}
else {
this._parseUrl(param);
}
}
_parseUrl(param) {
if (Utils.isString(param)) {
param = { url: param };
}
const _url = param['url'];
const onLoad = Utils.parseValue(param['onLoad'], null);
if (Utils.isObject(_url)) {
// convert object to array with a fixed order
if (_url['negx'] && _url['negy'] && _url['negz'] && _url['posx'] && _url['posy'] && _url['posz']) {
param['url'] = [_url['posx'], _url['negx'], _url['posy'], _url['negy'], _url['posz'], _url['negz']]
}
}
// Parse folder url path
else if (Utils.isString(_url)) {
if (!Utils.isImagePath(_url)) {
let suffix = '.jpg';
let preffix = _url;
if (_url.indexOf('?') > -1) {
let arr = _url.split('?');
suffix = '.' + arr.pop();
preffix = arr.join('');
}
let baseUrl = preffix + '/';
if (preffix.charAt(preffix.length - 1) === '/' || preffix.slice(preffix.length - 1, preffix.length - 2) === '\\') {
baseUrl = preffix;
}
let fileNames = ['posx', 'negx', 'posy', 'negy', 'posz', 'negz'];
param = {
url: fileNames.map(name => baseUrl + name + suffix),
// url: [
// baseUrl + 'posx.jpg', baseUrl + 'negx.jpg',
// baseUrl + 'posy.jpg', baseUrl + 'negy.jpg' ,
// baseUrl + 'posz.jpg' , baseUrl + 'negz.jpg'
// ]
};
}
}
if (Utils.isArray(param) || Utils.isString(param)) {
param = { url: param };
}
this._url = param['url'];
if (!this._url) {
this.onNotifyComplete();
}
// load image url
if (Utils.isArray(this._url)) {
let promises = [];
this._url.forEach(url => {
promises.push(this._loadImageFileAsync(url, param));
});
Promise.all(promises).then(
(images) => {
this._loadImages(images, onLoad);
},
(ev) => {
this.onTriggerErrorEvent(ev);
}
);
}
else if (Utils.isString(this._url)) {
this._loadImageFile();
}
}
_loadImages(image, onLoad) {
this._image = image;
// Check whether set the image format
if (this._image.length > 0) {
this._image.forEach((image) => {
if (image.format) {
this.colorFormat = image.format;
}
})
}
if (onLoad) {
onLoad({ images: this });
}
this.onNotifyComplete();
}
_loadImageFileAsync(url, options) {
const defaultOptions = {
flipY: this.flipY,
premultiplyAlpha: this.premultiplyAlpha,
generateMipmaps: this.generateMipmaps,
extensions: Utils.getCurrentApp().view.getExtensions()
};
const param = Object.assign({}, defaultOptions, options);
return Utils.loadImageFile(
url,
null,
null,
null,
param
);
}
_loadImageFile() {
Utils.loadImageFile(this._url,
// Load
(image) => {
this._image = image;
this.onFixupFromImage(image);
if (onLoad) {
onLoad({ images: this });
}
this.onNotifyComplete();
},
// Progress
(ev) => {
},
// Error
(ev) => {
this.onTriggerErrorEvent(ev);
},
{
flipY: this.flipY,
premultiplyAlpha: this.premultiplyAlpha,
generateMipmaps: this.generateMipmaps,
extensions: Utils.getCurrentApp().view.getExtensions()
}
);
}
onCreateTextureResource() {
let images = this._image;
if (images) {
// Image had been loaded
return Utils.createObject('CubeTextureResource', { data: images });
}
else {
let textureType = Utils.isString(this._url) ? "CompressedImage" : "ArrayImage";
// Image is still loading, should replace it when it finished
let textureResource = Utils.createObject('CubeTextureResource', { textureType });
this.waitForComplete().then((images) => {
if (images.resource) {
// Replace texture image
textureResource.setImages(images.resource);
}
});
return textureResource;
}
}
/**
* Get the image of the index.
* @param {Number} index The image index.
* @returns {Object}
* @private
*/
getImageByIndex() {
return this.textureResource.getImageByIndex(index);
}
// #region Accessors
/**
* Get/Set resource.
* @type {*}
* @private
*/
get resource() {
return this._image;
}
set resource(value) {
this._image = value;
if (this.textureResource) {
this.textureResource.setImages(value);
}
}
/**
* Get/Set images
* @type {Array<String>}
* @private
*/
get urls() {
return this._url;
}
set urls(value) {
this._setUrl(value);
}
// #endregion
/**
* Check class type.
* @type {Boolean}
* @example
* if (texture.isCubeTexture) {
* console.log(`It's cube texture`);
* }
* @public
*/
get isCubeTexture() {
return true;
}
}
export { CubeTexture }