import { Utils } from '../common/Utils'
import { BaseTexture } from './BaseTexture';
import { ImageColorFormat, ImageFilterType, ImageCompressionType } from '../const';
/**
* @class BaseImageTexture
* The image texture resource.
* @memberof THING
* @extends THING.BaseTexture
*/
class BaseImageTexture extends BaseTexture {
/**
* The image texture that load image resource and use by style.
* @param {Object} param The initial parameters.
*/
constructor(param = {}) {
super(param);
this._onUpdateUrl = param['onUpdateUrl'];
this.onLoad(param);
}
// #region Private
/**
* Called when update the url.
* @private
*/
_updateUrl() {
let onUpdateUrl = this._onUpdateUrl;
if (onUpdateUrl) {
onUpdateUrl(this, this._url);
}
}
/**
* Check whether it is a compressed texture.
* @returns {Boolean}
* @private
*/
_isCompressed(url) {
let image = this._image;
if (image) {
return image.format !== undefined && !!ImageCompressionType[image.format]
}
let isBasis = (_url_) => {
let extension = _url_._getExtension();
return extension == 'basis'
}
if (url) {
if (Utils.isArray(url)) {
for (let i = 0; i < url.length; i++) {
if (!isBasis(url[i])) {
return false;
}
}
return true;
}
else {
return isBasis(url);
}
}
else {
return false
}
}
/**
* Load texture.
* @param {Object} param The texture param.
* @private
*/
onLoad(param) { }
/**
* Set the urls.
* @param {Array<String>} value
* @private
*/
_setUrl(value) {
if (!value) {
return;
}
this.unloadResource();
this._url = value;
this._updateUrl();
// Break the previous loading
if (this.pendingPromise) {
this.pendingPromise.reject();
this.pendingPromise = null;
}
// Load resource
this.onLoad({
url: value,
onLoad: () => {
if (this.textureResource) {
if (Utils.isArray(value)) {
this.textureResource.setImages(this._image);
}
else {
this.textureResource.setImage(this._image);
}
}
}
});
}
_fixColorFomat(image) {
if (image.format) {
this.colorFormat = image.format;
}
}
_fixMinFilterType(image) {
// It's compressed texture
if (image.format === ImageColorFormat.BC7_M6_OPAQUE_ONLY) {
let mipmaps = image.mipmaps;
if (mipmaps && mipmaps.length !== 1) {
return;
}
this.minFilterType = ImageFilterType.LinearFilter;
}
else {
if (this.generateMipmaps) {
return;
}
// If we do not have any mipmaps then we can not use mipmaps filter
let mipmaps = image.mipmaps;
if (mipmaps && mipmaps.length !== 1) {
return;
}
if (this.minFilterType != ImageFilterType.NearestFilter || this.minFilterType != ImageFilterType.LinearFilter) {
this.minFilterType = ImageFilterType.LinearFilter;
}
}
}
// #endregion
// #region Override
onTriggerErrorEvent(ev) {
if (!ev) {
return;
}
let err;
let target = ev.target;
if (target) {
let src = ev.target.src;
err = {
desc: `Load '${src}' image texture failed`
}
}
else {
err = ev;
}
this.onNotifyError(err);
}
onFixupFromImage(image) {
this._fixColorFomat(image);
this._fixMinFilterType(image);
}
// #endregion
/**
* Copy from image.
* @param {THING.ImageTexture} source The image.
* @returns {THING.ImageTexture}
* @private
*/
copy(source) {
super.copy(source);
this._setUrl(source.url);
return this;
}
/**
* Clone image.
* @returns {THING.ImageTexture}
* @private
*/
clone() {
let resource = new ImageTexture();
resource.copy(this);
return resource;
}
/**
* Convert to uniform data.
* @returns {Object}
* @private
*/
toUniform() {
return {
key: this._url,
value: this.getTextureResource()
};
}
// #region Accessors
/**
* Get/Set the update url callback function.
* @type {Function}
* @private
*/
get onUpdateUrl() {
return this._onUpdateUrl;
}
set onUpdateUrl(value) {
if (!value) return
this._onUpdateUrl = value;
}
/**
* Get/Set url.
* @type {String}
*/
get url() {
return this._url;
}
set url(value) {
this._setUrl(value);
}
// #endregion
}
export { BaseImageTexture }