From 08445f623023b46c1c2121c2509c405e57f249b8 Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Tue, 4 Jan 2022 16:04:39 -0500 Subject: [PATCH] Make sure material eport sanitizes names Some recent code was not sanitizing the names of auxillary nodes, causing failures when namespaces are in use. --- .../translators/shading/mtlxBaseWriter.cpp | 10 +-- .../shading/mtlxFileTextureWriter.cpp | 5 +- .../shading/usdFileTextureWriter.cpp | 6 +- .../translators/testUsdExportMultiMaterial.py | 64 ++++++++++--------- .../testUsdExportStripNamespaces.py | 16 ++--- 5 files changed, 55 insertions(+), 46 deletions(-) diff --git a/lib/usd/translators/shading/mtlxBaseWriter.cpp b/lib/usd/translators/shading/mtlxBaseWriter.cpp index 3c483285a3..9d2100a9c3 100644 --- a/lib/usd/translators/shading/mtlxBaseWriter.cpp +++ b/lib/usd/translators/shading/mtlxBaseWriter.cpp @@ -117,7 +117,7 @@ UsdAttribute MtlxUsd_BaseWriter::AddConversion( TfToken converterName(TfStringPrintf( "%s_%s_%s_%s", _tokens->ConverterPrefix.GetText(), - depNodeFn.name().asChar(), + UsdMayaUtil::SanitizeName(depNodeFn.name().asChar()).c_str(), fromType.GetAsToken().GetText(), toType.GetAsToken().GetText())); const SdfPath converterPath = nodegraphPath.AppendChild(converterName); @@ -248,8 +248,10 @@ UsdAttribute MtlxUsd_BaseWriter::AddLuminance(int numChannels) UsdShadeNodeGraph nodegraphSchema(GetNodeGraph()); SdfPath nodegraphPath = nodegraphSchema.GetPath(); - TfToken luminanceName( - TfStringPrintf("%s_%s", _tokens->LuminancePrefix.GetText(), depNodeFn.name().asChar())); + TfToken luminanceName(TfStringPrintf( + "%s_%s", + _tokens->LuminancePrefix.GetText(), + UsdMayaUtil::SanitizeName(depNodeFn.name().asChar()).c_str())); const SdfPath luminancePath = nodegraphPath.AppendChild(luminanceName); UsdShadeShader luminanceSchema = UsdShadeShader::Define(GetUsdStage(), luminancePath); @@ -299,7 +301,7 @@ UsdAttribute MtlxUsd_BaseWriter::AddNormalMapping(UsdAttribute normalInput) TfToken nodeName(TfStringPrintf( "%s_%s_%s", _tokens->NormalMapPrefix.GetText(), - depNodeFn.name().asChar(), + UsdMayaUtil::SanitizeName(depNodeFn.name().asChar()).c_str(), normalInput.GetBaseName().GetText())); SdfPath nodePath = nodegraphPath.AppendChild(nodeName); UsdShadeShader nodeSchema = UsdShadeShader::Define(GetUsdStage(), nodePath); diff --git a/lib/usd/translators/shading/mtlxFileTextureWriter.cpp b/lib/usd/translators/shading/mtlxFileTextureWriter.cpp index 23674d5bd3..dfceac09ce 100644 --- a/lib/usd/translators/shading/mtlxFileTextureWriter.cpp +++ b/lib/usd/translators/shading/mtlxFileTextureWriter.cpp @@ -103,7 +103,8 @@ MtlxUsd_FileWriter::MtlxUsd_FileWriter( } SdfPath nodegraphPath = nodegraphSchema.GetPath(); - SdfPath texPath = nodegraphPath.AppendChild(TfToken(depNodeFn.name().asChar())); + SdfPath texPath + = nodegraphPath.AppendChild(TfToken(UsdMayaUtil::SanitizeName(depNodeFn.name().asChar()))); // Create a image shader as the "primary" shader for this writer. UsdShadeShader texSchema = UsdShadeShader::Define(GetUsdStage(), texPath); @@ -450,7 +451,7 @@ SdfPath MtlxUsd_FileWriter::_GetPlace2DTexturePath(const MFnDependencyNode& depN MPlug source = plug.source(&status); if (status == MS::kSuccess && !source.isNull()) { MFnDependencyNode sourceNode(source.node()); - usdUvTextureName = sourceNode.name().asChar(); + usdUvTextureName = UsdMayaUtil::SanitizeName(sourceNode.name().asChar()); } } diff --git a/lib/usd/translators/shading/usdFileTextureWriter.cpp b/lib/usd/translators/shading/usdFileTextureWriter.cpp index 4e3334b31f..68a326deda 100644 --- a/lib/usd/translators/shading/usdFileTextureWriter.cpp +++ b/lib/usd/translators/shading/usdFileTextureWriter.cpp @@ -538,7 +538,9 @@ void PxrUsdTranslators_FileTextureWriter::WriteTransform2dNode( std::string usdUvTransformName; if (primvarReaderShaderPath.GetName() == _tokens->PrimvarReaderShaderName.GetString()) { usdUvTransformName = TfStringPrintf( - "%s_%s", depNodeFn.name().asChar(), _tokens->UsdTransform2dShaderName.GetText()); + "%s_%s", + UsdMayaUtil::SanitizeName(depNodeFn.name().asChar()).c_str(), + _tokens->UsdTransform2dShaderName.GetText()); } else { usdUvTransformName = TfStringPrintf( @@ -639,7 +641,7 @@ PxrUsdTranslators_FileTextureWriter::getPlace2DTexturePath(const MFnDependencyNo MPlug source = plug.source(&status); if (status == MS::kSuccess && !source.isNull()) { MFnDependencyNode sourceNode(source.node()); - usdUvTextureName = sourceNode.name().asChar(); + usdUvTextureName = UsdMayaUtil::SanitizeName(sourceNode.name().asChar()); } } diff --git a/test/lib/usd/translators/testUsdExportMultiMaterial.py b/test/lib/usd/translators/testUsdExportMultiMaterial.py index 7a4280ef52..96841dec8d 100644 --- a/test/lib/usd/translators/testUsdExportMultiMaterial.py +++ b/test/lib/usd/translators/testUsdExportMultiMaterial.py @@ -103,6 +103,10 @@ def testVarnameMerging(self): """ cmds.file(f=True, new=True) + # Use a namespace, for testing name sanitization... + cmds.namespace(add="M") + cmds.namespace(set="M") + sphere_xform = cmds.polySphere()[0] material_node = cmds.shadingNode("usdPreviewSurface", asShader=True, @@ -153,62 +157,62 @@ def testVarnameMerging(self): # We expect 2 primvar readers, and 2 st transforms: stage = Usd.Stage.Open(usd_path) - mat_path = "/pSphere1/Looks/ss01SG" + mat_path = "/M_pSphere1/Looks/M_ss01SG" # Here are the expected connections in the produced USD file: connections = [ # UsdPreviewSurface section # Source node, input, destination node: - ("/UsdPreviewSurface/ss01", "diffuseColor", "/UsdPreviewSurface/file1"), - ("/UsdPreviewSurface/file1", "st", "/UsdPreviewSurface/place2dTexture1_UsdTransform2d"), - ("/UsdPreviewSurface/place2dTexture1_UsdTransform2d", "in", "/UsdPreviewSurface/place2dTexture1"), + ("/UsdPreviewSurface/M_ss01", "diffuseColor", "/UsdPreviewSurface/M_file1"), + ("/UsdPreviewSurface/M_file1", "st", "/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d"), + ("/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d", "in", "/UsdPreviewSurface/M_place2dTexture1"), - ("/UsdPreviewSurface/ss01", "emissiveColor", "/UsdPreviewSurface/file2"), - ("/UsdPreviewSurface/file2", "st", "/UsdPreviewSurface/place2dTexture1_UsdTransform2d"), # re-used + ("/UsdPreviewSurface/M_ss01", "emissiveColor", "/UsdPreviewSurface/M_file2"), + ("/UsdPreviewSurface/M_file2", "st", "/UsdPreviewSurface/M_place2dTexture1_UsdTransform2d"), # re-used # Note that the transform name is derived from place2DTexture name. - ("/UsdPreviewSurface/ss01", "metallic", "/UsdPreviewSurface/file3"), - ("/UsdPreviewSurface/file3", "st", "/UsdPreviewSurface/shared_TexCoordReader"), # no UV in Maya. + ("/UsdPreviewSurface/M_ss01", "metallic", "/UsdPreviewSurface/M_file3"), + ("/UsdPreviewSurface/M_file3", "st", "/UsdPreviewSurface/shared_TexCoordReader"), # no UV in Maya. - ("/UsdPreviewSurface/ss01", "roughness", "/UsdPreviewSurface/file4"), - ("/UsdPreviewSurface/file4", "st", "/UsdPreviewSurface/file4_UsdTransform2d"), # xform on file node - ("/UsdPreviewSurface/file4_UsdTransform2d", "in", "/UsdPreviewSurface/shared_TexCoordReader"), + ("/UsdPreviewSurface/M_ss01", "roughness", "/UsdPreviewSurface/M_file4"), + ("/UsdPreviewSurface/M_file4", "st", "/UsdPreviewSurface/M_file4_UsdTransform2d"), # xform on file node + ("/UsdPreviewSurface/M_file4_UsdTransform2d", "in", "/UsdPreviewSurface/shared_TexCoordReader"), # Note that the transform name is derived from file node name. # MaterialX section # Source node, input, destination node: - ("/MaterialX/MayaNG_MaterialX", "diffuseColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_file1_rgb"), - ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_file1_rgb", "in", "/MaterialX/MayaNG_MaterialX/file1"), - ("/MaterialX/MayaNG_MaterialX/file1", "texcoord", "/MaterialX/MayaNG_MaterialX/place2dTexture1"), + ("/MaterialX/MayaNG_MaterialX", "diffuseColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file1_rgb"), + ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file1_rgb", "in", "/MaterialX/MayaNG_MaterialX/M_file1"), + ("/MaterialX/MayaNG_MaterialX/M_file1", "texcoord", "/MaterialX/MayaNG_MaterialX/M_place2dTexture1"), - ("/MaterialX/MayaNG_MaterialX", "emissiveColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_file2_rgb"), - ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_file2_rgb", "in", "/MaterialX/MayaNG_MaterialX/file2"), - ("/MaterialX/MayaNG_MaterialX/file2", "texcoord", "/MaterialX/MayaNG_MaterialX/place2dTexture1"), # re-used + ("/MaterialX/MayaNG_MaterialX", "emissiveColor", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file2_rgb"), + ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file2_rgb", "in", "/MaterialX/MayaNG_MaterialX/M_file2"), + ("/MaterialX/MayaNG_MaterialX/M_file2", "texcoord", "/MaterialX/MayaNG_MaterialX/M_place2dTexture1"), # re-used - ("/MaterialX/MayaNG_MaterialX", "metallic", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_file3_r"), - ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_file3_r", "in", "/MaterialX/MayaNG_MaterialX/file3"), - ("/MaterialX/MayaNG_MaterialX/file3", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # no UV in Maya. + ("/MaterialX/MayaNG_MaterialX", "metallic", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file3_r"), + ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file3_r", "in", "/MaterialX/MayaNG_MaterialX/M_file3"), + ("/MaterialX/MayaNG_MaterialX/M_file3", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # no UV in Maya. - ("/MaterialX/MayaNG_MaterialX", "roughness", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_file4_r"), - ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_file4_r", "in", "/MaterialX/MayaNG_MaterialX/file4"), - ("/MaterialX/MayaNG_MaterialX/file4", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # re-used + ("/MaterialX/MayaNG_MaterialX", "roughness", "/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file4_r"), + ("/MaterialX/MayaNG_MaterialX/MayaSwizzle_M_file4_r", "in", "/MaterialX/MayaNG_MaterialX/M_file4"), + ("/MaterialX/MayaNG_MaterialX/M_file4", "texcoord", "/MaterialX/MayaNG_MaterialX/shared_MayaGeomPropValue"), # re-used # Making sure no NodeGraph boundaries were skipped downstream: ("", "surface", "/UsdPreviewSurface"), - ("/UsdPreviewSurface", "surface", "/UsdPreviewSurface/ss01"), + ("/UsdPreviewSurface", "surface", "/UsdPreviewSurface/M_ss01"), ("", "mtlx:surface", "/MaterialX"), - ("/MaterialX", "surface", "/MaterialX/ss01"), + ("/MaterialX", "surface", "/MaterialX/M_ss01"), # Making sure no NodeGraph boundaries were skipped upstream: - ("/UsdPreviewSurface/place2dTexture1", "varname", "/UsdPreviewSurface"), - ("/UsdPreviewSurface", "file1:varname", ""), + ("/UsdPreviewSurface/M_place2dTexture1", "varname", "/UsdPreviewSurface"), + ("/UsdPreviewSurface", "M:file1:varname", ""), - ("/MaterialX/MayaNG_MaterialX/place2dTexture1", "geomprop", "/MaterialX/MayaNG_MaterialX"), - ("/MaterialX/MayaNG_MaterialX", "file1:varnameStr", "/MaterialX"), - ("/MaterialX", "file1:varnameStr", ""), + ("/MaterialX/MayaNG_MaterialX/M_place2dTexture1", "geomprop", "/MaterialX/MayaNG_MaterialX"), + ("/MaterialX/MayaNG_MaterialX", "M:file1:varnameStr", "/MaterialX"), + ("/MaterialX", "M:file1:varnameStr", ""), ] for src_name, input_name, dst_name in connections: src_prim = stage.GetPrimAtPath(mat_path + src_name) diff --git a/test/lib/usd/translators/testUsdExportStripNamespaces.py b/test/lib/usd/translators/testUsdExportStripNamespaces.py index 9c0e0f8589..6bdfac3ae0 100644 --- a/test/lib/usd/translators/testUsdExportStripNamespaces.py +++ b/test/lib/usd/translators/testUsdExportStripNamespaces.py @@ -49,9 +49,9 @@ def testExportWithClashStripping(self): node1 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube1" ) cmds.namespace(add="foo") - cmds.namespace(set="foo"); + cmds.namespace(set="foo") node2 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube1" ) - cmds.namespace(set=":"); + cmds.namespace(set=":") usdFilePath = os.path.abspath('UsdExportStripNamespaces_EXPORTED.usda') @@ -80,11 +80,11 @@ def testExportWithStripAndMerge(self): cmds.namespace(add=":bar") node1 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube1" ) - cmds.namespace(set=":foo"); + cmds.namespace(set=":foo") node2 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube2" ) - cmds.namespace(set=":bar"); + cmds.namespace(set=":bar") node3 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube3" ) - cmds.namespace(set=":"); + cmds.namespace(set=":") usdFilePath = os.path.abspath('UsdExportStripNamespaces_EXPORTED.usda') @@ -111,11 +111,11 @@ def testExportWithStrip(self): cmds.namespace(add=":bar") node1 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube1" ) - cmds.namespace(set=":foo"); + cmds.namespace(set=":foo") node2 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube2" ) - cmds.namespace(set=":bar"); + cmds.namespace(set=":bar") node3 = cmds.polyCube( sx=5, sy=5, sz=5, name="cube3" ) - cmds.namespace(set=":"); + cmds.namespace(set=":") usdFilePath = os.path.abspath('UsdExportStripNamespaces_EXPORTED.usda')