MaterialXUSD 0.0.1
Utilities for using MaterialX with USD
Loading...
Searching...
No Matches
materialxusd.materialxusd_utils.MaterialXUsdUtilities Class Reference

A collection of support utilities for working with MaterialX and USD. More...

Public Member Functions

 __init__ (self)
 Constructor.
 
 load_standard_libraries (self)
 Load standard MaierialX libraries.
 
 get_standard_libraries (self)
 Get standard MaierialX libraries.
 
 create_document (self, str path)
 Create a MaterialX document from a file path.
 
 write_document (self, mx.Document doc, str path)
 Write a MaterialX document to a file.
 
 create_FileSearchPath (self, list search_paths)
 Create a MaterialX file search path from a list of string paths.
 
 resolve_image_file_paths (self, mx.Document doc, mx.FileSearchPath search_paths)
 Resolve image file paths in a MaterialX document.
 
 add_nodegraph_output_qualifier_on_shaders (self, mx.Document doc)
 Add nodegraph output qualifier on shaders in the MaterialX document if not already set.
 
 add_materials_for_shaders (self, mx.Document doc)
 Add materials for shaders at the root level of a MaterialX document.
 
 add_downstream_materials (self, mx.Document doc, logger=None)
 Add downstream materials to the MaterialX graph.
 
 add_explicit_geometry_stream (self, mx.GraphElement graph)
 Add explicit geometry stream nodes for inputs with defaultgeomprop specified in nodes definition.
 
 encapsulate_top_level_nodes (self, mx.Document doc, str nodegraph_name="top_level_nodes", bool remove_original=True)
 Encapsulate top level nodes in a nodegraph.
 
 encapsulate_top_level_nodes_file (self, str input_path, str new_input_path, str nodegraph_name='top_level_nodes', bool remove_original_nodes=True)
 Encapsulate top level nodes in a nodegraph.
 

Public Attributes

 logger = logging.getLogger('MXUSDUTIL')
 

Protected Attributes

 _stdlib
 
 _libFiles = self.load_standard_libraries()
 

Detailed Description

A collection of support utilities for working with MaterialX and USD.

Definition at line 10 of file materialxusd_utils.py.

Constructor & Destructor Documentation

◆ __init__()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.__init__ ( self)

Constructor.

Definition at line 15 of file materialxusd_utils.py.

15 def __init__(self):
16 '''
17 @brief Constructor.
18 '''
19 self._stdlib, self._libFiles = self.load_standard_libraries()
20 logging.basicConfig(level=logging.INFO)
21 self.logger = logging.getLogger('MXUSDUTIL')
22

Member Function Documentation

◆ add_downstream_materials()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.add_downstream_materials ( self,
mx.Document doc,
logger = None )

Add downstream materials to the MaterialX graph.

Parameters
docThe MaterialX document.
Returns
The number of materials added.

Definition at line 144 of file materialxusd_utils.py.

