MaterialXLab API  0.0.1
APIs For MaterialXLab Libraries
Loading...
Searching...
No Matches
MxGraphBuilder Class Reference

Class which will build node graph connectivity information from a MaterialX document. More...

Public Member Functions

 constructor (doc)
 Constructor.
 
 setIncludeGraphs (graphs)
 Set graphs to include.
 
 getDictionary ()
 Get the graph dictionary.
 
 getConnections ()
 Get graph connections.
 
 updateGraphDictionaryPath (key, item, nodetype, type, value, graphDictionary)
 Update the graph dictionary with a new item.
 
 updateGraphDictionaryItem (item, graphDictionary)
 Update the graph dictionary with a new item.
 
 printGraphDictionary (graphDictionary)
 Print the graph dictionary.
 
 getParentGraph (elem)
 Get the parent graph of an element.
 
 getDefaultOutput (node)
 Get the default output of a node.
 
 appendPath (p1, p2)
 Append two paths together.
 
 buildPortConnection (doc, portPath, connections, portIsNode)
 Store a port connection.
 
 buildConnections (doc, graphElement, connections)
 Build the connections between graph elements.
 
 buildGraphDictionary (doc)
 Build the graph dictionary.
 
 execute ()
 Build the graph information.
 
 getJSON (inputFileName)
 Get the JSON representation of the graph information.
 
 exportToJSON (filename, inputFileName)
 Export the graph information to a JSON file.
 
 importFromJSON (filename)
 Import the graph information from a JSON file.
 

Detailed Description

Class which will build node graph connectivity information from a MaterialX document.

Definition at line 6 of file JsMaterialXGraph.js.

Member Function Documentation

◆ appendPath()

MxGraphBuilder::appendPath ( p1,
p2 )

Append two paths together.

Parameters
p1Path 1
p2Path 2
Returns
Appended path

Definition at line 167 of file JsMaterialXGraph.js.

167 {
168 return p2 ? p1 + '/' + p2 : p1;
169 }

◆ buildConnections()

MxGraphBuilder::buildConnections ( doc,
graphElement,
connections )

Build the connections between graph elements.

Parameters
docDocument
graphElementGraph element
connectionsSet of connections
Returns
{void}

Definition at line 305 of file JsMaterialXGraph.js.

305 {
306 let root = doc.getDocument();
307
308 for (let elem of graphElement.getChildren()) {
309 if (!elem.hasSourceUri()) {
310 if (elem instanceof mx.Input) {
311 this.buildPortConnection(root, elem.getNamePath(), connections, true);
312 } else if (elem instanceof mx.Output) {
313 this.buildPortConnection(root, elem.getNamePath(), connections, true);
314 } else if (elem instanceof mx.Node) {
315 let nodeInputs = elem.getInputs();
316 for (let nodeInput of nodeInputs) {
317 this.buildPortConnection(root, nodeInput.getNamePath(), connections, false);
318 }
319 } else if (elem instanceof mx.NodeGraph) {
320 let nodedef = elem.getNodeDef();
321 if (nodedef) {
322 connections.push([elem.getNamePath(), '', nodedef.getName(), '', 'nodedef']);
323 }
324 let visited = new Set();
325 let path = elem.getNamePath();
326 if (!visited.has(path)) {
327 visited.add(path);
328 this.buildConnections(root, elem, connections);
329 }
330 }
331 }
332 }
333 }
buildPortConnection(doc, portPath, connections, portIsNode)
Store a port connection.
buildConnections(doc, graphElement, connections)
Build the connections between graph elements.

◆ buildGraphDictionary()

MxGraphBuilder::buildGraphDictionary ( doc)

Build the graph dictionary.

Parameters
docDocument
Returns
Graph dictionary

Definition at line 340 of file JsMaterialXGraph.js.

