Skip to content

Commit 37daca1

Browse files
committed
add overrideNode
1 parent aee0fd4 commit 37daca1

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

src/Three.TSL.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ export const output = TSL.output;
417417
export const outputStruct = TSL.outputStruct;
418418
export const overlay = TSL.overlay;
419419
export const overloadingFn = TSL.overloadingFn;
420+
export const overrideNode = TSL.overrideNode;
420421
export const parabola = TSL.parabola;
421422
export const parallaxDirection = TSL.parallaxDirection;
422423
export const parallaxUV = TSL.parallaxUV;

src/nodes/Nodes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export { default as BypassNode } from './core/BypassNode.js';
99
export { default as IsolateNode } from './core/IsolateNode.js';
1010
export { default as ConstNode } from './core/ConstNode.js';
1111
export { default as ContextNode } from './core/ContextNode.js';
12+
export { default as OverrideContextNode } from './core/OverrideContextNode.js';
1213
export { default as IndexNode } from './core/IndexNode.js';
1314
export { default as LightingModel } from './core/LightingModel.js';
1415
export { default as Node } from './core/Node.js';

src/nodes/TSL.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './core/AttributeNode.js';
77
export * from './core/BypassNode.js';
88
export * from './core/IsolateNode.js';
99
export * from './core/ContextNode.js';
10+
export * from './core/OverrideContextNode.js';
1011
export * from './core/IndexNode.js';
1112
export * from './core/ParameterNode.js';
1213
export * from './core/PropertyNode.js';

src/nodes/core/Node.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,43 @@ class Node extends EventDispatcher {
554554
const hash = this.getHash( builder );
555555
const nodeFromHash = builder.getNodeFromHash( hash );
556556

557-
return nodeFromHash || this;
557+
let sharedNode = null;
558+
559+
if ( nodeFromHash && nodeFromHash !== this ) {
560+
561+
sharedNode = nodeFromHash;
562+
563+
} else if ( builder.context.overrideNodes ) {
564+
565+
const callback = builder.context.overrideNodes.get( this );
566+
567+
if ( callback ) {
568+
569+
const nodeData = builder.getDataFromNode( this );
570+
571+
if ( nodeData.isOverwritten !== true ) {
572+
573+
nodeData.isOverwritten = true;
574+
575+
// cancel the override for use the same node inside the callback
576+
577+
sharedNode = callback().overrideNode( this, null );
578+
579+
nodeData.sharedNode = sharedNode;
580+
581+
} else {
582+
583+
// avoid recursive override calls
584+
585+
sharedNode = nodeData.sharedNode;
586+
587+
}
588+
589+
}
590+
591+
}
592+
593+
return sharedNode || this;
558594

559595
}
560596

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import ContextNode from './ContextNode.js';
2+
import { addMethodChaining } from '../tsl/TSLCore.js';
3+
4+
/**
5+
* A context node that overrides a target node within a callback function.
6+
*
7+
* @augments ContextNode
8+
*/
9+
class OverrideContextNode extends ContextNode {
10+
11+
static get type() {
12+
13+
return 'OverrideContextNode';
14+
15+
}
16+
17+
constructor( targetNode, callback, flowNode = null ) {
18+
19+
super( flowNode, {
20+
overrideNodes: new Map( [[ targetNode, callback ]] )
21+
} );
22+
23+
/**
24+
* This flag can be used for type testing.
25+
*
26+
* @type {boolean}
27+
* @readonly
28+
* @default true
29+
*/
30+
this.isOverrideContextNode = true;
31+
32+
/**
33+
* A reference to the target node to override.
34+
*
35+
* @type {Node}
36+
*/
37+
this.targetNode = targetNode;
38+
39+
/**
40+
* A callback function that returns the overriding node.
41+
*
42+
* @type {Function}
43+
*/
44+
this.callback = callback;
45+
46+
}
47+
48+
/**
49+
* Gathers the context data from all parent context nodes.
50+
*
51+
* @return {Object} The gathered context data.
52+
*/
53+
getFlowContextData() {
54+
55+
const children = [];
56+
57+
this.traverse( ( node ) => {
58+
59+
if ( node.isOverrideContextNode === true ) {
60+
61+
children.push( node.value.overrideNodes );
62+
63+
}
64+
65+
} );
66+
67+
const overrideNodes = new Map( children.flatMap( ( map ) => Array.from( map.entries() ) ) );
68+
69+
const data = super.getFlowContextData();
70+
data.overrideNodes = overrideNodes;
71+
72+
return data;
73+
74+
}
75+
76+
}
77+
78+
export default OverrideContextNode;
79+
80+
/**
81+
* Creates an OverrideContextNode that overrides a target node within a callback function.
82+
*
83+
* @param {Node} targetNode - The target node to override.
84+
* @param {Function} callback - A callback function that returns the overriding node.
85+
* @param {Node} [flowNode=null] - An optional flow node.
86+
* @return {OverrideContextNode} The created OverrideContextNode.
87+
*/
88+
export function overrideNode( targetNode, callback, flowNode = null ) {
89+
90+
return new OverrideContextNode( targetNode, callback, flowNode );
91+
92+
}
93+
94+
addMethodChaining( 'overrideNode', ( flowNode, node, callback ) => overrideNode( node, callback, flowNode ) );

0 commit comments

Comments
 (0)