144 def add_downstream_materials(self, doc: mx.Document, logger=None):
145 '''
146 @brief Add downstream materials to the MaterialX graph.
147 @param doc The MaterialX document.
148 @return The number of materials added.
149 '''
150 # If has materials skip
151 material_count = len(doc.getMaterialNodes())
152 if material_count > 0:
153 return 0
154
155 nodegraphs = doc.getNodeGraphs()
156 if not nodegraphs:
157 return 0
158
159 # Only support these types of graph outputs
160 supported_output_types = [ 'float', 'vector2', 'vector3', 'vector4', 'integer', 'boolean', 'color3', 'color4' ]
161
162 for graph in nodegraphs:
163 if graph.hasSourceUri():
164 continue
165
166
167 graph_outputs = graph.getOutputs()
168 if not graph_outputs:
169 continue
170
171 self.logger.debug(f'Scan graph: {graph.getName()}')
172
173 # Use does not support these nodes so need to do it the hard way....
174 usd_supports_convert_to_surface_shader = False
175
176 downstream_ports = graph.getDownstreamPorts()
177 for output in graph_outputs:
178 # See if output name path is in downstream ports
179 match = False
180 for port in downstream_ports:
181 if port.getNamePath() == output.getNamePath():
182 match = True
183 break
184 if match:
185 downstream_ports.remove(port)
186
187 #downstream_port_count = 0
188 #for port in downstream_ports:
189 # match = False
190 # for output in graph_outputs:
191 # if port.getName() == output.getName():
192 # match = True
193 # break
194 # if not match:
195 # downstream_port_count += 1
196
197 if downstream_ports:
198 self.logger.info('>>> Downstream port:' + ",".join( [port.getNamePath() for port in downstream_ports]))
199 if len(downstream_ports) == 0:
200 # Add a material per output
201 #
202 is_multi_output = len(graph_outputs) > 1
203 for output in graph_outputs:
204 #if downstream_ports:
205 # for port in downstream_ports:
206 # if port.getNamePath() == output.getNamePath():
207 # self.logger.info('---- SKIP OUTPUT :', output.getNamePath())
208 # continue
209
210 output_name = output.getName()
211 output_type = output.getType()
212
213 #self.logger.info(f'>>> Scan output: {output_name}. type: {output_type}')
214
215 # Special case for surfaceshader outputs. Just add in a downstream material
216 if output_type == 'surfaceshader':
217 graph_parent = graph.getParent()
218 connected_ss = output.getConnectedNode()
219 if not graph_parent or not connected_ss:
220 continue
221
222 self.logger.info(f'Extract unsupported shader inside nodegraph: {connected_ss.getNamePath()}')
223
224 shadernode_name = graph_parent.createValidChildName(connected_ss.getName())
225 shadernode_nodedef = connected_ss.getNodeDef()
226 shadernode = graph_parent.addNodeInstance(shadernode_nodedef, shadernode_name)
227 shadernode.copyContentFrom(connected_ss)
228
229 # For every connected input on the surfaceshader node
230 # create a nodegraph output
231 for ss_input in connected_ss.getInputs():
232 ss_input_input = ss_input.getNodeName() if ss_input.getNodeName() else ss_input.getInterfaceName()
233 if not ss_input_input:
234 continue
235 ss_input_type = ss_input.getType()
236 ss_input_output = graph.addOutput(graph.createValidChildName('out'), ss_input_type)
237 ss_input_output.setNodeName(ss_input_input)
238 if ss_input.getOutputString():
239 ss_input_output.setOutputString(ss_input.getOutputString())
240
241 # Connect new graph output to new shader node's input to
242 shadernode_input = shadernode.getInput(ss_input.getName())
243 if shadernode_input:
244 shadernode_input.removeAttribute('nodename')
245 shadernode_input.removeAttribute('value')
246 shadernode_input.setNodeGraphString(graph.getName())
247 shadernode_input.setOutputString(ss_input_output.getName())
248
249 # Should do this after scanning all surfaceshader nodes...
250 graph.removeNode(connected_ss.getName())
251 graph.removeOutput(output_name)
252
253 # Add a material for the shader
254 material_name = doc.createValidChildName(graph.getName() + '_' + output_name)
255 material_node = doc.addMaterialNode(material_name)
256 if material_node:
257 self.logger.info(f"Added material node: {material_node.getName()}, for graph shader output: {output_name}")
258 material_node_input = material_node.addInput(output_type, output_type)
259 #material_node_input.setNodeGraphString(graph.getName())
260 #material_node_input.setOutputString(output_name)
261 material_node_input.setNodeName(shadernode_name)
262 material_node_input.removeAttribute('value')
263 material_count += 1
264
265 elif output_type in supported_output_types:
266
267 if usd_supports_convert_to_surface_shader:
268 # Create a new material node
269 shadernode_name = doc.createValidChildName('SHD_' + graph.getName() + '_' + output_name)
270 materialnode_name = doc.createValidChildName('MAT' + graph.getName() + '_' + output_name)
271
272 convert_definition = 'ND_convert_' + output_type + '_color3'
273 convert_node = doc.getNodeDef(convert_definition)
274 if not convert_node:
275 self.logger.info(f'>>>> Failed to find conversion definition: {convert_definition}')
276 else:
277 shadernode = doc.addNodeInstance(convert_node, shadernode_name)
278 shadernode.removeAttribute('nodedef')
279 new_input = shadernode.addInput('in', output_type)
280 new_input.setNodeGraphString(graph.getName())
281 new_input.removeAttribute('value')
282 #if is_multi_output:
283 # ISSUE: USD does not handle nodegraph without an explicit output propoerly
284 # so always added in the output string !
285 new_input.setOutputString(output_name)
286 materialnode = doc.addMaterialNode(materialnode_name, shadernode)
287
288 if materialnode:
289 material_count += 1
290
291 else:
292 #self.logger.info(f'Scan: {graph.getName()} output: {output_name} type: {output_type}')
293
294 # If not color3 or float add a convert node and connect it to the current upstream node
295 # and then add in a new output which is of type color3
296 if output_type != 'color3' and output_type != 'float':
297
298 convert_definition = 'ND_convert_' + output_type + '_color3'
299 convert_nodedef = doc.getNodeDef(convert_definition)
300 if not convert_nodedef:
301 self.logger.info(">>>> Failed to find conversion definition: %s" % convert_definition)
302 continue
303
304 # Find upstream node or interface input
305 convert_upstream = None
306 if len(output.getNodeName()) > 0:
307 convert_upstream = output.getNodeName()
308 elif output.hasInterfaceName():
309 convert_upstream = output.getInterfaceName()
310 if not convert_upstream:
311 self.logger.info("> Failed to find upstream node for output: %s" % output.getName())
312 continue
313
314 # Insert convert node
315 convert_node = graph.addNodeInstance(convert_nodedef, graph.createValidChildName(f'convert_{convert_upstream}'))
316 convert_node.removeAttribute('nodedef')
317 convert_input = convert_node.addInput('in', output_type)
318 if len(output.getNodeName()) > 0:
319 convert_input.setNodeName(output.getNodeName())
320 elif output.hasInterfaceName():
321 convert_input.setInterfaceName(output.getInterfaceName())
322 convert_input.removeAttribute('value')
323
324 # Overwrite the upstream connection on the output
325 # and change it's type
326 output.setNodeName(convert_node.getName())
327 output.removeAttribute('value')
328 output.setType('color3')
329 output_type = 'color3'
330
331 # Create downstream (umlit) shader
332 shadernode_name = doc.createValidChildName('shader_' + graph.getName() + '_' + output_name)
333 materialnode_name = doc.createValidChildName(graph.getName() + '_' + output_name)
334 unlitDefinition = 'ND_surface_unlit'
335 unlitNode = doc.getNodeDef(unlitDefinition)
336 shadernode = doc.addNodeInstance(unlitNode, shadernode_name)
337 shadernode.removeAttribute('nodedef')
338
339 # Connect upstream output to shader input (based on type)
340 new_input = None
341 if output_type == 'color3':
342 new_input = shadernode.addInput('emission_color', output_type)
343 else:
344 new_input = shadernode.addInput('emission', output_type)
345 new_input.setNodeGraphString(graph.getName())
346 new_input.removeAttribute('value')
347 #if is_multi_output:
348 # ISSUE: USD does not handle nodegraph without an explicit output propoerly
349 # so always added in the output string !
350 new_input.setOutputString(output_name)
351
352 # Add downstream material node connected to shadernode
353 materialnode = doc.addMaterialNode(materialnode_name, shadernode)
354
355 if materialnode:
356 material_count += 1
357
358 return material_count
359
360

