Jelajahi Sumber

TSL: Deferred function call and `.once()` (#29121)

sunag 1 tahun lalu
induk
melakukan
f8b24f7e66
1 mengubah file dengan 57 tambahan dan 33 penghapusan
  1. 57 33
      src/nodes/shadernode/ShaderNode.js

+ 57 - 33
src/nodes/shadernode/ShaderNode.js

@@ -251,15 +251,7 @@ class ShaderCallNodeInternal extends Node {
 
 	getNodeType( builder ) {
 
-		const properties = builder.getNodeProperties( this );
-
-		if ( properties.outputNode === null ) {
-
-			properties.outputNode = this.setupOutput( builder );
-
-		}
-
-		return properties.outputNode.getNodeType( builder );
+		return this.shaderNode.nodeType || this.getOutputNode( builder ).getNodeType( builder );
 
 	}
 
@@ -267,6 +259,13 @@ class ShaderCallNodeInternal extends Node {
 
 		const { shaderNode, inputNodes } = this;
 
+		const properties = builder.getNodeProperties( shaderNode );
+		if ( properties.onceOutput ) return properties.onceOutput;
+
+		//
+
+		let result = null;
+
 		if ( shaderNode.layout ) {
 
 			let functionNodesCacheMap = nodeBuilderFunctionsCacheMap.get( builder.constructor );
@@ -295,22 +294,44 @@ class ShaderCallNodeInternal extends Node {
 
 			}
 
-			return nodeObject( functionNode.call( inputNodes ) );
+			result = nodeObject( functionNode.call( inputNodes ) );
+
+		} else {
+
+			const jsFunc = shaderNode.jsFunc;
+			const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder );
+
+			result = nodeObject( outputNode );
 
 		}
 
-		const jsFunc = shaderNode.jsFunc;
-		const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder );
+		if ( shaderNode.once ) {
+
+			properties.onceOutput = result;
+
+		}
 
-		return nodeObject( outputNode );
+		return result;
 
 	}
 
-	setup( builder ) {
+	getOutputNode( builder ) {
 
-		const { outputNode } = builder.getNodeProperties( this );
+		const properties = builder.getNodeProperties( this );
 
-		return outputNode || this.setupOutput( builder );
+		if ( properties.outputNode === null ) {
+
+			properties.outputNode = this.setupOutput( builder );
+
+		}
+
+		return properties.outputNode;
+
+	}
+
+	setup( builder ) {
+
+		return this.getOutputNode( builder );
 
 	}
 
@@ -326,17 +347,9 @@ class ShaderCallNodeInternal extends Node {
 
 	generate( builder, output ) {
 
-		const { outputNode } = builder.getNodeProperties( this );
-
-		if ( outputNode === null ) {
-
-			// TSL: It's recommended to use `tslFn` in setup() pass.
-
-			return this.call( builder ).build( builder, output );
+		const outputNode = this.getOutputNode( builder );
 
-		}
-
-		return super.generate( builder, output );
+		return outputNode.build( builder, output );
 
 	}
 
@@ -344,15 +357,17 @@ class ShaderCallNodeInternal extends Node {
 
 class ShaderNodeInternal extends Node {
 
-	constructor( jsFunc ) {
+	constructor( jsFunc, nodeType ) {
 
-		super();
+		super( nodeType );
 
 		this.jsFunc = jsFunc;
 		this.layout = null;
 
 		this.global = true;
 
+		this.once = false;
+
 	}
 
 	get isArrayInput() {
@@ -480,9 +495,9 @@ export const getConstNodeType = ( value ) => ( value !== undefined && value !==
 
 // shader node base
 
-export function ShaderNode( jsFunc ) {
+export function ShaderNode( jsFunc, nodeType ) {
 
-	return new Proxy( new ShaderNodeInternal( jsFunc ), shaderNodeHandler );
+	return new Proxy( new ShaderNodeInternal( jsFunc, nodeType ), shaderNodeHandler );
 
 }
 
@@ -492,9 +507,9 @@ export const nodeArray = ( val, altType = null ) => new ShaderNodeArray( val, al
 export const nodeProxy = ( ...params ) => new ShaderNodeProxy( ...params );
 export const nodeImmutable = ( ...params ) => new ShaderNodeImmutable( ...params );
 
-export const Fn = ( jsFunc ) => {
+export const Fn = ( jsFunc, nodeType ) => {
 
-	const shaderNode = new ShaderNode( jsFunc );
+	const shaderNode = new ShaderNode( jsFunc, nodeType );
 
 	const fn = ( ...params ) => {
 
@@ -517,6 +532,7 @@ export const Fn = ( jsFunc ) => {
 	};
 
 	fn.shaderNode = shaderNode;
+
 	fn.setLayout = ( layout ) => {
 
 		shaderNode.setLayout( layout );
@@ -525,13 +541,21 @@ export const Fn = ( jsFunc ) => {
 
 	};
 
+	fn.once = () => {
+
+		shaderNode.once = true;
+
+		return fn;
+
+	};
+
 	return fn;
 
 };
 
 export const tslFn = ( ...params ) => { // @deprecated, r168
 
-	console.warn( 'TSL.tslFn: tslFn() has been renamed to Fn().' );
+	console.warn( 'TSL.ShaderNode: tslFn() has been renamed to Fn().' );
 	return Fn( ...params );
 
 };

粤ICP备19079148号