Просмотр исходного кода

TSL: Replace `Proxy` approach with `prototypes` (#31691)

* remove `Proxy` approach

* Update TSLCore.js

* Node: Remove`.getSelf()`

* Update TSLCore.js
sunag 4 месяцев назад
Родитель
Сommit
f78867d90a

+ 1 - 1
src/nodes/accessors/CubeTextureNode.js

@@ -162,7 +162,7 @@ export const cubeTexture = ( value = EmptyTexture, uvNode = null, levelNode = nu
 	if ( value && value.isCubeTextureNode === true ) {
 
 		textureNode = nodeObject( value.clone() );
-		textureNode.referenceNode = value.getSelf(); // Ensure the reference is set to the original node
+		textureNode.referenceNode = value; // Ensure the reference is set to the original node
 
 		if ( uvNode !== null ) textureNode.uvNode = nodeObject( uvNode );
 		if ( levelNode !== null ) textureNode.levelNode = nodeObject( levelNode );

+ 1 - 1
src/nodes/accessors/ReferenceBaseNode.js

@@ -211,7 +211,7 @@ class ReferenceBaseNode extends Node {
 	 */
 	setNodeType( uniformType ) {
 
-		const node = uniform( null, uniformType ).getSelf();
+		const node = uniform( null, uniformType );
 
 		if ( this.group !== null ) {
 

+ 1 - 1
src/nodes/accessors/ReferenceNode.js

@@ -284,7 +284,7 @@ class ReferenceNode extends Node {
 
 		if ( this.name !== null ) node.setName( this.name );
 
-		this.node = node.getSelf();
+		this.node = node;
 
 	}
 

+ 1 - 1
src/nodes/accessors/TextureNode.js

@@ -667,7 +667,7 @@ class TextureNode extends UniformNode {
 	 */
 	getBase() {
 
-		return this.referenceNode ? this.referenceNode.getBase() : this.getSelf();
+		return this.referenceNode ? this.referenceNode.getBase() : this;
 
 	}
 

+ 2 - 16
src/nodes/core/Node.js

@@ -172,7 +172,7 @@ class Node extends EventDispatcher {
 	onUpdate( callback, updateType ) {
 
 		this.updateType = updateType;
-		this.update = callback.bind( this.getSelf() );
+		this.update = callback.bind( this );
 
 		return this;
 
@@ -225,26 +225,12 @@ class Node extends EventDispatcher {
 	 */
 	onReference( callback ) {
 
-		this.updateReference = callback.bind( this.getSelf() );
+		this.updateReference = callback.bind( this );
 
 		return this;
 
 	}
 
-	/**
-	 * The `this` reference might point to a Proxy so this method can be used
-	 * to get the reference to the actual node instance.
-	 *
-	 * @return {Node} A reference to the node.
-	 */
-	getSelf() {
-
-		// Returns non-node object.
-
-		return this.self || this;
-
-	}
-
 	/**
 	 * Nodes might refer to other objects like materials. This method allows to dynamically update the reference
 	 * to such objects based on a given state (e.g. the current node frame or builder).

+ 3 - 3
src/nodes/core/NodeBuilder.js

@@ -729,7 +729,7 @@ class NodeBuilder {
 
 			if ( updateType !== NodeUpdateType.NONE ) {
 
-				this.updateNodes.push( node.getSelf() );
+				this.updateNodes.push( node );
 
 			}
 
@@ -742,13 +742,13 @@ class NodeBuilder {
 
 			if ( updateBeforeType !== NodeUpdateType.NONE ) {
 
-				this.updateBeforeNodes.push( node.getSelf() );
+				this.updateBeforeNodes.push( node );
 
 			}
 
 			if ( updateAfterType !== NodeUpdateType.NONE ) {
 
-				this.updateAfterNodes.push( node.getSelf() );
+				this.updateAfterNodes.push( node );
 
 			}
 

+ 1 - 1
src/nodes/core/NodeUniform.js

@@ -43,7 +43,7 @@ class NodeUniform {
 		 *
 		 * @type {UniformNode}
 		 */
-		this.node = node.getSelf();
+		this.node = node;
 
 	}
 

+ 1 - 2
src/nodes/core/NodeUtils.js

@@ -88,7 +88,6 @@ export function getCacheKey( object, force = false ) {
 	if ( object.isNode === true ) {
 
 		values.push( object.id );
-		object = object.getSelf();
 
 	}
 
@@ -113,7 +112,7 @@ export function getCacheKey( object, force = false ) {
  */
 export function* getNodeChildren( node, toJSON = false ) {
 
-	for ( const property in node ) {
+	for ( const property of Object.getOwnPropertyNames( node ) ) {
 
 		// Ignore private properties.
 		if ( property.startsWith( '_' ) === true ) continue;

+ 2 - 4
src/nodes/core/UniformNode.js

@@ -123,13 +123,11 @@ class UniformNode extends InputNode {
 
 	onUpdate( callback, updateType ) {
 
-		const self = this.getSelf();
-
-		callback = callback.bind( self );
+		callback = callback.bind( this );
 
 		return super.onUpdate( ( frame ) => {
 
-			const value = callback( frame, self );
+			const value = callback( frame, this );
 
 			if ( value !== undefined ) {
 

+ 1 - 1
src/nodes/lighting/LightsNode.js

@@ -159,7 +159,7 @@ class LightsNode extends Node {
 
 			for ( const lightNode of this._lightNodes ) {
 
-				hash.push( lightNode.getSelf().getHash() );
+				hash.push( lightNode.getHash() );
 
 			}
 

+ 185 - 69
src/nodes/tsl/TSLCore.js

@@ -13,6 +13,8 @@ let currentStack = null;
 
 const NodeElements = new Map();
 
+// Extend Node Class for TSL using prototype
+
 export function addMethodChaining( name, nodeElement ) {
 
 	if ( NodeElements.has( name ) ) {
@@ -26,152 +28,266 @@ export function addMethodChaining( name, nodeElement ) {
 
 	NodeElements.set( name, nodeElement );
 
+	if ( name !== 'assign' ) {
+
+		// Changing Node prototype to add method chaining
+
+		Node.prototype[ name ] = function ( ...params ) {
+
+			//if ( name === 'toVarIntent' ) return this;
+
+			return this.isStackNode ? this.add( nodeElement( ...params ) ) : nodeElement( this, ...params );
+
+		};
+
+		// Adding assign method chaining
+
+		Node.prototype[ name + 'Assign' ] = function ( ...params ) {
+
+			return this.isStackNode ? this.assign( params[ 0 ], nodeElement( ...params ) ) : this.assign( nodeElement( this, ...params ) );
+
+		};
+
+	}
+
 }
 
 const parseSwizzle = ( props ) => props.replace( /r|s/g, 'x' ).replace( /g|t/g, 'y' ).replace( /b|p/g, 'z' ).replace( /a|q/g, 'w' );
 const parseSwizzleAndSort = ( props ) => parseSwizzle( props ).split( '' ).sort().join( '' );
 
-const shaderNodeHandler = {
+Node.prototype.assign = function ( ...params ) {
 
-	setup( NodeClosure, params ) {
+	if ( this.isStackNode !== true ) {
 
-		const inputs = params.shift();
+		currentStack.assign( this, ...params );
 
-		return NodeClosure( nodeObjects( inputs ), ...params );
+		return this;
 
-	},
+	} else {
 
-	get( node, prop, nodeObj ) {
+		const nodeElement = NodeElements.get( 'assign' );
 
-		if ( typeof prop === 'string' && node[ prop ] === undefined ) {
+		return this.add( nodeElement( ...params ) );
 
-			if ( node.isStackNode !== true && prop === 'assign' ) {
+	}
 
-				return ( ...params ) => {
+};
 
-					currentStack.assign( nodeObj, ...params );
+Node.prototype.toVarIntent = function () {
 
-					return nodeObj;
+	return this;
 
-				};
+};
+
+Node.prototype.get = function ( value ) {
+
+	return new MemberNode( this, value );
 
-			} else if ( NodeElements.has( prop ) ) {
+};
+
+// Cache prototype for TSL
+
+const proto = {};
+
+// Set swizzle properties for xyzw, rgba, and stpq.
+
+function setProtoSwizzle( property, altA, altB ) {
+
+	// swizzle properties
 
-				const nodeElement = NodeElements.get( prop );
+	proto[ property ] = proto[ altA ] = proto[ altB ] = {
 
-				return node.isStackNode ? ( ...params ) => nodeObj.add( nodeElement( ...params ) ) : ( ...params ) => nodeElement( nodeObj, ...params );
+		get() {
 
-			} else if ( prop === 'toVarIntent' ) {
+			this._cache = this._cache || {};
 
-				return () => nodeObj;
+			//
+
+			let split = this._cache[ property ];
 
-			} else if ( prop === 'self' ) {
+			if ( split === undefined ) {
 
-				return node;
+				split = new SplitNode( this, property );
 
-			} else if ( prop.endsWith( 'Assign' ) && NodeElements.has( prop.slice( 0, prop.length - 'Assign'.length ) ) ) {
+				this._cache[ property ] = split;
 
-				const nodeElement = NodeElements.get( prop.slice( 0, prop.length - 'Assign'.length ) );
+			}
 
-				return node.isStackNode ? ( ...params ) => nodeObj.assign( params[ 0 ], nodeElement( ...params ) ) : ( ...params ) => nodeObj.assign( nodeElement( nodeObj, ...params ) );
+			return split;
 
-			} else if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true ) {
+		},
 
-				// accessing properties ( swizzle )
+		set( value ) {
 
-				prop = parseSwizzle( prop );
+			this[ property ].assign( nodeObject( value ) );
 
-				return nodeObject( new SplitNode( nodeObj, prop ) );
+		}
 
-			} else if ( /^set[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) {
+	};
 
-				// set properties ( swizzle ) and sort to xyzw sequence
+	// set properties ( swizzle ) and sort to xyzw sequence
 
-				prop = parseSwizzleAndSort( prop.slice( 3 ).toLowerCase() );
+	const propUpper = property.toUpperCase();
+	const altAUpper = altA.toUpperCase();
+	const altBUpper = altB.toUpperCase();
 
-				return ( value ) => nodeObject( new SetNode( node, prop, nodeObject( value ) ) );
+	// Set methods for swizzle properties
 
-			} else if ( /^flip[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) {
+	Node.prototype[ 'set' + propUpper ] = Node.prototype[ 'set' + altAUpper ] = Node.prototype[ 'set' + altBUpper ] = function ( value ) {
 
-				// set properties ( swizzle ) and sort to xyzw sequence
+		const swizzle = parseSwizzleAndSort( property );
+
+		return new SetNode( this, swizzle, nodeObject( value ) );
+
+	};
+
+	// Set methods for flip properties
+
+	Node.prototype[ 'flip' + propUpper ] = Node.prototype[ 'flip' + altAUpper ] = Node.prototype[ 'flip' + altBUpper ] = function () {
+
+		const swizzle = parseSwizzleAndSort( property );
+
+		return new FlipNode( this, swizzle );
+
+	};
+
+}
 
-				prop = parseSwizzleAndSort( prop.slice( 4 ).toLowerCase() );
+const swizzleA = [ 'x', 'y', 'z', 'w' ];
+const swizzleB = [ 'r', 'g', 'b', 'a' ];
+const swizzleC = [ 's', 't', 'p', 'q' ];
 
-				return () => nodeObject( new FlipNode( nodeObject( node ), prop ) );
+for ( let a = 0; a < 4; a ++ ) {
 
-			} else if ( prop === 'width' || prop === 'height' || prop === 'depth' ) {
+	let prop = swizzleA[ a ];
+	let altA = swizzleB[ a ];
+	let altB = swizzleC[ a ];
 
-				// accessing property
+	setProtoSwizzle( prop, altA, altB );
 
-				if ( prop === 'width' ) prop = 'x';
-				else if ( prop === 'height' ) prop = 'y';
-				else if ( prop === 'depth' ) prop = 'z';
+	for ( let b = 0; b < 4; b ++ ) {
 
-				return nodeObject( new SplitNode( node, prop ) );
+		prop = swizzleA[ a ] + swizzleA[ b ];
+		altA = swizzleB[ a ] + swizzleB[ b ];
+		altB = swizzleC[ a ] + swizzleC[ b ];
 
-			} else if ( /^\d+$/.test( prop ) === true ) {
+		setProtoSwizzle( prop, altA, altB );
 
-				// accessing array
+		for ( let c = 0; c < 4; c ++ ) {
 
-				return nodeObject( new ArrayElementNode( nodeObj, new ConstNode( Number( prop ), 'uint' ) ) );
+			prop = swizzleA[ a ] + swizzleA[ b ] + swizzleA[ c ];
+			altA = swizzleB[ a ] + swizzleB[ b ] + swizzleB[ c ];
+			altB = swizzleC[ a ] + swizzleC[ b ] + swizzleC[ c ];
 
-			} else if ( /^get$/.test( prop ) === true ) {
+			setProtoSwizzle( prop, altA, altB );
 
-				// accessing properties
+			for ( let d = 0; d < 4; d ++ ) {
 
-				return ( value ) => nodeObject( new MemberNode( nodeObj, value ) );
+				prop = swizzleA[ a ] + swizzleA[ b ] + swizzleA[ c ] + swizzleA[ d ];
+				altA = swizzleB[ a ] + swizzleB[ b ] + swizzleB[ c ] + swizzleB[ d ];
+				altB = swizzleC[ a ] + swizzleC[ b ] + swizzleC[ c ] + swizzleC[ d ];
+
+				setProtoSwizzle( prop, altA, altB );
 
 			}
 
 		}
 
-		return Reflect.get( node, prop, nodeObj );
+	}
+
+}
+
+// Set/get static properties for array elements (0-31).
+
+for ( let i = 0; i < 32; i ++ ) {
 
-	},
+	proto[ i ] = {
 
-	set( node, prop, value, nodeObj ) {
+		get() {
 
-		if ( typeof prop === 'string' && node[ prop ] === undefined ) {
+			this._cache = this._cache || {};
 
-			// setting properties
+			//
+
+			let element = this._cache[ i ];
 
-			if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true || prop === 'width' || prop === 'height' || prop === 'depth' || /^\d+$/.test( prop ) === true ) {
+			if ( element === undefined ) {
 
-				nodeObj[ prop ].assign( value );
+				element = new ArrayElementNode( this, new ConstNode( i, 'uint' ) );
 
-				return true;
+				this._cache[ i ] = element;
 
 			}
 
+			return element;
+
+		},
+
+		set( value ) {
+
+			this[ i ].assign( nodeObject( value ) );
+
 		}
 
-		return Reflect.set( node, prop, value, nodeObj );
+	};
 
-	}
+}
 
-};
+/*
+// Set properties for width, height, and depth.
 
-const nodeObjectsCacheMap = new WeakMap();
-const nodeBuilderFunctionsCacheMap = new WeakMap();
+function setProtoProperty( property, target ) {
 
-const ShaderNodeObject = function ( obj, altType = null ) {
+	proto[ property ] = {
 
-	const type = getValueType( obj );
+		get() {
 
-	if ( type === 'node' ) {
+			this._cache = this._cache || {};
+
+			//
 
-		let nodeObject = nodeObjectsCacheMap.get( obj );
+			let split = this._cache[ target ];
 
-		if ( nodeObject === undefined ) {
+			if ( split === undefined ) {
 
-			nodeObject = new Proxy( obj, shaderNodeHandler );
+				split = new SplitNode( this, target );
 
-			nodeObjectsCacheMap.set( obj, nodeObject );
-			nodeObjectsCacheMap.set( nodeObject, nodeObject );
+				this._cache[ target ] = split;
+
+			}
+
+			return split;
+
+		},
+
+		set( value ) {
+
+			this[ target ].assign( nodeObject( value ) );
 
 		}
 
-		return nodeObject;
+	};
+
+}
+
+setProtoProperty( 'width', 'x' );
+setProtoProperty( 'height', 'y' );
+setProtoProperty( 'depth', 'z' );
+*/
+
+Object.defineProperties( Node.prototype, proto );
+
+// --- FINISH ---
+
+const nodeBuilderFunctionsCacheMap = new WeakMap();
+
+const ShaderNodeObject = function ( obj, altType = null ) {
+
+	const type = getValueType( obj );
+
+	if ( type === 'node' ) {
+
+		return obj;
 
 	} else if ( ( altType === null && ( type === 'float' || type === 'boolean' ) ) || ( type && type !== 'shader' && type !== 'string' ) ) {
 
@@ -778,7 +894,7 @@ export const getConstNodeType = ( value ) => ( value !== undefined && value !==
 
 export function ShaderNode( jsFunc, nodeType ) {
 
-	return new Proxy( new ShaderNodeInternal( jsFunc, nodeType ), shaderNodeHandler );
+	return new ShaderNodeInternal( jsFunc, nodeType );
 
 }
 

粤ICP备19079148号