◆ add_explicit_geometry_stream()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.add_explicit_geometry_stream ( self,
mx.GraphElement graph )

Add explicit geometry stream nodes for inputs with defaultgeomprop specified in nodes definition.

Do this for unconnected inputs only.

Parameters
graphThe MaterialX graph element.
Returns
The number of implicit nodes added.

Definition at line 361 of file materialxusd_utils.py.

361 def add_explicit_geometry_stream(self, graph: mx.GraphElement):
362 '''
363 @brief Add explicit geometry stream nodes for inputs with defaultgeomprop specified
364 in nodes definition. Do this for unconnected inputs only.
365 @param graph The MaterialX graph element.
366 @return The number of implicit nodes added.
367 '''
368
369 graph_default_nodes = {}
370
371 for node in graph.getNodes():
372 if node.hasSourceUri() or (node.getCategory() in ["nodedef"]):
373 continue
374
375 nodedef = node.getNodeDef(node.getType())
376 #self.logger.info('Node:', node.getName(), 'NodeDef:', nodedef.getName() if nodedef else "None")
377 if not nodedef:
378 continue
379
380 for nodedef_input in nodedef.getInputs():
381 node_input = node.getInput(nodedef_input.getName())
382 # Skip if is a connected input
383 if node_input:
384 if node_input.getInterfaceName() or node_input.getNodeName() or node_input.getNodeGraphString():
385 continue
386
387 # Skip if no defaultgeomprop
388 defaultgeomprop = nodedef_input.getDefaultGeomProp()
389 if not defaultgeomprop:
390 continue
391
392 # Firewall. USD does not appear to handle bitangent properly so
393 # skip it for now.
394 if defaultgeomprop.getGeomProp() == "bitangent":
395 #self.logger.info(f'> WARNING: Skipping adding explicit bitangent node for: "{node.getNamePath()}"')
396 continue
397
398 # Fix this up to get information from the defaultgromprop e.g.
399 # - texcoord <geompropdef name="UV0" type="vector2" geomprop="texcoord" index="0">
400 defaultgeomprop_name = defaultgeomprop.getName()
401 defaultgeomprop_prop = defaultgeomprop.getGeomProp()
402 defaultgeomprop_type = defaultgeomprop.getType()
403 defaultgeomprop_index = defaultgeomprop.getIndex()
404 defaultgeomprop_space = defaultgeomprop.getSpace()
405
406 if not node_input:
407 node_input = node.addInput(nodedef_input.getName(), nodedef_input.getType())
408 if defaultgeomprop_name not in graph_default_nodes:
409 upstream_default_node = graph.addNode(defaultgeomprop_prop,
410 graph.createValidChildName(defaultgeomprop_name),
411 defaultgeomprop_type)
412 upstream_default_node.addInputsFromNodeDef()
413
414 # Set space and set index
415 index_input = upstream_default_node.getInput("index")
416 if index_input:
417 index_input.setValue(defaultgeomprop_index, 'integer')
418 space_input = upstream_default_node.getInput("space")
419 if space_input:
420 space_input.setValue(defaultgeomprop_space, 'string')
421
422 #self.logger.info(f'> Added upstream node "{upstream_default_node.getNamePath()}" : {upstream_default_node}')
423 graph_default_nodes[defaultgeomprop_name] = upstream_default_node
424 else:
425 upstream_default_node = graph_default_nodes[defaultgeomprop_name]
426 #self.logger.info('Use upstream node for defaultgromprop:', nodedef_input.getName(), defaultgeomprop)
427 node_input.setNodeName(upstream_default_node.getName())
428 node_input.removeAttribute('value')
429
430 implicit_nodes_added = len(graph_default_nodes)
431 if graph.getCategory() not in "nodegraph":
432 for child_graph in graph.getNodeGraphs():
433 if child_graph.hasSourceUri():
434 continue
435 implicit_nodes_added += self.add_explicit_geometry_stream(child_graph)
436
437 return implicit_nodes_added
438
439