340 {
341 let graphDictionary = {};
342 let root = doc.getDocument();
343 let skipped = [];
344
345 for (let elem of doc.getChildren()) {
346 if (elem.hasSourceUri()) {
347 skipped.push(elem.getNamePath());
348 } else {
349 if ((elem instanceof mx.Input) || (elem instanceof mx.Output) || (elem instanceof mx.Node)) {
350 //console.log('Scan element:', elem.getNamePath(), elem.getCategory(), mx.NodeGraph);
351 this.updateGraphDictionaryItem(elem, graphDictionary);
352 } else if (elem instanceof mx.NodeGraph) {
353 //console.log('Scan graph:', elem.getNamePath(), elem.getCategory(), mx.NodeGraph);
354 if (elem.getAttribute('nodedef')) {
355 let nodeDef = elem.getAttribute('nodedef');
356 nodeDef = root.getDescendant(nodeDef);
357 if (nodeDef) {
358 for (let nodeDefInput of nodeDef.getInputs()) {
359 if (elem.getChild("def_" + nodeDefInput.getName())) {
360 continue;
361 }
362 let newInput = elem.addInput("def_" + nodeDefInput.getName(), nodeDefInput.getType());
363 newInput.copyContentFrom(nodeDefInput);
364 }
365 }
366 }
367
368 for (let node of elem.getInputs()) {
369 this.updateGraphDictionaryItem(node, graphDictionary);
370 }
371 for (let node of elem.getOutputs()) {
372 this.updateGraphDictionaryItem(node, graphDictionary);
373 }
374 for (let node of elem.getNodes()) {
375 this.updateGraphDictionaryItem(node, graphDictionary);
376 }
377 for (let node of elem.getTokens()) {
378 this.updateGraphDictionaryItem(node, graphDictionary);
379 }
380 } else if ((elem instanceof mx.NodeDef) || (elem instanceof mx.Token)) {
381 this.updateGraphDictionaryItem(elem, graphDictionary);
382 }
383 }
384 }
385
386 return graphDictionary;
387 }
updateGraphDictionaryItem(item, graphDictionary)
Update the graph dictionary with a new item.

◆ buildPortConnection()

MxGraphBuilder::buildPortConnection ( doc,
portPath,
connections,
portIsNode )

Store a port connection.

Parameters
docDocument
portPathPath of the port
connectionsSet of connections
portIsNodePort is a node
Returns
{void}

Definition at line 179 of file JsMaterialXGraph.js.

179 {
180 let root = doc.getDocument();
181 let port = root.getDescendant(portPath);
182 if (!port) {
183 console.log('Element not found:', portPath);
184 return;
185 }
186
187 if (!(port instanceof mx.Input) && !(port instanceof mx.Output)) {
188 console.log('Element is not an input or output');
189 return;
190 }
191
192 let parent = port.getParent();
193 let parentPath = parent.getNamePath();
194 let parentGraph = this.getParentGraph(port);
195
196 if ((port instanceof mx.Input) && (parent instanceof mx.NodeGraph)) {
197 parentGraph = parentGraph.getParent();
198 }
199
200 if (!parentGraph) {
201 console.log('Cannot find parent graph of port', port);
202 //return;
203 }
204 let parentGraphPath = parentGraph.getNamePath();
205
206 let outputName = port.getOutputString();
207
208 let destNode = portIsNode ? portPath : parentPath;
209 let destPort = portIsNode ? '' : port.getName();
210
211 let nodename = port.getAttribute('nodename');
212 if (nodename) {
213 let result;
214 if (!parentGraphPath) {
215 result = [this.appendPath(nodename, ''), outputName, destNode, destPort, 'nodename'];
216 } else {
217 result = [this.appendPath(parentGraphPath, nodename), outputName, destNode, destPort, 'nodename'];
218 }
219 connections.push(result);
220 return;
221 }
222
223 let nodegraph = port.getNodeGraphString();
224 if (nodegraph) {
225 if (!outputName) {
226 outputName = this.getDefaultOutput(parentGraph.getChild(nodegraph));
227 }
228 let result;
229 if (!parentGraphPath) {
230 result = [this.appendPath(nodegraph, outputName), '', destNode, destPort, 'nodename'];
231 } else {
232 result = [this.appendPath(parentGraphPath, nodegraph), outputName, destNode, destPort, 'nodegraph'];
233 }
234 connections.push(result);
235 return;
236 }
237
238 let interfaceName = port.getInterfaceName();
239 if (interfaceName) {
240 let result;
241 if (!parentGraphPath) {
242 if (!outputName) {
243 outputName = this.getDefaultOutput(parentGraph.getChild(interfaceName));
244 }
245 result = [this.appendPath(interfaceName, outputName), '', destNode, destPort, 'nodename'];
246 } else {
247 let outputName = '';
248 let itemValue = '';
249 if (destNode === parentGraphPath + '/' + interfaceName) {
250 let dictItem = this.graphDictionary[parentGraphPath];
251 if (dictItem) {
252 let found = false;
253 for (let item of dictItem) {
254 if (item[0] === parentGraphPath + '/' + interfaceName) {
255 found = true;
256 break;
257 }
258 }
259 if (found) {
260 console.log('Warning: Rename duplicate interface:', parentGraphPath + '/' + interfaceName + ':in');
261 interfaceName = interfaceName + ':in';
262 }
263 }
264 }
265
266 let found = false;
267 let dictItem = this.graphDictionary[parentGraphPath];
268 if (dictItem) {
269 for (let item of dictItem) {
270 if (item[0] === parentGraphPath + '/' + interfaceName) {
271 found = true;
272 break;
273 }
274 }
275 }
276
277 if (!found) {
278 this.updateGraphDictionaryPath(parentGraphPath, parentGraphPath + '/' + interfaceName, 'input', port.getType(), itemValue, this.graphDictionary);
279 }
280 result = [this.appendPath(parentGraphPath, interfaceName), outputName, destNode, destPort, 'interfacename'];
281 }
282 connections.push(result);
283 return;
284 }
285
286 if (outputName) {
287 let result;
288 if (!parentGraphPath) {
289 result = [this.appendPath(outputName, ''), '', parentPath, port.getName(), 'nodename'];
290 } else {
291 result = [this.appendPath(parentGraphPath, outputName), '', parentPath, port.getName(), 'output'];
292 }
293 connections.push(result);
294 return;
295 }
296 }
getParentGraph(elem)
Get the parent graph of an element.
updateGraphDictionaryPath(key, item, nodetype, type, value, graphDictionary)
Update the graph dictionary with a new item.
appendPath(p1, p2)
Append two paths together.
getDefaultOutput(node)
Get the default output of a node.

