import { TextureInfo } from "./TextureInfo";
import "../../utils/Utils";
const _placeholderImage = document.createElement("img");
/**
* Texture
* @extends {TextureInfo}
*/
export class Texture extends TextureInfo {
/**
* Creates an instance of Texture.
* @constructor
* @param {HTMLElement} source
* @param {boolean} shouldUpdate
*/
constructor(source, shouldUpdate) {
super();
this._source = _placeholderImage;
this._parseTextureSize = this._parseTextureSize.bind(this);
this.isVideo = false;
this.source = source;
this.shouldUpdate = shouldUpdate;
this._dimensionWidthName = "width";
this._dimensionHeightName = "height";
this._currentRenderTime =
this._loadUpdateId =
this._currentLoadUpdateId =
0;
this._eventType;
}
/**
* Get width
* @readonly
* @type {number}
*/
get width() {
return this._sourceWidth || 1;
}
/**
* Get height
* @readonly
* @type {number}
*/
get height() {
return this._sourceHeight || 1;
}
/**
* Set/Get source of the texture
* @type {HTMLElement}
*/
get source() {
return this._source;
}
set source(value) {
if (value) {
this._source.removeEventListener(this._eventType, this._parseTextureSize);
this._source = value ? value : _placeholderImage;
this.isVideo = value.tagName
? value.tagName.toLowerCase() === "video"
: false;
this._eventType = this.isVideo ? "canplay" : "load";
value &&
!this._parseTextureSize() &&
value.addEventListener(this._eventType, this._parseTextureSize, {
once: true,
});
}
}
/**
* Destruct the class
*/
destruct() {
this._source.removeEventListener(this._eventType, this._parseTextureSize);
}
/**
* @param {WebGL2Context} gl
* @param {number} id
* @param {number} renderTime
* @returns {boolean}
* @ignore
*/
$hasNeedToDraw(gl, id, renderTime) {
if (this.$currentAglId < gl.agl_id) {
this.$currentAglId = gl.agl_id;
this._baseTexture = gl.createTexture();
this.useActiveTexture(gl, id);
return true;
}
if (this.$currentUpdateId < this.$updateId) {
this.$currentUpdateId = this.$updateId;
this.useActiveTexture(gl, id);
return true;
}
if (this._currentLoadUpdateId < this._loadUpdateId) {
this._currentLoadUpdateId = this._loadUpdateId;
this.useActiveTexture(gl, id);
return true;
}
if (this.shouldUpdate && this._currentRenderTime < renderTime) {
this._currentRenderTime = renderTime;
this.useActiveTexture(gl, id);
return true;
}
if (this.isVideo && !this._source.paused) {
this.useActiveTexture(gl, id);
return true;
}
}
/**
* @readonly
* @type {number}
* @ignore
*/
get _sourceWidth() {
return this._source[this._dimensionWidthName];
}
/**
* @readonly
* @type {number}
* @ignore
*/
get _sourceHeight() {
return this._source[this._dimensionHeightName];
}
/**
* @ignore
*/
_parseTextureSize() {
this._dimensionWidthName = "width";
this._dimensionHeightName = "height";
if (this._source.naturalWidth) {
this._dimensionWidthName = "naturalWidth";
this._dimensionHeightName = "naturalHeight";
} else if (this._source.videoWidth) {
this._dimensionWidthName = "videoWidth";
this._dimensionHeightName = "videoHeight";
}
if (this._sourceWidth * this._sourceHeight > 0) {
this._renderSource = this._source;
++this._loadUpdateId;
return true;
} else this._renderSource = null;
}
}
/**
* Create a new Texture from an image source
* @function
* @param {HTMLElement} src
* @param {boolean} shouldUpdate
* @returns {Texture}
*/
Texture.loadImage = (src, shouldUpdate) => {
const image = document.createElement("img");
const texture = new Texture(image, shouldUpdate);
image.src = src;
return texture;
};
/**
* Create a new Texture from a video source
* @function
* @param {HTMLVideoElement} src
* @param {boolean} shouldUpdate
* @returns {Texture}
*/
Texture.loadVideo = (src, shouldUpdate) => {
const video = document.createElement("video");
const texture = new Texture(video, shouldUpdate);
video.src = src;
return texture;
};