import { Nullable } from "../../types"; import { BaseTexture } from "../../Materials/Textures/baseTexture"; import { Constants } from "../../Engines/constants"; import { Matrix } from '../../Maths/math.vector'; import "../../Engines/Extensions/engine.dynamicTexture"; import "../../Engines/Extensions/engine.videoTexture"; declare type ThinEngine = import("../../Engines/thinEngine").ThinEngine; declare type Scene = import("../../scene").Scene; /** * Defines the options related to the creation of an HtmlElementTexture */ export interface IHtmlElementTextureOptions { /** * Defines wether mip maps should be created or not. */ generateMipMaps?: boolean; /** * Defines the sampling mode of the texture. */ samplingMode?: number; /** * Defines the engine instance to use the texture with. It is not mandatory if you define a scene. */ engine: Nullable; /** * Defines the scene the texture belongs to. It is not mandatory if you define an engine. */ scene: Nullable; } /** * This represents the smallest workload to use an already existing element (Canvas or Video) as a texture. * To be as efficient as possible depending on your constraints nothing aside the first upload * is automatically managed. * It is a cheap VideoTexture or DynamicTexture if you prefer to keep full control of the elements * in your application. * * As the update is not automatic, you need to call them manually. */ export class HtmlElementTexture extends BaseTexture { /** * The texture URL. */ public element: HTMLVideoElement | HTMLCanvasElement; private static readonly DefaultOptions: IHtmlElementTextureOptions = { generateMipMaps: false, samplingMode: Constants.TEXTURE_BILINEAR_SAMPLINGMODE, engine: null, scene: null }; private _textureMatrix: Matrix; private _engine: ThinEngine; private _isVideo: boolean; private _generateMipMaps: boolean; private _samplingMode: number; /** * Instantiates a HtmlElementTexture from the following parameters. * * @param name Defines the name of the texture * @param element Defines the video or canvas the texture is filled with * @param options Defines the other none mandatory texture creation options */ constructor(name: string, element: HTMLVideoElement | HTMLCanvasElement, options: IHtmlElementTextureOptions) { super(options.scene); if (!element || (!options.engine && !options.scene)) { return; } options = { ...HtmlElementTexture.DefaultOptions, ...options }; this._engine = options.engine || options.scene!.getEngine(); this._generateMipMaps = options.generateMipMaps!; this._samplingMode = options.samplingMode!; this._textureMatrix = Matrix.Identity(); this.name = name; this.element = element; this._isVideo = (element instanceof HTMLVideoElement); this.anisotropicFilteringLevel = 1; this._createInternalTexture(); } private _createInternalTexture(): void { let width = 0; let height = 0; if (this._isVideo) { width = (this.element as HTMLVideoElement).videoWidth; height = (this.element as HTMLVideoElement).videoHeight; } else { width = this.element.width; height = this.element.height; } this._texture = this._engine.createDynamicTexture( width, height, this._generateMipMaps, this._samplingMode ); this.update(); } /** * Returns the texture matrix used in most of the material. */ public getTextureMatrix(): Matrix { return this._textureMatrix; } /** * Updates the content of the texture. * @param invertY Defines wether the texture should be inverted on Y (false by default on video and true on canvas) */ public update(invertY: Nullable = null): void { if (this._texture == null) { return; } if (this._isVideo) { const videoElement = this.element as HTMLVideoElement; if (videoElement.readyState < videoElement.HAVE_CURRENT_DATA) { return; } this._engine.updateVideoTexture(this._texture, videoElement, invertY === null ? true : invertY); } else { const canvasElement = this.element as HTMLCanvasElement; this._engine.updateDynamicTexture(this._texture, canvasElement, invertY === null ? true : invertY, false); } } }