◆ constructor()

MxGraphBuilder::constructor ( doc)

Constructor.

Parameters
{docMaterialX document

Definition at line 12 of file JsMaterialXGraph.js.

12 {
13 this.doc = doc;
14 this.graphDictionary = {};
15 this.connections = [];
16 this.includeGraphs = '';
17 }

◆ execute()

MxGraphBuilder::execute ( )

Build the graph information.

Returns
{void}

Definition at line 393 of file JsMaterialXGraph.js.

393 {
394 this.connections = [];
395 this.graphDictionary = {};
396
397 let graphElement = this.doc;
398 if (this.includeGraphs) {
399 let graph = this.includeGraphs;
400 graphElement = this.doc.getDescendant(graph);
401 if (graphElement) {
402 graphElement.setSourceUri('');
403 console.log('Scan graph:', graphElement.getNamePath());
404 } else {
405 console.log('Graph not found:', graph);
406 }
407 }
408
409 this.graphDictionary = this.buildGraphDictionary(graphElement);
410 this.buildConnections(this.doc, graphElement, this.connections);
411 }
buildGraphDictionary(doc)
Build the graph dictionary.

◆ exportToJSON()

MxGraphBuilder::exportToJSON ( filename,
inputFileName )

Export the graph information to a JSON file.

Parameters
filenameOutput file name
inputFileNameInput file name
Returns
{void}

Definition at line 434 of file JsMaterialXGraph.js.

434 {
435 let data = {
436 doc: 'Graph connections for: ' + inputFileName,
437 //copyright: 'Copyright 2024, NanMu Consulting. kwokcb@gmail.com',
438 graph: this.graphDictionary,
439 connections: this.connections
440 };
441
442 //let fs = require('fs');
443 //fs.writeFileSync(filename, JSON.stringify(data, null, 2));
444
445 let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data, null, 2));
446 let downloadAnchorNode = document.createElement('a');
447 downloadAnchorNode.setAttribute("href", dataStr);
448 downloadAnchorNode.setAttribute("download", filename);
449 document.body.appendChild(downloadAnchorNode); // required for firefox
450 downloadAnchorNode.click();
451 downloadAnchorNode.remove();
452 }

◆ getConnections()

MxGraphBuilder::getConnections ( )

Get graph connections.

Returns
Graph connections

Definition at line 40 of file JsMaterialXGraph.js.

40 {
41 return this.connections;
42 }

◆ getDefaultOutput()

MxGraphBuilder::getDefaultOutput ( node)

Get the default output of a node.

Parameters
nodeNode to check
Returns
Default output

Definition at line 143 of file JsMaterialXGraph.js.

143 {
144 if (!node) return '';
145
146 let defaultOutput = null;
147 if (node instanceof mx.Node) {
148 let nodedef = node.getNodeDef();
149 if (nodedef) {
150 defaultOutput = nodedef.getActiveOutputs()[0];
151 } else {
152 console.log('Cannot find nodedef for node:', node.getNamePath());
153 }
154 } else if (node instanceof mx.NodeGraph) {
155 defaultOutput = node.getOutputs()[0];
156 }
157
158 return defaultOutput ? defaultOutput.getName() : '';
159 }

◆ getDictionary()

MxGraphBuilder::getDictionary ( )

Get the graph dictionary.

