From 25c7d446ba518c5e132b8faa69f4dd0345a5bb5f Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Fri, 24 Feb 2023 17:00:23 -0500 Subject: [PATCH] Use "mtl" as default scope name on export This centralizes the declaration of the name and the two environment variable affecting it. It also exposes that name to the Python API for use in export scenarios. Unit tests that were relying on "Looks" had the USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME added to their environment when running. --- lib/mayaUsd/commands/Readme.md | 13 +++-- lib/mayaUsd/fileio/jobs/jobArgs.cpp | 19 ++++++- lib/mayaUsd/fileio/jobs/jobArgs.h | 8 ++- lib/mayaUsd/python/wrapPrimWriter.cpp | 4 +- lib/mayaUsd/ufe/UsdUndoMaterialCommands.cpp | 15 +----- .../adsk/scripts/mayaUsdTranslatorExport.mel | 10 ---- test/lib/CMakeLists.txt | 1 - test/lib/mayaUsd/fileio/CMakeLists.txt | 1 + ...estMayaUsdInteractiveMaterialsScopeName.py | 49 ------------------- .../usd/pxrUsdPreviewSurface/CMakeLists.txt | 2 + test/lib/usd/translators/CMakeLists.txt | 37 +++++++++++--- .../translators/testUsdExportMultiMaterial.py | 18 ++++++- 12 files changed, 90 insertions(+), 87 deletions(-) delete mode 100644 test/lib/testMayaUsdInteractiveMaterialsScopeName.py diff --git a/lib/mayaUsd/commands/Readme.md b/lib/mayaUsd/commands/Readme.md index 78180e894f..98a4ba6fd7 100644 --- a/lib/mayaUsd/commands/Readme.md +++ b/lib/mayaUsd/commands/Readme.md @@ -255,9 +255,16 @@ primitive. The original name will be preserved in custom data for roundtripping. #### Material Scopes -The default material scope when exporting materials is named `mtl`. Users can -change this default material scope name by setting the environment variable -named `MAYAUSD_MATERIALS_SCOPE_NAME`. +The recommended way of selecting a global scope name for materials is to use the +materialsScopeName argument of MayaUSDExportCommand. + +If that argument is not specified, we will use "mtl" as a globally defined default. +This follows the [Guidelines for Structuring USD Assets](https://wiki.aswf.io/display/WGUSD/Guidelines+for+Structuring+USD+Assets) +as defined by the USD Assets WG. + +The `MAYAUSD_MATERIALS_SCOPE_NAME` environment variable can be used to change +that default on a global level. The value defined in that env var will take +precedence over any value passed in the materialsScopeName argument. This environment variable was added in part to support legacy user of mayaUSD: in past versions of the plugin, the material scope was named `Looks`. The change diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.cpp b/lib/mayaUsd/fileio/jobs/jobArgs.cpp index 97b37122a8..ba4abd0319 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.cpp +++ b/lib/mayaUsd/fileio/jobs/jobArgs.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,10 @@ TF_DEFINE_PRIVATE_TOKENS( namespace { +// Default material scope name as defined by USD Assets working group. +// See https://wiki.aswf.io/display/WGUSD/Guidelines+for+Structuring+USD+Assets +static constexpr auto kDefaultMaterialScopeName = "mtl"; + using namespace MayaUsd::DictUtils; // The chaser args are stored as vectors of vectors (since this is how you @@ -176,6 +181,12 @@ TfToken _GetMaterialsScopeName(const std::string& materialsScopeName) // If the env setting is set, make sure we don't allow the materials // scope name to be overridden by a parameter value. return defaultMaterialsScopeName; + } else { + const std::string mayaUsdDefaultMaterialsScopeName + = TfGetenv("MAYAUSD_MATERIALS_SCOPE_NAME"); + if (!mayaUsdDefaultMaterialsScopeName.empty()) { + return TfToken(mayaUsdDefaultMaterialsScopeName); + } } if (SdfPath::IsValidIdentifier(materialsScopeName)) { @@ -826,8 +837,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary() d[UsdMayaJobExportArgsTokens->kind] = std::string(); d[UsdMayaJobExportArgsTokens->disableModelKindProcessor] = false; d[UsdMayaJobExportArgsTokens->materialCollectionsPath] = std::string(); - d[UsdMayaJobExportArgsTokens->materialsScopeName] - = UsdUtilsGetMaterialsScopeName().GetString(); + d[UsdMayaJobExportArgsTokens->materialsScopeName] = kDefaultMaterialScopeName; d[UsdMayaJobExportArgsTokens->melPerFrameCallback] = std::string(); d[UsdMayaJobExportArgsTokens->melPostCallback] = std::string(); d[UsdMayaJobExportArgsTokens->mergeTransformAndShape] = true; @@ -940,6 +950,11 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary() return d; } +const std::string UsdMayaJobExportArgs::GetDefaultMaterialsScopeName() +{ + return _GetMaterialsScopeName(kDefaultMaterialScopeName); +} + std::string UsdMayaJobExportArgs::GetResolvedFileName() const { MFileObject fileObj; diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.h b/lib/mayaUsd/fileio/jobs/jobArgs.h index c52382c37c..bd9fccc56b 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.h +++ b/lib/mayaUsd/fileio/jobs/jobArgs.h @@ -124,7 +124,7 @@ TF_DECLARE_PUBLIC_TOKENS( /* geomSidedness values */ \ (derived) \ (single) \ - ((double_, "double")) \ + ((double_, "double")) // clang-format on TF_DECLARE_PUBLIC_TOKENS( @@ -294,6 +294,12 @@ struct UsdMayaJobExportArgs MAYAUSD_CORE_PUBLIC static const VtDictionary& GetGuideDictionary(); + /// Gets the resolved default material scope name. + /// + /// Accounts for all env vars that can affect the scope name. + MAYAUSD_CORE_PUBLIC + static const std::string GetDefaultMaterialsScopeName(); + /// Returns the resolved file name of the final export location MAYAUSD_CORE_PUBLIC std::string GetResolvedFileName() const; diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index f2fa7fe477..d3f5f6ce8c 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -592,7 +592,9 @@ void wrapJobExportArgs() &UsdMayaJobExportArgs::usdModelRootOverridePath, return_value_policy())) .def_readonly("verbose", &UsdMayaJobExportArgs::verbose) - .def("GetResolvedFileName", &UsdMayaJobExportArgs::GetResolvedFileName); + .def("GetResolvedFileName", &UsdMayaJobExportArgs::GetResolvedFileName) + .def("GetDefaultMaterialsScopeName", &UsdMayaJobExportArgs::GetDefaultMaterialsScopeName) + .staticmethod("GetDefaultMaterialsScopeName"); } void wrapPrimWriter() diff --git a/lib/mayaUsd/ufe/UsdUndoMaterialCommands.cpp b/lib/mayaUsd/ufe/UsdUndoMaterialCommands.cpp index b994055640..7dc27e970a 100644 --- a/lib/mayaUsd/ufe/UsdUndoMaterialCommands.cpp +++ b/lib/mayaUsd/ufe/UsdUndoMaterialCommands.cpp @@ -15,10 +15,9 @@ // #include "UsdUndoMaterialCommands.h" +#include #include -#include -#include #include #include #include @@ -286,17 +285,7 @@ Ufe::SceneItem::Ptr UsdUndoAssignNewMaterialCommand::insertedChild() const std::string UsdUndoAssignNewMaterialCommand::resolvedMaterialScopeName() { - std::string materialsScopeName = kDefaultMaterialScopeName; - if (TfGetEnvSetting(USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME)) { - materialsScopeName = UsdUtilsGetMaterialsScopeName().GetString(); - } else { - const std::string mayaUsdDefaultMaterialsScopeName - = TfGetenv("MAYAUSD_MATERIALS_SCOPE_NAME"); - if (!mayaUsdDefaultMaterialsScopeName.empty()) { - materialsScopeName = mayaUsdDefaultMaterialsScopeName; - } - } - return materialsScopeName; + return UsdMayaJobExportArgs::GetDefaultMaterialsScopeName(); } void UsdUndoAssignNewMaterialCommand::execute() diff --git a/plugin/adsk/scripts/mayaUsdTranslatorExport.mel b/plugin/adsk/scripts/mayaUsdTranslatorExport.mel index bfe0a62cc2..e334295f3a 100644 --- a/plugin/adsk/scripts/mayaUsdTranslatorExport.mel +++ b/plugin/adsk/scripts/mayaUsdTranslatorExport.mel @@ -219,14 +219,6 @@ proc string mayaUsdTranslatorExport_AppendFromTextField(string $currentOptions, return $currentOptions + ";" + $arg + "=" + $value; } -proc string mayaUsdTranslatorExport_AppendFromEnvElseDefault(string $currentOptions, string $arg, string $envVarName, string $defaultValue) { - string $value = `getenv $envVarName`; - if ($value == "") { - $value = $defaultValue; - } - return $currentOptions + ";" + $arg + "=" + $value; -} - global proc mayaUsdTranslatorExport_AnimationCB() { if (`checkBoxGrp -exists animationCheckBox` == 0) return; @@ -797,8 +789,6 @@ global proc int mayaUsdTranslatorExport (string $parent, $currentOptions = mayaUsdTranslatorExport_AppendJobContexts($currentOptions, "jobContext"); } - $currentOptions = mayaUsdTranslatorExport_AppendFromEnvElseDefault($currentOptions, "materialsScopeName", "MAYAUSD_MATERIALS_SCOPE_NAME", `getMayaUsdString("kExportMaterialsDefaultScopeName")`); - eval($resultCallback+" \""+$currentOptions+"\""); $bResult = 1; diff --git a/test/lib/CMakeLists.txt b/test/lib/CMakeLists.txt index eb76b43b0a..209bada204 100644 --- a/test/lib/CMakeLists.txt +++ b/test/lib/CMakeLists.txt @@ -17,7 +17,6 @@ endif() # Interactive Unit test scripts. set(INTERACTIVE_TEST_SCRIPT_FILES testMayaUsdInteractiveLayerEditorCommands.py - testMayaUsdInteractiveMaterialsScopeName.py ) foreach(script ${TEST_SCRIPT_FILES}) diff --git a/test/lib/mayaUsd/fileio/CMakeLists.txt b/test/lib/mayaUsd/fileio/CMakeLists.txt index ac2d0235ce..49c99309dc 100644 --- a/test/lib/mayaUsd/fileio/CMakeLists.txt +++ b/test/lib/mayaUsd/fileio/CMakeLists.txt @@ -49,6 +49,7 @@ foreach(script ${TEST_SCRIPT_FILES}) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ENV "UFE_PREVIEW_VERSION_NUM=${UFE_PREVIEW_VERSION_NUM}" + "USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME=1" ) # Add a ctest label to these tests for easy filtering. diff --git a/test/lib/testMayaUsdInteractiveMaterialsScopeName.py b/test/lib/testMayaUsdInteractiveMaterialsScopeName.py deleted file mode 100644 index f3c94175e4..0000000000 --- a/test/lib/testMayaUsdInteractiveMaterialsScopeName.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env mayapy -# -# Copyright 2021 Autodesk -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -import unittest - -import maya.cmds as cmds -import maya.mel as mel -import fixturesUtils - -class MayaUsdInteractiveMaterialsScopeNameTestCase(unittest.TestCase): - """Test interactive commands that set the materials scope name.""" - - @classmethod - def setUpClass(cls): - inputPath = fixturesUtils.setUpClass(__file__, initializeStandalone=False, loadPlugin=False) - cmds.loadPlugin('mayaUsdPlugin') - - def testDefault(self): - cmds.file(new=True, force=True) - # Look for a materialsScopeName of mtl (should pass) - result1 = mel.eval("$w = `window`; $scrollLayout = `scrollLayout`; proc testTranslator(string $s){ global int $materialsScopeResult; $materialsScopeResult=endsWith($s, \"materialsScopeName=mtl\"); } mayaUsdTranslatorExport($scrollLayout, \"query\", \"\", \"testTranslator\"); deleteUI $w; global int $materialsScopeResult; int $r=$materialsScopeResult;"); - self.assertTrue(result1) - # Look for a materialsScopeName of shouldFail (should fail) - result2 = mel.eval("$w = `window`; $scrollLayout = `scrollLayout`; proc testTranslator(string $s){ global int $materialsScopeResult; $materialsScopeResult=endsWith($s, \"materialsScopeName=shouldFail\"); } mayaUsdTranslatorExport($scrollLayout, \"query\", \"\", \"testTranslator\"); deleteUI $w; global int $materialsScopeResult; int $r=$materialsScopeResult;"); - self.assertFalse(result2) - - def testMaterialsScopeNameEnvVariable(self): - cmds.file(new=True, force=True) - # Look for a materialsScopeName of test based upon env variable (should pass) - mel.eval("putenv(\"MAYAUSD_MATERIALS_SCOPE_NAME\", \"test\")") - result1 = mel.eval("$w = `window`; $scrollLayout = `scrollLayout`; proc testTranslator(string $s){ global int $materialsScopeResult; $materialsScopeResult=endsWith($s, \"materialsScopeName=test\"); } mayaUsdTranslatorExport($scrollLayout, \"query\", \"\", \"testTranslator\"); deleteUI $w; global int $materialsScopeResult; int $r=$materialsScopeResult;"); - self.assertTrue(result1) - -if __name__ == '__main__': - fixturesUtils.runTests(globals()) diff --git a/test/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt b/test/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt index 607daf3af7..8585a5145c 100644 --- a/test/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt +++ b/test/lib/usd/pxrUsdPreviewSurface/CMakeLists.txt @@ -17,6 +17,8 @@ foreach(script ${TEST_SCRIPT_FILES}) mayaUsd_add_test(${target} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} PYTHON_MODULE ${target} + ENV + "USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME=1" ) set_property(TEST ${target} APPEND PROPERTY LABELS usdPreviewSurface) endforeach() diff --git a/test/lib/usd/translators/CMakeLists.txt b/test/lib/usd/translators/CMakeLists.txt index 348adb0334..f25a311a14 100644 --- a/test/lib/usd/translators/CMakeLists.txt +++ b/test/lib/usd/translators/CMakeLists.txt @@ -6,7 +6,6 @@ set(TEST_SCRIPT_FILES testUsdExportCamera.py testUsdExportColorSets.py testUsdExportConnected.py - testUsdExportDisplacement.py testUsdExportDisplayColor.py testUsdExportEulerFilter.py testUsdExportFileFormat.py @@ -39,8 +38,6 @@ set(TEST_SCRIPT_FILES testUsdExportRootsAndParentScope.py testUsdExportSelection.py testUsdExportSelectionHierarchy.py - testUsdExportShadingInstanced.py - testUsdExportShadingModePxrRis.py testUsdExportSkeleton.py testUsdExportStripNamespaces.py testUsdExportStroke.py @@ -76,7 +73,6 @@ set(TEST_SCRIPT_FILES testUsdImportUVSetMappings.py testUsdImportUSDZTextures.py testUsdExportImportRoundtripPreviewSurface.py - testUsdExportImportUDIM.py testUsdImportSkeleton.py testUsdImportXforms.py testUsdImportXformAnim.py @@ -104,12 +100,40 @@ endif() if (BUILD_RFM_TRANSLATORS) list(APPEND TEST_SCRIPT_FILES - testUsdExportRfMShaders.py testUsdImportRfMShaders.py ) endif() foreach(script ${TEST_SCRIPT_FILES}) + mayaUsd_get_unittest_target(target ${script}) + mayaUsd_add_test(${target} + PYTHON_MODULE ${target} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ENV + "USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME=1" + ) + + # Add a ctest label to these tests for easy filtering. + set_property(TEST ${target} APPEND PROPERTY LABELS translators) +endforeach() + +# These tests use custom material scope names and must not use +# the USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME env var because +# it takes precedence over the provided material scope name. +set(TEST_SCRIPT_FILES_WITH_MATERIAL_SCOPE + testUsdExportDisplacement.py + testUsdExportShadingInstanced.py + testUsdExportShadingModePxrRis.py + testUsdExportImportUDIM.py +) + +if (BUILD_RFM_TRANSLATORS) + list(APPEND TEST_SCRIPT_FILES_WITH_MATERIAL_SCOPE + testUsdExportRfMShaders.py + ) +endif() + +foreach(script ${TEST_SCRIPT_FILES_WITH_MATERIAL_SCOPE}) mayaUsd_get_unittest_target(target ${script}) mayaUsd_add_test(${target} PYTHON_MODULE ${target} @@ -202,7 +226,8 @@ if (MAYA_APP_VERSION VERSION_GREATER_EQUAL 2020) "${PXR_OVERRIDE_PLUGINPATH_NAME}=${CMAKE_CURRENT_BINARY_DIR}/../plugin/${plugin_type}" "INPUT_PATH=${CMAKE_CURRENT_SOURCE_DIR}" "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}" - ) + "USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME=1" + ) set_property(TEST ${target} APPEND PROPERTY LABELS translators) endforeach() endforeach() diff --git a/test/lib/usd/translators/testUsdExportMultiMaterial.py b/test/lib/usd/translators/testUsdExportMultiMaterial.py index 7cc0308a94..88db51b1b3 100644 --- a/test/lib/usd/translators/testUsdExportMultiMaterial.py +++ b/test/lib/usd/translators/testUsdExportMultiMaterial.py @@ -70,6 +70,21 @@ def testStageOpens(self): ''' self.assertTrue(self._stage) + def testMaterialScopeResolution(self): + # New default value as per USD Asset WG: + self.assertEqual(mayaUsdLib.JobExportArgs.GetDefaultMaterialsScopeName(), "mtl") + + # This override is low-priority + os.environ["MAYAUSD_MATERIALS_SCOPE_NAME"] = "MyMaterialScope" + self.assertEqual(mayaUsdLib.JobExportArgs.GetDefaultMaterialsScopeName(), "MyMaterialScope") + + # The USD_FORCE_DEFAULT_MATERIALS_SCOPE_NAME override has higher priority, but is read + # at startup and can not be turned on/off for this test. It was used on all tests that + # relied on "Looks" being the default name instead of "mtl" + + os.environ.pop("MAYAUSD_MATERIALS_SCOPE_NAME") + self.assertEqual(mayaUsdLib.JobExportArgs.GetDefaultMaterialsScopeName(), "mtl") + def testExportedUsdShadeNodeTypes(self): ''' Tests that all node ids are what we expect: @@ -154,7 +169,8 @@ def testVarnameMerging(self): cmds.usdExport(mergeTransformAndShape=True, file=usd_path, shadingMode='useRegistry', - convertMaterialsTo=['MaterialX', 'UsdPreviewSurface']) + convertMaterialsTo=['MaterialX', 'UsdPreviewSurface'], + materialsScopeName='Looks') # We expect 2 primvar readers, and 2 st transforms: stage = Usd.Stage.Open(usd_path)