◆ add_materials_for_shaders()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.add_materials_for_shaders ( self,
mx.Document doc )

Add materials for shaders at the root level of a MaterialX document.

Nodegraphs are not considered as this is not supported by USD.

Parameters
docThe MaterialX document.
loggerThe logger to use for output.
Returns
The number of materials added.

Definition at line 114 of file materialxusd_utils.py.

114 def add_materials_for_shaders(self, doc: mx.Document):
115 '''
116 @brief Add materials for shaders at the root level of a MaterialX document. Nodegraphs are not considered as this is not supported by USD.
117 @param doc The MaterialX document.
118 @param logger The logger to use for output.
119 @return The number of materials added.
120 '''
121 # If has materials skip
122 materials = doc.getMaterialNodes()
123 if len(materials):
124 return 0
125
126 material_count = 0
127
128 surfaceshader_nodes = doc.getChildren()
129 for surfaceshader_node in surfaceshader_nodes:
130 if surfaceshader_node.getType() not in ['surfaceshader']:
131 continue
132 self.logger.info(f'>> Scan shader: {surfaceshader_node.getName()}')
133 downstream_ports = surfaceshader_node.getDownstreamPorts()
134 if not downstream_ports:
135 # Add a material for the shader
136 material_name = doc.createValidChildName('material_' + surfaceshader_node.getName())
137 material_node = doc.addMaterialNode(material_name, surfaceshader_node)
138 if material_node:
139 material_count += 1
140
141 return material_count
142
143

