UNPKG

@polygonjs/polygonjs

Version:

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

153 lines (134 loc) 4.82 kB
import {ParamEvent} from './../../../../poly/ParamEvent'; import {Constructor} from '../../../../../types/GlobalTypes'; import {Texture, TextureDataType} from 'three'; import {TypedCopNode} from './../../_Base'; import {BaseNodeType} from '../../../_Base'; import {NodeParamsConfig, ParamConfig} from '../../../utils/params/ParamsConfig'; import {TextureParamsController, TextureParamConfig} from './../../utils/TextureParamsController'; import {isUrlStaticImage} from '../../../../../core/FileTypeController'; import {InputCloneMode} from '../../../../poly/InputCloneMode'; import {isBooleanTrue} from '../../../../../core/BooleanValue'; import {FileTypeCheckCopParamConfig} from './../../utils/CheckFileType'; import {Poly} from '../../../../Poly'; import {BaseCoreImageLoader} from '../../../../../core/loader/texture/_BaseImageLoader'; interface CopImageNodeFactoryOptions { type: string; defaultUrl: string; extensions: string[]; getLoader: (url: string, node: BaseNodeType) => BaseCoreImageLoader; } function imageCopParamConfig<TBase extends Constructor>(Base: TBase) { return class Mixin extends Base { /** @param url to fetch the image from */ url = ParamConfig.STRING(''); /** @param reload the image */ reload = ParamConfig.BUTTON(null); }; } class BaseImageCopParamsConfig extends FileTypeCheckCopParamConfig( TextureParamConfig(imageCopParamConfig(NodeParamsConfig)) ) {} const ParamsConfig = new BaseImageCopParamsConfig(); export class copImageNodeFactoryFactoryResult extends TypedCopNode<BaseImageCopParamsConfig> { override paramsConfig = ParamsConfig; public readonly textureParamsController: TextureParamsController = new TextureParamsController(this); } export function copImageNodeFactoryFactory( options: CopImageNodeFactoryOptions ): typeof copImageNodeFactoryFactoryResult { function imageCopParamConfig<TBase extends Constructor>(Base: TBase) { return class Mixin extends Base { /** @param url to fetch the image from */ url = ParamConfig.STRING(options.defaultUrl, { fileBrowse: {extensions: options.extensions}, }); /** @param reload the image */ reload = ParamConfig.BUTTON(null, { callback: (node: BaseNodeType) => { BaseImageCopNode.PARAM_CALLBACK_reload(node as BaseImageCopNode); }, }); }; } class BaseImageCopParamsConfig extends FileTypeCheckCopParamConfig( TextureParamConfig(imageCopParamConfig(NodeParamsConfig)) ) {} const ParamsConfig = new BaseImageCopParamsConfig(); class BaseImageCopNode extends TypedCopNode<BaseImageCopParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return options.type; } public readonly textureParamsController: TextureParamsController = new TextureParamsController(this); override dispose(): void { super.dispose(); Poly.blobs.clearBlobsForNode(this); } override initializeNode() { this.io.inputs.setCount(0, 1); this.io.inputs.initInputsClonedState(InputCloneMode.NEVER); } override async cook(inputContents: Texture[]) { if (isBooleanTrue(this.pv.checkFileType) && !isUrlStaticImage(this.pv.url)) { this.states.error.set('url is not an image'); } else { const texture = await this._loadTexture(); if (texture) { const inputTexture = inputContents[0]; if (inputTexture) { TextureParamsController.copyTextureAttributes(texture, inputTexture); } await this.textureParamsController.update(texture); this.setTexture(texture); } else { this._clearTexture(); } } } // // // UTILS // // static PARAM_CALLBACK_reload(node: BaseImageCopNode) { node.paramCallbackReload(); } private paramCallbackReload() { // this.clearLoadedBlob(); // set the param dirty is preferable to just the successors, in case the expression result needs to be updated // this.p.url.set_successors_dirty(); this.p.url.setDirty(); this.p.url.emit(ParamEvent.ASSET_RELOAD_REQUEST); } protected _loader() { return options.getLoader(this.pv.url, this); } private async _loadTexture() { let texture: Texture | null = null; try { const loader = this._loader(); texture = await loader.loadImage({ tdataType: this.pv.ttype && this.pv.tadvanced, dataType: this.pv.type as TextureDataType, }); if (texture) { texture.matrixAutoUpdate = false; } } catch (e) {} if (!texture) { // we don't override the error, // in case it comes from the loader itself, // which would have hints to install the library. if (!this.states.error.active()) { this.states.error.set(`could not load texture '${this.pv.url}'`); } } return texture; } // clearLoadedBlob() { // const loader = this._loader(); // loader.deregisterUrl(); // } } return BaseImageCopNode; }