1- import { expect } from 'chai ' ;
1+ import { test , expect } from '@playwright/test ' ;
22import Module from './_build/JsMaterialXCore.js' ;
33import { getMtlxStrings } from './testHelpers.js' ;
44
5- describe ( 'Code Examples' , ( ) =>
5+ test . describe ( 'Code Examples' , ( ) =>
66{
7- it ( 'Building a MaterialX Document' , async ( ) =>
7+ test ( 'Building a MaterialX Document' , async ( ) =>
88 {
99 const mx = await Module ( ) ;
1010 // Create a document.
1111 const doc = mx . createDocument ( ) ;
1212
1313 // Create a node graph with a single image node and output.
1414 const nodeGraph = doc . addNodeGraph ( ) ;
15- expect ( doc . getNodeGraphs ( ) . length ) . to . equal ( 1 ) ;
15+ expect ( doc . getNodeGraphs ( ) . length ) . toBe ( 1 ) ;
1616 const image = nodeGraph . addNode ( 'image' ) ;
1717 const nodes = nodeGraph . getNodes ( ) ;
18- expect ( nodes . length ) . to . equal ( 1 ) ;
19- expect ( nodes [ 0 ] ) . to . eql ( image ) ;
18+ expect ( nodes . length ) . toBe ( 1 ) ;
19+ expect ( nodes [ 0 ] . equals ( image ) ) . toBe ( true ) ;
2020
2121 image . setInputValueString ( 'file' , 'image1.tif' , 'filename' ) ;
2222 const input = image . getInput ( 'file' ) ;
23- expect ( input ) . to . not . be . null ;
24- expect ( input . getValue ( ) . getData ( ) ) . to . equal ( 'image1.tif' ) ;
23+ expect ( input ) . not . toBeNull ( ) ;
24+ expect ( input . getValue ( ) . getData ( ) ) . toBe ( 'image1.tif' ) ;
2525
2626 const output = nodeGraph . addOutput ( ) ;
2727 const outputs = nodeGraph . getOutputs ( ) ;
28- expect ( outputs . length ) . to . equal ( 1 ) ;
29- expect ( outputs [ 0 ] ) . to . eql ( output ) ;
28+ expect ( outputs . length ) . toBe ( 1 ) ;
29+ expect ( outputs [ 0 ] . equals ( output ) ) . toBe ( true ) ;
3030
3131 output . setConnectedNode ( image ) ;
3232 const connectedNode = output . getConnectedNode ( ) ;
33- expect ( connectedNode ) . to . not . be . null ;
34- expect ( connectedNode instanceof mx . Node ) . to . be . true ;
33+ expect ( connectedNode ) . not . toBeNull ( ) ;
34+ expect ( connectedNode instanceof mx . Node ) . toBe ( true ) ;
3535
3636 // Create a simple shader interface.
3737 const simpleSrf = doc . addNodeDef ( 'ND_simpleSrf' , 'surfaceshader' , 'simpleSrf' ) ;
3838 const nodeDefs = doc . getNodeDefs ( ) ;
39- expect ( nodeDefs . length ) . to . equal ( 1 ) ;
40- expect ( nodeDefs [ 0 ] ) . to . eql ( simpleSrf ) ;
39+ expect ( nodeDefs . length ) . toBe ( 1 ) ;
40+ expect ( nodeDefs [ 0 ] . equals ( simpleSrf ) ) . toBe ( true ) ;
4141
4242 simpleSrf . setInputValueColor3 ( 'diffColor' , new mx . Color3 ( 1.0 , 1.0 , 1.0 ) ) ;
4343 let inputValue = simpleSrf . getInputValue ( 'diffColor' ) ;
44- expect ( inputValue ) . to . not . be . null ;
45- expect ( inputValue . getData ( ) ) . to . eql ( new mx . Color3 ( 1.0 , 1.0 , 1.0 ) ) ;
44+ expect ( inputValue ) . not . toBeNull ( ) ;
45+ expect ( inputValue . getData ( ) . equals ( new mx . Color3 ( 1.0 , 1.0 , 1.0 ) ) ) . toBe ( true ) ;
4646
4747 simpleSrf . setInputValueColor3 ( 'specColor' , new mx . Color3 ( 0.0 , 0.0 , 0.0 ) ) ;
4848 inputValue = simpleSrf . getInputValue ( 'specColor' ) ;
49- expect ( inputValue ) . to . not . be . null ;
50- expect ( inputValue . getData ( ) ) . to . eql ( new mx . Color3 ( 0.0 , 0.0 , 0.0 ) ) ;
49+ expect ( inputValue ) . not . toBeNull ( ) ;
50+ expect ( inputValue . getData ( ) . equals ( new mx . Color3 ( 0.0 , 0.0 , 0.0 ) ) ) . toBe ( true ) ;
5151
5252 const roughness = simpleSrf . setInputValueFloat ( 'roughness' , 0.25 ) ;
5353 inputValue = simpleSrf . getInputValue ( 'roughness' ) ;
54- expect ( inputValue ) . to . not . be . null ;
55- expect ( inputValue . getData ( ) ) . to . equal ( 0.25 ) ;
56-
57- // // Create a material that instantiates the shader.
58- // const material = doc.addMaterial();
59- // const materials = doc.getMaterials();
60- // expect(materials.length).to.equal(1);
61- // expect(materials[0]).to.eql(material);
62- // const refSimpleSrf = material.addShaderRef('SR_simpleSrf', 'simpleSrf');
63- // const shaderRefs = material.getShaderRefs();
64- // expect(shaderRefs.length).to.equal(1);
65- // expect(shaderRefs[0]).to.eql(refSimpleSrf);
66- // expect(shaderRefs[0].getName()).to.equal('SR_simpleSrf');
67-
68- // // Bind roughness to a new value within this material.
69- // const bindInput = refSimpleSrf.addBindInput('roughness');
70- // const bindInputs = refSimpleSrf.getBindInputs();
71- // expect(bindInputs.length).to.equal(1);
72- // expect(bindInputs[0]).to.eql(bindInput);
73- // bindInput.setValuefloat(0.5);
74- // expect(bindInput.getValue()).to.not.be.null;
75- // expect(bindInput.getValue().getData()).to.equal(0.5);
76-
77- // // Validate the value of roughness in the context of this material.
78- // expect(roughness.getBoundValue(material).getValueString()).to.equal('0.5');
54+ expect ( inputValue ) . not . toBeNull ( ) ;
55+ expect ( inputValue . getData ( ) ) . toBe ( 0.25 ) ;
56+
57+ // Instantiate the shader and create a material node that references it.
58+ const shaderNode = doc . addNodeInstance ( simpleSrf ) ;
59+ const materialNode = doc . addMaterialNode ( '' , shaderNode ) ;
60+ expect ( doc . getMaterialNodes ( ) . length ) . toBe ( 1 ) ;
61+
62+ // Connect the diffuse color of the shader to the image output, and
63+ // confirm that the upstream image node is reachable from the shader.
64+ shaderNode . setConnectedOutput ( 'diffColor' , output ) ;
65+ const upstreamNode = shaderNode . getUpstreamElement ( ) ;
66+ expect ( upstreamNode ) . not . toBeNull ( ) ;
67+ expect ( upstreamNode . getName ( ) ) . toBe ( image . getName ( ) ) ;
68+
69+ // Override roughness on this shader instance; its default value is
70+ // inherited from the shader's nodedef.
71+ const instanceRoughness = shaderNode . setInputValueFloat ( 'roughness' , 0.5 ) ;
72+ expect ( instanceRoughness . getValue ( ) . getData ( ) ) . toBe ( 0.5 ) ;
73+ expect ( instanceRoughness . getDefaultValue ( ) . getData ( ) ) . toBe ( roughness . getValue ( ) . getData ( ) ) ;
74+
7975 // Cleanup wrappers
8076 nodeDefs . forEach ( nd => nd . delete ( ) ) ;
77+ upstreamNode . delete ( ) ;
78+ instanceRoughness . delete ( ) ;
79+ materialNode . delete ( ) ;
80+ shaderNode . delete ( ) ;
8181 output . delete ( ) ;
8282 image . delete ( ) ;
8383 nodeGraph . delete ( ) ;
8484 doc . delete ( ) ;
8585 } ) ;
8686
87- it ( 'Traversing a Document Tree' , async ( ) =>
87+ test ( 'Traversing a Document Tree' , async ( ) =>
8888 {
8989 const xmlStr = getMtlxStrings (
9090 [ 'standard_surface_greysphere_calibration.mtlx' ] ,
@@ -106,11 +106,11 @@ describe('Code Examples', () =>
106106 imageCount ++ ;
107107 }
108108 }
109- expect ( imageCount ) . to . greaterThan ( 0 ) ;
109+ expect ( imageCount ) . toBeGreaterThan ( 0 ) ;
110110 doc . delete ( ) ;
111111 } ) ;
112112
113- it ( 'Building a MaterialX Document ', async ( ) =>
113+ test ( 'Traversing a Dataflow Graph ', async ( ) =>
114114 {
115115 const xmlStr = getMtlxStrings ( [ 'standard_surface_marble_solid.mtlx' ] , '../../resources/Materials/Examples/StandardSurface' ) [ 0 ] ;
116116 const mx = await Module ( ) ;
@@ -119,27 +119,49 @@ describe('Code Examples', () =>
119119 const doc = mx . createDocument ( ) ;
120120 await mx . readFromXmlString ( doc , xmlStr ) ;
121121
122- // let materialCount = 0;
123- // let shaderInputCount = 0;
124- // // Iterate through 1.37 materials for which there should be none
125- // const materials = doc.getMaterials();
126- // materials.forEach((material) => {
127- // materialCount++;
128-
129- // // For each shader input, find all upstream images in the dataflow graph.
130- // const primaryShaderInputs = material.getPrimaryShaderInputs();
131- // primaryShaderInputs.forEach((input) => {
132- // const graphIter = input.traverseGraph(material);
133- // let edge = graphIter.next();
134- // while (edge) {
135- // shaderInputCount++;
136- // edge = graphIter.next();
137- // }
138- // });
139- // });
140-
141- // expect(materialCount).to.equal(0);
142- // expect(shaderInputCount).to.equal(0);
122+ // For each material node, locate its surface shader and traverse the
123+ // dataflow graph upstream, gathering the nodes that contribute to the
124+ // shading result. The marble surface is driven by a procedural noise
125+ // network bound through a nodegraph, so the traversal crosses from the
126+ // top-level document into that nodegraph.
127+ const materialNodes = doc . getMaterialNodes ( ) ;
128+ expect ( materialNodes . length ) . toBe ( 1 ) ;
129+
130+ let nodeCount = 0 ;
131+ let crossedIntoNodeGraph = false ;
132+ for ( const materialNode of materialNodes )
133+ {
134+ const shaderNodes = mx . getShaderNodes ( materialNode ) ;
135+ for ( const shaderNode of shaderNodes )
136+ {
137+ for ( const edge of shaderNode . traverseGraph ( ) )
138+ {
139+ const upstreamElem = edge . getUpstreamElement ( ) ;
140+ if ( upstreamElem instanceof mx . Node )
141+ {
142+ nodeCount ++ ;
143+
144+ // An upstream node whose parent is a nodegraph rather
145+ // than the document confirms that the traversal has
146+ // descended into the bound nodegraph.
147+ const parent = upstreamElem . getParent ( ) ;
148+ if ( parent instanceof mx . NodeGraph )
149+ {
150+ crossedIntoNodeGraph = true ;
151+ }
152+ if ( parent ) parent . delete ( ) ;
153+ }
154+ if ( upstreamElem ) upstreamElem . delete ( ) ;
155+ if ( edge ) edge . delete ( ) ;
156+ }
157+ }
158+ shaderNodes . forEach ( s => s . delete ( ) ) ;
159+ }
160+ expect ( nodeCount ) . toBeGreaterThan ( 0 ) ;
161+ expect ( crossedIntoNodeGraph ) . toBe ( true ) ;
162+
163+ // Cleanup wrappers
164+ materialNodes . forEach ( n => n . delete ( ) ) ;
143165 doc . delete ( ) ;
144166 } ) ;
145167} ) ;
0 commit comments