◆ add_nodegraph_output_qualifier_on_shaders()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.add_nodegraph_output_qualifier_on_shaders ( self,
mx.Document doc )

Add nodegraph output qualifier on shaders in the MaterialX document if not already set.

USD appears to require this for shader inputs to be connected to outputs on a nodegraph sometimes – when the output name is not "out" ?

Parameters
docThe MaterialX document.
Returns
The number of explicit outputs added.

Definition at line 83 of file materialxusd_utils.py.

83 def add_nodegraph_output_qualifier_on_shaders(self, doc: mx.Document):
84 '''
85 @brief Add nodegraph output qualifier on shaders in the MaterialX document if not already set.
86 USD appears to require this for shader inputs to be connected to outputs on a nodegraph
87 sometimes -- when the output name is not "out" ?
88 @param doc The MaterialX document.
89 @return The number of explicit outputs added.
90 '''
91 explicit_outputs_added = 0
92 surfaceshader_nodes = doc.getChildren()
93 for surfaceshader_node in surfaceshader_nodes:
94 if surfaceshader_node.getType() not in ['surfaceshader']:
95 continue
96
97 # Scan all inputs on the shader node
98 for input in surfaceshader_node.getInputs():
99 # Check for nodegraph output qualifier
100 nodegraph_string = input.getNodeGraphString()
101 if nodegraph_string:
102 if not input.getOutputString():
103 nodegraph = doc.getNodeGraph(nodegraph_string)
104 if nodegraph:
105 outputs = nodegraph.getOutputs()
106 if outputs:
107 input.setOutputString(outputs[0].getName())
108 explicit_outputs_added += 1
109 self.logger.debug(f'>> Add output qualifier for shader input {mx.prettyPrint(input)}')
110
111 return explicit_outputs_added
112
113

◆ create_document()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.create_document ( self,
str path )

Create a MaterialX document from a file path.

Parameters
pathThe path to the MaterialX document.
Returns
The MaterialX document if successful, None otherwise.

Definition at line 41 of file materialxusd_utils.py.

41 def create_document(self, path: str):
42 '''
43 @brief Create a MaterialX document from a file path.
44 @param path The path to the MaterialX document.
45 @return The MaterialX document if successful, None otherwise.
46 '''
47 doc = mx.createDocument()
48 mx.readFromXmlFile(doc, mx.FilePath(path))
49 return doc
50
51

◆ create_FileSearchPath()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.create_FileSearchPath ( self,
list search_paths )

Create a MaterialX file search path from a list of string paths.

Parameters
search_pathsA list of string paths.
Returns
The MaterialX file search path.

Definition at line 62 of file materialxusd_utils.py.

62 def create_FileSearchPath(self, search_paths: list):
63 '''
64 @brief Create a MaterialX file search path from a list of string paths.
65 @param search_paths A list of string paths.
66 @return The MaterialX file search path.
67 '''
68 #self.logger.info(f'> Creating file search path: {search_paths}')
69 search_path = mx.FileSearchPath()
70 for path in search_paths:
71 search_path.append(path)
72 return search_path
73
74

◆ encapsulate_top_level_nodes()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.encapsulate_top_level_nodes ( self,
mx.Document doc,
str nodegraph_name = "top_level_nodes",
bool remove_original = True )

Encapsulate top level nodes in a nodegraph.

Remap any connections to the top level nodes to outputs on a new nodegraph.

Parameters
docThe MaterialX document.
nodegraph_nameThe name of the new nodegraph to encapsulate the top level nodes. Default is 'top_level_nodes'.
remove_originalIf True, remove the original top level nodes from the document. Default is True.
Returns
The number of top level nodes found

Definition at line 440 of file materialxusd_utils.py.

