From 3cd2c3a6718598c5e7af18c3af51ff146f3956de Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Fri, 3 Feb 2023 12:02:44 +0100 Subject: [PATCH 01/18] Viewport and Outliner menu entries: Assign New Material, Assign Existing Material Final fixes --- lib/mayaUsd/ufe/UsdContextOps.cpp | 177 ++++-------------- plugin/adsk/plugin/CMakeLists.txt | 1 + plugin/adsk/plugin/adskMaterialCommands.cpp | 173 +++++++++++++++++ plugin/adsk/plugin/adskMaterialCommands.h | 98 ++++++++++ plugin/adsk/plugin/plugin.cpp | 5 + plugin/adsk/scripts/USDMenuProc.mel | 127 +++++++++++++ test/lib/mayaUsd/utils/CMakeLists.txt | 1 + .../lib/mayaUsd/utils/testMaterialCommands.py | 92 +++++++++ 8 files changed, 530 insertions(+), 144 deletions(-) create mode 100644 plugin/adsk/plugin/adskMaterialCommands.cpp create mode 100644 plugin/adsk/plugin/adskMaterialCommands.h create mode 100644 test/lib/mayaUsd/utils/testMaterialCommands.py diff --git a/lib/mayaUsd/ufe/UsdContextOps.cpp b/lib/mayaUsd/ufe/UsdContextOps.cpp index 470e078b9e..8f9485a69e 100644 --- a/lib/mayaUsd/ufe/UsdContextOps.cpp +++ b/lib/mayaUsd/ufe/UsdContextOps.cpp @@ -144,16 +144,8 @@ static constexpr char kAssignNewMaterialItem[] = "Assign New Material"; static constexpr char kAssignNewMaterialLabel[] = "Assign New Material"; static constexpr char kAddNewMaterialItem[] = "Add New Material"; static constexpr char kAddNewMaterialLabel[] = "Add New Material"; -static constexpr char kAssignNewUsdMaterialItem[] = "USD Material"; -static constexpr char kAssignNewUsdMaterialLabel[] = "USD"; -static constexpr char kAssignNewMaterialXMaterialItem[] = "MaterialX Material"; -static constexpr char kAssignNewMaterialXMaterialLabel[] = "MaterialX"; -static constexpr char kAssignNewArnoldMaterialItem[] = "Arnold Material"; -static constexpr char kAssignNewArnoldMaterialLabel[] = "Arnold"; -static constexpr char kAssignNewUsdPreviewSurfaceMaterialItem[] = "UsdPreviewSurface"; -static constexpr char kAssignNewUsdPreviewSurfaceMaterialLabel[] = "USD Preview Surface"; -static constexpr char kAssignNewAIStandardSurfaceMaterialItem[] = "arnold:standard_surface"; -static constexpr char kAssignNewAIStandardSurfaceMaterialLabel[] = "AI Standard Surface"; +static constexpr char kAssignExistingMaterialItem[] = "Assign Existing Material"; +static constexpr char kAssignExistingMaterialLabel[] = "Assign Existing Material"; #endif #endif @@ -201,63 +193,6 @@ struct WaitCursor ~WaitCursor() { MGlobal::executeCommand("waitCursor -state 0"); } }; -#if UFE_PREVIEW_VERSION_NUM >= 4010 -//! \brief This check has a 3 seconds slowdown to load all Sdr nodes in the registry. We do it in -/// advance in order to not have this 3 seconds delay when the "Assign New Material" submenu -/// is built for the first time. -bool _hasArnoldShaders() -{ - auto findArnold = []() { - const auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); - auto sourceTypes = sdrRegistry.GetAllNodeSourceTypes(); - return std::find(sourceTypes.cbegin(), sourceTypes.cend(), TfToken("arnold")) - != sourceTypes.cend(); - }; - static const bool kHasArnoldShaders = findArnold(); - return kHasArnoldShaders; -}; - -struct MxShaderMenuEntry -{ - MxShaderMenuEntry(const std::string& label, const std::string& identifier) - : _label(label) - , _identifier(identifier) - { - } - const std::string _label; - const std::string& _identifier; -}; -typedef std::vector MxShaderMenuEntryVec; - -const MxShaderMenuEntryVec& getMaterialXSurfaceShaders() -{ - static MxShaderMenuEntryVec mxSurfaceShaders; - static bool initialized = false; - if (!initialized) { - auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); - // Here is a list of nodes we know work fine as starting materials for the contextual menu. - // We might add discovery code later, but this discovery code will have the difficult task - // of filtering out: - // - utility nodes like ND_add_surfaceshader - // - basic building blocks like ND_thin_surface - // - shaders that exist only as pure definitions like ND_disney_bsdf_2015_surface - static const std::vector> vettedSurfaces - = { { "ND_standard_surface_surfaceshader", "Standard Surface" }, - { "ND_gltf_pbr_surfaceshader", "glTF PBR" }, - { "ND_UsdPreviewSurface_surfaceshader", "USD Preview Surface" } }; - for (auto&& info : vettedSurfaces) { - auto shaderDef = sdrRegistry.GetShaderNodeByIdentifier(TfToken(info.first)); - if (!shaderDef) { - continue; - } - mxSurfaceShaders.emplace_back(info.second, info.first); - } - initialized = true; - } - return mxSurfaceShaders; -} -#endif - #ifdef UFE_V3_FEATURES_AVAILABLE //! \brief Create a Prim and select it: class UsdUndoAddNewPrimAndSelectCommand : public Ufe::CompositeUndoableCommand @@ -947,58 +882,6 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& if (!fIsAGatewayType) { // Top level item - Bind/unbind existing materials bool materialSeparatorsAdded = false; - if (sceneItemSupportsShading(fItem)) { - // Show bind menu if there is at least one bindable material in the stage. - // - // TODO: Show only materials that are inside of the asset's namespace otherwise - // there will be "refers to a path outside the scope" errors. See - // https://groups.google.com/g/usd-interest/c/dmjV5bQBKIo/m/LeozZ3k6BAAJ - // This might help restrict the stage traversal scope and improve performance. - // - // For completeness, and to point out that material assignments are complex: - // - // TODO: Introduce the "rendering purpose" concept - // TODO: Introduce material binding via collections API - // - // Find materials in the global selection. Either directly selected or a direct - // child of the selection. This way we limit how many items we traverse in search of - // something to bind. - if (!materialSeparatorsAdded) { - items.emplace_back(Ufe::ContextItem::kSeparator); - materialSeparatorsAdded = true; - } - bool foundMaterialItem = false; - if (auto globalSn = Ufe::GlobalSelection::get()) { - for (auto&& selItem : *globalSn) { - UsdSceneItem::Ptr usdItem - = std::dynamic_pointer_cast(selItem); - if (!usdItem) { - continue; - } - UsdShadeMaterial material(usdItem->prim()); - if (material) { - foundMaterialItem = true; - break; - } - for (auto&& usdChild : usdItem->prim().GetChildren()) { - UsdShadeMaterial material(usdChild); - if (material) { - foundMaterialItem = true; - break; - } - } - if (foundMaterialItem) { - break; - } - } - if (foundMaterialItem) { - items.emplace_back( - BindMaterialUndoableCommand::commandName, - BindMaterialUndoableCommand::commandName, - Ufe::ContextItem::kHasChildren); - } - } - } #if UFE_PREVIEW_VERSION_NUM >= 4010 if (sceneItemSupportsShading(fItem)) { if (!materialSeparatorsAdded) { @@ -1009,6 +892,10 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& kAssignNewMaterialItem, kAssignNewMaterialLabel, Ufe::ContextItem::kHasChildren); + items.emplace_back( + kAssignExistingMaterialItem, + kAssignExistingMaterialLabel, + Ufe::ContextItem::kHasChildren); } #endif if (fItem->prim().HasAPI()) { @@ -1157,30 +1044,17 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& } else if ( itemPath.size() == 1u && (itemPath[0] == kAssignNewMaterialItem || itemPath[0] == kAddNewMaterialItem)) { - items.emplace_back( - kAssignNewUsdMaterialItem, - kAssignNewUsdMaterialLabel, - Ufe::ContextItem::kHasChildren); - items.emplace_back( - kAssignNewMaterialXMaterialItem, - kAssignNewMaterialXMaterialLabel, - Ufe::ContextItem::kHasChildren); - if (_hasArnoldShaders()) { - items.emplace_back( - kAssignNewArnoldMaterialItem, - kAssignNewArnoldMaterialLabel, - Ufe::ContextItem::kHasChildren); - } - } else if (itemPath.size() == 2u && itemPath[1] == kAssignNewUsdMaterialItem) { - items.emplace_back( - kAssignNewUsdPreviewSurfaceMaterialItem, kAssignNewUsdPreviewSurfaceMaterialLabel); - } else if (itemPath.size() == 2u && itemPath[1] == kAssignNewMaterialXMaterialItem) { - for (auto&& menuEntry : getMaterialXSurfaceShaders()) { - items.emplace_back(menuEntry._identifier, menuEntry._label); - } - } else if (itemPath.size() == 2u && itemPath[1] == kAssignNewArnoldMaterialItem) { - items.emplace_back( - kAssignNewAIStandardSurfaceMaterialItem, kAssignNewAIStandardSurfaceMaterialLabel); + MString script; + script.format( + "MayaUsdMenuAddNewMaterialsForRenderers \"^1s\"", + Ufe::PathString::string(fItem->path()).c_str()); + MString result = MGlobal::executeCommandStringResult(script, false, false); + } else if (itemPath.size() == 1u && itemPath[0] == kAssignExistingMaterialItem) { + MString script; + script.format( + "MayaUsdMenuAddExistingMaterials \"^1s\"", + Ufe::PathString::string(fItem->path()).c_str()); + MString result = MGlobal::executeCommandStringResult(script, false, false); #endif } #endif @@ -1319,7 +1193,7 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) return std::make_shared(fItem->prim()); #if UFE_PREVIEW_VERSION_NUM >= 4010 } else if (itemPath.size() == 3u && itemPath[0] == kAssignNewMaterialItem) { - // Make a copy so that we don't change to user's original selection + // Make a copy so that we don't change the user's original selection. Ufe::Selection sceneItems(*Ufe::GlobalSelection::get()); // As per UX' wishes, we add the item that was right-clicked, // regardless of its selection state. @@ -1331,6 +1205,21 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) } else if (itemPath.size() == 3u && itemPath[0] == kAddNewMaterialItem) { return std::make_shared( UsdUndoAddNewMaterialCommand::create(fItem, itemPath[2])); + } else if (itemPath.size() == 2u && itemPath[0] == kAssignExistingMaterialItem) { + std::shared_ptr compositeCmd; + Ufe::Selection sceneItems(*Ufe::GlobalSelection::get()); + sceneItems.append(fItem); + for (auto& sceneItem : sceneItems) { + UsdPrim compatiblePrim = BindMaterialUndoableCommand::CompatiblePrim(sceneItem); + if (compatiblePrim) { + if (!compositeCmd) { + compositeCmd = std::make_shared(); + } + compositeCmd->append(std::make_shared( + compatiblePrim, SdfPath(itemPath[1]))); + } + } + return compositeCmd; #endif } #endif diff --git a/plugin/adsk/plugin/CMakeLists.txt b/plugin/adsk/plugin/CMakeLists.txt index 88d3157cf8..101c476e98 100644 --- a/plugin/adsk/plugin/CMakeLists.txt +++ b/plugin/adsk/plugin/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources(${TARGET_NAME} adskExportCommand.cpp adskListJobContextsCommand.cpp adskListShadingModesCommand.cpp + adskMaterialCommands.cpp adskStageLoadUnloadCommands.cpp geomNode.cpp importTranslator.cpp diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp new file mode 100644 index 0000000000..69c71a0700 --- /dev/null +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -0,0 +1,173 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "adskMaterialCommands.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace MAYAUSD_NS_DEF { + +/* +// ADSKMayaUSDGetMaterialsForRenderersCommand +*/ + +const char ADSKMayaUSDGetMaterialsForRenderersCommand::commandName[] = "mayaUsdGetMaterialsFromRenderers"; + +// plug-in callback to create the command object +void* ADSKMayaUSDGetMaterialsForRenderersCommand::creator() +{ + return static_cast(new ADSKMayaUSDGetMaterialsForRenderersCommand()); +} + +// private argument parsing helper +MStatus ADSKMayaUSDGetMaterialsForRenderersCommand::parseArgs(const MArgList& argList) { return MS::kSuccess; } + +void ADSKMayaUSDGetMaterialsForRenderersCommand::appendMaterialXMaterials() const +{ + // TODO: Replace hard-coded materials with dynamically generated list. + static const std::vector> vettedSurfaces + = { { "ND_standard_surface_surfaceshader", "Standard Surface" }, + { "ND_gltf_pbr_surfaceshader", "glTF PBR" }, + { "ND_UsdPreviewSurface_surfaceshader", "USD Preview Surface" } }; + auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); + for (auto&& info : vettedSurfaces) { + auto shaderDef = sdrRegistry.GetShaderNodeByIdentifier(TfToken(info.first)); + if (!shaderDef) { + continue; + } + const MString label = info.second.c_str(); + const MString identifier = info.first.c_str(); + appendToResult("MaterialX/" + label + "|" + identifier); + } +} + +void ADSKMayaUSDGetMaterialsForRenderersCommand::appendArnoldMaterials() const +{ + auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); + const auto sourceTypes = sdrRegistry.GetAllNodeSourceTypes(); + const bool hasArnoldMaterials + = std::find(sourceTypes.cbegin(), sourceTypes.cend(), TfToken("arnold")) + != sourceTypes.cend(); + + if (hasArnoldMaterials) { + // TODO: Replace hard-coded materials with dynamically generated list. + const MString label = "AI Standard Surface"; + const MString identifier = "arnold:standard_surface"; + appendToResult("Arnold/" + label + "|" + identifier); + } +} + +void ADSKMayaUSDGetMaterialsForRenderersCommand::appendUsdMaterials() const +{ + // TODO: Replace hard-coded materials with dynamically generated list. + const MString label = "USD Preview Surface"; + const MString identifier = "UsdPreviewSurface"; + appendToResult("USD/" + label + "|" + identifier); +} + +// main MPxCommand execution point +MStatus ADSKMayaUSDGetMaterialsForRenderersCommand::doIt(const MArgList& argList) +{ + clearResult(); + + MStatus status; + if (!status) + return status; + + // TODO: The list of returned materials is currently hard-coded and only for select, + // known renderers. We should populate the material lists dynamically based on what the + // installed renderers report as supported materials. + appendUsdMaterials(); + appendArnoldMaterials(); + appendMaterialXMaterials(); + + return MS::kSuccess; +} + +MSyntax ADSKMayaUSDGetMaterialsForRenderersCommand::createSyntax() +{ + MSyntax syntax; + return syntax; +} + +/* +// ADSKMayaUSDGetMaterialsInStageCommand +*/ + +const char ADSKMayaUSDGetMaterialsInStageCommand::commandName[] = "mayaUsdGetMaterialsInScene"; + +static const TfToken materialType("Material"); + +// plug-in callback to create the command object +void* ADSKMayaUSDGetMaterialsInStageCommand::creator() +{ + return static_cast(new ADSKMayaUSDGetMaterialsInStageCommand()); +} + +// private argument parsing helper +MStatus ADSKMayaUSDGetMaterialsInStageCommand::parseArgs(const MArgList& argList) { return MS::kSuccess; } + +// main MPxCommand execution point +MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) +{ + clearResult(); + + MStatus status; + MArgDatabase args(syntax(), argList, &status); + if (!status) + return status; + + MString ufePathString; + args.getFlagArgument(kSceneItem, 0, ufePathString); + if (ufePathString.isEmpty()) { + MGlobal::displayError("Missing argument 'sceneItem'."); + return MS::kFailure; + } + + const auto ufePath = Ufe::PathString::path(ufePathString.asChar()); + UsdStagePtr stage = ufe::getStage(ufePath); + if (stage) { + for (auto prim : stage->Traverse()) { + if (prim.GetTypeName() == materialType) { + appendToResult(MString(prim.GetPath().GetString().c_str())); + } + } + } + + return MS::kSuccess; +} + +MSyntax ADSKMayaUSDGetMaterialsInStageCommand::createSyntax() +{ + MSyntax syntax; + syntax.addFlag("-si", "-sceneItem", MSyntax::kString); + return syntax; +} + +} // namespace MAYAUSD_NS_DEF diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h new file mode 100644 index 0000000000..e717502a7d --- /dev/null +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -0,0 +1,98 @@ +// +// Copyright 2023 Autodesk +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#pragma once + +#ifndef ADSK_MAYA_MATERIAL_COMMANDS_H +#define ADSK_MAYA_MATERIAL_COMMANDS_H + +#include +#include +#include + +#include +#include +#include + +namespace MAYAUSD_NS_DEF { + +//------------------------------------------------------------------------------ +// GetMaterialXMaterialsCommand +//------------------------------------------------------------------------------ + +struct MxShaderMenuEntry +{ + MxShaderMenuEntry(const std::string& label, const std::string& identifier) + : _label(label) + , _identifier(identifier) + { + } + const std::string _label; + const std::string& _identifier; +}; +typedef std::vector MxShaderMenuEntryVec; + +//! \brief Fills the currently active menu with submenus listing available materials from different +//! renderers. +//! \todo: The list of materials and renderers is currently hard-coded. We need to make +//! it dynamic so that third-party renderers can hook in to provide their own materials. +class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MPxCommand +{ +public: + // plugin registration requirements + static const char commandName[]; + static void* creator(); + static MSyntax createSyntax(); + + MStatus doIt(const MArgList& argList) override; + bool isUndoable() const override + { + return false; + } + +private: + MStatus parseArgs(const MArgList& argList); + + void appendMaterialXMaterials() const; + void appendArnoldMaterials() const; + void appendUsdMaterials() const; +}; + +//! \brief Fills the currently active menu with the available materials existing in the given +//! object's stage. +class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsInStageCommand : public MPxCommand +{ + static constexpr auto kSceneItem = "si"; + static constexpr auto kSceneItemLong = "sceneItem"; + +public: + // plugin registration requirements + static const char commandName[]; + static void* creator(); + static MSyntax createSyntax(); + + MStatus doIt(const MArgList& argList) override; + bool isUndoable() const override + { + return false; + } + +private: + MStatus parseArgs(const MArgList& argList); +}; + +} // namespace MAYAUSD_NS_DEF + +#endif /* ADSK_MAYA_MATERIAL_COMMANDS_H */ diff --git a/plugin/adsk/plugin/plugin.cpp b/plugin/adsk/plugin/plugin.cpp index 43040b26b6..772402c2a9 100644 --- a/plugin/adsk/plugin/plugin.cpp +++ b/plugin/adsk/plugin/plugin.cpp @@ -18,6 +18,7 @@ #include "adskImportCommand.h" #include "adskListJobContextsCommand.h" #include "adskListShadingModesCommand.h" +#include "adskMaterialCommands.h" #include "adskStageLoadUnloadCommands.h" #include "base/api.h" #include "exportTranslator.h" @@ -220,6 +221,8 @@ MStatus initializePlugin(MObject obj) registerCommandCheck(plugin); registerCommandCheck(plugin); registerCommandCheck(plugin); + registerCommandCheck(plugin); + registerCommandCheck(plugin); #if defined(WANT_QT_BUILD) registerCommandCheck(plugin); #endif @@ -400,6 +403,8 @@ MStatus uninitializePlugin(MObject obj) deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); + deregisterCommandCheck(plugin); + deregisterCommandCheck(plugin); #if defined(WANT_QT_BUILD) deregisterCommandCheck(plugin); MayaUsd::LayerEditorWindowCommand::cleanupOnPluginUnload(); diff --git a/plugin/adsk/scripts/USDMenuProc.mel b/plugin/adsk/scripts/USDMenuProc.mel index 5741cffb0f..fccbe2642d 100644 --- a/plugin/adsk/scripts/USDMenuProc.mel +++ b/plugin/adsk/scripts/USDMenuProc.mel @@ -55,6 +55,117 @@ global proc mayaUsdMenu_duplicate(string $ufePath) } } +global proc mayaUsdMenu_assignNewMaterial(string $ufePath, string $material) +{ + if (!hasPrimUpdater()) + return; + + if (size($ufePath) != 0 && size($material) != 0) { + string $temp = `python("import ufe;\ + ufePath = ufe.PathString.path('" + $ufePath + "');\ + item = ufe.Hierarchy.createItem(ufePath);\ + contextOps = ufe.ContextOps.contextOps(item);\ + cmd = contextOps.doOpCmd(['Assign New Material', 'USD', '" + $material + "']);\ + cmd.execute();")`; + } +} + +global proc mayaUsdMenu_assignExistingMaterial(string $ufePath, string $material) +{ + if (!hasPrimUpdater()) + return; + + if (size($ufePath) != 0 && size($material) != 0) { + string $temp = `python("import ufe;\ + ufePath = ufe.PathString.path('" + $ufePath + "');\ + item = ufe.Hierarchy.createItem(ufePath);\ + contextOps = ufe.ContextOps.contextOps(item);\ + cmd = contextOps.doOpCmd(['Assign Existing Material', '" + $material + "']);\ + cmd.execute();")`; + } +} + +global proc MayaUsdMenuAddNewMaterialsForRenderers(string $ufePath) +{ + string $materials[] = `mayaUsdGetMaterialsFromRenderers -si $ufePath`; + string $previousRendererString; + string $menuItem; + for ($material in $materials) + { + // We want our materials grouped into submenus according to their path in the hierarchy. + string $rendererAndMaterial[]; + $numTokens = `tokenize $material "/" $rendererAndMaterial`; + + // Expects tokenized string in the form "RendererName/Material Name|MaterialIdentifer" + if ($numTokens != 2) + continue; + + string $materialName = $rendererAndMaterial[$numTokens - 1]; + + // Get a string containing the path to the material without the name of the material itself. + string $renderer[] = $rendererAndMaterial; + stringArrayRemoveAtIndex($numTokens - 1, $renderer); + string $rendererString = stringArrayToString($renderer, "/"); + + // Create a new submenu for each path. + if ($previousRendererString != $rendererString) + { + if ($menuItem != "") + { + setParent -menu ..; + } + + $previousRendererString = $rendererString; + $menuItem = `menuItem -subMenu true -tearOff false -label $rendererString`; + } + + string $labelAndIdentifier[]; + $numTokens = `tokenize $materialName "|" $labelAndIdentifier`; + + // Expects tokenized string in the form "Material Name|MaterialIdentifer" + if ($numTokens != 2) + continue; + + menuItem -label $labelAndIdentifier[0] -command ("mayaUsdMenu_assignNewMaterial \"" + $ufePath + "\" \"" + $labelAndIdentifier[1] + "\""); + } + setParent -menu ..; +} + +global proc MayaUsdMenuAddExistingMaterials(string $ufePath) +{ + string $materials[] = `mayaUsdGetMaterialsInScene -si $ufePath`; + string $previousPathString; + string $menuItem; + for ($material in $materials) + { + // We want our materials grouped into submenus according to their path in the hierarchy. + string $pathAndMaterial[]; + $numTokens = `tokenize $material "/" $pathAndMaterial`; + + string $materialName = $pathAndMaterial[$numTokens - 1]; + + // Get a string containing the path to the material without the name of the material itself. + string $path[] = $pathAndMaterial; + stringArrayRemoveAtIndex($numTokens - 1, $path); + string $pathString = stringArrayToString($path, "/"); + + // Create a new submenu for each path. + if ($previousPathString != $pathString) + { + if ($menuItem != "") + { + setParent -menu ..; + } + + $previousPathString = $pathString; + $menuItem = `menuItem -subMenu true -tearOff false -label $pathString`; + } + + menuItem -label $materialName -parent $menuItem -command ("mayaUsdMenu_assignExistingMaterial \"" + $ufePath + "\" \"" + $material + "\""); + } + setParent -menu ..; +} + // On right click in the viewport, either through selection or through a pick // hit, Maya will look for a procedure called $runTimeName + "MenuProc". // and call it. When the selection or pick hit is a USD prim, this calls the @@ -75,6 +186,22 @@ global proc USDMenuProc(string $parent, string $obj) menuItem -label "Edit As Maya Data" -image "edit_as_Maya.png" -command ("{waitCursor -state 1; mayaUsdMenu_editAsMaya \"" + $obj + "\"; waitCursor -state 0;}"); } menuItem -label "Duplicate As Maya Data" -command ("{waitCursor -state 1; mayaUsdMenu_duplicate \"" + $obj + "\"; waitCursor -state 0;}"); + + menuItem -divider true; + + // "Assign New Material" from a list of materials provided by the renderers. + menuItem -subMenu true -tearOff false -label "Assign New Material"; + { + MayaUsdMenuAddNewMaterialsForRenderers($obj); + } + setParent -menu ..; + + // "Assign Existing Material" from a list of materials in the selected item's stage. + menuItem -subMenu true -tearOff false -label "Assign Existing Material"; + { + MayaUsdMenuAddExistingMaterials($obj); + } + setParent -menu ..; } // Allow the user to define a proc with additional menu items diff --git a/test/lib/mayaUsd/utils/CMakeLists.txt b/test/lib/mayaUsd/utils/CMakeLists.txt index 5b336f67e6..3b999a7887 100644 --- a/test/lib/mayaUsd/utils/CMakeLists.txt +++ b/test/lib/mayaUsd/utils/CMakeLists.txt @@ -5,6 +5,7 @@ set(TEST_SCRIPT_FILES testBlockSceneModificationContext.py testDiagnosticDelegate.py + testMaterialCommands.py ) if(CMAKE_UFE_V2_FEATURES_AVAILABLE) diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py new file mode 100644 index 0000000000..0107c49ee3 --- /dev/null +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +# +# Copyright 2023 Autodesk +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import fixturesUtils +import mayaUtils +import testUtils + +from maya import cmds +from maya import standalone + +import unittest + + +class testMaterialCommands(unittest.TestCase): + ''' + Verify the correctness of the data returned by the MaterialCommands. Currently the + returned values are largely hard-coded, so this test will become more complex in the + future once we dynamically query the renderers for their materials. + ''' + + pluginsLoaded = False + + @classmethod + def setUpClass(cls): + fixturesUtils.readOnlySetUpClass(__file__, loadPlugin=False) + + if not cls.pluginsLoaded: + cls.pluginsLoaded = mayaUtils.isMayaUsdPluginLoaded() + + @classmethod + def tearDownClass(cls): + standalone.uninitialize() + + def setUp(self): + ''' Called initially to set up the maya test environment ''' + # Load plugins + self.assertTrue(self.pluginsLoaded) + + def _StartTest(self, testName=None): + cmds.file(force=True, new=True) + if (testName): + self._testName = testName + testFile = testUtils.getTestScene("material", self._testName + ".usda") + mayaUtils.createProxyFromFile(testFile) + + def testMayaUsdGetNewMaterials(self): + """ + Checks that the list of new materials for different renderers matches the expected values. + Arnold is excluded here as it cannot be assumed to be installed in the testing environment. + """ + + self._StartTest() + + expectedMaterials = ['USD/USD Preview Surface|UsdPreviewSurface', + 'MaterialX/Standard Surface|ND_standard_surface_surfaceshader', + 'MaterialX/glTF PBR|ND_gltf_pbr_surfaceshader', + 'MaterialX/USD Preview Surface|ND_UsdPreviewSurface_surfaceshader' + ] + + materials = cmds.mayaUsdGetMaterialsFromRenderers() + self.assertCountEqual(materials, expectedMaterials) + + + def testMayaUsdGetExistingMaterials(self): + """ + Checks that the list of materials found in the stage matches the expected values. + """ + self._StartTest('multipleMaterials') + + expectedMaterials = ['/mtl/UsdPreviewSurface1', '/mtl/UsdPreviewSurface2'] + + materialsInStage = cmds.mayaUsdGetMaterialsInScene(si="|stage|stageShape,/cube") + self.assertEqual(materialsInStage, expectedMaterials) + + +if __name__ == '__main__': + unittest.main(globals()) From d936496ce0474f040f7c23352cce2d17cfb9b5a3 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 23 Feb 2023 15:36:07 +0100 Subject: [PATCH 02/18] Fix formatting --- plugin/adsk/plugin/adskMaterialCommands.cpp | 27 +++++++++++++-------- plugin/adsk/plugin/adskMaterialCommands.h | 14 +++-------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp index 69c71a0700..e7ba459543 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.cpp +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -37,7 +37,8 @@ namespace MAYAUSD_NS_DEF { // ADSKMayaUSDGetMaterialsForRenderersCommand */ -const char ADSKMayaUSDGetMaterialsForRenderersCommand::commandName[] = "mayaUsdGetMaterialsFromRenderers"; +const char ADSKMayaUSDGetMaterialsForRenderersCommand::commandName[] + = "mayaUsdGetMaterialsFromRenderers"; // plug-in callback to create the command object void* ADSKMayaUSDGetMaterialsForRenderersCommand::creator() @@ -46,7 +47,10 @@ void* ADSKMayaUSDGetMaterialsForRenderersCommand::creator() } // private argument parsing helper -MStatus ADSKMayaUSDGetMaterialsForRenderersCommand::parseArgs(const MArgList& argList) { return MS::kSuccess; } +MStatus ADSKMayaUSDGetMaterialsForRenderersCommand::parseArgs(const MArgList& argList) +{ + return MS::kSuccess; +} void ADSKMayaUSDGetMaterialsForRenderersCommand::appendMaterialXMaterials() const { @@ -69,9 +73,9 @@ void ADSKMayaUSDGetMaterialsForRenderersCommand::appendMaterialXMaterials() cons void ADSKMayaUSDGetMaterialsForRenderersCommand::appendArnoldMaterials() const { - auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); - const auto sourceTypes = sdrRegistry.GetAllNodeSourceTypes(); - const bool hasArnoldMaterials + auto& sdrRegistry = PXR_NS::SdrRegistry::GetInstance(); + const auto sourceTypes = sdrRegistry.GetAllNodeSourceTypes(); + const bool hasArnoldMaterials = std::find(sourceTypes.cbegin(), sourceTypes.cend(), TfToken("arnold")) != sourceTypes.cend(); @@ -96,7 +100,7 @@ MStatus ADSKMayaUSDGetMaterialsForRenderersCommand::doIt(const MArgList& argList { clearResult(); - MStatus status; + MStatus status; if (!status) return status; @@ -131,7 +135,10 @@ void* ADSKMayaUSDGetMaterialsInStageCommand::creator() } // private argument parsing helper -MStatus ADSKMayaUSDGetMaterialsInStageCommand::parseArgs(const MArgList& argList) { return MS::kSuccess; } +MStatus ADSKMayaUSDGetMaterialsInStageCommand::parseArgs(const MArgList& argList) +{ + return MS::kSuccess; +} // main MPxCommand execution point MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) @@ -146,8 +153,8 @@ MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) MString ufePathString; args.getFlagArgument(kSceneItem, 0, ufePathString); if (ufePathString.isEmpty()) { - MGlobal::displayError("Missing argument 'sceneItem'."); - return MS::kFailure; + MGlobal::displayError("Missing argument 'sceneItem'."); + return MS::kFailure; } const auto ufePath = Ufe::PathString::path(ufePathString.asChar()); @@ -159,7 +166,7 @@ MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) } } } - + return MS::kSuccess; } diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h index e717502a7d..7ab55dc1b4 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.h +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -45,7 +45,7 @@ struct MxShaderMenuEntry typedef std::vector MxShaderMenuEntryVec; //! \brief Fills the currently active menu with submenus listing available materials from different -//! renderers. +//! renderers. //! \todo: The list of materials and renderers is currently hard-coded. We need to make //! it dynamic so that third-party renderers can hook in to provide their own materials. class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MPxCommand @@ -57,14 +57,11 @@ class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MP static MSyntax createSyntax(); MStatus doIt(const MArgList& argList) override; - bool isUndoable() const override - { - return false; - } + bool isUndoable() const override { return false; } private: MStatus parseArgs(const MArgList& argList); - + void appendMaterialXMaterials() const; void appendArnoldMaterials() const; void appendUsdMaterials() const; @@ -84,10 +81,7 @@ class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsInStageCommand : public MPxComm static MSyntax createSyntax(); MStatus doIt(const MArgList& argList) override; - bool isUndoable() const override - { - return false; - } + bool isUndoable() const override { return false; } private: MStatus parseArgs(const MArgList& argList); From 73b76ad2afb61aa5984a1963fbe97eed8514d161 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Mon, 27 Feb 2023 09:42:27 +0100 Subject: [PATCH 03/18] Changes for Code Review --- lib/mayaUsd/ufe/UsdContextOps.cpp | 87 ++++++++++++++++--- plugin/adsk/plugin/adskMaterialCommands.cpp | 20 ++--- plugin/adsk/plugin/adskMaterialCommands.h | 31 ++----- plugin/adsk/scripts/USDMenuProc.mel | 18 ++-- .../lib/mayaUsd/utils/testMaterialCommands.py | 4 +- test/lib/ufe/testContextOps.py | 60 +++++++++++++ 6 files changed, 162 insertions(+), 58 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdContextOps.cpp b/lib/mayaUsd/ufe/UsdContextOps.cpp index 8f9485a69e..02df11aca1 100644 --- a/lib/mayaUsd/ufe/UsdContextOps.cpp +++ b/lib/mayaUsd/ufe/UsdContextOps.cpp @@ -66,6 +66,7 @@ #include #include +#include #include #include @@ -1041,20 +1042,78 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& } } #if UFE_PREVIEW_VERSION_NUM >= 4010 - } else if ( - itemPath.size() == 1u - && (itemPath[0] == kAssignNewMaterialItem || itemPath[0] == kAddNewMaterialItem)) { - MString script; - script.format( - "MayaUsdMenuAddNewMaterialsForRenderers \"^1s\"", - Ufe::PathString::string(fItem->path()).c_str()); - MString result = MGlobal::executeCommandStringResult(script, false, false); - } else if (itemPath.size() == 1u && itemPath[0] == kAssignExistingMaterialItem) { - MString script; + } else if (itemPath[0] == kAssignNewMaterialItem || itemPath[0] == kAddNewMaterialItem) { + std::multimap renderersAndMaterials; + MStringArray materials; + MGlobal::executeCommand("mayaUsdGetMaterialsFromRenderers", materials); + + for (const auto& materials : materials) { + // Expects a string in the format "renderer/Material Name|Material Identifier". + MStringArray rendererAndMaterial; + MStatus status = materials.split('/', rendererAndMaterial); + if (status == MS::kSuccess && rendererAndMaterial.length() == 2) { + renderersAndMaterials.emplace( + std::string(rendererAndMaterial[0].asChar()), rendererAndMaterial[1]); + } + } + + if (itemPath.size() == 1u) { + // Populate list of known renderers (first menu level). + for (auto it = renderersAndMaterials.begin(), end = renderersAndMaterials.end(); + it != end; + it = renderersAndMaterials.upper_bound(it->first)) { + items.emplace_back(it->first, it->first, Ufe::ContextItem::kHasChildren); + } + } else if (itemPath.size() == 2u) { + // Populate list of materials for a given renderer (second menu level). + const auto range = renderersAndMaterials.equal_range(itemPath[1]); + for (auto it = range.first; it != range.second; ++it) { + MStringArray materialAndIdentifier; + // Expects a string in the format "Material Name|MaterialIdentifer". + MStatus status = it->second.split('|', materialAndIdentifier); + if (status == MS::kSuccess && materialAndIdentifier.length() == 2) { + items.emplace_back( + materialAndIdentifier[1].asChar(), materialAndIdentifier[0].asChar()); + } + } + } + } else if (itemPath[0] == kAssignExistingMaterialItem) { + std::multimap pathsAndMaterials; + MStringArray materials; + MString script; script.format( - "MayaUsdMenuAddExistingMaterials \"^1s\"", + "mayaUsdGetMaterialsInStage \"^1s\"", Ufe::PathString::string(fItem->path()).c_str()); - MString result = MGlobal::executeCommandStringResult(script, false, false); + MGlobal::executeCommand(script, materials); + + for (const auto& material : materials) { + MStringArray pathAndMaterial; + MStatus status = material.split('/', pathAndMaterial); + // Expects a string in the format "/path1/path2|Material". + if (status == MS::kFailure || pathAndMaterial.length() < 2) { + continue; + } + + MString pathToMaterial = ""; + for (int i = 0; i < pathAndMaterial.length() - 1; i++) { + pathToMaterial += "/" + pathAndMaterial[i]; + } + pathsAndMaterials.emplace(std::string(pathToMaterial.asChar()), material); + } + + if (itemPath.size() == 1u) { + // Populate list of paths to materials (first menu level). + for (auto it = pathsAndMaterials.begin(), end = pathsAndMaterials.end(); it != end; + it = pathsAndMaterials.upper_bound(it->first)) { + items.emplace_back(it->first, it->first, Ufe::ContextItem::kHasChildren); + } + } else if (itemPath.size() == 2u) { + // Populate list of to materials for given path (second menu level). + const auto range = pathsAndMaterials.equal_range(itemPath[1]); + for (auto it = range.first; it != range.second; ++it) { + items.emplace_back(it->second.asChar(), it->second.asChar()); + } + } #endif } #endif @@ -1205,7 +1264,7 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) } else if (itemPath.size() == 3u && itemPath[0] == kAddNewMaterialItem) { return std::make_shared( UsdUndoAddNewMaterialCommand::create(fItem, itemPath[2])); - } else if (itemPath.size() == 2u && itemPath[0] == kAssignExistingMaterialItem) { + } else if (itemPath.size() == 3u && itemPath[0] == kAssignExistingMaterialItem) { std::shared_ptr compositeCmd; Ufe::Selection sceneItems(*Ufe::GlobalSelection::get()); sceneItems.append(fItem); @@ -1216,7 +1275,7 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) compositeCmd = std::make_shared(); } compositeCmd->append(std::make_shared( - compatiblePrim, SdfPath(itemPath[1]))); + compatiblePrim, SdfPath(itemPath[2]))); } } return compositeCmd; diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp index e7ba459543..3c113bd38d 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.cpp +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -89,7 +89,6 @@ void ADSKMayaUSDGetMaterialsForRenderersCommand::appendArnoldMaterials() const void ADSKMayaUSDGetMaterialsForRenderersCommand::appendUsdMaterials() const { - // TODO: Replace hard-coded materials with dynamically generated list. const MString label = "USD Preview Surface"; const MString identifier = "UsdPreviewSurface"; appendToResult("USD/" + label + "|" + identifier); @@ -124,7 +123,7 @@ MSyntax ADSKMayaUSDGetMaterialsForRenderersCommand::createSyntax() // ADSKMayaUSDGetMaterialsInStageCommand */ -const char ADSKMayaUSDGetMaterialsInStageCommand::commandName[] = "mayaUsdGetMaterialsInScene"; +const char ADSKMayaUSDGetMaterialsInStageCommand::commandName[] = "mayaUsdGetMaterialsInStage"; static const TfToken materialType("Material"); @@ -150,18 +149,17 @@ MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) if (!status) return status; - MString ufePathString; - args.getFlagArgument(kSceneItem, 0, ufePathString); - if (ufePathString.isEmpty()) { - MGlobal::displayError("Missing argument 'sceneItem'."); - return MS::kFailure; + MString ufePathString = args.commandArgumentString(0); + if (ufePathString.length() == 0) { + MGlobal::displayError("Missing argument 'UFE Path'."); + throw MS::kFailure; } const auto ufePath = Ufe::PathString::path(ufePathString.asChar()); UsdStagePtr stage = ufe::getStage(ufePath); if (stage) { for (auto prim : stage->Traverse()) { - if (prim.GetTypeName() == materialType) { + if (UsdShadeMaterial(prim)) { appendToResult(MString(prim.GetPath().GetString().c_str())); } } @@ -173,8 +171,10 @@ MStatus ADSKMayaUSDGetMaterialsInStageCommand::doIt(const MArgList& argList) MSyntax ADSKMayaUSDGetMaterialsInStageCommand::createSyntax() { MSyntax syntax; - syntax.addFlag("-si", "-sceneItem", MSyntax::kString); + syntax.addArg(MSyntax::kString); + syntax.enableQuery(false); + syntax.enableEdit(false); return syntax; } -} // namespace MAYAUSD_NS_DEF +} // namespace MAYAUSD_NS_DEF \ No newline at end of file diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h index 7ab55dc1b4..5ac4390e92 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.h +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -13,8 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#pragma once - #ifndef ADSK_MAYA_MATERIAL_COMMANDS_H #define ADSK_MAYA_MATERIAL_COMMANDS_H @@ -32,22 +30,12 @@ namespace MAYAUSD_NS_DEF { // GetMaterialXMaterialsCommand //------------------------------------------------------------------------------ -struct MxShaderMenuEntry -{ - MxShaderMenuEntry(const std::string& label, const std::string& identifier) - : _label(label) - , _identifier(identifier) - { - } - const std::string _label; - const std::string& _identifier; -}; -typedef std::vector MxShaderMenuEntryVec; - -//! \brief Fills the currently active menu with submenus listing available materials from different -//! renderers. -//! \todo: The list of materials and renderers is currently hard-coded. We need to make -//! it dynamic so that third-party renderers can hook in to provide their own materials. +//! \brief Returns an array of strings containing materials associated with a given renderer.The +//! strings are in the format: "Renderer Name/Material Label|MaterialIdentifier" e.g. "Arnold/AI +//! Standard Surface|arnold:standard_surface" The main intention is for the returned strings to be +//! split in order to populate menu entries. \todo: The list of materials and renderers is currently +//! hard-coded. We need to make it dynamic so that third-party renderers can hook in to provide +//! their own materials. class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MPxCommand { public: @@ -67,13 +55,10 @@ class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MP void appendUsdMaterials() const; }; -//! \brief Fills the currently active menu with the available materials existing in the given -//! object's stage. +//! \brief Returns an array of materials in the same stage as the object passed in via argument. +//! The returned strings are simply paths to a material. class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsInStageCommand : public MPxCommand { - static constexpr auto kSceneItem = "si"; - static constexpr auto kSceneItemLong = "sceneItem"; - public: // plugin registration requirements static const char commandName[]; diff --git a/plugin/adsk/scripts/USDMenuProc.mel b/plugin/adsk/scripts/USDMenuProc.mel index fccbe2642d..94ae460a3f 100644 --- a/plugin/adsk/scripts/USDMenuProc.mel +++ b/plugin/adsk/scripts/USDMenuProc.mel @@ -65,7 +65,7 @@ global proc mayaUsdMenu_assignNewMaterial(string $ufePath, string $material) ufePath = ufe.PathString.path('" + $ufePath + "');\ item = ufe.Hierarchy.createItem(ufePath);\ contextOps = ufe.ContextOps.contextOps(item);\ - cmd = contextOps.doOpCmd(['Assign New Material', 'USD', '" + $material + "']);\ + cmd = contextOps.doOpCmd(['Assign New Material', '', '" + $material + "']);\ cmd.execute();")`; } } @@ -80,14 +80,14 @@ global proc mayaUsdMenu_assignExistingMaterial(string $ufePath, string $material ufePath = ufe.PathString.path('" + $ufePath + "');\ item = ufe.Hierarchy.createItem(ufePath);\ contextOps = ufe.ContextOps.contextOps(item);\ - cmd = contextOps.doOpCmd(['Assign Existing Material', '" + $material + "']);\ + cmd = contextOps.doOpCmd(['Assign Existing Material', '', '" + $material + "']);\ cmd.execute();")`; } } -global proc MayaUsdMenuAddNewMaterialsForRenderers(string $ufePath) +global proc mayaUsdMenu_addNewMaterials(string $ufePath) { - string $materials[] = `mayaUsdGetMaterialsFromRenderers -si $ufePath`; + string $materials[] = `mayaUsdGetMaterialsFromRenderers`; string $previousRendererString; string $menuItem; for ($material in $materials) @@ -131,9 +131,9 @@ global proc MayaUsdMenuAddNewMaterialsForRenderers(string $ufePath) setParent -menu ..; } -global proc MayaUsdMenuAddExistingMaterials(string $ufePath) +global proc mayaUsdMenu_addExistingMaterials(string $ufePath) { - string $materials[] = `mayaUsdGetMaterialsInScene -si $ufePath`; + string $materials[] = `mayaUsdGetMaterialsInStage $ufePath`; string $previousPathString; string $menuItem; for ($material in $materials) @@ -192,14 +192,14 @@ global proc USDMenuProc(string $parent, string $obj) // "Assign New Material" from a list of materials provided by the renderers. menuItem -subMenu true -tearOff false -label "Assign New Material"; { - MayaUsdMenuAddNewMaterialsForRenderers($obj); + mayaUsdMenu_addNewMaterials($obj); } setParent -menu ..; // "Assign Existing Material" from a list of materials in the selected item's stage. menuItem -subMenu true -tearOff false -label "Assign Existing Material"; { - MayaUsdMenuAddExistingMaterials($obj); + mayaUsdMenu_addExistingMaterials($obj); } setParent -menu ..; } @@ -209,4 +209,4 @@ global proc USDMenuProc(string $parent, string $obj) { USDUserMenuProc($parent,$obj); } -} +} \ No newline at end of file diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py index 0107c49ee3..1d102cdc74 100644 --- a/test/lib/mayaUsd/utils/testMaterialCommands.py +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -73,7 +73,7 @@ def testMayaUsdGetNewMaterials(self): ] materials = cmds.mayaUsdGetMaterialsFromRenderers() - self.assertCountEqual(materials, expectedMaterials) + self.assertTrue(set(materials).issuperset(set(expectedMaterials))) def testMayaUsdGetExistingMaterials(self): @@ -84,7 +84,7 @@ def testMayaUsdGetExistingMaterials(self): expectedMaterials = ['/mtl/UsdPreviewSurface1', '/mtl/UsdPreviewSurface2'] - materialsInStage = cmds.mayaUsdGetMaterialsInScene(si="|stage|stageShape,/cube") + materialsInStage = cmds.mayaUsdGetMaterialsInStage("|stage|stageShape,/cube") self.assertEqual(materialsInStage, expectedMaterials) diff --git a/test/lib/ufe/testContextOps.py b/test/lib/ufe/testContextOps.py index 5ce25fcc5d..de80b09f96 100644 --- a/test/lib/ufe/testContextOps.py +++ b/test/lib/ufe/testContextOps.py @@ -1416,5 +1416,65 @@ def _validateLoadAndUnloadItems(hierItem, itemStrings): _validateLoadAndUnloadItems(ball15Item, ['Load', 'Load with Descendants']) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4010', 'Test only available in UFE preview version 0.4.10 and greater') + @unittest.skipUnless(Usd.GetVersion() >= (0, 21, 8), 'Requires CanApplySchema from USD') + def testAssignExistingMaterialToSingleObject(self): + """This test assigns an existing material from the stage via ContextOps capabilities.""" + cmds.file(new=True, force=True) + + # Create a proxy shape with empty stage to start with. + import mayaUsd_createStageWithNewLayer + proxyShape = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + + # Create a ContextOps interface for the proxy shape. + proxyPathSegment = mayaUtils.createUfePathSegment(proxyShape) + proxyShapePath = ufe.Path([proxyPathSegment]) + proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath) + contextOps = ufe.ContextOps.contextOps(proxyShapeItem) + + rootHier = ufe.Hierarchy.hierarchy(proxyShapeItem) + + # Create a single object in our stage to test with. + cmd = contextOps.doOpCmd(['Add New Prim', 'Capsule']) + self.assertIsNotNone(cmd) + ufeCmd.execute(cmd) + capsuleItem = rootHier.children()[0] + capsulePrim = usdUtils.getPrimFromSceneItem(capsuleItem) + contextOps = ufe.ContextOps.contextOps(capsuleItem) + + # We should have no material assigned after creating an object. + capsulePrim = usdUtils.getPrimFromSceneItem(capsuleItem) + self.assertFalse(capsulePrim.HasAPI(UsdShade.MaterialBindingAPI)) + + # Add a new material to the stage (but don't assign it just yet). + cmd = contextOps.doOpCmd(['Add New Material', 'USD', 'UsdPreviewSurface']) + self.assertIsNotNone(cmd) + ufeCmd.execute(cmd) + + # We created a new material, but it should not have been assigned to our Capsule. + capsulePrim = usdUtils.getPrimFromSceneItem(capsuleItem) + self.assertFalse(capsulePrim.HasAPI(UsdShade.MaterialBindingAPI)) + + # Now we explictly assign the material to our Capsule. + cmd = contextOps.doOpCmd(['Assign Existing Material', '', '/Capsule1/UsdPreviewSurface1' ]) + self.assertIsNotNone(cmd) + ufeCmd.execute(cmd) + + # Confirm the material is assigned. + capsuleBindAPI = UsdShade.MaterialBindingAPI(capsulePrim) + self.assertTrue(capsuleBindAPI) + self.assertEqual(capsuleBindAPI.GetDirectBinding().GetMaterialPath(), Sdf.Path("/Capsule1/UsdPreviewSurface1")) + + # Make sure the command plays nice with undo/redo. + cmds.undo() + self.assertFalse(capsulePrim.HasAPI(UsdShade.MaterialBindingAPI)) + + cmds.redo() + self.assertTrue(capsulePrim.HasAPI(UsdShade.MaterialBindingAPI)) + self.assertEqual(capsuleBindAPI.GetDirectBinding().GetMaterialPath(), Sdf.Path("/Capsule1/UsdPreviewSurface1")) + + cmds.undo() + self.assertFalse(capsulePrim.HasAPI(UsdShade.MaterialBindingAPI)) + if __name__ == '__main__': unittest.main(verbosity=2) From dd2ce21a06c928efc9e87a2f6b5be43281ebb616 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 09:25:18 +0100 Subject: [PATCH 04/18] Fix undo, second level menus in Outliner --- lib/mayaUsd/ufe/UsdContextOps.cpp | 22 +++++++++++----------- plugin/adsk/scripts/USDMenuProc.mel | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdContextOps.cpp b/lib/mayaUsd/ufe/UsdContextOps.cpp index 02df11aca1..e88f6b7f1f 100644 --- a/lib/mayaUsd/ufe/UsdContextOps.cpp +++ b/lib/mayaUsd/ufe/UsdContextOps.cpp @@ -1088,17 +1088,12 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& for (const auto& material : materials) { MStringArray pathAndMaterial; - MStatus status = material.split('/', pathAndMaterial); - // Expects a string in the format "/path1/path2|Material". - if (status == MS::kFailure || pathAndMaterial.length() < 2) { - continue; + // Expects a string in the format "/path1/path2/Material". + const int lastSlash = material.rindex('/'); + if (lastSlash >= 0) { + MString pathToMaterial = material.substring(0, lastSlash); + pathsAndMaterials.emplace(std::string(pathToMaterial.asChar()), material); } - - MString pathToMaterial = ""; - for (int i = 0; i < pathAndMaterial.length() - 1; i++) { - pathToMaterial += "/" + pathAndMaterial[i]; - } - pathsAndMaterials.emplace(std::string(pathToMaterial.asChar()), material); } if (itemPath.size() == 1u) { @@ -1111,7 +1106,12 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& // Populate list of to materials for given path (second menu level). const auto range = pathsAndMaterials.equal_range(itemPath[1]); for (auto it = range.first; it != range.second; ++it) { - items.emplace_back(it->second.asChar(), it->second.asChar()); + const int lastSlash = it->second.rindex('/'); + if (lastSlash >= 0) { + MString materialName + = it->second.substring(lastSlash + 1, it->second.length() - 1); + items.emplace_back(it->second.asChar(), materialName.asChar()); + } } } #endif diff --git a/plugin/adsk/scripts/USDMenuProc.mel b/plugin/adsk/scripts/USDMenuProc.mel index 94ae460a3f..0e6b5dced0 100644 --- a/plugin/adsk/scripts/USDMenuProc.mel +++ b/plugin/adsk/scripts/USDMenuProc.mel @@ -66,7 +66,7 @@ global proc mayaUsdMenu_assignNewMaterial(string $ufePath, string $material) item = ufe.Hierarchy.createItem(ufePath);\ contextOps = ufe.ContextOps.contextOps(item);\ cmd = contextOps.doOpCmd(['Assign New Material', '', '" + $material + "']);\ - cmd.execute();")`; + ufe.UndoableCommandMgr.instance().executeCmd(cmd);")`; } } @@ -81,8 +81,8 @@ global proc mayaUsdMenu_assignExistingMaterial(string $ufePath, string $material item = ufe.Hierarchy.createItem(ufePath);\ contextOps = ufe.ContextOps.contextOps(item);\ cmd = contextOps.doOpCmd(['Assign Existing Material', '', '" + $material + "']);\ - cmd.execute();")`; - } + ufe.UndoableCommandMgr.instance().executeCmd(cmd);")`; + } } global proc mayaUsdMenu_addNewMaterials(string $ufePath) From 63f3dcf8137d78277eb6cf3dcd0251fb04f7d9bb Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 12:25:26 +0100 Subject: [PATCH 05/18] Attempt to fix build error: "definition of dllimport static data member not allowed" --- plugin/adsk/plugin/adskMaterialCommands.cpp | 10 +++++----- plugin/adsk/plugin/adskMaterialCommands.h | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp index 3c113bd38d..c384e9477e 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.cpp +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -33,13 +34,14 @@ PXR_NAMESPACE_USING_DIRECTIVE namespace MAYAUSD_NS_DEF { +const MString + ADSKMayaUSDGetMaterialsForRenderersCommand::commandName("mayaUsdGetMaterialsFromRenderers"); +const MString ADSKMayaUSDGetMaterialsInStageCommand::commandName("mayaUsdGetMaterialsInStage"); + /* // ADSKMayaUSDGetMaterialsForRenderersCommand */ -const char ADSKMayaUSDGetMaterialsForRenderersCommand::commandName[] - = "mayaUsdGetMaterialsFromRenderers"; - // plug-in callback to create the command object void* ADSKMayaUSDGetMaterialsForRenderersCommand::creator() { @@ -123,8 +125,6 @@ MSyntax ADSKMayaUSDGetMaterialsForRenderersCommand::createSyntax() // ADSKMayaUSDGetMaterialsInStageCommand */ -const char ADSKMayaUSDGetMaterialsInStageCommand::commandName[] = "mayaUsdGetMaterialsInStage"; - static const TfToken materialType("Material"); // plug-in callback to create the command object diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h index 5ac4390e92..19a6a0d284 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.h +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -16,9 +16,10 @@ #ifndef ADSK_MAYA_MATERIAL_COMMANDS_H #define ADSK_MAYA_MATERIAL_COMMANDS_H +#include "base/api.h" + #include #include -#include #include #include @@ -36,13 +37,13 @@ namespace MAYAUSD_NS_DEF { //! split in order to populate menu entries. \todo: The list of materials and renderers is currently //! hard-coded. We need to make it dynamic so that third-party renderers can hook in to provide //! their own materials. -class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MPxCommand +class MAYAUSD_PLUGIN_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MPxCommand { public: // plugin registration requirements - static const char commandName[]; - static void* creator(); - static MSyntax createSyntax(); + static const MString commandName; + static void* creator(); + static MSyntax createSyntax(); MStatus doIt(const MArgList& argList) override; bool isUndoable() const override { return false; } @@ -57,13 +58,13 @@ class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsForRenderersCommand : public MP //! \brief Returns an array of materials in the same stage as the object passed in via argument. //! The returned strings are simply paths to a material. -class MAYAUSD_CORE_PUBLIC ADSKMayaUSDGetMaterialsInStageCommand : public MPxCommand +class MAYAUSD_PLUGIN_PUBLIC ADSKMayaUSDGetMaterialsInStageCommand : public MPxCommand { public: // plugin registration requirements - static const char commandName[]; - static void* creator(); - static MSyntax createSyntax(); + static const MString commandName; + static void* creator(); + static MSyntax createSyntax(); MStatus doIt(const MArgList& argList) override; bool isUndoable() const override { return false; } From 3f03cd0109da2c69c08255ab2c0d020abe2bb02b Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 12:43:22 +0100 Subject: [PATCH 06/18] Fix formatting --- plugin/adsk/plugin/adskMaterialCommands.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp index c384e9477e..35f8737e38 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.cpp +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -34,8 +34,7 @@ PXR_NAMESPACE_USING_DIRECTIVE namespace MAYAUSD_NS_DEF { -const MString - ADSKMayaUSDGetMaterialsForRenderersCommand::commandName("mayaUsdGetMaterialsFromRenderers"); +const MString ADSKMayaUSDGetMaterialsForRenderersCommand::commandName("mayaUsdGetMaterialsFromRenderers"); const MString ADSKMayaUSDGetMaterialsInStageCommand::commandName("mayaUsdGetMaterialsInStage"); /* From 1d2e5287081d34f561195d65712ab1323c39ce60 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 12:48:28 +0100 Subject: [PATCH 07/18] Another try to assuage the clang-formatter... --- plugin/adsk/plugin/adskMaterialCommands.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.cpp b/plugin/adsk/plugin/adskMaterialCommands.cpp index 35f8737e38..c3e33d3965 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.cpp +++ b/plugin/adsk/plugin/adskMaterialCommands.cpp @@ -34,7 +34,8 @@ PXR_NAMESPACE_USING_DIRECTIVE namespace MAYAUSD_NS_DEF { -const MString ADSKMayaUSDGetMaterialsForRenderersCommand::commandName("mayaUsdGetMaterialsFromRenderers"); +const MString + ADSKMayaUSDGetMaterialsForRenderersCommand::commandName("mayaUsdGetMaterialsFromRenderers"); const MString ADSKMayaUSDGetMaterialsInStageCommand::commandName("mayaUsdGetMaterialsInStage"); /* From c7fbf476c605234cd54e6fb3c2894c5d7e69a2b9 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 15:32:01 +0100 Subject: [PATCH 08/18] Print variables for debugging --- test/lib/mayaUsd/utils/testMaterialCommands.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py index 1d102cdc74..0da8a9c2af 100644 --- a/test/lib/mayaUsd/utils/testMaterialCommands.py +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -73,6 +73,11 @@ def testMayaUsdGetNewMaterials(self): ] materials = cmds.mayaUsdGetMaterialsFromRenderers() + + # TODO: Remove after debugging + print(materials) + print(expectedMaterials) + self.assertTrue(set(materials).issuperset(set(expectedMaterials))) From c197028c85a0e1c501432da00d3053053f6af8fa Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 15:36:21 +0100 Subject: [PATCH 09/18] Remove MaterialX/glTF material from unit tests --- test/lib/mayaUsd/utils/testMaterialCommands.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py index 0da8a9c2af..455d30284d 100644 --- a/test/lib/mayaUsd/utils/testMaterialCommands.py +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -68,16 +68,13 @@ def testMayaUsdGetNewMaterials(self): expectedMaterials = ['USD/USD Preview Surface|UsdPreviewSurface', 'MaterialX/Standard Surface|ND_standard_surface_surfaceshader', - 'MaterialX/glTF PBR|ND_gltf_pbr_surfaceshader', + # Not available in earlier versions of USD + # 'MaterialX/glTF PBR|ND_gltf_pbr_surfaceshader', 'MaterialX/USD Preview Surface|ND_UsdPreviewSurface_surfaceshader' ] materials = cmds.mayaUsdGetMaterialsFromRenderers() - # TODO: Remove after debugging - print(materials) - print(expectedMaterials) - self.assertTrue(set(materials).issuperset(set(expectedMaterials))) From 9dd1a0f3332f476a5725b4f86e88273fbdbfdab9 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 15:55:33 +0100 Subject: [PATCH 10/18] Fix preflight issues --- plugin/adsk/plugin/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/adsk/plugin/CMakeLists.txt b/plugin/adsk/plugin/CMakeLists.txt index 101c476e98..05c56fbddb 100644 --- a/plugin/adsk/plugin/CMakeLists.txt +++ b/plugin/adsk/plugin/CMakeLists.txt @@ -27,7 +27,6 @@ target_sources(${TARGET_NAME} adskExportCommand.cpp adskListJobContextsCommand.cpp adskListShadingModesCommand.cpp - adskMaterialCommands.cpp adskStageLoadUnloadCommands.cpp geomNode.cpp importTranslator.cpp @@ -35,6 +34,13 @@ target_sources(${TARGET_NAME} ProxyShape.cpp ) +if (UFE_FOUND) + target_sources(${TARGET_NAME} + PRIVATE + adskMaterialCommands.cpp + ) +endif() + # ----------------------------------------------------------------------------- # compile configuration # ----------------------------------------------------------------------------- From 2a2ad7ac1d7423fe791be62758338b274a2bc8cd Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 16:46:42 +0100 Subject: [PATCH 11/18] Print test output --- test/lib/mayaUsd/utils/testMaterialCommands.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py index 455d30284d..b0c1f35b31 100644 --- a/test/lib/mayaUsd/utils/testMaterialCommands.py +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -75,6 +75,10 @@ def testMayaUsdGetNewMaterials(self): materials = cmds.mayaUsdGetMaterialsFromRenderers() + # TODO: Remove after debugging + print(materials) + print(expectedMaterials) + self.assertTrue(set(materials).issuperset(set(expectedMaterials))) From e29b14c1e61fed01951d7b2d89a3a5b104a24c09 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Wed, 8 Mar 2023 17:20:51 +0100 Subject: [PATCH 12/18] Add testMaterialCommands.py only when CMAKE_WANT_MATERIALX_BUILD enabled --- test/lib/mayaUsd/utils/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/lib/mayaUsd/utils/CMakeLists.txt b/test/lib/mayaUsd/utils/CMakeLists.txt index 3b999a7887..9087fa7e69 100644 --- a/test/lib/mayaUsd/utils/CMakeLists.txt +++ b/test/lib/mayaUsd/utils/CMakeLists.txt @@ -5,9 +5,14 @@ set(TEST_SCRIPT_FILES testBlockSceneModificationContext.py testDiagnosticDelegate.py - testMaterialCommands.py ) +if(CMAKE_WANT_MATERIALX_BUILD) + list(APPEND TEST_SCRIPT_FILES + testMaterialCommands.py + ) +endif() + if(CMAKE_UFE_V2_FEATURES_AVAILABLE) list(APPEND TEST_SCRIPT_FILES testUtilsEditability.py From f8db282eb5bd472f7328db3e9d007aa61c8cfcd8 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 09:39:35 +0100 Subject: [PATCH 13/18] Remove unneeded includes --- plugin/adsk/plugin/adskMaterialCommands.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h index 19a6a0d284..a1045ae51f 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.h +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -22,8 +22,7 @@ #include #include -#include -#include + namespace MAYAUSD_NS_DEF { From ad5854ced678ff267589b214b82e8234e49ab015 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 09:42:52 +0100 Subject: [PATCH 14/18] Formatting --- plugin/adsk/plugin/adskMaterialCommands.h | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/adsk/plugin/adskMaterialCommands.h b/plugin/adsk/plugin/adskMaterialCommands.h index a1045ae51f..be6a87a344 100644 --- a/plugin/adsk/plugin/adskMaterialCommands.h +++ b/plugin/adsk/plugin/adskMaterialCommands.h @@ -23,7 +23,6 @@ #include - namespace MAYAUSD_NS_DEF { //------------------------------------------------------------------------------ From 5433bb517e6c7e2a85eeec9509f00729268f82e0 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 10:53:33 +0100 Subject: [PATCH 15/18] Guard behind UFE_V3_FEATURES --- plugin/adsk/plugin/CMakeLists.txt | 2 +- plugin/adsk/plugin/plugin.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/adsk/plugin/CMakeLists.txt b/plugin/adsk/plugin/CMakeLists.txt index 05c56fbddb..2353ba7d68 100644 --- a/plugin/adsk/plugin/CMakeLists.txt +++ b/plugin/adsk/plugin/CMakeLists.txt @@ -34,7 +34,7 @@ target_sources(${TARGET_NAME} ProxyShape.cpp ) -if (UFE_FOUND) +if (CMAKE_UFE_V3_FEATURES_AVAILABLE) target_sources(${TARGET_NAME} PRIVATE adskMaterialCommands.cpp diff --git a/plugin/adsk/plugin/plugin.cpp b/plugin/adsk/plugin/plugin.cpp index 772402c2a9..221fa0ff29 100644 --- a/plugin/adsk/plugin/plugin.cpp +++ b/plugin/adsk/plugin/plugin.cpp @@ -18,7 +18,6 @@ #include "adskImportCommand.h" #include "adskListJobContextsCommand.h" #include "adskListShadingModesCommand.h" -#include "adskMaterialCommands.h" #include "adskStageLoadUnloadCommands.h" #include "base/api.h" #include "exportTranslator.h" @@ -76,6 +75,7 @@ #ifdef UFE_V3_FEATURES_AVAILABLE #include #include +#include "adskMaterialCommands.h" #endif #if defined(WANT_QT_BUILD) @@ -221,8 +221,6 @@ MStatus initializePlugin(MObject obj) registerCommandCheck(plugin); registerCommandCheck(plugin); registerCommandCheck(plugin); - registerCommandCheck(plugin); - registerCommandCheck(plugin); #if defined(WANT_QT_BUILD) registerCommandCheck(plugin); #endif @@ -232,6 +230,8 @@ MStatus initializePlugin(MObject obj) registerCommandCheck(plugin); registerCommandCheck(plugin); registerCommandCheck(plugin); + registerCommandCheck(plugin); + registerCommandCheck(plugin); #endif status = plugin.registerCommand( @@ -403,8 +403,6 @@ MStatus uninitializePlugin(MObject obj) deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); - deregisterCommandCheck(plugin); - deregisterCommandCheck(plugin); #if defined(WANT_QT_BUILD) deregisterCommandCheck(plugin); MayaUsd::LayerEditorWindowCommand::cleanupOnPluginUnload(); @@ -415,6 +413,8 @@ MStatus uninitializePlugin(MObject obj) deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); deregisterCommandCheck(plugin); + deregisterCommandCheck(plugin); + deregisterCommandCheck(plugin); #endif status = plugin.deregisterNode(MayaUsd::ProxyShape::typeId); From 3a251044eb8de47b28b01371b121569fb05a0d3b Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 11:29:51 +0100 Subject: [PATCH 16/18] Formatting --- plugin/adsk/plugin/plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/adsk/plugin/plugin.cpp b/plugin/adsk/plugin/plugin.cpp index 221fa0ff29..02a916baa1 100644 --- a/plugin/adsk/plugin/plugin.cpp +++ b/plugin/adsk/plugin/plugin.cpp @@ -73,9 +73,10 @@ #endif #ifdef UFE_V3_FEATURES_AVAILABLE +#include "adskMaterialCommands.h" + #include #include -#include "adskMaterialCommands.h" #endif #if defined(WANT_QT_BUILD) From a4c08058b80fdedee6a37246ec3b6a8a4037bf00 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 12:24:56 +0100 Subject: [PATCH 17/18] More guards --- test/lib/mayaUsd/utils/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/mayaUsd/utils/CMakeLists.txt b/test/lib/mayaUsd/utils/CMakeLists.txt index 9087fa7e69..78a67890bd 100644 --- a/test/lib/mayaUsd/utils/CMakeLists.txt +++ b/test/lib/mayaUsd/utils/CMakeLists.txt @@ -7,7 +7,7 @@ set(TEST_SCRIPT_FILES testDiagnosticDelegate.py ) -if(CMAKE_WANT_MATERIALX_BUILD) +if(CMAKE_WANT_MATERIALX_BUILD AND CMAKE_UFE_V3_FEATURES_AVAILABLE) list(APPEND TEST_SCRIPT_FILES testMaterialCommands.py ) From c1b909e3710cac8da2d1ada88a700ce34c7a3ed3 Mon Sep 17 00:00:00 2001 From: Stefan Minning Date: Thu, 9 Mar 2023 13:40:48 +0100 Subject: [PATCH 18/18] Remove debug prints --- test/lib/mayaUsd/utils/testMaterialCommands.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/lib/mayaUsd/utils/testMaterialCommands.py b/test/lib/mayaUsd/utils/testMaterialCommands.py index b0c1f35b31..455d30284d 100644 --- a/test/lib/mayaUsd/utils/testMaterialCommands.py +++ b/test/lib/mayaUsd/utils/testMaterialCommands.py @@ -75,10 +75,6 @@ def testMayaUsdGetNewMaterials(self): materials = cmds.mayaUsdGetMaterialsFromRenderers() - # TODO: Remove after debugging - print(materials) - print(expectedMaterials) - self.assertTrue(set(materials).issuperset(set(expectedMaterials)))