diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c469c1364..8e42f85c98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(BUILD_ADSK_PLUGIN "Build Autodesk USD plugin." ON) option(BUILD_PXR_PLUGIN "Build the Pixar USD plugin and libraries." ON) option(BUILD_AL_PLUGIN "Build the Animal Logic USD plugin and libraries." ON) option(BUILD_HDMAYA "Build the Maya-To-Hydra plugin and scene delegate." ON) +option(BUILD_RFM_TRANSLATORS "Build translators for RenderMan for Maya shaders." ON) option(BUILD_TESTS "Build tests." ON) option(BUILD_STRICT_MODE "Enforce all warnings as errors." ON) option(BUILD_SHARED_LIBS "Build libraries as shared or static." ON) diff --git a/doc/build.md b/doc/build.md index e7f57120fe..a06e543f1b 100644 --- a/doc/build.md +++ b/doc/build.md @@ -107,6 +107,7 @@ BUILD_ADSK_PLUGIN | builds Autodesk USD plugin. BUILD_PXR_PLUGIN | builds the Pixar USD plugin and libraries. | ON BUILD_AL_PLUGIN | builds the Animal Logic USD plugin and libraries. | ON BUILD_HDMAYA | builds the Maya-To-Hydra plugin and scene delegate. | ON +BUILD_RFM_TRANSLATORS | builds translators for RenderMan for Maya shaders. | ON BUILD_TESTS | builds all unit tests. | ON BUILD_STRICT_MODE | enforces all warnings as errors. | ON BUILD_WITH_PYTHON_3 | build with python 3. | OFF diff --git a/lib/mayaUsd/fileio/shading/CMakeLists.txt b/lib/mayaUsd/fileio/shading/CMakeLists.txt index e4d80461c8..27be9624a0 100644 --- a/lib/mayaUsd/fileio/shading/CMakeLists.txt +++ b/lib/mayaUsd/fileio/shading/CMakeLists.txt @@ -13,6 +13,7 @@ target_sources(${PROJECT_NAME} ) set(HEADERS + rfmShaderMap.h shadingModeExporter.h shadingModeExporterContext.h shadingModeImporter.h diff --git a/lib/mayaUsd/fileio/shading/rfmShaderMap.h b/lib/mayaUsd/fileio/shading/rfmShaderMap.h new file mode 100644 index 0000000000..2c39468071 --- /dev/null +++ b/lib/mayaUsd/fileio/shading/rfmShaderMap.h @@ -0,0 +1,223 @@ +// +// Copyright 2016 Pixar +// +// 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. +// +// This table comes from RenderMan for Maya version 23.5, and is based on the +// config/mayaTranslation.json in the installation. +// +// The software does under the hood transformation implementing some Maya +// native shader nodes as RIS pattern objects. The conversion allows writing +// a fully working shader graph to USD. +// We use this table both for export and for import when RIS mode is active. + +#ifndef MAYAUSD_FILEIO_SHADING_RFM_SHADER_MAP_H +#define MAYAUSD_FILEIO_SHADING_RFM_SHADER_MAP_H + +#include +#include + +#include +#include + + +PXR_NAMESPACE_OPEN_SCOPE + + +static const std::vector> RfmNodesToShaderIds = { + // These Maya nodes are provided by Maya itself, so we map a Maya node type + // name to a "Pxr" prefixed RenderMan for Maya shader ID. + { TfToken("bifrostAeroMaterial", TfToken::Immortal), TfToken("PxrBifrostAero", TfToken::Immortal) }, + { TfToken("xgen_hair_physical", TfToken::Immortal), TfToken("PxrMayaXgenHairPhysical", TfToken::Immortal) }, + { TfToken("blendColors", TfToken::Immortal), TfToken("PxrMayaBlendColors", TfToken::Immortal) }, + { TfToken("blinn", TfToken::Immortal), TfToken("PxrMayaBlinn", TfToken::Immortal) }, + { TfToken("bulge", TfToken::Immortal), TfToken("PxrMayaBulge", TfToken::Immortal) }, + { TfToken("bump2d", TfToken::Immortal), TfToken("PxrMayaBump2d", TfToken::Immortal) }, + { TfToken("bump3d", TfToken::Immortal), TfToken("PxrMayaBump3d", TfToken::Immortal) }, + { TfToken("brownian", TfToken::Immortal), TfToken("PxrMayaBrownian", TfToken::Immortal) }, + { TfToken("checker", TfToken::Immortal), TfToken("PxrMayaChecker", TfToken::Immortal) }, + { TfToken("clamp", TfToken::Immortal), TfToken("PxrMayaClamp", TfToken::Immortal) }, + { TfToken("cloth", TfToken::Immortal), TfToken("PxrMayaCloth", TfToken::Immortal) }, + { TfToken("cloud", TfToken::Immortal), TfToken("PxrMayaCloud", TfToken::Immortal) }, + { TfToken("condition", TfToken::Immortal), TfToken("PxrCondition", TfToken::Immortal) }, + { TfToken("contrast", TfToken::Immortal), TfToken("PxrMayaContrast", TfToken::Immortal) }, + { TfToken("crater", TfToken::Immortal), TfToken("PxrMayaCrater", TfToken::Immortal) }, + { TfToken("file", TfToken::Immortal), TfToken("PxrMayaFile", TfToken::Immortal) }, + { TfToken("fluidShape", TfToken::Immortal), TfToken("PxrMayaFluidShape", TfToken::Immortal) }, + { TfToken("fractal", TfToken::Immortal), TfToken("PxrMayaFractal", TfToken::Immortal) }, + { TfToken("gammaCorrect", TfToken::Immortal), TfToken("PxrMayaGammaCorrect", TfToken::Immortal) }, + { TfToken("granite", TfToken::Immortal), TfToken("PxrMayaGranite", TfToken::Immortal) }, + { TfToken("grid", TfToken::Immortal), TfToken("PxrMayaGrid", TfToken::Immortal) }, + { TfToken("hairSystem", TfToken::Immortal), TfToken("PxrMayaHair", TfToken::Immortal) }, + { TfToken("hsvToRgb", TfToken::Immortal), TfToken("PxrMayaHsvToRgb", TfToken::Immortal) }, + { TfToken("imagePlane", TfToken::Immortal), TfToken("PxrMayaImagePlane", TfToken::Immortal) }, + { TfToken("lambert", TfToken::Immortal), TfToken("PxrMayaLambert", TfToken::Immortal) }, + { TfToken("layeredTexture", TfToken::Immortal), TfToken("PxrMayaLayeredTexture", TfToken::Immortal) }, + { TfToken("leather", TfToken::Immortal), TfToken("PxrMayaLeather", TfToken::Immortal) }, + { TfToken("luminance", TfToken::Immortal), TfToken("PxrMayaLuminance", TfToken::Immortal) }, + { TfToken("marble", TfToken::Immortal), TfToken("PxrMayaMarble", TfToken::Immortal) }, + { TfToken("mountain", TfToken::Immortal), TfToken("PxrMayaMountain", TfToken::Immortal) }, + { TfToken("multiplyDivide", TfToken::Immortal), TfToken("PxrMultiplyDivide", TfToken::Immortal) }, + { TfToken("noise", TfToken::Immortal), TfToken("PxrMayaNoise", TfToken::Immortal) }, + { TfToken("place2dTexture", TfToken::Immortal), TfToken("PxrMayaPlacement2d", TfToken::Immortal) }, + { TfToken("place3dTexture", TfToken::Immortal), TfToken("PxrMayaPlacement3d", TfToken::Immortal) }, + { TfToken("plusMinusAverage", TfToken::Immortal), TfToken("PxrMayaPlusMinusAverage", TfToken::Immortal) }, + { TfToken("projection", TfToken::Immortal), TfToken("PxrMayaProjection", TfToken::Immortal) }, + { TfToken("ramp", TfToken::Immortal), TfToken("PxrMayaRamp", TfToken::Immortal) }, + { TfToken("remapColor", TfToken::Immortal), TfToken("PxrMayaRemapColor", TfToken::Immortal) }, + { TfToken("remapHsv", TfToken::Immortal), TfToken("PxrMayaRemapHsv", TfToken::Immortal) }, + { TfToken("remapValue", TfToken::Immortal), TfToken("PxrMayaRemapValue", TfToken::Immortal) }, + { TfToken("reverse", TfToken::Immortal), TfToken("PxrMayaReverse", TfToken::Immortal) }, + { TfToken("rgbToHsv", TfToken::Immortal), TfToken("PxrMayaRgbToHsv", TfToken::Immortal) }, + { TfToken("rock", TfToken::Immortal), TfToken("PxrMayaRock", TfToken::Immortal) }, + { TfToken("setRange", TfToken::Immortal), TfToken("PxrMayaSetRange", TfToken::Immortal) }, + { TfToken("snow", TfToken::Immortal), TfToken("PxrMayaSnow", TfToken::Immortal) }, + { TfToken("solidFractal", TfToken::Immortal), TfToken("PxrMayaSolidFractal", TfToken::Immortal) }, + { TfToken("stucco", TfToken::Immortal), TfToken("PxrMayaStucco", TfToken::Immortal) }, + { TfToken("uvChooser", TfToken::Immortal), TfToken("PxrMayaUVChooser", TfToken::Immortal) }, + { TfToken("volumeFog", TfToken::Immortal), TfToken("PxrMayaVolumeFog", TfToken::Immortal) }, + { TfToken("volumeNoise", TfToken::Immortal), TfToken("PxrMayaVolumeNoise", TfToken::Immortal) }, + { TfToken("wood", TfToken::Immortal), TfToken("PxrMayaWood", TfToken::Immortal) }, + { TfToken("locator", TfToken::Immortal), TfToken("PxrProcedural", TfToken::Immortal) }, + + // These nodes are provided by RenderMan for Maya, so the Maya node type + // name matches the RenderMan for Maya shader ID exactly. + // The list can be obtained in Maya with this Python snippet: + // cmds.loadPlugin('RenderMan_for_Maya') + // allRfmNodes = cmds.pluginInfo('RenderMan_for_Maya', q=True, dependNode=True) + // sorted([node for node in allRfmNodes if node.startswith('Pxr')]) + { TfToken("PxrAdjustNormal", TfToken::Immortal), TfToken("PxrAdjustNormal", TfToken::Immortal) }, + { TfToken("PxrAovLight", TfToken::Immortal), TfToken("PxrAovLight", TfToken::Immortal) }, + { TfToken("PxrAttribute", TfToken::Immortal), TfToken("PxrAttribute", TfToken::Immortal) }, + { TfToken("PxrBackgroundDisplayFilter", TfToken::Immortal), TfToken("PxrBackgroundDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrBackgroundSampleFilter", TfToken::Immortal), TfToken("PxrBackgroundSampleFilter", TfToken::Immortal) }, + { TfToken("PxrBakePointCloud", TfToken::Immortal), TfToken("PxrBakePointCloud", TfToken::Immortal) }, + { TfToken("PxrBakeTexture", TfToken::Immortal), TfToken("PxrBakeTexture", TfToken::Immortal) }, + { TfToken("PxrBarnLightFilter", TfToken::Immortal), TfToken("PxrBarnLightFilter", TfToken::Immortal) }, + { TfToken("PxrBlack", TfToken::Immortal), TfToken("PxrBlack", TfToken::Immortal) }, + { TfToken("PxrBlackBody", TfToken::Immortal), TfToken("PxrBlackBody", TfToken::Immortal) }, + { TfToken("PxrBlend", TfToken::Immortal), TfToken("PxrBlend", TfToken::Immortal) }, + { TfToken("PxrBlockerLightFilter", TfToken::Immortal), TfToken("PxrBlockerLightFilter", TfToken::Immortal) }, + { TfToken("PxrBump", TfToken::Immortal), TfToken("PxrBump", TfToken::Immortal) }, + { TfToken("PxrBumpManifold2D", TfToken::Immortal), TfToken("PxrBumpManifold2D", TfToken::Immortal) }, + { TfToken("PxrCamera", TfToken::Immortal), TfToken("PxrCamera", TfToken::Immortal) }, + { TfToken("PxrChecker", TfToken::Immortal), TfToken("PxrChecker", TfToken::Immortal) }, + { TfToken("PxrClamp", TfToken::Immortal), TfToken("PxrClamp", TfToken::Immortal) }, + { TfToken("PxrColorCorrect", TfToken::Immortal), TfToken("PxrColorCorrect", TfToken::Immortal) }, + { TfToken("PxrConstant", TfToken::Immortal), TfToken("PxrConstant", TfToken::Immortal) }, + { TfToken("PxrCookieLightFilter", TfToken::Immortal), TfToken("PxrCookieLightFilter", TfToken::Immortal) }, + { TfToken("PxrCopyAOVDisplayFilter", TfToken::Immortal), TfToken("PxrCopyAOVDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrCopyAOVSampleFilter", TfToken::Immortal), TfToken("PxrCopyAOVSampleFilter", TfToken::Immortal) }, + { TfToken("PxrCross", TfToken::Immortal), TfToken("PxrCross", TfToken::Immortal) }, + { TfToken("PxrCryptomatte", TfToken::Immortal), TfToken("PxrCryptomatte", TfToken::Immortal) }, + { TfToken("PxrCurvature", TfToken::Immortal), TfToken("PxrCurvature", TfToken::Immortal) }, + { TfToken("PxrCylinderCamera", TfToken::Immortal), TfToken("PxrCylinderCamera", TfToken::Immortal) }, + { TfToken("PxrCylinderLight", TfToken::Immortal), TfToken("PxrCylinderLight", TfToken::Immortal) }, + { TfToken("PxrDefault", TfToken::Immortal), TfToken("PxrDefault", TfToken::Immortal) }, + { TfToken("PxrDiffuse", TfToken::Immortal), TfToken("PxrDiffuse", TfToken::Immortal) }, + { TfToken("PxrDirectLighting", TfToken::Immortal), TfToken("PxrDirectLighting", TfToken::Immortal) }, + { TfToken("PxrDirt", TfToken::Immortal), TfToken("PxrDirt", TfToken::Immortal) }, + { TfToken("PxrDiskLight", TfToken::Immortal), TfToken("PxrDiskLight", TfToken::Immortal) }, + { TfToken("PxrDisney", TfToken::Immortal), TfToken("PxrDisney", TfToken::Immortal) }, + { TfToken("PxrDispScalarLayer", TfToken::Immortal), TfToken("PxrDispScalarLayer", TfToken::Immortal) }, + { TfToken("PxrDispTransform", TfToken::Immortal), TfToken("PxrDispTransform", TfToken::Immortal) }, + { TfToken("PxrDispVectorLayer", TfToken::Immortal), TfToken("PxrDispVectorLayer", TfToken::Immortal) }, + { TfToken("PxrDisplace", TfToken::Immortal), TfToken("PxrDisplace", TfToken::Immortal) }, + { TfToken("PxrDistantLight", TfToken::Immortal), TfToken("PxrDistantLight", TfToken::Immortal) }, + { TfToken("PxrDomeLight", TfToken::Immortal), TfToken("PxrDomeLight", TfToken::Immortal) }, + { TfToken("PxrDot", TfToken::Immortal), TfToken("PxrDot", TfToken::Immortal) }, + { TfToken("PxrEdgeDetect", TfToken::Immortal), TfToken("PxrEdgeDetect", TfToken::Immortal) }, + { TfToken("PxrEnvDayLight", TfToken::Immortal), TfToken("PxrEnvDayLight", TfToken::Immortal) }, + { TfToken("PxrExposure", TfToken::Immortal), TfToken("PxrExposure", TfToken::Immortal) }, + { TfToken("PxrFacingRatio", TfToken::Immortal), TfToken("PxrFacingRatio", TfToken::Immortal) }, + { TfToken("PxrFilmicTonemapperDisplayFilter", TfToken::Immortal), TfToken("PxrFilmicTonemapperDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrFilmicTonemapperSampleFilter", TfToken::Immortal), TfToken("PxrFilmicTonemapperSampleFilter", TfToken::Immortal) }, + { TfToken("PxrFlakes", TfToken::Immortal), TfToken("PxrFlakes", TfToken::Immortal) }, + { TfToken("PxrFractal", TfToken::Immortal), TfToken("PxrFractal", TfToken::Immortal) }, + { TfToken("PxrGamma", TfToken::Immortal), TfToken("PxrGamma", TfToken::Immortal) }, + { TfToken("PxrGoboLightFilter", TfToken::Immortal), TfToken("PxrGoboLightFilter", TfToken::Immortal) }, + { TfToken("PxrGradeDisplayFilter", TfToken::Immortal), TfToken("PxrGradeDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrGradeSampleFilter", TfToken::Immortal), TfToken("PxrGradeSampleFilter", TfToken::Immortal) }, + { TfToken("PxrHSL", TfToken::Immortal), TfToken("PxrHSL", TfToken::Immortal) }, + { TfToken("PxrHairColor", TfToken::Immortal), TfToken("PxrHairColor", TfToken::Immortal) }, + { TfToken("PxrHalfBufferErrorFilter", TfToken::Immortal), TfToken("PxrHalfBufferErrorFilter", TfToken::Immortal) }, + { TfToken("PxrImageDisplayFilter", TfToken::Immortal), TfToken("PxrImageDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrIntMultLightFilter", TfToken::Immortal), TfToken("PxrIntMultLightFilter", TfToken::Immortal) }, + { TfToken("PxrInvert", TfToken::Immortal), TfToken("PxrInvert", TfToken::Immortal) }, + { TfToken("PxrLayer", TfToken::Immortal), TfToken("PxrLayer", TfToken::Immortal) }, + { TfToken("PxrLayerMixer", TfToken::Immortal), TfToken("PxrLayerMixer", TfToken::Immortal) }, + { TfToken("PxrLayerSurface", TfToken::Immortal), TfToken("PxrLayerSurface", TfToken::Immortal) }, + { TfToken("PxrLayeredBlend", TfToken::Immortal), TfToken("PxrLayeredBlend", TfToken::Immortal) }, + { TfToken("PxrLayeredTexture", TfToken::Immortal), TfToken("PxrLayeredTexture", TfToken::Immortal) }, + { TfToken("PxrLightProbe", TfToken::Immortal), TfToken("PxrLightProbe", TfToken::Immortal) }, + { TfToken("PxrLightSaturation", TfToken::Immortal), TfToken("PxrLightSaturation", TfToken::Immortal) }, + { TfToken("PxrManifold2D", TfToken::Immortal), TfToken("PxrManifold2D", TfToken::Immortal) }, + { TfToken("PxrManifold3D", TfToken::Immortal), TfToken("PxrManifold3D", TfToken::Immortal) }, + { TfToken("PxrMarschnerHair", TfToken::Immortal), TfToken("PxrMarschnerHair", TfToken::Immortal) }, + { TfToken("PxrMatteID", TfToken::Immortal), TfToken("PxrMatteID", TfToken::Immortal) }, + { TfToken("PxrMeshLight", TfToken::Immortal), TfToken("PxrMeshLight", TfToken::Immortal) }, + { TfToken("PxrMix", TfToken::Immortal), TfToken("PxrMix", TfToken::Immortal) }, + { TfToken("PxrMultiTexture", TfToken::Immortal), TfToken("PxrMultiTexture", TfToken::Immortal) }, + { TfToken("PxrNormalMap", TfToken::Immortal), TfToken("PxrNormalMap", TfToken::Immortal) }, + { TfToken("PxrOSL", TfToken::Immortal), TfToken("PxrOSL", TfToken::Immortal) }, + { TfToken("PxrOcclusion", TfToken::Immortal), TfToken("PxrOcclusion", TfToken::Immortal) }, + { TfToken("PxrPanini", TfToken::Immortal), TfToken("PxrPanini", TfToken::Immortal) }, + { TfToken("PxrPathTracer", TfToken::Immortal), TfToken("PxrPathTracer", TfToken::Immortal) }, + { TfToken("PxrPortalLight", TfToken::Immortal), TfToken("PxrPortalLight", TfToken::Immortal) }, + { TfToken("PxrPrimvar", TfToken::Immortal), TfToken("PxrPrimvar", TfToken::Immortal) }, + { TfToken("PxrProjectionLayer", TfToken::Immortal), TfToken("PxrProjectionLayer", TfToken::Immortal) }, + { TfToken("PxrProjectionStack", TfToken::Immortal), TfToken("PxrProjectionStack", TfToken::Immortal) }, + { TfToken("PxrProjector", TfToken::Immortal), TfToken("PxrProjector", TfToken::Immortal) }, + { TfToken("PxrPtexture", TfToken::Immortal), TfToken("PxrPtexture", TfToken::Immortal) }, + { TfToken("PxrRamp", TfToken::Immortal), TfToken("PxrRamp", TfToken::Immortal) }, + { TfToken("PxrRampLightFilter", TfToken::Immortal), TfToken("PxrRampLightFilter", TfToken::Immortal) }, + { TfToken("PxrRandomTextureManifold", TfToken::Immortal), TfToken("PxrRandomTextureManifold", TfToken::Immortal) }, + { TfToken("PxrRectLight", TfToken::Immortal), TfToken("PxrRectLight", TfToken::Immortal) }, + { TfToken("PxrRemap", TfToken::Immortal), TfToken("PxrRemap", TfToken::Immortal) }, + { TfToken("PxrRodLightFilter", TfToken::Immortal), TfToken("PxrRodLightFilter", TfToken::Immortal) }, + { TfToken("PxrRoundCube", TfToken::Immortal), TfToken("PxrRoundCube", TfToken::Immortal) }, + { TfToken("PxrSeExpr", TfToken::Immortal), TfToken("PxrSeExpr", TfToken::Immortal) }, + { TfToken("PxrShadedSide", TfToken::Immortal), TfToken("PxrShadedSide", TfToken::Immortal) }, + { TfToken("PxrShadowDisplayFilter", TfToken::Immortal), TfToken("PxrShadowDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrShadowFilter", TfToken::Immortal), TfToken("PxrShadowFilter", TfToken::Immortal) }, + { TfToken("PxrSharedSignalLightFilter", TfToken::Immortal), TfToken("PxrSharedSignalLightFilter", TfToken::Immortal) }, + { TfToken("PxrSphereCamera", TfToken::Immortal), TfToken("PxrSphereCamera", TfToken::Immortal) }, + { TfToken("PxrSphereLight", TfToken::Immortal), TfToken("PxrSphereLight", TfToken::Immortal) }, + { TfToken("PxrSurface", TfToken::Immortal), TfToken("PxrSurface", TfToken::Immortal) }, + { TfToken("PxrSwitch", TfToken::Immortal), TfToken("PxrSwitch", TfToken::Immortal) }, + { TfToken("PxrTangentField", TfToken::Immortal), TfToken("PxrTangentField", TfToken::Immortal) }, + { TfToken("PxrTee", TfToken::Immortal), TfToken("PxrTee", TfToken::Immortal) }, + { TfToken("PxrTexture", TfToken::Immortal), TfToken("PxrTexture", TfToken::Immortal) }, + { TfToken("PxrThinFilm", TfToken::Immortal), TfToken("PxrThinFilm", TfToken::Immortal) }, + { TfToken("PxrThreshold", TfToken::Immortal), TfToken("PxrThreshold", TfToken::Immortal) }, + { TfToken("PxrTileManifold", TfToken::Immortal), TfToken("PxrTileManifold", TfToken::Immortal) }, + { TfToken("PxrToFloat", TfToken::Immortal), TfToken("PxrToFloat", TfToken::Immortal) }, + { TfToken("PxrToFloat3", TfToken::Immortal), TfToken("PxrToFloat3", TfToken::Immortal) }, + { TfToken("PxrVCM", TfToken::Immortal), TfToken("PxrVCM", TfToken::Immortal) }, + { TfToken("PxrVariable", TfToken::Immortal), TfToken("PxrVariable", TfToken::Immortal) }, + { TfToken("PxrVary", TfToken::Immortal), TfToken("PxrVary", TfToken::Immortal) }, + { TfToken("PxrVisualizer", TfToken::Immortal), TfToken("PxrVisualizer", TfToken::Immortal) }, + { TfToken("PxrVolume", TfToken::Immortal), TfToken("PxrVolume", TfToken::Immortal) }, + { TfToken("PxrVoronoise", TfToken::Immortal), TfToken("PxrVoronoise", TfToken::Immortal) }, + { TfToken("PxrWatermarkFilter", TfToken::Immortal), TfToken("PxrWatermarkFilter", TfToken::Immortal) }, + { TfToken("PxrWhitePointDisplayFilter", TfToken::Immortal), TfToken("PxrWhitePointDisplayFilter", TfToken::Immortal) }, + { TfToken("PxrWhitePointSampleFilter", TfToken::Immortal), TfToken("PxrWhitePointSampleFilter", TfToken::Immortal) }, + { TfToken("PxrWireframe", TfToken::Immortal), TfToken("PxrWireframe", TfToken::Immortal) }, + { TfToken("PxrWorley", TfToken::Immortal), TfToken("PxrWorley", TfToken::Immortal) } +}; + + +PXR_NAMESPACE_CLOSE_SCOPE + + +#endif diff --git a/lib/mayaUsd/fileio/shading/shadingModeExporterContext.cpp b/lib/mayaUsd/fileio/shading/shadingModeExporterContext.cpp index 07b9513338..9cb21e10fe 100644 --- a/lib/mayaUsd/fileio/shading/shadingModeExporterContext.cpp +++ b/lib/mayaUsd/fileio/shading/shadingModeExporterContext.cpp @@ -511,29 +511,5 @@ UsdMayaShadingModeExportContext::MakeStandardMaterialPrim( return UsdPrim(); } -std::string -UsdMayaShadingModeExportContext::GetStandardAttrName( - const MPlug& plug, - const bool allowMultiElementArrays) const -{ - if (plug.isElement()) { - MString mayaPlgName = plug.array().partialName(false, false, false, false, false, true); - unsigned int logicalIdx = plug.logicalIndex(); - if (allowMultiElementArrays) { - return TfStringPrintf("%s_%d", mayaPlgName.asChar(), logicalIdx); - } - else if (logicalIdx == 0) { - return mayaPlgName.asChar(); - } - else { - return TfToken(); - } - } - else { - MString mayaPlgName = plug.partialName(false, false, false, false, false, true); - return mayaPlgName.asChar(); - } -} - PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/fileio/shading/shadingModeExporterContext.h b/lib/mayaUsd/fileio/shading/shadingModeExporterContext.h index b7d2559652..9c5b12927f 100644 --- a/lib/mayaUsd/fileio/shading/shadingModeExporterContext.h +++ b/lib/mayaUsd/fileio/shading/shadingModeExporterContext.h @@ -117,20 +117,6 @@ class UsdMayaShadingModeExportContext const std::string& name=std::string(), SdfPathSet* const boundPrimPaths=nullptr) const; - /// Use this function to get a "standard" usd attr name for \p attrPlug. - /// The definition of "standard" may depend on arguments passed to the - /// script (i.e. stripping namespaces, etc.). - /// - /// If attrPlug is an element in an array and if \p allowMultiElementArrays - /// is true, this will _. - /// - /// If it's false, this will return if it's the 0-th logical - /// element and an empty token otherwise. - MAYAUSD_CORE_PUBLIC - std::string GetStandardAttrName( - const MPlug& attrPlug, - const bool allowMultiElementArrays) const; - MAYAUSD_CORE_PUBLIC UsdMayaShadingModeExportContext( const MObject& shadingEngine, diff --git a/lib/mayaUsd/fileio/shading/shadingModePxrRis.cpp b/lib/mayaUsd/fileio/shading/shadingModePxrRis.cpp index de95dd4702..2ff1ef4855 100644 --- a/lib/mayaUsd/fileio/shading/shadingModePxrRis.cpp +++ b/lib/mayaUsd/fileio/shading/shadingModePxrRis.cpp @@ -14,15 +14,14 @@ // limitations under the License. // -// Defines the RenderMan for Maya mapping between Pxr objects and Maya internal nodes -#include "shadingModePxrRis_rfm_map.h" - +#include #include #include #include #include #include #include +#include #include #include #include @@ -125,7 +124,7 @@ class PxrRisShadingModeExporter : public UsdMayaShadingModeExporter { // Now look into the RIS TABLE if the typeName doesn't starts with Pxr. if (!TfStringStartsWith(mayaTypeName, _tokens->PxrShaderPrefix)) { - for (const auto& i : _RFM_RISNODE_TABLE) { + for (const auto& i : RfmNodesToShaderIds) { if (i.first == mayaTypeName) { return i.second; } @@ -225,7 +224,7 @@ class PxrRisShadingModeExporter : public UsdMayaShadingModeExporter { // maybe that's OK? nothing downstream cares about it. const TfToken attrName = TfToken( - context.GetStandardAttrName(attrPlug, false)); + UsdMayaShadingUtil::GetStandardAttrName(attrPlug, false)); if (attrName.IsEmpty()) { continue; } @@ -270,7 +269,7 @@ class PxrRisShadingModeExporter : public UsdMayaShadingModeExporter { UsdShadeConnectableAPI::ConnectToSource( input, UsdShadeShader(cPrim), - TfToken(context.GetStandardAttrName(connectedPlug, false))); + TfToken(UsdMayaShadingUtil::GetStandardAttrName(connectedPlug, false))); } } @@ -455,7 +454,7 @@ _GetMayaTypeNameForShaderId( const TfToken& shaderId) { // Remap the mayaTypeName if found in the RIS table. - for (const auto & i : _RFM_RISNODE_TABLE) { + for (const auto & i : RfmNodesToShaderIds) { if (i.second == shaderId) { return i.first; } diff --git a/lib/mayaUsd/fileio/shading/shadingModePxrRis_rfm_map.h b/lib/mayaUsd/fileio/shading/shadingModePxrRis_rfm_map.h deleted file mode 100644 index fe854a6aca..0000000000 --- a/lib/mayaUsd/fileio/shading/shadingModePxrRis_rfm_map.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2016 Pixar -// -// 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. -// -// This table comes from RenderMan for Maya version 20.1 -// The software does under the hood transformation implementing some Maya native shader nodes -// as RIS patter objects. The conversion allows to write in USD a fully working shader graph -// We use this table both for export and for import when RIS mode is active. -// XXX This should probably live in a xml or json file that can be easily updated without recompile - -#include -#include - -#include -#include - -PXR_NAMESPACE_OPEN_SCOPE - -static const std::vector > _RFM_RISNODE_TABLE = { - { TfToken("blendColors", TfToken::Immortal), TfToken("PxrMayaBlendColors", TfToken::Immortal) }, - { TfToken("bulge", TfToken::Immortal), TfToken("PxrMayaBulge", TfToken::Immortal) }, - { TfToken("bump2d", TfToken::Immortal), TfToken("PxrMayaBump2d", TfToken::Immortal) }, - { TfToken("bump3d", TfToken::Immortal), TfToken("PxrMayaBump3d", TfToken::Immortal) }, - { TfToken("brownian", TfToken::Immortal), TfToken("PxrMayaBrownian", TfToken::Immortal) }, - { TfToken("checker", TfToken::Immortal), TfToken("PxrMayaChecker", TfToken::Immortal) }, - { TfToken("clamp", TfToken::Immortal), TfToken("PxrMayaClamp", TfToken::Immortal) }, - { TfToken("cloth", TfToken::Immortal), TfToken("PxrMayaCloth", TfToken::Immortal) }, - { TfToken("cloud", TfToken::Immortal), TfToken("PxrMayaCloud", TfToken::Immortal) }, - { TfToken("condition", TfToken::Immortal), TfToken("PxrCondition", TfToken::Immortal) }, - { TfToken("contrast", TfToken::Immortal), TfToken("PxrMayaContrast", TfToken::Immortal) }, - { TfToken("crater", TfToken::Immortal), TfToken("PxrMayaCrater", TfToken::Immortal) }, - { TfToken("file", TfToken::Immortal), TfToken("PxrMayaFile", TfToken::Immortal) }, - { TfToken("fluidShape", TfToken::Immortal), TfToken("PxrMayaFluidShape", TfToken::Immortal) }, - { TfToken("fractal", TfToken::Immortal), TfToken("PxrMayaFractal", TfToken::Immortal) }, - { TfToken("gammaCorrect", TfToken::Immortal), TfToken("PxrMayaGammaCorrect", TfToken::Immortal) }, - { TfToken("granite", TfToken::Immortal), TfToken("PxrMayaGranite", TfToken::Immortal) }, - { TfToken("grid", TfToken::Immortal), TfToken("PxrMayaGrid", TfToken::Immortal) }, - { TfToken("hairSystem", TfToken::Immortal), TfToken("PxrMayaHair", TfToken::Immortal) }, - { TfToken("hsvToRgb", TfToken::Immortal), TfToken("PxrMayaHsvToRgb", TfToken::Immortal) }, - { TfToken("imagePlane", TfToken::Immortal), TfToken("PxrMayaImagePlane", TfToken::Immortal) }, - { TfToken("layeredTexture", TfToken::Immortal), TfToken("PxrMayaLayeredTexture", TfToken::Immortal) }, - { TfToken("leather", TfToken::Immortal), TfToken("PxrMayaLeather", TfToken::Immortal) }, - { TfToken("luminance", TfToken::Immortal), TfToken("PxrMayaLuminance", TfToken::Immortal) }, - { TfToken("marble", TfToken::Immortal), TfToken("PxrMayaMarble", TfToken::Immortal) }, - { TfToken("mountain", TfToken::Immortal), TfToken("PxrMayaMountain", TfToken::Immortal) }, - { TfToken("multiplyDivide", TfToken::Immortal), TfToken("PxrMultiplyDivide", TfToken::Immortal) }, - { TfToken("noise", TfToken::Immortal), TfToken("PxrMayaNoise", TfToken::Immortal) }, - { TfToken("place2dTexture", TfToken::Immortal), TfToken("PxrMayaPlacement2d", TfToken::Immortal) }, - { TfToken("place3dTexture", TfToken::Immortal), TfToken("PxrMayaPlacement3d", TfToken::Immortal) }, - { TfToken("plusMinusAverage", TfToken::Immortal), TfToken("PxrMayaPlusMinusAverage", TfToken::Immortal) }, - { TfToken("ramp", TfToken::Immortal), TfToken("PxrMayaRamp", TfToken::Immortal) }, - { TfToken("remapColor", TfToken::Immortal), TfToken("PxrMayaRemapColor", TfToken::Immortal) }, - { TfToken("remapHsv", TfToken::Immortal), TfToken("PxrMayaRemapHsv", TfToken::Immortal) }, - { TfToken("remapValue", TfToken::Immortal), TfToken("PxrMayaRemapValue", TfToken::Immortal) }, - { TfToken("reverse", TfToken::Immortal), TfToken("PxrMayaReverse", TfToken::Immortal) }, - { TfToken("rgbToHsv", TfToken::Immortal), TfToken("PxrMayaRgbToHsv", TfToken::Immortal) }, - { TfToken("rock", TfToken::Immortal), TfToken("PxrMayaRock", TfToken::Immortal) }, - { TfToken("setRange", TfToken::Immortal), TfToken("PxrMayaSetRange", TfToken::Immortal) }, - { TfToken("snow", TfToken::Immortal), TfToken("PxrMayaSnow", TfToken::Immortal) }, - { TfToken("solidFractal", TfToken::Immortal), TfToken("PxrMayaSolidFractal", TfToken::Immortal) }, - { TfToken("stucco", TfToken::Immortal), TfToken("PxrMayaStucco", TfToken::Immortal) }, - { TfToken("uvChooser", TfToken::Immortal), TfToken("PxrMayaUVChooser", TfToken::Immortal) }, - { TfToken("volumeFog", TfToken::Immortal), TfToken("PxrMayaVolumeFog", TfToken::Immortal) }, - { TfToken("volumeNoise", TfToken::Immortal), TfToken("PxrMayaVolumeNoise", TfToken::Immortal) }, - { TfToken("wood", TfToken::Immortal), TfToken("PxrMayaWood", TfToken::Immortal) } -}; - - -PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/fileio/shading/shadingModeUseRegistry.cpp b/lib/mayaUsd/fileio/shading/shadingModeUseRegistry.cpp index 9d1a6407dd..ebe9566681 100644 --- a/lib/mayaUsd/fileio/shading/shadingModeUseRegistry.cpp +++ b/lib/mayaUsd/fileio/shading/shadingModeUseRegistry.cpp @@ -89,12 +89,6 @@ class UseRegistryShadingModeExporter : public UsdMayaShadingModeExporter return nullptr; } - if (depNode.hasFn(MFn::kDagNode)) { - // XXX: Skip DAG nodes for now, but we may eventually want/need - // to consider them. - return nullptr; - } - if (!UsdMayaUtil::isWritable(depNode)) { return nullptr; } @@ -266,14 +260,14 @@ class UseRegistryShadingModeExporter : public UsdMayaShadingModeExporter // Maya plugs represent so that we can author the // connection in USD. - const TfToken srcPlugName = - TfToken(context.GetStandardAttrName(srcPlug, false)); + const TfToken srcPlugName = TfToken( + UsdMayaShadingUtil::GetStandardAttrName(srcPlug, false)); UsdAttribute srcAttribute = srcShaderInfo->GetShadingAttributeForMayaAttrName( srcPlugName); - const TfToken dstPlugName = - TfToken(context.GetStandardAttrName(dstPlug, false)); + const TfToken dstPlugName = TfToken( + UsdMayaShadingUtil::GetStandardAttrName(dstPlug, false)); UsdAttribute dstAttribute = dstShaderInfo->GetShadingAttributeForMayaAttrName( dstPlugName); diff --git a/lib/mayaUsd/fileio/utils/shadingUtil.cpp b/lib/mayaUsd/fileio/utils/shadingUtil.cpp index 0342fad10c..92f52b7150 100644 --- a/lib/mayaUsd/fileio/utils/shadingUtil.cpp +++ b/lib/mayaUsd/fileio/utils/shadingUtil.cpp @@ -16,6 +16,7 @@ #include "shadingUtil.h" #include +#include #include #include #include @@ -23,8 +24,39 @@ #include #include +#include +#include + +#include + + PXR_NAMESPACE_USING_DIRECTIVE + +std::string +UsdMayaShadingUtil::GetStandardAttrName( + const MPlug& attrPlug, + bool allowMultiElementArrays) +{ + if (!attrPlug.isElement()) { + const MString mayaPlugName = + attrPlug.partialName(false, false, false, false, false, true); + return mayaPlugName.asChar(); + } + + const MString mayaPlugName = + attrPlug.array().partialName(false, false, false, false, false, true); + const unsigned int logicalIndex = attrPlug.logicalIndex(); + + if (allowMultiElementArrays) { + return TfStringPrintf("%s_%d", mayaPlugName.asChar(), logicalIndex); + } else if (logicalIndex == 0) { + return mayaPlugName.asChar(); + } + + return std::string(); +} + UsdShadeInput UsdMayaShadingUtil::CreateMaterialInputAndConnectShader( UsdShadeMaterial& material, diff --git a/lib/mayaUsd/fileio/utils/shadingUtil.h b/lib/mayaUsd/fileio/utils/shadingUtil.h index ea2a7c5fa3..ffe78d5789 100644 --- a/lib/mayaUsd/fileio/utils/shadingUtil.h +++ b/lib/mayaUsd/fileio/utils/shadingUtil.h @@ -16,6 +16,10 @@ #ifndef PXRUSDMAYA_SHADING_UTIL_H #define PXRUSDMAYA_SHADING_UTIL_H +/// \file + +#include + #include #include #include @@ -24,12 +28,30 @@ #include #include -#include +#include + +#include + PXR_NAMESPACE_OPEN_SCOPE + namespace UsdMayaShadingUtil { +/// Get a "standard" USD attribute name for \p attrPlug. +/// +/// If \p attrPlug is not an element in a Maya array attribute, then its name +/// is simply returned. +/// +/// If \p attrPlug is an element in an array and if \p allowMultiElementArrays +/// is true, this will return a name of the form "_". If +/// \p allowMultiElementArrays is false, this will return if it's +/// the 0-th logical element. Otherwise it will return an empty string. +MAYAUSD_CORE_PUBLIC +std::string GetStandardAttrName( + const MPlug& attrPlug, + bool allowMultiElementArrays); + /// Create an input on the given material and shader and create a connection /// between them. /// diff --git a/lib/usd/translators/shading/CMakeLists.txt b/lib/usd/translators/shading/CMakeLists.txt index c3e59a22f2..4fb246c43d 100644 --- a/lib/usd/translators/shading/CMakeLists.txt +++ b/lib/usd/translators/shading/CMakeLists.txt @@ -1,8 +1,9 @@ # ----------------------------------------------------------------------------- # sources # ----------------------------------------------------------------------------- -target_sources(${TARGET_NAME} +target_sources(${TARGET_NAME} PRIVATE + symmetricShaderWriter.cpp usdBlinnReader.cpp usdBlinnWriter.cpp usdFileTextureWriter.cpp @@ -18,8 +19,15 @@ target_sources(${TARGET_NAME} usdUVTextureReader.cpp ) +if (BUILD_RFM_TRANSLATORS) + target_sources(${TARGET_NAME} + PRIVATE + rfmShaderTranslation.cpp + ) +endif() + if (MAYA_APP_VERSION VERSION_GREATER_EQUAL 2020) - target_sources(${TARGET_NAME} + target_sources(${TARGET_NAME} PRIVATE usdStandardSurfaceReader.cpp usdStandardSurfaceWriter.cpp diff --git a/lib/usd/translators/shading/rfmShaderTranslation.cpp b/lib/usd/translators/shading/rfmShaderTranslation.cpp new file mode 100644 index 0000000000..ca9e585787 --- /dev/null +++ b/lib/usd/translators/shading/rfmShaderTranslation.cpp @@ -0,0 +1,62 @@ +// +// Copyright 2020 Pixar +// +// 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. +// +#include "symmetricShaderWriter.h" + +#include +#include +#include + +#include +#include +#include +#include + + +PXR_NAMESPACE_OPEN_SCOPE + + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + + ((conversionName, "rendermanForMaya")) + ((renderContext, "ri")) + ((niceName, "RenderMan for Maya")) + ((description, "Exports bound shaders as a RenderMan for Maya UsdShade network.")) +); + + +REGISTER_SHADING_MODE_EXPORT_MATERIAL_CONVERSION( + _tokens->conversionName, + _tokens->renderContext, + _tokens->niceName, + _tokens->description); + + +// Register a symmetric shader writer for each Maya node type name and USD +// shader ID mapping. These writers will only apply when the applicable +// material conversion is requested. +TF_REGISTRY_FUNCTION(UsdMayaShaderWriterRegistry) +{ + for (const auto& i : RfmNodesToShaderIds) { + PxrUsdTranslators_SymmetricShaderWriter::RegisterWriter( + i.first, + i.second, + _tokens->conversionName); + } +}; + + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/usd/translators/shading/symmetricShaderWriter.cpp b/lib/usd/translators/shading/symmetricShaderWriter.cpp new file mode 100644 index 0000000000..af5ac5fe49 --- /dev/null +++ b/lib/usd/translators/shading/symmetricShaderWriter.cpp @@ -0,0 +1,250 @@ +// +// Copyright 2020 Pixar +// +// 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. +// +#include "symmetricShaderWriter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +PXR_NAMESPACE_OPEN_SCOPE + + +/* static */ +void +PxrUsdTranslators_SymmetricShaderWriter::RegisterWriter( + const TfToken& mayaNodeTypeName, + const TfToken& usdShaderId, + const TfToken& materialConversionName) +{ + UsdMayaShaderWriterRegistry::Register( + mayaNodeTypeName, + [materialConversionName](const UsdMayaJobExportArgs& exportArgs) { + return PxrUsdTranslators_SymmetricShaderWriter::CanExport( + exportArgs, + materialConversionName); + }, + [usdShaderId]( + const MFnDependencyNode& depNodeFn, + const SdfPath& usdPath, + UsdMayaWriteJobContext& jobCtx) { + return std::make_shared( + depNodeFn, + usdPath, + jobCtx, + usdShaderId); + }); +} + +/* static */ +UsdMayaShaderWriter::ContextSupport +PxrUsdTranslators_SymmetricShaderWriter::CanExport( + const UsdMayaJobExportArgs& exportArgs, + const TfToken& materialConversionName) +{ + if (materialConversionName.IsEmpty() || + exportArgs.convertMaterialsTo == materialConversionName) { + return ContextSupport::Supported; + } + + return ContextSupport::Unsupported; +} + +PxrUsdTranslators_SymmetricShaderWriter::PxrUsdTranslators_SymmetricShaderWriter( + const MFnDependencyNode& depNodeFn, + const SdfPath& usdPath, + UsdMayaWriteJobContext& jobCtx, + const TfToken& usdShaderId) : + UsdMayaShaderWriter(depNodeFn, usdPath, jobCtx) +{ + UsdShadeShader shaderSchema = + UsdShadeShader::Define(GetUsdStage(), GetUsdPath()); + if (!TF_VERIFY( + shaderSchema, + "Could not define UsdShadeShader at path '%s'\n", + GetUsdPath().GetText())) { + return; + } + + _usdPrim = shaderSchema.GetPrim(); + if (!TF_VERIFY( + _usdPrim, + "Could not get UsdPrim for UsdShadeShader at path '%s'\n", + shaderSchema.GetPath().GetText())) { + return; + } + + shaderSchema.CreateIdAttr(VtValue(usdShaderId)); + + for (unsigned int i = 0u; i < depNodeFn.attributeCount(); ++i) { + const MObject attrObj = depNodeFn.reorderedAttribute(i); + MPlug attrPlug = depNodeFn.findPlug(attrObj, true); + + if (attrPlug.isProcedural()) { + // The Maya docs say these should not be saved off. + continue; + } + + if (attrPlug.isChild()) { + continue; + } + + // For now, we only support arrays of length 1. If we encounter such an + // array, we emit it's 0-th element. + if (attrPlug.isArray()) { + const unsigned int numElements = attrPlug.evaluateNumElements(); + if (numElements == 0u) { + // Empty array, so skip this attribute. + continue; + } + + if (numElements > 1u) { + TF_WARN( + "Array with multiple elements encountered for " + "attribute '%s' on node '%s'. Currently, only arrays " + "with a single element are supported.", + attrPlug.name().asChar(), + UsdMayaUtil::GetMayaNodeName(depNodeFn.object()).c_str()); + } + + attrPlug = attrPlug[0]; + } + + // Keep our authoring sparse by ignoring attributes with no values set + // and no connections. + if (!UsdMayaUtil::IsAuthored(attrPlug) && !attrPlug.isConnected()) { + continue; + } + + const TfToken usdAttrName = TfToken( + UsdMayaShadingUtil::GetStandardAttrName(attrPlug, false)); + if (usdAttrName.IsEmpty()) { + continue; + } + + const SdfValueTypeName valueTypeName = + MAYAUSD_NS::Converter::getUsdTypeName(attrPlug); + if (!valueTypeName) { + // Unsupported Maya attribute type (e.g. "message" attributes). + continue; + } + + // If the Maya attribute is writable, we assume it must be an input. + // Inputs can still be connected as sources to inputs on other shaders. + if (MFnAttribute(attrPlug.attribute()).isWritable()) { + UsdShadeInput input = + shaderSchema.CreateInput(usdAttrName, valueTypeName); + if (!input) { + continue; + } + + if (attrPlug.isElement()) { + UsdMayaRoundTripUtil::MarkAttributeAsArray(input.GetAttr(), 0u); + } + + // Add this input to the name/attrPlug map. We'll iterate through + // these entries during Write() to set their values. + _inputNameAttrMap.insert(std::make_pair(usdAttrName, attrPlug)); + } else if (attrPlug.isConnected()) { + // Only author outputs for non-writable attributes if they are + // connected. + shaderSchema.CreateOutput(usdAttrName, valueTypeName); + } + } +} + +/* override */ +void +PxrUsdTranslators_SymmetricShaderWriter::Write(const UsdTimeCode& usdTime) +{ + UsdMayaShaderWriter::Write(usdTime); + + UsdShadeShader shaderSchema(_usdPrim); + if (!TF_VERIFY( + shaderSchema, + "Could not get UsdShadeShader schema for UsdPrim at path '%s'\n", + _usdPrim.GetPath().GetText())) { + return; + } + + for (const auto& inputAttrPair : _inputNameAttrMap) { + const TfToken& inputName = inputAttrPair.first; + const MPlug& attrPlug = inputAttrPair.second; + + UsdShadeInput input = shaderSchema.GetInput(inputName); + if (!input) { + continue; + } + + UsdMayaWriteUtil::SetUsdAttr( + attrPlug, + input.GetAttr(), + usdTime, + _GetSparseValueWriter()); + } +} + +/* override */ +TfToken +PxrUsdTranslators_SymmetricShaderWriter::GetShadingAttributeNameForMayaAttrName( + const TfToken& mayaAttrName) +{ + UsdShadeShader shaderSchema(_usdPrim); + if (!shaderSchema) { + return TfToken(); + } + + // Just check whether we created an input or an attribute with this name, + // and return its full name if so. + + const UsdShadeInput input = shaderSchema.GetInput(mayaAttrName); + if (input) { + return input.GetFullName(); + } + + const UsdShadeOutput output = shaderSchema.GetOutput(mayaAttrName); + if (output) { + return output.GetFullName(); + } + + return TfToken(); +} + + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/usd/translators/shading/symmetricShaderWriter.h b/lib/usd/translators/shading/symmetricShaderWriter.h new file mode 100644 index 0000000000..9a09e8e2c4 --- /dev/null +++ b/lib/usd/translators/shading/symmetricShaderWriter.h @@ -0,0 +1,106 @@ +// +// Copyright 2020 Pixar +// +// 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. +// +#ifndef USDTRANSLATORS_SHADING_SYMMETRIC_SHADER_WRITER_H +#define USDTRANSLATORS_SHADING_SYMMETRIC_SHADER_WRITER_H + +/// \file + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + + +PXR_NAMESPACE_OPEN_SCOPE + + +/// \class PxrUsdTranslators_SymmetricShaderWriter +/// \brief Provides "literal" translation of Maya shading nodes to USD Shader +/// prims. +/// +/// This shader writer performs a "literal" translation of a Maya shading node +/// type to USD. Input and output attributes on the Maya node translate +/// directly to inputs and outputs with the same names on the exported +/// UsdShadeShader. +/// +/// A static "RegisterWriter()" function is provided to simplify the +/// registration of writers that use this class. Note however that it should be +/// called inside a "TF_REGISTRY_FUNCTION(UsdMayaShaderWriterRegistry)" block, +/// for example: +/// +/// \code +/// TF_REGISTRY_FUNCTION(UsdMayaShaderWriterRegistry) +/// { +/// PxrUsdTranslators_SymmetricShaderWriter::RegisterWriter( +/// TfToken("myMayaNodeTypeName"), +/// TfToken("MyUsdShaderId"), +/// /* materialConversionName = */ TfToken("myMaterialConversionName")); +/// }; +/// \endcode +/// +class PxrUsdTranslators_SymmetricShaderWriter : public UsdMayaShaderWriter +{ +public: + /// Register a shader writer to translate \p mayaNodeTypeName Maya nodes to + /// USD shaders with ID \p usdShaderId. + /// + /// The shader writer can optionally be restricted to a particular material + /// conversion. If no conversion name is supplied, the writer's + /// "CanExport()" function will always return "Supported". If a conversion + /// name is supplied, "Supported" is returned if the conversion name + /// matches the one specified in the export args, and "Unsupported" is + /// returned otherwise. + /// + /// Note that this function should generally only be called inside a + /// TF_REGISTRY_FUNCTION(UsdMayaShaderWriterRegistry) block. + static void RegisterWriter( + const TfToken& mayaNodeTypeName, + const TfToken& usdShaderId, + const TfToken& materialConversionName = TfToken()); + + static ContextSupport CanExport( + const UsdMayaJobExportArgs& exportArgs, + const TfToken& materialConversionName = TfToken()); + + PxrUsdTranslators_SymmetricShaderWriter( + const MFnDependencyNode& depNodeFn, + const SdfPath& usdPath, + UsdMayaWriteJobContext& jobCtx, + const TfToken& usdShaderId); + + void Write(const UsdTimeCode& usdTime) override; + + TfToken GetShadingAttributeNameForMayaAttrName( + const TfToken& mayaAttrName) override; + +private: + std::unordered_map _inputNameAttrMap; +}; + + +PXR_NAMESPACE_CLOSE_SCOPE + + +#endif diff --git a/test/lib/usd/translators/CMakeLists.txt b/test/lib/usd/translators/CMakeLists.txt index 8496bd8f3a..f6fed1c2cd 100644 --- a/test/lib/usd/translators/CMakeLists.txt +++ b/test/lib/usd/translators/CMakeLists.txt @@ -61,6 +61,12 @@ set(TEST_SCRIPT_FILES testUsdMayaAdaptorUndoRedo.py ) +if (BUILD_RFM_TRANSLATORS) + list(APPEND TEST_SCRIPT_FILES + testUsdExportRfMShaders.py + ) +endif() + add_custom_target(${TARGET_NAME} ALL) # copy all the resources and python scripts to build directory diff --git a/test/lib/usd/translators/UsdExportRfMShadersTest/MarbleCube.ma b/test/lib/usd/translators/UsdExportRfMShadersTest/MarbleCube.ma new file mode 100644 index 0000000000..aa37d13f2f --- /dev/null +++ b/test/lib/usd/translators/UsdExportRfMShadersTest/MarbleCube.ma @@ -0,0 +1,239 @@ +//Maya ASCII 2019 scene +//Name: MarbleCube.ma +//Last modified: Mon, Sep 21, 2020 08:03:47 PM +//Codeset: UTF-8 +requires maya "2019"; +currentUnit -l centimeter -a degree -t film; +fileInfo "application" "maya"; +fileInfo "product" "Maya 2019"; +fileInfo "version" "2019"; +fileInfo "cutIdentifier" "201911151315-ca4054ece1"; +fileInfo "osv" "Linux 3.10.0-1127.13.1.el7.x86_64 #1 SMP Fri Jun 12 14:34:17 EDT 2020 x86_64"; +createNode transform -s -n "persp"; + rename -uid "C1B558C0-0000-087C-5A34-142300000224"; + setAttr ".v" no; + setAttr ".t" -type "double3" 21.64333236336984 -21.668011191606261 13.005752923906172 ; + setAttr ".r" -type "double3" 71.066155704526608 0 44.967352835719566 ; +createNode camera -s -n "perspShape" -p "persp"; + rename -uid "C1B558C0-0000-087C-5A34-142300000225"; + setAttr -k off ".v" no; + setAttr ".fl" 34.999999999999993; + setAttr ".coi" 32.377575407819336; + setAttr ".imn" -type "string" "persp"; + setAttr ".den" -type "string" "persp_depth"; + setAttr ".man" -type "string" "persp_mask"; + setAttr ".tp" -type "double3" 0 0 2.5 ; + setAttr ".hc" -type "string" "viewSet -p %camera"; +createNode transform -s -n "top"; + rename -uid "C1B558C0-0000-087C-5A34-142300000226"; + setAttr ".v" no; + setAttr ".t" -type "double3" 0 0 365.86 ; +createNode camera -s -n "topShape" -p "top"; + rename -uid "C1B558C0-0000-087C-5A34-142300000227"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 365.86; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "top"; + setAttr ".den" -type "string" "top_depth"; + setAttr ".man" -type "string" "top_mask"; + setAttr ".hc" -type "string" "viewSet -t %camera"; + setAttr ".o" yes; +createNode transform -s -n "front"; + rename -uid "C1B558C0-0000-087C-5A34-142300000228"; + setAttr ".v" no; + setAttr ".t" -type "double3" 0 -365.86 0 ; + setAttr ".r" -type "double3" 89.999999999999986 0 0 ; +createNode camera -s -n "frontShape" -p "front"; + rename -uid "C1B558C0-0000-087C-5A34-142300000229"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 365.86; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "front"; + setAttr ".den" -type "string" "front_depth"; + setAttr ".man" -type "string" "front_mask"; + setAttr ".hc" -type "string" "viewSet -f %camera"; + setAttr ".o" yes; +createNode transform -s -n "side"; + rename -uid "C1B558C0-0000-087C-5A34-14230000022A"; + setAttr ".v" no; + setAttr ".t" -type "double3" 365.86 0 0 ; + setAttr ".r" -type "double3" 90 1.2722218725854067e-14 89.999999999999986 ; +createNode camera -s -n "sideShape" -p "side"; + rename -uid "C1B558C0-0000-087C-5A34-14230000022B"; + setAttr -k off ".v" no; + setAttr ".rnd" no; + setAttr ".coi" 365.86; + setAttr ".ow" 30; + setAttr ".imn" -type "string" "side"; + setAttr ".den" -type "string" "side_depth"; + setAttr ".man" -type "string" "side_mask"; + setAttr ".hc" -type "string" "viewSet -s %camera"; + setAttr ".o" yes; +createNode transform -n "MarbleCube"; + rename -uid "C1B558C0-0000-087C-5A34-14390000024A"; +createNode transform -n "Geom" -p "MarbleCube"; + rename -uid "C1B558C0-0000-087C-5A34-143500000249"; +createNode transform -n "Cube" -p "Geom"; + rename -uid "C1B558C0-0000-087C-5A34-142E00000248"; + setAttr ".rp" -type "double3" 0 0 2.5 ; + setAttr ".sp" -type "double3" 0 0 2.5 ; +createNode mesh -n "CubeShape" -p "Cube"; + rename -uid "C1B558C0-0000-087C-5A34-142E00000247"; + setAttr -k off ".v"; + setAttr ".vir" yes; + setAttr ".vif" yes; + setAttr ".uvst[0].uvsn" -type "string" "map1"; + setAttr ".cuvs" -type "string" "map1"; + setAttr ".dcc" -type "string" "Ambient+Diffuse"; + setAttr ".ds" no; + setAttr ".covm[0]" 0 1 1; + setAttr ".cdvm[0]" 0 1 1; +createNode place3dTexture -n "MarbleCubePlace3dTexture"; + rename -uid "C1B558C0-0000-087C-5A34-14B4000002F6"; + setAttr ".t" -type "double3" 0 0 2.5 ; + setAttr ".s" -type "double3" 5 5 5 ; +createNode lightLinker -s -n "lightLinker1"; + rename -uid "BE4949C0-0000-742A-5F69-698600000264"; + setAttr -s 3 ".lnk"; + setAttr -s 3 ".slnk"; +createNode displayLayerManager -n "layerManager"; + rename -uid "BE4949C0-0000-742A-5F69-698600000265"; +createNode displayLayer -n "defaultLayer"; + rename -uid "C1B558C0-0000-087C-5A34-142300000242"; +createNode renderLayerManager -n "renderLayerManager"; + rename -uid "BE4949C0-0000-742A-5F69-698600000267"; +createNode renderLayer -n "defaultRenderLayer"; + rename -uid "C1B558C0-0000-087C-5A34-142300000244"; + setAttr ".g" yes; +createNode polyCube -n "polyCube1"; + rename -uid "C1B558C0-0000-087C-5A34-142E00000246"; + setAttr ".w" 5; + setAttr ".h" 5; + setAttr ".d" 5; + setAttr ".sw" 5; + setAttr ".sh" 5; + setAttr ".sd" 5; + setAttr ".cuv" 4; +createNode transformGeometry -n "transformGeometry1"; + rename -uid "C1B558C0-0000-087C-5A34-14600000024F"; + setAttr ".txf" -type "matrix" 1 0 0 0 0 1 0 0 + 0 0 1 0 0 0 2.5 1; +createNode marble -n "MarbleShader"; + rename -uid "C1B558C0-0000-087C-5A34-14B4000002F5"; +createNode shapeEditorManager -n "shapeEditorManager"; + rename -uid "BE4949C0-0000-742A-5F69-69860000026C"; +createNode poseInterpolatorManager -n "poseInterpolatorManager"; + rename -uid "BE4949C0-0000-742A-5F69-69860000026D"; +createNode lambert -n "MarbleLambert"; + rename -uid "80A599C0-0000-412C-5F69-60DB0000027B"; +createNode shadingEngine -n "MarbleCubeSG"; + rename -uid "80A599C0-0000-412C-5F69-60DB0000027C"; + setAttr ".ihi" 0; + setAttr ".ro" yes; +createNode materialInfo -n "materialInfo2"; + rename -uid "80A599C0-0000-412C-5F69-60DB0000027D"; +createNode script -n "uiConfigurationScriptNode"; + rename -uid "BE4949C0-0000-742A-5F69-69930000027A"; + setAttr ".b" -type "string" ( + "// Maya Mel UI Configuration File.\n//\n// This script is machine generated. Edit at your own risk.\n//\n//\n\nglobal string $gMainPane;\nif (`paneLayout -exists $gMainPane`) {\n\n\tglobal int $gUseScenePanelConfig;\n\tint $useSceneConfig = $gUseScenePanelConfig;\n\tint $nodeEditorPanelVisible = stringArrayContains(\"nodeEditorPanel1\", `getPanel -vis`);\n\tint $nodeEditorWorkspaceControlOpen = (`workspaceControl -exists nodeEditorPanel1Window` && `workspaceControl -q -visible nodeEditorPanel1Window`);\n\tint $menusOkayInPanels = `optionVar -q allowMenusInPanels`;\n\tint $nVisPanes = `paneLayout -q -nvp $gMainPane`;\n\tint $nPanes = 0;\n\tstring $editorName;\n\tstring $panelName;\n\tstring $itemFilterName;\n\tstring $panelConfig;\n\n\t//\n\t// get current state of the UI\n\t//\n\tsceneUIReplacement -update $gMainPane;\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Top View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Top View\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"top\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 16384\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n" + + " -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n" + + " -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n" + + "\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Side View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Side View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"side\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n" + + " -textureDisplay \"modulate\" \n -textureMaxSize 16384\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n" + + " -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n" + + " -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Front View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Front View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"front\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n" + + " -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 0\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 16384\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n" + + " -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n" + + " -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1\n -height 1\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"modelPanel\" (localizedPanelLabel(\"Persp View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tmodelPanel -edit -l (localizedPanelLabel(\"Persp View\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n modelEditor -e \n -camera \"persp\" \n -useInteractiveMode 0\n -displayLights \"default\" \n -displayAppearance \"smoothShaded\" \n -activeOnly 0\n -ignorePanZoom 0\n" + + " -wireframeOnShaded 0\n -headsUpDisplay 1\n -holdOuts 1\n -selectionHiliteDisplay 1\n -useDefaultMaterial 0\n -bufferMode \"double\" \n -twoSidedLighting 0\n -backfaceCulling 0\n -xray 0\n -jointXray 0\n -activeComponentsXray 0\n -displayTextures 1\n -smoothWireframe 0\n -lineWidth 1\n -textureAnisotropic 0\n -textureHilight 1\n -textureSampling 2\n -textureDisplay \"modulate\" \n -textureMaxSize 16384\n -fogging 0\n -fogSource \"fragment\" \n -fogMode \"linear\" \n -fogStart 0\n -fogEnd 100\n -fogDensity 0.1\n -fogColor 0.5 0.5 0.5 1 \n -depthOfFieldPreview 1\n -maxConstantTransparency 1\n -rendererName \"vp2Renderer\" \n -objectFilterShowInHUD 1\n -isFiltered 0\n -colorResolution 256 256 \n -bumpResolution 512 512 \n" + + " -textureCompression 0\n -transparencyAlgorithm \"frontAndBackCull\" \n -transpInShadows 0\n -cullingOverride \"none\" \n -lowQualityLighting 0\n -maximumNumHardwareLights 1\n -occlusionCulling 0\n -shadingModel 0\n -useBaseRenderer 0\n -useReducedRenderer 0\n -smallObjectCulling 0\n -smallObjectThreshold -1 \n -interactiveDisableShadows 0\n -interactiveBackFaceCull 0\n -sortTransparent 1\n -controllers 1\n -nurbsCurves 1\n -nurbsSurfaces 1\n -polymeshes 1\n -subdivSurfaces 1\n -planes 1\n -lights 1\n -cameras 1\n -controlVertices 1\n -hulls 1\n -grid 1\n -imagePlane 1\n -joints 1\n -ikHandles 1\n -deformers 1\n -dynamics 1\n -particleInstancers 1\n -fluids 1\n -hairSystems 1\n -follicles 1\n" + + " -nCloths 1\n -nParticles 1\n -nRigids 1\n -dynamicConstraints 1\n -locators 1\n -manipulators 1\n -pluginShapes 1\n -dimensions 1\n -handles 1\n -pivots 1\n -textures 1\n -strokes 1\n -motionTrails 1\n -clipGhosts 1\n -greasePencils 1\n -shadows 0\n -captureSequenceNumber -1\n -width 1292\n -height 1000\n -sceneRenderFilter 0\n $editorName;\n modelEditor -e -viewSelected 0 $editorName;\n modelEditor -e \n -pluginObjects \"gpuCacheDisplayFilter\" 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"outlinerPanel\" (localizedPanelLabel(\"ToggledOutliner\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\toutlinerPanel -edit -l (localizedPanelLabel(\"ToggledOutliner\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\t$editorName = $panelName;\n outlinerEditor -e \n -docTag \"isolOutln_fromSeln\" \n -showShapes 1\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 1\n -showReferenceMembers 1\n -showAttributes 0\n -showConnected 0\n -showAnimCurvesOnly 0\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 1\n -showPublishedAsConnected 0\n -showParentContainers 0\n -showContainerContents 1\n -ignoreDagHierarchy 0\n -expandConnections 0\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 0\n -highlightActive 1\n -autoSelectNewObjects 0\n" + + " -doNotSelectNewObjects 0\n -dropIsParent 1\n -transmitFilters 0\n -setFilter \"defaultSetFilter\" \n -showSetMembers 1\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -isSet 0\n -isSetMember 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n -mapMotionTrails 0\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n -renderFilterIndex 0\n -selectionOrder \"chronological\" \n" + + " -expandAttribute 0\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"outlinerPanel\" (localizedPanelLabel(\"Outliner\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\toutlinerPanel -edit -l (localizedPanelLabel(\"Outliner\")) -mbv $menusOkayInPanels $panelName;\n\t\t$editorName = $panelName;\n outlinerEditor -e \n -showShapes 0\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 0\n -showConnected 0\n -showAnimCurvesOnly 0\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 1\n -showAssets 1\n -showContainedOnly 1\n -showPublishedAsConnected 0\n -showParentContainers 0\n" + + " -showContainerContents 1\n -ignoreDagHierarchy 0\n -expandConnections 0\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 0\n -highlightActive 1\n -autoSelectNewObjects 0\n -doNotSelectNewObjects 0\n -dropIsParent 1\n -transmitFilters 0\n -setFilter \"defaultSetFilter\" \n -showSetMembers 1\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n" + + " -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n -mapMotionTrails 0\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"graphEditor\" (localizedPanelLabel(\"Graph Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Graph Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = ($panelName+\"OutlineEd\");\n outlinerEditor -e \n -showShapes 1\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 1\n -showConnected 1\n -showAnimCurvesOnly 1\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n" + + " -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 1\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 0\n -showPublishedAsConnected 0\n -showParentContainers 1\n -showContainerContents 0\n -ignoreDagHierarchy 0\n -expandConnections 1\n -showUpstreamCurves 1\n -showUnitlessCurves 1\n -showCompounds 0\n -showLeafs 1\n -showNumericAttrsOnly 1\n -highlightActive 0\n -autoSelectNewObjects 1\n -doNotSelectNewObjects 0\n -dropIsParent 1\n -transmitFilters 1\n -setFilter \"0\" \n -showSetMembers 0\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n" + + " -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 1\n -mapMotionTrails 1\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n -renderFilterVisible 0\n $editorName;\n\n\t\t\t$editorName = ($panelName+\"GraphEd\");\n animCurveEditor -e \n -displayKeys 1\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 1\n -displayInfinities 0\n -displayValues 0\n -autoFit 1\n -autoFitTime 0\n -snapTime \"integer\" \n" + + " -snapValue \"none\" \n -showResults \"off\" \n -showBufferCurves \"off\" \n -smoothness \"fine\" \n -resultSamples 1\n -resultScreenSamples 0\n -resultUpdate \"delayed\" \n -showUpstreamCurves 1\n -showCurveNames 0\n -showActiveCurveNames 0\n -stackedCurves 0\n -stackedCurvesMin -1\n -stackedCurvesMax 1\n -stackedCurvesSpace 0.2\n -displayNormalized 0\n -preSelectionHighlight 0\n -constrainDrag 0\n -classicMode 1\n -valueLinesToggle 1\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dopeSheetPanel\" (localizedPanelLabel(\"Dope Sheet\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Dope Sheet\")) -mbv $menusOkayInPanels $panelName;\n" + + "\n\t\t\t$editorName = ($panelName+\"OutlineEd\");\n outlinerEditor -e \n -showShapes 1\n -showAssignedMaterials 0\n -showTimeEditor 1\n -showReferenceNodes 0\n -showReferenceMembers 0\n -showAttributes 1\n -showConnected 1\n -showAnimCurvesOnly 1\n -showMuteInfo 0\n -organizeByLayer 1\n -organizeByClip 1\n -showAnimLayerWeight 1\n -autoExpandLayers 1\n -autoExpand 0\n -showDagOnly 0\n -showAssets 1\n -showContainedOnly 0\n -showPublishedAsConnected 0\n -showParentContainers 1\n -showContainerContents 0\n -ignoreDagHierarchy 0\n -expandConnections 1\n -showUpstreamCurves 1\n -showUnitlessCurves 0\n -showCompounds 1\n -showLeafs 1\n -showNumericAttrsOnly 1\n" + + " -highlightActive 0\n -autoSelectNewObjects 0\n -doNotSelectNewObjects 1\n -dropIsParent 1\n -transmitFilters 0\n -setFilter \"0\" \n -showSetMembers 0\n -allowMultiSelection 1\n -alwaysToggleSelect 0\n -directSelect 0\n -displayMode \"DAG\" \n -expandObjects 0\n -setsIgnoreFilters 1\n -containersIgnoreFilters 0\n -editAttrName 0\n -showAttrValues 0\n -highlightSecondary 0\n -showUVAttrsOnly 0\n -showTextureNodesOnly 0\n -attrAlphaOrder \"default\" \n -animLayerFilterOptions \"allAffecting\" \n -sortOrder \"none\" \n -longNames 0\n -niceNames 1\n -showNamespace 1\n -showPinIcons 0\n -mapMotionTrails 1\n -ignoreHiddenAttribute 0\n -ignoreOutlinerColor 0\n" + + " -renderFilterVisible 0\n $editorName;\n\n\t\t\t$editorName = ($panelName+\"DopeSheetEd\");\n dopeSheetEditor -e \n -displayKeys 1\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"integer\" \n -snapValue \"none\" \n -outliner \"dopeSheetPanel1OutlineEd\" \n -showSummary 1\n -showScene 0\n -hierarchyBelow 0\n -showTicks 1\n -selectionWindow 0 0 0 0 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"timeEditorPanel\" (localizedPanelLabel(\"Time Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Time Editor\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"clipEditorPanel\" (localizedPanelLabel(\"Trax Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Trax Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = clipEditorNameFromPanel($panelName);\n clipEditor -e \n -displayKeys 0\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"none\" \n -snapValue \"none\" \n -initialized 0\n -manageSequencer 0 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"sequenceEditorPanel\" (localizedPanelLabel(\"Camera Sequencer\")) `;\n" + + "\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Camera Sequencer\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = sequenceEditorNameFromPanel($panelName);\n clipEditor -e \n -displayKeys 0\n -displayTangents 0\n -displayActiveKeys 0\n -displayActiveKeyTangents 0\n -displayInfinities 0\n -displayValues 0\n -autoFit 0\n -autoFitTime 0\n -snapTime \"none\" \n -snapValue \"none\" \n -initialized 0\n -manageSequencer 1 \n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"hyperGraphPanel\" (localizedPanelLabel(\"Hypergraph Hierarchy\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Hypergraph Hierarchy\")) -mbv $menusOkayInPanels $panelName;\n" + + "\n\t\t\t$editorName = ($panelName+\"HyperGraphEd\");\n hyperGraph -e \n -graphLayoutStyle \"hierarchicalLayout\" \n -orientation \"horiz\" \n -mergeConnections 0\n -zoom 1\n -animateTransition 0\n -showRelationships 1\n -showShapes 0\n -showDeformers 0\n -showExpressions 0\n -showConstraints 0\n -showConnectionFromSelected 0\n -showConnectionToSelected 0\n -showConstraintLabels 0\n -showUnderworld 0\n -showInvisible 0\n -transitionFrames 1\n -opaqueContainers 0\n -freeform 0\n -imagePosition 0 0 \n -imageScale 1\n -imageEnabled 0\n -graphType \"DAG\" \n -heatMapDisplay 0\n -updateSelection 1\n -updateNodeAdded 1\n -useDrawOverrideColor 0\n -limitGraphTraversal -1\n" + + " -range 0 0 \n -iconSize \"smallIcons\" \n -showCachedConnections 0\n $editorName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"hyperShadePanel\" (localizedPanelLabel(\"Hypershade\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Hypershade\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"visorPanel\" (localizedPanelLabel(\"Visor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Visor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"nodeEditorPanel\" (localizedPanelLabel(\"Node Editor\")) `;\n\tif ($nodeEditorPanelVisible || $nodeEditorWorkspaceControlOpen) {\n" + + "\t\tif (\"\" == $panelName) {\n\t\t\tif ($useSceneConfig) {\n\t\t\t\t$panelName = `scriptedPanel -unParent -type \"nodeEditorPanel\" -l (localizedPanelLabel(\"Node Editor\")) -mbv $menusOkayInPanels `;\n\n\t\t\t$editorName = ($panelName+\"NodeEditorEd\");\n nodeEditor -e \n -allAttributes 0\n -allNodes 0\n -autoSizeNodes 1\n -consistentNameSize 1\n -createNodeCommand \"nodeEdCreateNodeCommand\" \n -connectNodeOnCreation 0\n -connectOnDrop 0\n -copyConnectionsOnPaste 0\n -connectionStyle \"bezier\" \n -defaultPinnedState 0\n -additiveGraphingMode 0\n -settingsChangedCallback \"nodeEdSyncControls\" \n -traversalDepthLimit -1\n -keyPressCommand \"nodeEdKeyPressCommand\" \n -nodeTitleMode \"name\" \n -gridSnap 0\n -gridVisibility 1\n -crosshairOnEdgeDragging 0\n -popupMenuScript \"nodeEdBuildPanelMenus\" \n" + + " -showNamespace 1\n -showShapes 1\n -showSGShapes 0\n -showTransforms 1\n -useAssets 1\n -syncedSelection 1\n -extendToShapes 1\n -editorMode \"default\" \n -hasWatchpoint 0\n $editorName;\n\t\t\t}\n\t\t} else {\n\t\t\t$label = `panel -q -label $panelName`;\n\t\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Node Editor\")) -mbv $menusOkayInPanels $panelName;\n\n\t\t\t$editorName = ($panelName+\"NodeEditorEd\");\n nodeEditor -e \n -allAttributes 0\n -allNodes 0\n -autoSizeNodes 1\n -consistentNameSize 1\n -createNodeCommand \"nodeEdCreateNodeCommand\" \n -connectNodeOnCreation 0\n -connectOnDrop 0\n -copyConnectionsOnPaste 0\n -connectionStyle \"bezier\" \n -defaultPinnedState 0\n -additiveGraphingMode 0\n -settingsChangedCallback \"nodeEdSyncControls\" \n" + + " -traversalDepthLimit -1\n -keyPressCommand \"nodeEdKeyPressCommand\" \n -nodeTitleMode \"name\" \n -gridSnap 0\n -gridVisibility 1\n -crosshairOnEdgeDragging 0\n -popupMenuScript \"nodeEdBuildPanelMenus\" \n -showNamespace 1\n -showShapes 1\n -showSGShapes 0\n -showTransforms 1\n -useAssets 1\n -syncedSelection 1\n -extendToShapes 1\n -editorMode \"default\" \n -hasWatchpoint 0\n $editorName;\n\t\t\tif (!$useSceneConfig) {\n\t\t\t\tpanel -e -l $label $panelName;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"createNodePanel\" (localizedPanelLabel(\"Create Node\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Create Node\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n" + + "\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"polyTexturePlacementPanel\" (localizedPanelLabel(\"UV Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"UV Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"renderWindowPanel\" (localizedPanelLabel(\"Render View\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Render View\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"shapePanel\" (localizedPanelLabel(\"Shape Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tshapePanel -edit -l (localizedPanelLabel(\"Shape Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n" + + "\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextPanel \"posePanel\" (localizedPanelLabel(\"Pose Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tposePanel -edit -l (localizedPanelLabel(\"Pose Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dynRelEdPanel\" (localizedPanelLabel(\"Dynamic Relationships\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Dynamic Relationships\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"relationshipPanel\" (localizedPanelLabel(\"Relationship Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Relationship Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n" + + "\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"referenceEditorPanel\" (localizedPanelLabel(\"Reference Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Reference Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"componentEditorPanel\" (localizedPanelLabel(\"Component Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Component Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"dynPaintScriptedPanelType\" (localizedPanelLabel(\"Paint Effects\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Paint Effects\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"scriptEditorPanel\" (localizedPanelLabel(\"Script Editor\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Script Editor\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"profilerPanel\" (localizedPanelLabel(\"Profiler Tool\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Profiler Tool\")) -mbv $menusOkayInPanels $panelName;\n\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\t$panelName = `sceneUIReplacement -getNextScriptedPanel \"contentBrowserPanel\" (localizedPanelLabel(\"Content Browser\")) `;\n\tif (\"\" != $panelName) {\n\t\t$label = `panel -q -label $panelName`;\n\t\tscriptedPanel -edit -l (localizedPanelLabel(\"Content Browser\")) -mbv $menusOkayInPanels $panelName;\n" + + "\t\tif (!$useSceneConfig) {\n\t\t\tpanel -e -l $label $panelName;\n\t\t}\n\t}\n\n\n\tif ($useSceneConfig) {\n string $configName = `getPanel -cwl (localizedPanelLabel(\"Current Layout\"))`;\n if (\"\" != $configName) {\n\t\t\tpanelConfiguration -edit -label (localizedPanelLabel(\"Current Layout\")) \n\t\t\t\t-userCreated false\n\t\t\t\t-defaultImage \"vacantCell.xP:/\"\n\t\t\t\t-image \"\"\n\t\t\t\t-sc false\n\t\t\t\t-configString \"global string $gMainPane; paneLayout -e -cn \\\"single\\\" -ps 1 100 100 $gMainPane;\"\n\t\t\t\t-removeAllPanels\n\t\t\t\t-ap false\n\t\t\t\t\t(localizedPanelLabel(\"Persp View\")) \n\t\t\t\t\t\"modelPanel\"\n" + + "\t\t\t\t\t\"$panelName = `modelPanel -unParent -l (localizedPanelLabel(\\\"Persp View\\\")) -mbv $menusOkayInPanels `;\\n$editorName = $panelName;\\nmodelEditor -e \\n -cam `findStartUpCamera persp` \\n -useInteractiveMode 0\\n -displayLights \\\"default\\\" \\n -displayAppearance \\\"smoothShaded\\\" \\n -activeOnly 0\\n -ignorePanZoom 0\\n -wireframeOnShaded 0\\n -headsUpDisplay 1\\n -holdOuts 1\\n -selectionHiliteDisplay 1\\n -useDefaultMaterial 0\\n -bufferMode \\\"double\\\" \\n -twoSidedLighting 0\\n -backfaceCulling 0\\n -xray 0\\n -jointXray 0\\n -activeComponentsXray 0\\n -displayTextures 1\\n -smoothWireframe 0\\n -lineWidth 1\\n -textureAnisotropic 0\\n -textureHilight 1\\n -textureSampling 2\\n -textureDisplay \\\"modulate\\\" \\n -textureMaxSize 16384\\n -fogging 0\\n -fogSource \\\"fragment\\\" \\n -fogMode \\\"linear\\\" \\n -fogStart 0\\n -fogEnd 100\\n -fogDensity 0.1\\n -fogColor 0.5 0.5 0.5 1 \\n -depthOfFieldPreview 1\\n -maxConstantTransparency 1\\n -rendererName \\\"vp2Renderer\\\" \\n -objectFilterShowInHUD 1\\n -isFiltered 0\\n -colorResolution 256 256 \\n -bumpResolution 512 512 \\n -textureCompression 0\\n -transparencyAlgorithm \\\"frontAndBackCull\\\" \\n -transpInShadows 0\\n -cullingOverride \\\"none\\\" \\n -lowQualityLighting 0\\n -maximumNumHardwareLights 1\\n -occlusionCulling 0\\n -shadingModel 0\\n -useBaseRenderer 0\\n -useReducedRenderer 0\\n -smallObjectCulling 0\\n -smallObjectThreshold -1 \\n -interactiveDisableShadows 0\\n -interactiveBackFaceCull 0\\n -sortTransparent 1\\n -controllers 1\\n -nurbsCurves 1\\n -nurbsSurfaces 1\\n -polymeshes 1\\n -subdivSurfaces 1\\n -planes 1\\n -lights 1\\n -cameras 1\\n -controlVertices 1\\n -hulls 1\\n -grid 1\\n -imagePlane 1\\n -joints 1\\n -ikHandles 1\\n -deformers 1\\n -dynamics 1\\n -particleInstancers 1\\n -fluids 1\\n -hairSystems 1\\n -follicles 1\\n -nCloths 1\\n -nParticles 1\\n -nRigids 1\\n -dynamicConstraints 1\\n -locators 1\\n -manipulators 1\\n -pluginShapes 1\\n -dimensions 1\\n -handles 1\\n -pivots 1\\n -textures 1\\n -strokes 1\\n -motionTrails 1\\n -clipGhosts 1\\n -greasePencils 1\\n -shadows 0\\n -captureSequenceNumber -1\\n -width 1292\\n -height 1000\\n -sceneRenderFilter 0\\n $editorName;\\nmodelEditor -e -viewSelected 0 $editorName;\\nmodelEditor -e \\n -pluginObjects \\\"gpuCacheDisplayFilter\\\" 1 \\n $editorName\"\n" + + "\t\t\t\t\t\"modelPanel -edit -l (localizedPanelLabel(\\\"Persp View\\\")) -mbv $menusOkayInPanels $panelName;\\n$editorName = $panelName;\\nmodelEditor -e \\n -cam `findStartUpCamera persp` \\n -useInteractiveMode 0\\n -displayLights \\\"default\\\" \\n -displayAppearance \\\"smoothShaded\\\" \\n -activeOnly 0\\n -ignorePanZoom 0\\n -wireframeOnShaded 0\\n -headsUpDisplay 1\\n -holdOuts 1\\n -selectionHiliteDisplay 1\\n -useDefaultMaterial 0\\n -bufferMode \\\"double\\\" \\n -twoSidedLighting 0\\n -backfaceCulling 0\\n -xray 0\\n -jointXray 0\\n -activeComponentsXray 0\\n -displayTextures 1\\n -smoothWireframe 0\\n -lineWidth 1\\n -textureAnisotropic 0\\n -textureHilight 1\\n -textureSampling 2\\n -textureDisplay \\\"modulate\\\" \\n -textureMaxSize 16384\\n -fogging 0\\n -fogSource \\\"fragment\\\" \\n -fogMode \\\"linear\\\" \\n -fogStart 0\\n -fogEnd 100\\n -fogDensity 0.1\\n -fogColor 0.5 0.5 0.5 1 \\n -depthOfFieldPreview 1\\n -maxConstantTransparency 1\\n -rendererName \\\"vp2Renderer\\\" \\n -objectFilterShowInHUD 1\\n -isFiltered 0\\n -colorResolution 256 256 \\n -bumpResolution 512 512 \\n -textureCompression 0\\n -transparencyAlgorithm \\\"frontAndBackCull\\\" \\n -transpInShadows 0\\n -cullingOverride \\\"none\\\" \\n -lowQualityLighting 0\\n -maximumNumHardwareLights 1\\n -occlusionCulling 0\\n -shadingModel 0\\n -useBaseRenderer 0\\n -useReducedRenderer 0\\n -smallObjectCulling 0\\n -smallObjectThreshold -1 \\n -interactiveDisableShadows 0\\n -interactiveBackFaceCull 0\\n -sortTransparent 1\\n -controllers 1\\n -nurbsCurves 1\\n -nurbsSurfaces 1\\n -polymeshes 1\\n -subdivSurfaces 1\\n -planes 1\\n -lights 1\\n -cameras 1\\n -controlVertices 1\\n -hulls 1\\n -grid 1\\n -imagePlane 1\\n -joints 1\\n -ikHandles 1\\n -deformers 1\\n -dynamics 1\\n -particleInstancers 1\\n -fluids 1\\n -hairSystems 1\\n -follicles 1\\n -nCloths 1\\n -nParticles 1\\n -nRigids 1\\n -dynamicConstraints 1\\n -locators 1\\n -manipulators 1\\n -pluginShapes 1\\n -dimensions 1\\n -handles 1\\n -pivots 1\\n -textures 1\\n -strokes 1\\n -motionTrails 1\\n -clipGhosts 1\\n -greasePencils 1\\n -shadows 0\\n -captureSequenceNumber -1\\n -width 1292\\n -height 1000\\n -sceneRenderFilter 0\\n $editorName;\\nmodelEditor -e -viewSelected 0 $editorName;\\nmodelEditor -e \\n -pluginObjects \\\"gpuCacheDisplayFilter\\\" 1 \\n $editorName\"\n" + + "\t\t\t\t$configName;\n\n setNamedPanelLayout (localizedPanelLabel(\"Current Layout\"));\n }\n\n panelHistory -e -clear mainPanelHistory;\n sceneUIReplacement -clear;\n\t}\n\n\ngrid -spacing 5 -size 12 -divisions 5 -displayAxes yes -displayGridLines yes -displayDivisionLines yes -displayPerspectiveLabels yes -displayOrthographicLabels yes -displayAxesBold yes -perspectiveLabelPosition axis -orthographicLabelPosition axis;\nviewManip -drawCompass 0 -compassAngle 0 -frontParameters \"\" -homeParameters \"\" -selectionLockParameters \"\";\n}\n"); + setAttr ".st" 3; +createNode script -n "sceneConfigurationScriptNode"; + rename -uid "BE4949C0-0000-742A-5F69-69930000027B"; + setAttr ".b" -type "string" "playbackOptions -min 1 -max 120 -ast 1 -aet 200 "; + setAttr ".st" 6; +select -ne :time1; + setAttr ".o" 0; +select -ne :hardwareRenderingGlobals; + setAttr ".otfna" -type "stringArray" 22 "NURBS Curves" "NURBS Surfaces" "Polygons" "Subdiv Surface" "Particles" "Particle Instance" "Fluids" "Strokes" "Image Planes" "UI" "Lights" "Cameras" "Locators" "Joints" "IK Handles" "Deformers" "Motion Trails" "Components" "Hair Systems" "Follicles" "Misc. UI" "Ornaments" ; + setAttr ".otfva" -type "Int32Array" 22 0 1 1 1 1 1 + 1 1 1 0 0 0 0 0 0 0 0 0 + 0 0 0 0 ; + setAttr ".etmr" no; + setAttr ".tmr" 4096; + setAttr ".fprt" yes; +select -ne :renderPartition; + setAttr -s 3 ".st"; +select -ne :renderGlobalsList1; +select -ne :defaultShaderList1; + setAttr -s 5 ".s"; +select -ne :postProcessList1; + setAttr -s 2 ".p"; +select -ne :defaultRenderUtilityList1; +select -ne :defaultRenderingList1; +select -ne :defaultTextureList1; +select -ne :initialShadingGroup; + setAttr ".ro" yes; +select -ne :initialParticleSE; + setAttr ".ro" yes; +select -ne :defaultRenderGlobals; + setAttr ".outf" 3; +select -ne :defaultResolution; + setAttr ".pa" 1; +select -ne :hardwareRenderGlobals; + setAttr ".ctrs" 256; + setAttr ".btrs" 512; +connectAttr "transformGeometry1.og" "CubeShape.i"; +relationship "link" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message"; +relationship "link" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message"; +relationship "link" ":lightLinker1" "MarbleCubeSG.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" ":initialShadingGroup.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" ":initialParticleSE.message" ":defaultLightSet.message"; +relationship "shadowLink" ":lightLinker1" "MarbleCubeSG.message" ":defaultLightSet.message"; +connectAttr "layerManager.dli[0]" "defaultLayer.id"; +connectAttr "renderLayerManager.rlmi[0]" "defaultRenderLayer.rlid"; +connectAttr "polyCube1.out" "transformGeometry1.ig"; +connectAttr "MarbleCubePlace3dTexture.wim" "MarbleShader.pm"; +connectAttr "MarbleShader.oc" "MarbleLambert.c"; +connectAttr "MarbleLambert.oc" "MarbleCubeSG.ss"; +connectAttr "CubeShape.iog" "MarbleCubeSG.dsm" -na; +connectAttr "MarbleCubeSG.msg" "materialInfo2.sg"; +connectAttr "MarbleLambert.msg" "materialInfo2.m"; +connectAttr "MarbleShader.msg" "materialInfo2.t" -na; +connectAttr "MarbleCubeSG.pa" ":renderPartition.st" -na; +connectAttr "MarbleLambert.msg" ":defaultShaderList1.s" -na; +connectAttr "MarbleCubePlace3dTexture.msg" ":defaultRenderUtilityList1.u" -na; +connectAttr "defaultRenderLayer.msg" ":defaultRenderingList1.r" -na; +connectAttr "MarbleShader.msg" ":defaultTextureList1.tx" -na; +connectAttr "MarbleShader.oc" ":internal_standInShader.ic"; +// End of MarbleCube.ma diff --git a/test/lib/usd/translators/testUsdExportRfMShaders.py b/test/lib/usd/translators/testUsdExportRfMShaders.py new file mode 100644 index 0000000000..3c0f270ac2 --- /dev/null +++ b/test/lib/usd/translators/testUsdExportRfMShaders.py @@ -0,0 +1,150 @@ +#!/pxrpythonsubst +# +# Copyright 2020 Pixar +# +# 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. +# + +from pxr import Usd +from pxr import UsdShade + +from maya import cmds +from maya import standalone + +import os +import unittest + +import fixturesUtils + + +class testUsdExportRfMShaders(unittest.TestCase): + + @classmethod + def setUpClass(cls): + inputPath = fixturesUtils.setUpClass(__file__) + + mayaFile = os.path.join(inputPath, 'UsdExportRfMShadersTest', + 'MarbleCube.ma') + cmds.file(mayaFile, force=True, open=True) + + # Export to USD. + usdFilePath = os.path.abspath('MarbleCube.usda') + cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath, + shadingMode='useRegistry', convertMaterialsTo='rendermanForMaya', + materialsScopeName='Materials') + + cls._stage = Usd.Stage.Open(usdFilePath) + + @classmethod + def tearDownClass(cls): + standalone.uninitialize() + + def testStageOpens(self): + ''' + Tests that the USD stage was opened successfully. + ''' + self.assertTrue(self._stage) + + def testExportRfMShaders(self): + ''' + Tests that exporting a Maya mesh with a simple Maya shading setup + results in the correct shading on the USD mesh. + ''' + cubePrim = self._stage.GetPrimAtPath('/MarbleCube/Geom/Cube') + self.assertTrue(cubePrim) + + # Validate the Material prim bound to the Mesh prim. + materialBindingAPI = UsdShade.MaterialBindingAPI(cubePrim) + material = materialBindingAPI.ComputeBoundMaterial()[0] + self.assertTrue(material) + materialPath = material.GetPath().pathString + self.assertEqual(materialPath, '/MarbleCube/Materials/MarbleCubeSG') + + # We expect four outputs on the material, the three built-in terminals + # for the universal renderContext, and a fourth for the "surface" + # terminal in the "ri" renderContext that the export should have + # authored. + materialOutputs = material.GetOutputs() + self.assertEqual(len(materialOutputs), 4) + + # Validate the lambert surface shader that is connected to the material. + materialOutput = material.GetOutput('ri:surface') + (connectableAPI, outputName, outputType) = materialOutput.GetConnectedSource() + self.assertEqual(outputName, UsdShade.Tokens.surface) + shader = UsdShade.Shader(connectableAPI) + self.assertTrue(shader) + shaderId = shader.GetIdAttr().Get() + self.assertEqual(shaderId, 'PxrMayaLambert') + + # Validate the connected input on the lambert surface shader. + shaderInput = shader.GetInput('color') + self.assertTrue(shaderInput) + (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() + self.assertEqual(outputName, 'outColor') + shader = UsdShade.Shader(connectableAPI) + self.assertTrue(shader) + shaderId = shader.GetIdAttr().Get() + self.assertEqual(shaderId, 'PxrMayaMarble') + + # Validate the connected input on the marble shader. + shaderInput = shader.GetInput('placementMatrix') + self.assertTrue(shaderInput) + (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() + self.assertEqual(outputName, 'worldInverseMatrix') + shader = UsdShade.Shader(connectableAPI) + self.assertTrue(shader) + shaderId = shader.GetIdAttr().Get() + self.assertEqual(shaderId, 'PxrMayaPlacement3d') + + def testShaderAttrsAuthoredSparsely(self): + ''' + Tests that only the attributes authored in Maya are exported to USD. + ''' + shaderPrimPath = '/MarbleCube/Materials/MarbleCubeSG/MarbleLambert' + shaderPrim = self._stage.GetPrimAtPath(shaderPrimPath) + self.assertTrue(shaderPrim) + shader = UsdShade.Shader(shaderPrim) + self.assertTrue(shader) + shaderId = shader.GetIdAttr().Get() + self.assertEqual(shaderId, 'PxrMayaLambert') + shaderInputs = shader.GetInputs() + self.assertEqual(len(shaderInputs), 1) + + # We actually expect two outputs on the "top-level" shader. The Maya + # node this shader came from would have had an "outColor" output that + # should have been translated, and then a "surface" output should have + # been created when the shader was bound into the Material. + shaderOutputs = shader.GetOutputs() + self.assertEqual(len(shaderOutputs), 2) + outputNames = {o.GetBaseName() for o in shaderOutputs} + self.assertEqual(outputNames, set(['outColor', 'surface'])) + + # Traverse the network down to the marble shader + shaderInput = shader.GetInput('color') + self.assertTrue(shaderInput) + (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() + shader = UsdShade.Shader(connectableAPI) + self.assertTrue(shader) + + inputPlacementMatrix = shader.GetInput('placementMatrix') + (connectableAPI, outputName, outputType) = inputPlacementMatrix.GetConnectedSource() + self.assertEqual(connectableAPI.GetPath().pathString, + '/MarbleCube/Materials/MarbleCubeSG/MarbleCubePlace3dTexture') + shaderId = shader.GetIdAttr().Get() + self.assertEqual(shaderId, 'PxrMayaMarble') + shaderOutputs = shader.GetOutputs() + self.assertEqual(len(shaderOutputs), 1) + + +if __name__ == '__main__': + unittest.main(verbosity=2)