440 def encapsulate_top_level_nodes(self, doc: mx.Document, nodegraph_name:str="top_level_nodes", remove_original:bool=True):
441 """
442 @brief Encapsulate top level nodes in a nodegraph. Remap any connections to the top level nodes
443 to outputs on a new nodegraph.
444 @param doc The MaterialX document.
445 @param nodegraph_name The name of the new nodegraph to encapsulate the top level nodes. Default is 'top_level_nodes'.
446 @param remove_original If True, remove the original top level nodes from the document. Default is True.
447 @return The number of top level nodes found
448 """
449 connections_made = 0
450 top_level_nodes_found = 0
451
452 # Find all children of document which are no material or shader nodes.
453 top_level_nodes = []
454 top_level_connections = []
455 for elem in doc.getNodes():
456
457 # skips elements that are part of the stdlib
458 if elem.hasSourceUri():
459 continue
460
461 if (elem.getName()
462 and (elem.getType() not in ["material", "surfaceshader"])
463 and elem.getCategory() not in ["nodegraph", "nodedef"]):
464 #self.logger.info("Finding top level nodes: ", elem.getName(), elem.getType())
465 top_level_nodes.append(elem)
466
467 elif elem.getType() in ["surfaceshader"]:
468 for input_port in elem.getInputs():
469 upstream_node_name = input_port.getNodeName()
470 if len(upstream_node_name) > 0:
471 upstream_output_name = input_port.getOutputString()
472
473 # Go through node outputs and nodedef outputs if needed if it's multi-output as
474 # we have to find the output name for usdMtlx to make the connection properly.
475 # It does not seem to hanlde upstream multioutputs properly and tries to connect to the first output
476 # or not connect at all ?
477 if not upstream_output_name:
478 upstream_node = doc.getDescendant(upstream_node_name)
479 upstream_node_outputs = upstream_node.getOutputs()
480 if len(upstream_node_outputs) > 1:
481 self.logger.debug(f"Find an output of name: {upstream_node_outputs[0].getName()}")
482 upstream_output_name = upstream_node_outputs[0].getName()
483 else:
484 upstream_node_nodedef = upstream_node.getNodeDef()
485 upstream_node_outputs = upstream_node_nodedef.getActiveOutputs()
486 if len(upstream_node_outputs) > 1:
487 self.logger.debug(f"Find an output of name: {upstream_node_outputs[0].getName()}")
488 upstream_output_name = upstream_node_outputs[0].getName()
489
490 #self.logger.info("Store connection: ", upstream_node_name, "<--", input_port.getNamePath())
491 top_level_connections.append([upstream_node_name, input_port.getNamePath(), upstream_output_name])
492
493 #self.logger.info("Top level connections: ", top_level_connections)
494 top_level_nodes_found = len(top_level_nodes)
495 if top_level_nodes_found == 0:
496 return top_level_nodes_found
497
498 # create nodegraph
499 ng_name = doc.createValidChildName(nodegraph_name)
500 ng = doc.addNodeGraph(ng_name)
501 for node in top_level_nodes:
502 #self.logger.info("Adding node: ", node.getName())
503 new_node = ng.addNode(node.getCategory(), mx.createValidName(node.getName()), node.getType())
504 new_node.copyContentFrom(node)
505 for connect in top_level_connections:
506 if connect[0] == node.getName():
507 the_input = doc.getDescendant(connect[1])
508 if not the_input:
509 continue
510
511 # Create a new output on the graph
512 new_output = ng.addOutput(ng.createValidChildName("out"), the_input.getType())
513 new_output.setNodeName(new_node.getName())
514 if len(connect[2]) > 0:
515 new_output.setOutputString(connect[2])
516 #self.logger.info("Create new output: ", mx.prettyPrint(new_output))
517 the_input.setNodeGraphString(ng_name)
518 the_input.setOutputString(new_output.getName())
519 the_input.removeAttribute("nodename")
520 the_input.removeAttribute("value")
521 #self.logger.info(f"Reconnecting {the_input.getNamePath()} {connect[1]} to {mx.prettyPrint(the_input)}")
522 connections_made += 1
523
524 if remove_original:
525 for node in top_level_nodes:
526 doc.removeChild(node.getName())
527
528 return top_level_nodes_found
529
530

◆ encapsulate_top_level_nodes_file()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.encapsulate_top_level_nodes_file ( self,
str input_path,
str new_input_path,
str nodegraph_name = 'top_level_nodes',
bool remove_original_nodes = True )

Encapsulate top level nodes in a nodegraph.

Remap any connections to the top level nodes to outputs on a new nodegraph.

Parameters
input_pathThe path to the MaterialX document.
new_input_pathThe path to write the modified MaterialX document.
nodegraph_nameThe name of the new nodegraph to encapsulate the top level nodes. Default is 'top_level_nodes'.
remove_original_nodesIf True, remove the original top level nodes from the document. Default is True.
Returns
The modified MaterialX document if top level connections were found, None otherwise.

