@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
153 lines (134 loc) • 4.82 kB
text/typescript
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;
}