@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
164 lines (149 loc) • 5.51 kB
text/typescript
import {CoreWalker} from '../../../core/Walker';
import {DecomposedPath} from '../../../core/DecomposedPath';
import {BaseParamType} from '../../params/_Base';
import {BaseNodeType} from '../../nodes/_Base';
import {MethodDependency} from '../MethodDependency';
import {CoreGraphNode} from '../../../core/graph/CoreGraphNode';
import {BaseContainer} from '../../containers/_Base';
import {ContainerMap} from '../../containers/utils/ContainerMap';
import {NodeContext} from '../../poly/NodeContext';
import {Poly} from '../../Poly';
import {isNumber, isString} from '../../../core/Type';
export interface BaseMethodFindDependencyArgs {
indexOrPath: string | number | undefined;
node?: BaseNodeType;
}
export class BaseMethod {
constructor(public readonly param: BaseParamType) {}
// the node is not fetched from the param in the constructor,
// since the param may not have a node yet, especially when the param's value
// is set on node creation
private _node: BaseNodeType | undefined;
protected node(): BaseNodeType | undefined {
return (this._node = this._node || this.param.node);
}
static requiredArguments(): any[] {
console.warn('Expression.Method._Base.required_arguments virtual method call. Please override');
return [];
}
static optionalArguments(): any[] {
return [];
}
static minAllowedArgumentsCount() {
return this.requiredArguments().length;
}
static maxAllowedArgumentsCount() {
return this.minAllowedArgumentsCount() + this.optionalArguments().length;
}
static allowedArgumentsCount(count: number) {
return count >= this.minAllowedArgumentsCount() && count <= this.maxAllowedArgumentsCount();
}
processArguments(args: any): Promise<any> {
throw 'Expression.Method._Base.process_arguments virtual method call. Please override';
}
async getReferencedNodeContainer(indexOrPath: number | string): Promise<BaseContainer> {
const referencedNode = this.getReferencedNode(indexOrPath);
if (referencedNode) {
let container: ContainerMap[NodeContext];
if (referencedNode.isDirty() || referencedNode.flags?.bypass?.active()) {
container = await referencedNode.compute();
} else {
container = referencedNode.containerController.container();
}
if (container) {
const coreContent = container.coreContent();
if (coreContent != null) {
return container;
}
}
throw `referenced node invalid: ${referencedNode.path()}`;
} else {
throw `invalid input (${indexOrPath})`;
}
}
getReferencedParam(path: string, decomposedPath?: DecomposedPath): BaseParamType | null {
const node = this.node();
if (node) {
return CoreWalker.findParam(node, path, decomposedPath);
}
// if (referenced_param != null) {
// if (this.update_dependencies_mode()) {
// //param_connect_result = this.param().addGraphInput(referenced_param)
// const expression_node_connect_result = this.jsep_node()._graph_node.addGraphInput(referenced_param);
// //if !(param_connect_result && expression_node_connect_result)
// if (!expression_node_connect_result) {
// throw "cannot create infinite graph";
// }
// }
// } else {
// throw `no param found for argument ${path}`;
// }
return null;
}
findReferencedGraphNode(indexOrPath: number | string, decomposedPath?: DecomposedPath): CoreGraphNode | null {
const is_index = isNumber(indexOrPath);
// let node
if (is_index) {
const index = indexOrPath as number;
const node = this.node();
if (node) {
const input_graph_node = node.io.inputs.inputGraphNode(index);
return input_graph_node;
}
} else {
const path = indexOrPath as string;
return this.getReferencedNode(path, decomposedPath);
}
return null;
}
// caching the node by path here prevents having expressions such as points_count(0)
// evaluate to an error when the input is disconnected
// private _node_by_path: Map<string | number, BaseNodeType | null | undefined> = new Map();
getReferencedNode(indexOrPath: string | number, decomposedPath?: DecomposedPath): BaseNodeType | null {
// let node = this._node_by_path.get(indexOrPath);
// if (node) {
// return node;
// } else {
let node: BaseNodeType | null = null;
const current_node = this.node();
if (isString(indexOrPath)) {
if (current_node) {
const path = indexOrPath;
node = CoreWalker.findNode(current_node, path, decomposedPath);
}
} else {
if (current_node) {
const index = indexOrPath;
node = current_node.io.inputs.input(index);
}
}
// this._node_by_path.set(indexOrPath, node);
return node || null;
//}
}
findDependency(arg: BaseMethodFindDependencyArgs): MethodDependency | null {
return null;
}
protected createDependencyFromIndexOrPath(args: BaseMethodFindDependencyArgs): MethodDependency | null {
if (this.param.disposed() == true) {
return null;
}
const {indexOrPath} = args;
const decomposedPath = new DecomposedPath();
const node = indexOrPath != null ? this.findReferencedGraphNode(indexOrPath, decomposedPath) : args.node;
if (node) {
return this.createDependency(node, args, decomposedPath);
} else {
Poly.warn(`node not found for path '${indexOrPath}' from param '${this.param.path()}'`);
}
return null;
}
protected createDependency(
node: CoreGraphNode,
pathArgs: BaseMethodFindDependencyArgs,
decomposedPath?: DecomposedPath
): MethodDependency | null {
const dependency = MethodDependency.create(this.param, pathArgs, node, decomposedPath);
return dependency;
}
}