Definition at line 531 of file materialxusd_utils.py.

531 def encapsulate_top_level_nodes_file(self, input_path:str, new_input_path:str, nodegraph_name:str='top_level_nodes', remove_original_nodes:bool =True):
532 '''
533 @brief Encapsulate top level nodes in a nodegraph. Remap any connections to the top level nodes
534 to outputs on a new nodegraph.
535 @param input_path The path to the MaterialX document.
536 @param new_input_path The path to write the modified MaterialX document.
537 @param nodegraph_name The name of the new nodegraph to encapsulate the top level nodes. Default is 'top_level_nodes'.
538 @param remove_original_nodes If True, remove the original top level nodes from the document. Default is True.
539 @return The modified MaterialX document if top level connections were found, None otherwise.
540 '''
541 doc = self.create_document(input_path)
542 top_level_nodes_found = self.encapsulate_top_level_nodes(doc, nodegraph_name, remove_original_nodes)
543 if top_level_nodes_found:
544 self.logger.info(f'> Encapsulated {top_level_nodes_found} top level nodes in a new nodegraph.')
545 if new_input_path:
546 print(f'> Writing modified MaterialX document to: {new_input_path}')
547 self.write_document(doc, new_input_path)
548 return doc
549 return None
550
551
552

◆ get_standard_libraries()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.get_standard_libraries ( self)

Get standard MaierialX libraries.

Returns
: The standard library and the list of library files.

Definition at line 31 of file materialxusd_utils.py.

31 def get_standard_libraries(self):
32 '''
33 @brief Get standard MaierialX libraries.
34 @return: The standard library and the list of library files.
35 '''
36 return self._stdlib
37

◆ load_standard_libraries()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.load_standard_libraries ( self)

Load standard MaierialX libraries.

Returns
: The standard library and the list of library files.

Definition at line 23 of file materialxusd_utils.py.

23 def load_standard_libraries(self):
24 '''Load standard MaierialX libraries.
25 @return: The standard library and the list of library files.
26 '''
27 stdlib = mx.createDocument()
28 libFiles = mx.loadLibraries(mx.getDefaultDataLibraryFolders(), mx.getDefaultDataSearchPath(), stdlib)
29 return stdlib, libFiles
30

◆ resolve_image_file_paths()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.resolve_image_file_paths ( self,
mx.Document doc,
mx.FileSearchPath search_paths )

Resolve image file paths in a MaterialX document.

Parameters
docThe MaterialX document.
search_pathsThe MaterialX file search path.

Definition at line 75 of file materialxusd_utils.py.

75 def resolve_image_file_paths(self, doc: mx.Document, search_paths: mx.FileSearchPath):
76 '''
77 @brief Resolve image file paths in a MaterialX document.
78 @param doc The MaterialX document.
79 @param search_paths The MaterialX file search path.
80 '''
81 mx.flattenFilenames(doc, search_paths)
82

◆ write_document()

materialxusd.materialxusd_utils.MaterialXUsdUtilities.write_document ( self,
mx.Document doc,
str path )

Write a MaterialX document to a file.

Parameters
docThe MaterialX document.
pathThe path to write the MaterialX document.
Returns
True if successful, False otherwise.

Definition at line 52 of file materialxusd_utils.py.

52 def write_document(self, doc: mx.Document, path: str):
53 '''
54 @brief Write a MaterialX document to a file.
55 @param doc The MaterialX document.
56 @param path The path to write the MaterialX document.
57 @return True if successful, False otherwise.
58 '''
59 return mx.writeToXmlFile(doc, path)
60
61

Member Data Documentation

◆ _libFiles

materialxusd.materialxusd_utils.MaterialXUsdUtilities._libFiles = self.load_standard_libraries()
protected

Definition at line 19 of file materialxusd_utils.py.

◆ _stdlib

materialxusd.materialxusd_utils.MaterialXUsdUtilities._stdlib
protected

Definition at line 19 of file materialxusd_utils.py.

◆ logger

materialxusd.materialxusd_utils.MaterialXUsdUtilities.logger = logging.getLogger('MXUSDUTIL')

Definition at line 21 of file materialxusd_utils.py.


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