UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

168 lines (160 loc) 5.33 kB
// /** // * Loads multiple images in order to quickly set the texture to one of them. // * // * @remarks // * // * This can replace the [cop/video](/docs/nodes/cop/video) when you'd like to go back and forth in the image sequence, // * as videos are less capable of going back without skipping frames. // * // * // */ // import {TypedCopNode} from './_Base'; // import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; // import {TextureParamsController, TextureParamConfig} from './utils/TextureParamsController'; // import {Constructor} from '../../../types/GlobalTypes'; // import {CanvasTexture} from 'three'; // import {BaseNodeType} from '../_Base'; // export function ImageSequenceCopNodeParamConfig<TBase extends Constructor>(Base: TBase) { // return class Mixin extends Base { // /** @param url to fetch the images from */ // url = ParamConfig.STRING('images.%05d.jpg'); // /** @param frame range */ // frameRange = ParamConfig.VECTOR2([1, 100]); // /** @param image index */ // frame = ParamConfig.INTEGER(1, { // range: [1, 100], // rangeLocked: [true, false], // cook: false, // callback: (node: BaseNodeType) => { // ImageSequenceCopNode.PARAM_CALLBACK_updateImageIndex(node as ImageSequenceCopNode); // }, // }); // /** @param forces images to reload*/ // reload = ParamConfig.BUTTON(null, { // cook: false, // callback: (node: BaseNodeType) => { // ImageSequenceCopNode.PARAM_CALLBACK_reload(node as ImageSequenceCopNode); // }, // }); // }; // } // class ImageSequenceCopParamConfig extends TextureParamConfig(ImageSequenceCopNodeParamConfig(NodeParamsConfig)) {} // const ParamsConfig = new ImageSequenceCopParamConfig(); // export class ImageSequenceCopNode extends TypedCopNode<ImageSequenceCopParamConfig> { // override paramsConfig = ParamsConfig; // static override type(): Readonly<'imageSequence'> { // return 'imageSequence'; // } // public readonly textureParamsController: TextureParamsController = new TextureParamsController(this); // override async cook() { // await this._loadImagesIfRequired(); // const texture = this._updateImageIndex(); // if (!texture) { // return; // } // await this.textureParamsController.update(texture); // texture.needsUpdate = true; // this.setTexture(texture); // } // // // // // // CANVAS TEXTURE // // // // // private __canvasTexture: CanvasTexture | undefined; // private _canvasTexture(image: HTMLImageElement) { // return (this.__canvasTexture = this.__canvasTexture || new CanvasTexture(this._canvas(image))); // } // // // // // // CANVAS // // // // // private __canvas: HTMLCanvasElement | undefined; // private _canvas(image: HTMLImageElement) { // return (this.__canvas = this.__canvas || this._createCanvas(image)); // } // private _createCanvas(image: HTMLImageElement) { // const canvas = document.createElement('canvas'); // canvas.width = image.width; // canvas.height = image.height; // return canvas; // } // // // // // // CACHE // // // // // private _images: Map<number, HTMLImageElement> = new Map(); // private async _loadImagesIfRequired() { // if (this._images.size > 0) { // return; // } // const frameRange = this.pv.frameRange; // const url = this.pv.url; // const paddingMatch = url.match(/(%0(\d)d)/); // if (!paddingMatch) { // this.states.error.set('no padding match'); // return; // } // const padding = parseInt(paddingMatch[2]); // const promises: Array<Promise<HTMLImageElement>> = []; // for (let frame = frameRange.x; frame <= frameRange.y; frame++) { // const imageUrl = url.replace(/(%0\dd)/, `${frame}`.padStart(padding, '0')); // promises.push(this._loadImage(imageUrl, frame)); // } // await Promise.all(promises); // } // private _loadImage(url: string, frame: number): Promise<HTMLImageElement> { // return new Promise((resolve, reject) => { // const image = new Image(); // image.onload = () => { // this._images.set(frame, image); // resolve(image); // }; // image.onerror = () => { // this.states.error.set(`failed to load url '${url}' (at frame ${frame})`); // resolve(image); // }; // image.src = url; // }); // } // // // // // // CALLBACK // // // // // static PARAM_CALLBACK_reload(node: ImageSequenceCopNode) { // node._reload(); // } // static PARAM_CALLBACK_updateImageIndex(node: ImageSequenceCopNode) { // node._updateImageIndex(); // } // private _reload() { // this._images.clear(); // this.__canvas = undefined; // this.__canvasTexture = undefined; // this._loadImagesIfRequired(); // } // private _updateImageIndex() { // if (!this._images) { // this.states.error.set('no images loaded'); // return; // } // const currentImage = this._images.get(this.pv.frame); // if (!currentImage) { // this.states.error.set(`image ${this.pv.frame} is not available`); // return; // } // const canvas = this._canvas(currentImage); // const context = canvas.getContext('2d'); // if (!context) { // this.states.error.set(`failed to get canvas context`); // return; // } // context.drawImage(currentImage, 0, 0); // const texture = this._canvasTexture(currentImage); // texture.needsUpdate = true; // return texture; // } // }