Returns
Graph dictionary

Definition at line 32 of file JsMaterialXGraph.js.

32 {
33 return this.graphDictionary;
34 }

◆ getJSON()

MxGraphBuilder::getJSON ( inputFileName)

Get the JSON representation of the graph information.

Parameters
inputFileNameInput file name
Returns
JSON string

Definition at line 418 of file JsMaterialXGraph.js.

418 {
419 let data = {
420 doc: 'Graph connections for: ' + inputFileName,
421 //copyright: 'Copyright 2024, NanMu Consulting. kwokcb@gmail.com',
422 graph: this.graphDictionary,
423 connections: this.connections
424 };
425 return JSON.stringify(data, null, 4);
426 }

◆ getParentGraph()

MxGraphBuilder::getParentGraph ( elem)

Get the parent graph of an element.

Parameters
elemElement to check
Returns
Parent graph

Definition at line 131 of file JsMaterialXGraph.js.

131 {
132 while (elem && !(elem instanceof mx.GraphElement)) {
133 elem = elem.getParent();
134 }
135 return elem;
136 }

◆ importFromJSON()

MxGraphBuilder::importFromJSON ( filename)

Import the graph information from a JSON file.

Parameters
filenameInput file name
Returns
{void}

Definition at line 459 of file JsMaterialXGraph.js.

459 {
460 let fs = require('fs');
461 let data = JSON.parse(fs.readFileSync(filename, 'utf8'));
462 this.graphDictionary = data.graph;
463 this.connections = data.connections;
464 }

◆ printGraphDictionary()

MxGraphBuilder::printGraphDictionary ( graphDictionary)

Print the graph dictionary.

Parameters
graphDictionaryGraph dictionary
Returns
{void}

Definition at line 97 of file JsMaterialXGraph.js.

97 {
98 for (let graphPath in graphDictionary) {
99 if (graphPath === '') {
100 console.log('Root Document:');
101 } else {
102 console.log(graphPath + ':');
103 }
104
105 let filter = 'input';
106 for (let item of graphDictionary[graphPath]) {
107 if (item[1] !== filter) continue;
108 console.log('- ', item);
109 }
110
111 filter = 'output';
112 for (let item of graphDictionary[graphPath]) {
113 if (item[1] !== filter) continue;
114 console.log('- ', item);
115 }
116
117 filter = ['output', 'input'];
118 for (let item of graphDictionary[graphPath]) {
119 if (!filter.includes(item[1])) {
120 console.log('- ', item);
121 }
122 }
123 }
124 }

◆ setIncludeGraphs()

MxGraphBuilder::setIncludeGraphs ( graphs)

Set graphs to include.

Parameters
graphsGraphs to include
Returns
{void}

Definition at line 24 of file JsMaterialXGraph.js.

24 {
25 this.includeGraphs = graphs;
26 }

◆ updateGraphDictionaryItem()

MxGraphBuilder::updateGraphDictionaryItem ( item,
graphDictionary )

Update the graph dictionary with a new item.

Parameters
itemItem to add
graphDictionaryGraph dictionary
Returns
{void}

Definition at line 68 of file JsMaterialXGraph.js.

68 {
69 if (!item) return;
70
71 let parentElem = item.getParent();
72 if (!parentElem || !(parentElem instanceof mx.GraphElement)) return;
73
74 let key = parentElem.getNamePath();
75 let value = item.getNamePath();
76 let itemType = item.getType();
77 let itemCategory = item.getCategory();
78 let itemValue = '';
79
80 if (item instanceof mx.Node) {
81 let inputs = item.getInputs();
82 if (inputs.length === 1) {
83 itemValue = inputs[0].getValueString();
84 }
85 } else if (item instanceof mx.Input) {
86 itemValue = item.getValueString();
87 }
88
89 this.updateGraphDictionaryPath(key, value, itemCategory, itemType, itemValue, graphDictionary);
90 }

◆ updateGraphDictionaryPath()

MxGraphBuilder::updateGraphDictionaryPath ( key,
item,
nodetype,
type,
value,
graphDictionary )

Update the graph dictionary with a new item.

Parameters
keyKey for the dictionary
itemItem to add
nodetypeNode type
typeType of the node
valueValue of the node
graphDictionaryGraph dictionary
Returns
{void}

Definition at line 54 of file JsMaterialXGraph.js.

54 {
55 if (key in graphDictionary) {
56 graphDictionary[key].push([item, nodetype, type, value]);
57 } else {
58 graphDictionary[key] = [[item, nodetype, type, value]];
59 }
60 }

The documentation for this class was generated from the following file: