diff --git a/lib/mayaUsd/python/CMakeLists.txt b/lib/mayaUsd/python/CMakeLists.txt index 46b79edcac..728d1a481a 100644 --- a/lib/mayaUsd/python/CMakeLists.txt +++ b/lib/mayaUsd/python/CMakeLists.txt @@ -30,6 +30,7 @@ target_sources(${PYTHON_TARGET_NAME} wrapAdaptor.cpp wrapBlockSceneModificationContext.cpp wrapColorSpace.cpp + wrapCommands.cpp wrapConverter.cpp wrapDiagnosticDelegate.cpp wrapMeshWriteUtils.cpp diff --git a/lib/mayaUsd/python/module.cpp b/lib/mayaUsd/python/module.cpp index 2757719fea..021dc47e3f 100644 --- a/lib/mayaUsd/python/module.cpp +++ b/lib/mayaUsd/python/module.cpp @@ -29,6 +29,7 @@ TF_WRAP_MODULE TF_WRAP(Adaptor); TF_WRAP(BlockSceneModificationContext); TF_WRAP(ColorSpace); + TF_WRAP(Commands); TF_WRAP(Converter); TF_WRAP(ConverterArgs); TF_WRAP(DiagnosticDelegate); diff --git a/lib/mayaUsd/python/wrapCommands.cpp b/lib/mayaUsd/python/wrapCommands.cpp new file mode 100644 index 0000000000..c7535d2cb3 --- /dev/null +++ b/lib/mayaUsd/python/wrapCommands.cpp @@ -0,0 +1,56 @@ +// +// 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 + +#include +#include + +using namespace boost::python; + +namespace { + +MayaUsd::ufe::UsdUndoLoadPayloadCommand* +LoadPayloadCommandInit(const PXR_NS::UsdPrim& prim, PXR_NS::UsdLoadPolicy policy) +{ + return new MayaUsd::ufe::UsdUndoLoadPayloadCommand(prim, policy); +} + +MayaUsd::ufe::UsdUndoUnloadPayloadCommand* UnloadPayloadCommandInit(const PXR_NS::UsdPrim& prim) +{ + return new MayaUsd::ufe::UsdUndoUnloadPayloadCommand(prim); +} + +} // namespace + +void wrapCommands() +{ + { + using This = MayaUsd::ufe::UsdUndoLoadPayloadCommand; + class_("LoadPayloadCommand", no_init) + .def("__init__", make_constructor(LoadPayloadCommandInit)) + .def("execute", &MayaUsd::ufe::UsdUndoLoadPayloadCommand::execute) + .def("undo", &MayaUsd::ufe::UsdUndoLoadPayloadCommand::undo) + .def("redo", &MayaUsd::ufe::UsdUndoLoadPayloadCommand::redo); + } + { + using This = MayaUsd::ufe::UsdUndoUnloadPayloadCommand; + class_("UnloadPayloadCommand", no_init) + .def("__init__", make_constructor(UnloadPayloadCommandInit)) + .def("execute", &MayaUsd::ufe::UsdUndoUnloadPayloadCommand::execute) + .def("undo", &MayaUsd::ufe::UsdUndoUnloadPayloadCommand::undo) + .def("redo", &MayaUsd::ufe::UsdUndoUnloadPayloadCommand::redo); + } +} diff --git a/lib/mayaUsd/ufe/CMakeLists.txt b/lib/mayaUsd/ufe/CMakeLists.txt index 5598594452..f7490ba3a1 100644 --- a/lib/mayaUsd/ufe/CMakeLists.txt +++ b/lib/mayaUsd/ufe/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${PROJECT_NAME} UsdTranslateUndoableCommand.cpp UsdUndoDeleteCommand.cpp UsdUndoDuplicateCommand.cpp + UsdUndoPayloadCommand.cpp UsdUndoRenameCommand.cpp Utils.cpp moduleDeps.cpp @@ -197,6 +198,7 @@ set(HEADERS UsdTranslateUndoableCommand.h UsdUndoDeleteCommand.h UsdUndoDuplicateCommand.h + UsdUndoPayloadCommand.h UsdUndoRenameCommand.h Utils.h ) diff --git a/lib/mayaUsd/ufe/UsdContextOps.cpp b/lib/mayaUsd/ufe/UsdContextOps.cpp index ac2576ac34..6028fa0a86 100644 --- a/lib/mayaUsd/ufe/UsdContextOps.cpp +++ b/lib/mayaUsd/ufe/UsdContextOps.cpp @@ -21,18 +21,23 @@ #include #include #endif -#include #include #include #include +#include #include #include #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -46,9 +51,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -196,34 +199,6 @@ struct WaitCursor }; #ifdef UFE_V3_FEATURES_AVAILABLE -//! \brief Create a Prim and select it: -class UsdUndoAddNewPrimAndSelectCommand : public Ufe::CompositeUndoableCommand -{ -public: - UsdUndoAddNewPrimAndSelectCommand(const UsdUfe::UsdUndoAddNewPrimCommand::Ptr& creationCmd) - : Ufe::CompositeUndoableCommand({ creationCmd }) - { - } - - void execute() override - { - auto addPrimCmd - = std::dynamic_pointer_cast(cmdsList().front()); - addPrimCmd->execute(); - // Create the selection command only if the creation succeeded: - if (!addPrimCmd->newUfePath().empty()) { - Ufe::Selection newSelection; - newSelection.append(Ufe::Hierarchy::createItem(addPrimCmd->newUfePath())); - append(Ufe::SelectionReplaceWith::createAndExecute( - Ufe::GlobalSelection::get(), newSelection)); - } - } - -#ifdef UFE_V4_FEATURES_AVAILABLE - std::string commandString() const override { return cmdsList().front()->commandString(); } -#endif -}; - //! \brief Create a working Material and select it: class InsertChildAndSelectCommand : public Ufe::CompositeUndoableCommand { @@ -253,166 +228,6 @@ class InsertChildAndSelectCommand : public Ufe::CompositeUndoableCommand }; #endif -//! \brief Undoable command for loading a USD prim. -class LoadUnloadBaseUndoableCommand : public Ufe::UndoableCommand -{ -protected: - LoadUnloadBaseUndoableCommand(const UsdPrim& prim, UsdLoadPolicy policy) - : _stage(prim.GetStage()) - , _primPath(prim.GetPath()) - , _policy(policy) - { - } - - LoadUnloadBaseUndoableCommand(const UsdPrim& prim) - : _stage(prim.GetStage()) - , _primPath(prim.GetPath()) - , _policy(UsdLoadPolicy::UsdLoadWithoutDescendants) - { - if (!_stage) - return; - - // When not provided with the load policy, we need to figure out - // what the current policy is. - UsdStageLoadRules loadRules = _stage->GetLoadRules(); - _policy = loadRules.GetEffectiveRuleForPath(_primPath) == UsdStageLoadRules::Rule::AllRule - ? UsdLoadPolicy::UsdLoadWithDescendants - : UsdLoadPolicy::UsdLoadWithoutDescendants; - } - - void doLoad() const - { - if (!_stage) - return; - - _stage->Load(_primPath, _policy); - saveModifiedLoadRules(); - } - - void doUnload() const - { - if (!_stage) - return; - - _stage->Unload(_primPath); - saveModifiedLoadRules(); - } - - void saveModifiedLoadRules() const - { - // Save the load rules so that switching the stage settings will be able to preserve the - // load rules. - MayaUsd::MayaUsdProxyShapeStageExtraData::saveLoadRules(_stage); - } - -private: - const UsdStageWeakPtr _stage; - const SdfPath _primPath; - UsdLoadPolicy _policy; -}; - -//! \brief Undoable command for loading a USD prim. -class LoadUndoableCommand : public LoadUnloadBaseUndoableCommand -{ -public: - LoadUndoableCommand(const UsdPrim& prim, UsdLoadPolicy policy) - : LoadUnloadBaseUndoableCommand(prim, policy) - { - } - - void redo() override { doLoad(); } - void undo() override { doUnload(); } -}; - -//! \brief Undoable command for unloading a USD prim. -class UnloadUndoableCommand : public LoadUnloadBaseUndoableCommand -{ -public: - UnloadUndoableCommand(const UsdPrim& prim) - : LoadUnloadBaseUndoableCommand(prim) - { - } - - void redo() override { doUnload(); } - void undo() override { doLoad(); } -}; - -//! \brief Undoable command for prim active state change -class ToggleActiveStateCommand : public Ufe::UndoableCommand -{ -public: - ToggleActiveStateCommand(const UsdPrim& prim) - { - _stage = prim.GetStage(); - _primPath = prim.GetPath(); - _active = prim.IsActive(); - } - - void undo() override - { - if (_stage) { - UsdPrim prim = _stage->GetPrimAtPath(_primPath); - if (prim.IsValid()) { - UsdUfe::InAddOrDeleteOperation ad; - prim.SetActive(_active); - } - } - } - - void redo() override - { - if (_stage) { - UsdPrim prim = _stage->GetPrimAtPath(_primPath); - if (prim.IsValid()) { - UsdUfe::InAddOrDeleteOperation ad; - prim.SetActive(!_active); - } - } - } - -private: - PXR_NS::UsdStageWeakPtr _stage; - PXR_NS::SdfPath _primPath; - bool _active; -}; - -//! \brief Undoable command for prim instanceable state change -class ToggleInstanceableStateCommand : public Ufe::UndoableCommand -{ -public: - ToggleInstanceableStateCommand(const UsdPrim& prim) - { - _stage = prim.GetStage(); - _primPath = prim.GetPath(); - _instanceable = prim.IsInstanceable(); - } - - void undo() override - { - if (_stage) { - UsdPrim prim = _stage->GetPrimAtPath(_primPath); - if (prim.IsValid()) { - prim.SetInstanceable(_instanceable); - } - } - } - - void redo() override - { - if (_stage) { - UsdPrim prim = _stage->GetPrimAtPath(_primPath); - if (prim.IsValid()) { - prim.SetInstanceable(!_instanceable); - } - } - } - -private: - PXR_NS::UsdStageWeakPtr _stage; - PXR_NS::SdfPath _primPath; - bool _instanceable; -}; - const PXR_NS::SdfLayerHandle getCurrentTargetLayer(const UsdPrim& prim) { auto stage = prim.GetStage(); @@ -513,140 +328,6 @@ makeUSDReferenceFilePathRelativeIfRequested(const std::string& filePath, const U return relativePathAndSuccess.first; } -class AddUsdReferenceUndoableCommand : public Ufe::UndoableCommand -{ -public: - AddUsdReferenceUndoableCommand(const UsdPrim& prim, const std::string& filePath, bool prepend) - : _prim(prim) - , _sdfRef() - , _filePath(filePath) - , _listPos(prepend ? UsdListPositionBackOfPrependList : UsdListPositionBackOfAppendList) - { - } - - void undo() override - { - if (_prim.IsValid()) { - UsdReferences primRefs = _prim.GetReferences(); - primRefs.RemoveReference(_sdfRef); - } - } - - void redo() override - { - if (_prim.IsValid()) { - if (TfStringEndsWith(_filePath, ".mtlx")) { - _sdfRef = SdfReference(_filePath, SdfPath("/MaterialX")); - } else { - _sdfRef = SdfReference(_filePath); - } - UsdReferences primRefs = _prim.GetReferences(); - primRefs.AddReference(_sdfRef, _listPos); - } - } - -private: - UsdPrim _prim; - SdfReference _sdfRef; - std::string _filePath; - UsdListPosition _listPos; -}; - -class AddUsdPayloadUndoableCommand : public Ufe::UndoableCommand -{ -public: - AddUsdPayloadUndoableCommand(const UsdPrim& prim, const std::string& filePath, bool prepend) - : _prim(prim) - , _sdfPayload() - , _filePath(filePath) - , _listPos(prepend ? UsdListPositionBackOfPrependList : UsdListPositionBackOfAppendList) - { - } - - void undo() override - { - if (!_prim.IsValid()) - return; - - UsdPayloads primPayloads = _prim.GetPayloads(); - primPayloads.RemovePayload(_sdfPayload); - } - - void redo() override - { - if (!_prim.IsValid()) - return; - - if (TfStringEndsWith(_filePath, ".mtlx")) { - _sdfPayload = SdfPayload(_filePath, SdfPath("/MaterialX")); - } else { - _sdfPayload = SdfPayload(_filePath); - } - UsdPayloads primPayloads = _prim.GetPayloads(); - primPayloads.AddPayload(_sdfPayload, _listPos); - } - -private: - UsdPrim _prim; - SdfPayload _sdfPayload; - std::string _filePath; - UsdListPosition _listPos; -}; - -class ClearAllReferencesUndoableCommand : public Ufe::UndoableCommand -{ -public: - ClearAllReferencesUndoableCommand(const UsdPrim& prim) - : _prim(prim) - { - } - - void undo() override { _undoItem.undo(); } - - void redo() override { _undoItem.redo(); } - - void execute() override - { - if (!_prim.IsValid()) - return; - - UsdUfe::UsdUndoBlock block(&_undoItem); - UsdReferences primRefs = _prim.GetReferences(); - primRefs.ClearReferences(); - } - -private: - UsdPrim _prim; - UsdUfe::UsdUndoableItem _undoItem; -}; - -class ClearAllPayloadsUndoableCommand : public Ufe::UndoableCommand -{ -public: - ClearAllPayloadsUndoableCommand(const UsdPrim& prim) - : _prim(prim) - { - } - - void undo() override { _undoItem.undo(); } - - void redo() override { _undoItem.redo(); } - - void execute() override - { - if (!_prim.IsValid()) - return; - - UsdUfe::UsdUndoBlock block(&_undoItem); - UsdPayloads primRefs = _prim.GetPayloads(); - primRefs.ClearPayloads(); - } - -private: - UsdPrim _prim; - UsdUfe::UsdUndoableItem _undoItem; -}; - std::vector> _computeLoadAndUnloadItems(const UsdPrim& prim) { @@ -1179,9 +860,9 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) ? UsdLoadWithDescendants : UsdLoadWithoutDescendants; - return std::make_shared(prim(), policy); + return std::make_shared(prim(), policy); } else if (itemPath[0u] == kUSDUnloadItem) { - return std::make_shared(prim()); + return std::make_shared(prim()); } else if (itemPath[0] == kUSDVariantSetsItem) { // Operation is to set a variant in a variant set. Need both the // variant set and the variant as arguments to the operation. @@ -1203,10 +884,10 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) return object3d->setVisibleCmd(!current); } // Visibility else if (itemPath[0] == kUSDToggleActiveStateItem) { - return std::make_shared(prim()); + return std::make_shared(prim()); } // ActiveState else if (itemPath[0] == kUSDToggleInstanceableStateItem) { - return std::make_shared(prim()); + return std::make_shared(prim()); } // InstanceableState else if (!itemPath.empty() && (itemPath[0] == kUSDAddNewPrimItem)) { // Operation is to create a new prim of the type specified. @@ -1217,8 +898,8 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) // At this point we know the last item in the itemPath is the prim type to create auto primType = itemPath[itemPath.size() - 1]; #ifdef UFE_V3_FEATURES_AVAILABLE - return std::make_shared( - UsdUfe::UsdUndoAddNewPrimCommand::create(fItem, primType, primType)); + return UsdUfe::UsdUndoSelectAfterCommand::create( + fItem, primType, primType); #else return UsdUfe::UsdUndoAddNewPrimCommand::create(fItem, primType, primType); #endif @@ -1252,17 +933,19 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) const bool asRef = UsdMayaUtilFileSystem::wantReferenceCompositionArc(); const bool prepend = UsdMayaUtilFileSystem::wantPrependCompositionArc(); if (asRef) { - return std::make_shared(prim(), path, prepend); + return std::make_shared(prim(), path, prepend); } else { Ufe::UndoableCommand::Ptr preloadCmd; const bool preload = UsdMayaUtilFileSystem::wantPayloadLoaded(); if (preload) { - preloadCmd = std::make_shared(prim(), UsdLoadWithDescendants); + preloadCmd + = std::make_shared(prim(), UsdLoadWithDescendants); } else { - preloadCmd = std::make_shared(prim()); + preloadCmd = std::make_shared(prim()); } - auto payloadCmd = std::make_shared(prim(), path, prepend); + auto payloadCmd + = std::make_shared(prim(), path, prepend); auto compoCmd = std::make_shared(); compoCmd->append(preloadCmd); @@ -1290,12 +973,13 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) if (!compositeCmd) { compositeCmd = std::make_shared(); } - compositeCmd->append(std::make_shared(prim())); + compositeCmd->append( + std::make_shared(prim())); } else if (res == "payloads") { if (!compositeCmd) { compositeCmd = std::make_shared(); } - compositeCmd->append(std::make_shared(prim())); + compositeCmd->append(std::make_shared(prim())); } } return compositeCmd; diff --git a/lib/mayaUsd/ufe/UsdUndoPayloadCommand.cpp b/lib/mayaUsd/ufe/UsdUndoPayloadCommand.cpp new file mode 100644 index 0000000000..2528ee2b28 --- /dev/null +++ b/lib/mayaUsd/ufe/UsdUndoPayloadCommand.cpp @@ -0,0 +1,93 @@ +// +// 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 "UsdUndoPayloadCommand.h" + +#include + +namespace MAYAUSD_NS_DEF { +namespace ufe { + +UsdUndoLoadUnloadBaseCommand::UsdUndoLoadUnloadBaseCommand( + const PXR_NS::UsdPrim& prim, + PXR_NS::UsdLoadPolicy policy) + : _stage(prim.GetStage()) + , _primPath(prim.GetPath()) + , _policy(policy) +{ +} + +UsdUndoLoadUnloadBaseCommand::UsdUndoLoadUnloadBaseCommand(const PXR_NS::UsdPrim& prim) + : _stage(prim.GetStage()) + , _primPath(prim.GetPath()) + , _policy(PXR_NS::UsdLoadPolicy::UsdLoadWithoutDescendants) +{ + if (!_stage) + return; + + // When not provided with the load policy, we need to figure out + // what the current policy is. + PXR_NS::UsdStageLoadRules loadRules = _stage->GetLoadRules(); + _policy + = loadRules.GetEffectiveRuleForPath(_primPath) == PXR_NS::UsdStageLoadRules::Rule::AllRule + ? PXR_NS::UsdLoadPolicy::UsdLoadWithDescendants + : PXR_NS::UsdLoadPolicy::UsdLoadWithoutDescendants; +} + +void UsdUndoLoadUnloadBaseCommand::doLoad() const +{ + if (!_stage) + return; + + _stage->Load(_primPath, _policy); + saveModifiedLoadRules(); +} + +void UsdUndoLoadUnloadBaseCommand::doUnload() const +{ + if (!_stage) + return; + + _stage->Unload(_primPath); + saveModifiedLoadRules(); +} + +void UsdUndoLoadUnloadBaseCommand::saveModifiedLoadRules() const +{ + // Save the load rules so that switching the stage settings will be able to preserve the + // load rules. + MayaUsd::MayaUsdProxyShapeStageExtraData::saveLoadRules(_stage); +} + +UsdUndoLoadPayloadCommand::UsdUndoLoadPayloadCommand( + const PXR_NS::UsdPrim& prim, + PXR_NS::UsdLoadPolicy policy) + : UsdUndoLoadUnloadBaseCommand(prim, policy) +{ +} + +void UsdUndoLoadPayloadCommand::redo() { doLoad(); } +void UsdUndoLoadPayloadCommand::undo() { doUnload(); } + +UsdUndoUnloadPayloadCommand::UsdUndoUnloadPayloadCommand(const PXR_NS::UsdPrim& prim) + : UsdUndoLoadUnloadBaseCommand(prim) +{ +} + +void UsdUndoUnloadPayloadCommand::redo() { doUnload(); } +void UsdUndoUnloadPayloadCommand::undo() { doLoad(); } + +} // namespace ufe +} // namespace MAYAUSD_NS_DEF diff --git a/lib/mayaUsd/ufe/UsdUndoPayloadCommand.h b/lib/mayaUsd/ufe/UsdUndoPayloadCommand.h new file mode 100644 index 0000000000..98ba12c018 --- /dev/null +++ b/lib/mayaUsd/ufe/UsdUndoPayloadCommand.h @@ -0,0 +1,72 @@ +// +// 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. +// +#ifndef MAYAUSD_UFE_USDUNDOPAYLOADCOMMAND_H +#define MAYAUSD_UFE_USDUNDOPAYLOADCOMMAND_H + +#include + +#include +#include +#include +#include + +#include + +namespace MAYAUSD_NS_DEF { +namespace ufe { + +//! \brief Undoable command for loading a USD prim. +class MAYAUSD_CORE_PUBLIC UsdUndoLoadUnloadBaseCommand : public Ufe::UndoableCommand +{ +protected: + UsdUndoLoadUnloadBaseCommand(const PXR_NS::UsdPrim& prim, PXR_NS::UsdLoadPolicy policy); + UsdUndoLoadUnloadBaseCommand(const PXR_NS::UsdPrim& prim); + + void doLoad() const; + void doUnload() const; + + void saveModifiedLoadRules() const; + +private: + const PXR_NS::UsdStageWeakPtr _stage; + const PXR_NS::SdfPath _primPath; + PXR_NS::UsdLoadPolicy _policy; +}; + +//! \brief Undoable command for loading a USD prim. +class MAYAUSD_CORE_PUBLIC UsdUndoLoadPayloadCommand : public UsdUndoLoadUnloadBaseCommand +{ +public: + UsdUndoLoadPayloadCommand(const PXR_NS::UsdPrim& prim, PXR_NS::UsdLoadPolicy policy); + + void redo() override; + void undo() override; +}; + +//! \brief Undoable command for unloading a USD prim. +class MAYAUSD_CORE_PUBLIC UsdUndoUnloadPayloadCommand : public UsdUndoLoadUnloadBaseCommand +{ +public: + UsdUndoUnloadPayloadCommand(const PXR_NS::UsdPrim& prim); + + void redo() override; + void undo() override; +}; + +} // namespace ufe +} // namespace MAYAUSD_NS_DEF + +#endif diff --git a/lib/usdUfe/python/CMakeLists.txt b/lib/usdUfe/python/CMakeLists.txt index 2d9595edef..ff7abe595d 100644 --- a/lib/usdUfe/python/CMakeLists.txt +++ b/lib/usdUfe/python/CMakeLists.txt @@ -21,6 +21,7 @@ target_sources(${PYTHON_TARGET_NAME} wrapGlobal.cpp wrapTokens.cpp wrapUtils.cpp + wrapCommands.cpp ) # ----------------------------------------------------------------------------- diff --git a/lib/usdUfe/python/module.cpp b/lib/usdUfe/python/module.cpp index 85963266e2..bf02e21ec1 100644 --- a/lib/usdUfe/python/module.cpp +++ b/lib/usdUfe/python/module.cpp @@ -24,4 +24,5 @@ TF_WRAP_MODULE TF_WRAP(Global); TF_WRAP(Tokens); TF_WRAP(Utils); + TF_WRAP(Commands); } diff --git a/lib/usdUfe/python/wrapCommands.cpp b/lib/usdUfe/python/wrapCommands.cpp new file mode 100644 index 0000000000..ad8e21e2cf --- /dev/null +++ b/lib/usdUfe/python/wrapCommands.cpp @@ -0,0 +1,114 @@ +// +// 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 +#include +#include +#include +#include +#include + +#include +#include + +using namespace boost::python; + +namespace { + +UsdUfe::UsdUndoAddPayloadCommand* +AddPayloadCommandInit(const PXR_NS::UsdPrim& prim, const std::string& filePath, bool prepend) +{ + return new UsdUfe::UsdUndoAddPayloadCommand(prim, filePath, prepend); +} + +UsdUfe::UsdUndoClearPayloadsCommand* ClearPayloadsCommandInit(const PXR_NS::UsdPrim& prim) +{ + return new UsdUfe::UsdUndoClearPayloadsCommand(prim); +} + +UsdUfe::UsdUndoAddReferenceCommand* +AddReferenceCommandInit(const PXR_NS::UsdPrim& prim, const std::string& filePath, bool prepend) +{ + return new UsdUfe::UsdUndoAddReferenceCommand(prim, filePath, prepend); +} + +UsdUfe::UsdUndoClearReferencesCommand* ClearReferencesCommandInit(const PXR_NS::UsdPrim& prim) +{ + return new UsdUfe::UsdUndoClearReferencesCommand(prim); +} + +UsdUfe::UsdUndoToggleActiveCommand* ToggleActiveCommandInit(const PXR_NS::UsdPrim& prim) +{ + return new UsdUfe::UsdUndoToggleActiveCommand(prim); +} + +UsdUfe::UsdUndoToggleInstanceableCommand* ToggleInstanceableCommandInit(const PXR_NS::UsdPrim& prim) +{ + return new UsdUfe::UsdUndoToggleInstanceableCommand(prim); +} + +} // namespace + +void wrapCommands() +{ + { + using This = UsdUfe::UsdUndoAddPayloadCommand; + class_("AddPayloadCommand", no_init) + .def("__init__", make_constructor(AddPayloadCommandInit)) + .def("execute", &UsdUfe::UsdUndoAddPayloadCommand::execute) + .def("undo", &UsdUfe::UsdUndoAddPayloadCommand::undo) + .def("redo", &UsdUfe::UsdUndoAddPayloadCommand::redo); + } + { + using This = UsdUfe::UsdUndoClearPayloadsCommand; + class_("ClearPayloadsCommand", no_init) + .def("__init__", make_constructor(ClearPayloadsCommandInit)) + .def("execute", &UsdUfe::UsdUndoClearPayloadsCommand::execute) + .def("undo", &UsdUfe::UsdUndoClearPayloadsCommand::undo) + .def("redo", &UsdUfe::UsdUndoClearPayloadsCommand::redo); + } + { + using This = UsdUfe::UsdUndoAddReferenceCommand; + class_("AddReferenceCommand", no_init) + .def("__init__", make_constructor(AddReferenceCommandInit)) + .def("execute", &UsdUfe::UsdUndoAddReferenceCommand::execute) + .def("undo", &UsdUfe::UsdUndoAddReferenceCommand::undo) + .def("redo", &UsdUfe::UsdUndoAddReferenceCommand::redo); + } + { + using This = UsdUfe::UsdUndoClearReferencesCommand; + class_("ClearReferencesCommand", no_init) + .def("__init__", make_constructor(ClearReferencesCommandInit)) + .def("execute", &UsdUfe::UsdUndoClearReferencesCommand::execute) + .def("undo", &UsdUfe::UsdUndoClearReferencesCommand::undo) + .def("redo", &UsdUfe::UsdUndoClearReferencesCommand::redo); + } + { + using This = UsdUfe::UsdUndoToggleActiveCommand; + class_("ToggleActiveCommand", no_init) + .def("__init__", make_constructor(ToggleActiveCommandInit)) + .def("execute", &UsdUfe::UsdUndoToggleActiveCommand::execute) + .def("undo", &UsdUfe::UsdUndoToggleActiveCommand::undo) + .def("redo", &UsdUfe::UsdUndoToggleActiveCommand::redo); + } + { + using This = UsdUfe::UsdUndoToggleInstanceableCommand; + class_("ToggleInstanceableCommand", no_init) + .def("__init__", make_constructor(ToggleInstanceableCommandInit)) + .def("execute", &UsdUfe::UsdUndoToggleInstanceableCommand::execute) + .def("undo", &UsdUfe::UsdUndoToggleInstanceableCommand::undo) + .def("redo", &UsdUfe::UsdUndoToggleInstanceableCommand::redo); + } +} diff --git a/lib/usdUfe/ufe/CMakeLists.txt b/lib/usdUfe/ufe/CMakeLists.txt index 2d96de497c..4633c6cf1d 100644 --- a/lib/usdUfe/ufe/CMakeLists.txt +++ b/lib/usdUfe/ufe/CMakeLists.txt @@ -21,10 +21,17 @@ if(CMAKE_UFE_V2_FEATURES_AVAILABLE) UsdObject3dHandler.cpp UsdUndoableCommand.cpp UsdUndoAddNewPrimCommand.cpp + UsdUndoAddPayloadCommand.cpp + UsdUndoAddReferenceCommand.cpp + UsdUndoClearPayloadsCommand.cpp + UsdUndoClearReferencesCommand.cpp UsdUndoCreateGroupCommand.cpp UsdUndoInsertChildCommand.cpp UsdUndoReorderCommand.cpp + UsdUndoSelectAfterCommand.cpp UsdUndoSetKindCommand.cpp + UsdUndoToggleActiveCommand.cpp + UsdUndoToggleInstanceableCommand.cpp UsdUndoVisibleCommand.cpp ) endif() @@ -56,10 +63,17 @@ if(CMAKE_UFE_V2_FEATURES_AVAILABLE) UsdObject3dHandler.h UsdUndoableCommand.h UsdUndoAddNewPrimCommand.h + UsdUndoAddPayloadCommand.h + UsdUndoAddReferenceCommand.h + UsdUndoClearPayloadsCommand.h + UsdUndoClearReferencesCommand.h UsdUndoCreateGroupCommand.h UsdUndoInsertChildCommand.h UsdUndoReorderCommand.h + UsdUndoSelectAfterCommand.h UsdUndoSetKindCommand.h + UsdUndoToggleActiveCommand.h + UsdUndoToggleInstanceableCommand.h UsdUndoVisibleCommand.h ) endif() diff --git a/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.cpp b/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.cpp index 54474e00af..d9ac02d1bf 100644 --- a/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.cpp +++ b/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.cpp @@ -145,4 +145,11 @@ UsdUndoAddNewPrimCommand::Ptr UsdUndoAddNewPrimCommand::create( return std::make_shared(usdSceneItem, name, type); } +Ufe::Selection getNewSelectionFromCommand(const UsdUndoAddNewPrimCommand& cmd) +{ + Ufe::Selection newSelection; + newSelection.append(Ufe::Hierarchy::createItem(cmd.newUfePath())); + return newSelection; +} + } // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.h b/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.h index 59def7b92f..5bbb4942df 100644 --- a/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.h +++ b/lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace USDUFE_NS_DEF { @@ -67,6 +68,10 @@ class USDUFE_PUBLIC UsdUndoAddNewPrimCommand : public Ufe::UndoableCommand }; // UsdUndoAddNewPrimCommand +//! \brief Retrieve the desired selection after the command has executed. +// \see UsdUndoSelectAfterCommand. +Ufe::Selection USDUFE_PUBLIC getNewSelectionFromCommand(const UsdUndoAddNewPrimCommand& cmd); + } // namespace USDUFE_NS_DEF #endif diff --git a/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.cpp b/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.cpp new file mode 100644 index 0000000000..22e002c266 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.cpp @@ -0,0 +1,51 @@ +// +// 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 "UsdUndoAddPayloadCommand.h" + +#include +#include + +namespace USDUFE_NS_DEF { + +UsdUndoAddPayloadCommand::UsdUndoAddPayloadCommand( + const PXR_NS::UsdPrim& prim, + const std::string& filePath, + bool prepend) + : _prim(prim) + , _sdfPayload() + , _filePath(filePath) + , _listPos( + prepend ? PXR_NS::UsdListPositionBackOfPrependList + : PXR_NS::UsdListPositionBackOfAppendList) +{ +} + +void UsdUndoAddPayloadCommand::executeImplementation() +{ + if (!_prim.IsValid()) + return; + + if (PXR_NS::TfStringEndsWith(_filePath, ".mtlx")) { + _sdfPayload = PXR_NS::SdfPayload(_filePath, PXR_NS::SdfPath("/MaterialX")); + } else { + _sdfPayload = PXR_NS::SdfPayload(_filePath); + } + PXR_NS::UsdPayloads primPayloads = _prim.GetPayloads(); + primPayloads.AddPayload(_sdfPayload, _listPos); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.h b/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.h new file mode 100644 index 0000000000..ea132914b6 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoAddPayloadCommand.h @@ -0,0 +1,52 @@ +// +// 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. +// +#ifndef USD_UFE_ADD_PAYLOAD_COMMAND +#define USD_UFE_ADD_PAYLOAD_COMMAND + +#include +#include + +#include +#include + +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Command to add a payload to a prim. +class USDUFE_PUBLIC UsdUndoAddPayloadCommand : public UsdUndoableCommand +{ +public: + UsdUndoAddPayloadCommand( + const PXR_NS::UsdPrim& prim, + const std::string& filePath, + bool prepend); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdPrim _prim; + PXR_NS::SdfPayload _sdfPayload; + std::string _filePath; + PXR_NS::UsdListPosition _listPos; +}; + +} // namespace USDUFE_NS_DEF + +#endif /* USD_UFE_ADD_PAYLOAD_COMMAND */ diff --git a/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.cpp b/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.cpp new file mode 100644 index 0000000000..e968cab91b --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.cpp @@ -0,0 +1,50 @@ +// +// 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 "UsdUndoAddReferenceCommand.h" + +#include +#include + +namespace USDUFE_NS_DEF { + +//! \brief Command to add a reference to a prim. +UsdUndoAddReferenceCommand::UsdUndoAddReferenceCommand( + const PXR_NS::UsdPrim& prim, + const std::string& filePath, + bool prepend) + : _prim(prim) + , _sdfRef() + , _filePath(filePath) + , _listPos( + prepend ? PXR_NS::UsdListPositionBackOfPrependList + : PXR_NS::UsdListPositionBackOfAppendList) +{ +} + +void UsdUndoAddReferenceCommand::executeImplementation() +{ + if (!_prim.IsValid()) + return; + + _sdfRef = PXR_NS::TfStringEndsWith(_filePath, ".mtlx") + ? PXR_NS::SdfReference(_filePath, PXR_NS::SdfPath("/MaterialX")) + : PXR_NS::SdfReference(_filePath); + + PXR_NS::UsdReferences primRefs = _prim.GetReferences(); + primRefs.AddReference(_sdfRef, _listPos); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.h b/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.h new file mode 100644 index 0000000000..09b67273f0 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoAddReferenceCommand.h @@ -0,0 +1,52 @@ +// +// 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. +// +#ifndef USD_UFE_ADD_REFERENCE_COMMAND +#define USD_UFE_ADD_REFERENCE_COMMAND + +#include +#include + +#include +#include + +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Command to add a reference to a prim. +class USDUFE_PUBLIC UsdUndoAddReferenceCommand : public UsdUndoableCommand +{ +public: + UsdUndoAddReferenceCommand( + const PXR_NS::UsdPrim& prim, + const std::string& filePath, + bool prepend); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdPrim _prim; + PXR_NS::SdfReference _sdfRef; + std::string _filePath; + PXR_NS::UsdListPosition _listPos; +}; + +} // namespace USDUFE_NS_DEF + +#endif /* USD_UFE_ADD_REFERENCE_COMMAND */ diff --git a/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.cpp b/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.cpp new file mode 100644 index 0000000000..5ac8606028 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.cpp @@ -0,0 +1,36 @@ +// +// 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 "UsdUndoClearPayloadsCommand.h" + +#include + +namespace USDUFE_NS_DEF { + +UsdUndoClearPayloadsCommand::UsdUndoClearPayloadsCommand(const PXR_NS::UsdPrim& prim) + : _prim(prim) +{ +} + +void UsdUndoClearPayloadsCommand::executeImplementation() +{ + if (!_prim.IsValid()) + return; + + _prim.GetPayloads().ClearPayloads(); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.h b/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.h new file mode 100644 index 0000000000..6c0e78ebb7 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.h @@ -0,0 +1,43 @@ +// +// 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. +// +#ifndef USD_UFE_CLEAR_PAYLOADS_COMMAND +#define USD_UFE_CLEAR_PAYLOADS_COMMAND + +#include +#include + +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Command to clear (remove all) payloads from a prim. +class USDUFE_PUBLIC UsdUndoClearPayloadsCommand : public UsdUndoableCommand +{ +public: + UsdUndoClearPayloadsCommand(const PXR_NS::UsdPrim& prim); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdPrim _prim; +}; + +} // namespace USDUFE_NS_DEF + +#endif /* USD_UFE_CLEAR_PAYLOADS_COMMAND */ diff --git a/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.cpp b/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.cpp new file mode 100644 index 0000000000..d476ac2080 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.cpp @@ -0,0 +1,36 @@ +// +// 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 "UsdUndoClearReferencesCommand.h" + +#include + +namespace USDUFE_NS_DEF { + +UsdUndoClearReferencesCommand::UsdUndoClearReferencesCommand(const PXR_NS::UsdPrim& prim) + : _prim(prim) +{ +} + +void UsdUndoClearReferencesCommand::executeImplementation() +{ + if (!_prim.IsValid()) + return; + + _prim.GetReferences().ClearReferences(); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.h b/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.h new file mode 100644 index 0000000000..b59a04231e --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoClearReferencesCommand.h @@ -0,0 +1,43 @@ +// +// 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. +// +#ifndef USD_UFE_CLEAR_REFERENCES_COMMAND +#define USD_UFE_CLEAR_REFERENCES_COMMAND + +#include +#include + +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Command to clear (remove all) references from a prim. +class USDUFE_PUBLIC UsdUndoClearReferencesCommand : public UsdUndoableCommand +{ +public: + UsdUndoClearReferencesCommand(const PXR_NS::UsdPrim& prim); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdPrim _prim; +}; + +} // namespace USDUFE_NS_DEF + +#endif /* USD_UFE_CLEAR_REFERENCES_COMMAND */ diff --git a/lib/usdUfe/ufe/UsdUndoInsertChildCommand.h b/lib/usdUfe/ufe/UsdUndoInsertChildCommand.h index b786977431..3b3ebaab18 100644 --- a/lib/usdUfe/ufe/UsdUndoInsertChildCommand.h +++ b/lib/usdUfe/ufe/UsdUndoInsertChildCommand.h @@ -23,6 +23,7 @@ #include #include +#include namespace USDUFE_NS_DEF { diff --git a/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.cpp b/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.cpp new file mode 100644 index 0000000000..58b9469056 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.cpp @@ -0,0 +1,28 @@ +// +// 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 "UsdUndoSelectAfterCommand.h" + +namespace USDUFE_NS_DEF { + +Ufe::Selection getNewSelectionFromCommand(const Ufe::InsertChildCommand& cmd) +{ + Ufe::Selection newSelection; + newSelection.append(cmd.insertedChild()); + return newSelection; +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.h b/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.h new file mode 100644 index 0000000000..60dbfba4f7 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoSelectAfterCommand.h @@ -0,0 +1,88 @@ +// +// 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. +// +#ifndef UFE_USD_SELECT_AFTER_COMMAND +#define UFE_USD_SELECT_AFTER_COMMAND + +#include + +#include +#include +#include +#include +#include + +namespace USDUFE_NS_DEF { + +//! \brief Add post-command selection to another command. +template class UsdUndoSelectAfterCommand : public OTHER_COMMAND +{ +public: + using OtherCommand = OTHER_COMMAND; + using Ptr = std::shared_ptr>; + + // Bring in the base class constructors. + using OtherCommand::OtherCommand; + + ~UsdUndoSelectAfterCommand() override { } + + void execute() override + { + _previousSelection = *Ufe::GlobalSelection::get(); + OtherCommand::execute(); + // Note: each class that wish to be able to have the selection set after + // must provide an overload of this function. See for example the + // implementation for UsdUndoAddNewPrimCommand in its header file. + // It is usually a two-line function. + _newSelection = getNewSelectionFromCommand(*this); + setSelection(_newSelection); + } + + void undo() override + { + OtherCommand::undo(); + setSelection(_previousSelection); + } + + void redo() override + { + OtherCommand::redo(); + setSelection(_newSelection); + } + + template + static UsdUndoSelectAfterCommand::Ptr create(ARGS... args) + { + return std::make_shared>(args...); + } + +private: + static void setSelection(const Ufe::Selection& newSelection) + { + if (newSelection.empty()) + return; + Ufe::GlobalSelection::get()->replaceWith(newSelection); + } + + Ufe::Selection _previousSelection; + Ufe::Selection _newSelection; +}; + +//! \brief Retrieve the desired selection after the command has executed. +Ufe::Selection USDUFE_PUBLIC getNewSelectionFromCommand(const Ufe::InsertChildCommand& cmd); + +} // namespace USDUFE_NS_DEF + +#endif /* UFE_USD_SELECT_AFTER_COMMAND */ diff --git a/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.cpp b/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.cpp new file mode 100644 index 0000000000..651f08f7d7 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.cpp @@ -0,0 +1,42 @@ +// +// 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 "UsdUndoToggleActiveCommand.h" + +#include "private/UfeNotifGuard.h" + +namespace USDUFE_NS_DEF { + +UsdUndoToggleActiveCommand::UsdUndoToggleActiveCommand(const PXR_NS::UsdPrim& prim) + : _stage(prim.GetStage()) + , _primPath(prim.GetPath()) +{ +} + +void UsdUndoToggleActiveCommand::executeImplementation() +{ + if (!_stage) + return; + + PXR_NS::UsdPrim prim = _stage->GetPrimAtPath(_primPath); + if (!prim.IsValid()) + return; + + UsdUfe::InAddOrDeleteOperation ad; + prim.SetActive(!prim.IsActive()); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.h b/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.h new file mode 100644 index 0000000000..48da144aca --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoToggleActiveCommand.h @@ -0,0 +1,46 @@ +// +// 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. +// +#ifndef USD_UFE_TOGGLE_ACTIVE_COMMAND +#define USD_UFE_TOGGLE_ACTIVE_COMMAND + +#include +#include + +#include +#include +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Undoable command to toggle the active flag of a prim. +class USDUFE_PUBLIC UsdUndoToggleActiveCommand : public UsdUndoableCommand +{ +public: + UsdUndoToggleActiveCommand(const PXR_NS::UsdPrim& prim); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdStageWeakPtr _stage; + PXR_NS::SdfPath _primPath; +}; + +} // namespace USDUFE_NS_DEF + +#endif diff --git a/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.cpp b/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.cpp new file mode 100644 index 0000000000..3e16e94f64 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.cpp @@ -0,0 +1,39 @@ +// +// 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 "UsdUndoToggleInstanceableCommand.h" + +namespace USDUFE_NS_DEF { + +UsdUndoToggleInstanceableCommand::UsdUndoToggleInstanceableCommand(const PXR_NS::UsdPrim& prim) + : _stage(prim.GetStage()) + , _primPath(prim.GetPath()) +{ +} + +void UsdUndoToggleInstanceableCommand::executeImplementation() +{ + if (!_stage) + return; + + PXR_NS::UsdPrim prim = _stage->GetPrimAtPath(_primPath); + if (!prim.IsValid()) + return; + + prim.SetInstanceable(!prim.IsInstanceable()); +} + +} // namespace USDUFE_NS_DEF diff --git a/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.h b/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.h new file mode 100644 index 0000000000..427c9b40e2 --- /dev/null +++ b/lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.h @@ -0,0 +1,47 @@ +// +// 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. +// +#ifndef USD_UFE_TOGGLE_INSTANCEABLE_COMMAND +#define USD_UFE_TOGGLE_INSTANCEABLE_COMMAND + +#include +#include + +#include +#include +#include + +#include + +namespace USDUFE_NS_DEF { + +//! \brief Undoable command to toggle the instanceable flag of a prim. +class USDUFE_PUBLIC UsdUndoToggleInstanceableCommand + : public UsdUndoableCommand +{ +public: + UsdUndoToggleInstanceableCommand(const PXR_NS::UsdPrim& prim); + +protected: + void executeImplementation() override; + +private: + PXR_NS::UsdStageWeakPtr _stage; + PXR_NS::SdfPath _primPath; +}; + +} // namespace USDUFE_NS_DEF + +#endif diff --git a/test/lib/ufe/CMakeLists.txt b/test/lib/ufe/CMakeLists.txt index 16dcd6c60a..3b0da7a0ed 100644 --- a/test/lib/ufe/CMakeLists.txt +++ b/test/lib/ufe/CMakeLists.txt @@ -38,13 +38,16 @@ if(CMAKE_UFE_V2_FEATURES_AVAILABLE) testObject3d.py testRename.py testParentCmd.py + testPayloadCommands.py testPointInstances.py + testReferenceCommands.py testReorderCmd.py testRotateCmd.py testRotateCmdUndoRedo.py testRotatePivot.py testScaleCmd.py testSceneItem.py + testToggleCommands.py testTransform3dChainOfResponsibility.py testTransform3dTranslate.py testUIInfoHandler.py diff --git a/test/lib/ufe/testEditRouting.py b/test/lib/ufe/testEditRouting.py index c1ee5db6c2..b246492765 100644 --- a/test/lib/ufe/testEditRouting.py +++ b/test/lib/ufe/testEditRouting.py @@ -11,16 +11,7 @@ import unittest import usdUtils from pxr import UsdGeom - -##################################################################### -# -# Helper to compare strings. - -def filterUsdStr(usdSceneStr): - '''Remove empty lines and lines starting with pound character.''' - nonBlankLines = filter(None, [l.strip() for l in usdSceneStr.splitlines()]) - finalLines = [l for l in nonBlankLines if not l.startswith('#')] - return '\n'.join(finalLines) +from usdUtils import filterUsdStr ##################################################################### diff --git a/test/lib/ufe/testParentCmd.py b/test/lib/ufe/testParentCmd.py index 64e03d8671..74d0cfaaa4 100644 --- a/test/lib/ufe/testParentCmd.py +++ b/test/lib/ufe/testParentCmd.py @@ -21,6 +21,7 @@ import testUtils from testUtils import assertVectorAlmostEqual, assertVectorNotAlmostEqual import usdUtils +from usdUtils import filterUsdStr import mayaUsd.ufe @@ -34,12 +35,6 @@ import os import unittest -def filterUsdStr(usdSceneStr): - '''Remove empty lines and lines starting with pound character.''' - nonBlankLines = filter(None, [l.rstrip() for l in usdSceneStr.splitlines()]) - finalLines = [l for l in nonBlankLines if not l.startswith('#')] - return '\n'.join(finalLines) - def childrenNames(children): return [str(child.path().back()) for child in children] @@ -1389,7 +1384,7 @@ def firstSubLayer(context, routingData): # Check that layer B now has the parent overs. self.assertEqual(filterUsdStr(bSubLayer.ExportToString()), - 'over "C"\n{\n def Xform "B"\n {\n }\n}') + filterUsdStr('over "C"\n{\n def Xform "B"\n {\n }\n}')) finally: # Restore default edit router. mayaUsd.lib.restoreDefaultEditRouter('parent') diff --git a/test/lib/ufe/testPayloadCommands.py b/test/lib/ufe/testPayloadCommands.py new file mode 100644 index 0000000000..015d5c164a --- /dev/null +++ b/test/lib/ufe/testPayloadCommands.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python + +import fixturesUtils +from maya import cmds +from maya import standalone +import mayaUsd.ufe +import mayaUtils +import usdUfe +import ufe +import unittest +import usdUtils +import testUtils +from usdUtils import filterUsdStr + +from pxr import Usd + + +##################################################################### +# +# Tests + +class PayloadCommandsTestCase(unittest.TestCase): + 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): + self.assertTrue(self.pluginsLoaded) + + cmds.file(new=True, force=True) + import mayaUsd_createStageWithNewLayer + + # Create the following hierarchy: + # + # proxy shape + # |_ A + # |_ B + # + + psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + self.stage = mayaUsd.lib.GetPrim(psPathStr).GetStage() + self.stage.DefinePrim('/A', 'Xform') + self.stage.DefinePrim('/B', 'Xform') + + psPath = ufe.PathString.path(psPathStr) + psPathSegment = psPath.segments[0] + aPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/A')]) + bPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/B')]) + self.a = ufe.Hierarchy.createItem(aPath) + self.b = ufe.Hierarchy.createItem(bPath) + + cmds.select(clear=True) + + def testAddAndClearPayloadCommands(self): + ''' + Test add and clear payload commands. + ''' + prim = mayaUsd.ufe.ufePathToPrim("|stage1|stageShape1,/A") + + # Verify the initial state + self.assertFalse(prim.HasPayload()) + originalRootContents = filterUsdStr(self.stage.GetRootLayer().ExportToString()) + + # Verify add payload + payloadFile = testUtils.getTestScene('twoSpheres', 'sphere.usda') + cmd = usdUfe.AddPayloadCommand(prim, payloadFile, True) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertTrue(prim.HasPayload()) + + cmd.undo() + self.assertFalse(prim.HasPayload()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.redo() + self.assertTrue(prim.HasPayload()) + + # Verify clear payload + cmd = usdUfe.ClearPayloadsCommand(prim) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertFalse(prim.HasPayload()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.undo() + self.assertTrue(prim.HasPayload()) + + cmd.redo() + self.assertFalse(prim.HasPayload()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + def testLoadAndUnloadPayloadCommands(self): + ''' + Test unload and load payload commands. + ''' + primUfePath = "|stage1|stageShape1,/A" + prim = mayaUsd.ufe.ufePathToPrim(primUfePath) + + # Verify initial state + self.assertFalse(prim.HasPayload()) + + payloadFile = testUtils.getTestScene('twoSpheres', 'sphere.usda') + cmd = usdUfe.AddPayloadCommand(prim, payloadFile, True) + self.assertIsNotNone(cmd) + + # Verify state after add payload + cmd.execute() + self.assertTrue(prim.HasPayload()) + self.assertTrue(prim.IsLoaded()) + + # Verify unload payload + cmd = mayaUsd.lib.UnloadPayloadCommand(prim) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertFalse(prim.IsLoaded()) + + cmd.undo() + self.assertTrue(prim.IsLoaded()) + + cmd.redo() + self.assertFalse(prim.IsLoaded()) + + # Verify load payload + cmd = mayaUsd.lib.LoadPayloadCommand(prim, Usd.LoadWithDescendants) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertTrue(prim.IsLoaded()) + + cmd.undo() + self.assertFalse(prim.IsLoaded()) + + cmd.redo() + self.assertTrue(prim.IsLoaded()) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/test/lib/ufe/testReferenceCommands.py b/test/lib/ufe/testReferenceCommands.py new file mode 100644 index 0000000000..d5bd08d704 --- /dev/null +++ b/test/lib/ufe/testReferenceCommands.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +import fixturesUtils +from maya import cmds +from maya import standalone +import mayaUsd.ufe +import mayaUtils +import usdUfe +import ufe +import unittest +import usdUtils +import testUtils +from usdUtils import filterUsdStr + +##################################################################### +# +# Tests + +class ReferenceCommandsTestCase(unittest.TestCase): + 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): + self.assertTrue(self.pluginsLoaded) + + cmds.file(new=True, force=True) + import mayaUsd_createStageWithNewLayer + + # Create the following hierarchy: + # + # proxy shape + # |_ A + # |_ B + # + + psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + self.stage = mayaUsd.lib.GetPrim(psPathStr).GetStage() + self.stage.DefinePrim('/A', 'Xform') + self.stage.DefinePrim('/B', 'Xform') + + psPath = ufe.PathString.path(psPathStr) + psPathSegment = psPath.segments[0] + aPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/A')]) + bPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/B')]) + self.a = ufe.Hierarchy.createItem(aPath) + self.b = ufe.Hierarchy.createItem(bPath) + + cmds.select(clear=True) + + def testAddAndClearReferenceCommands(self): + ''' + Test add and clear reference commands. + ''' + # Get the session layer + prim = mayaUsd.ufe.ufePathToPrim("|stage1|stageShape1,/A") + + self.assertFalse(prim.HasAuthoredReferences()) + originalRootContents = filterUsdStr(self.stage.GetRootLayer().ExportToString()) + + referencedFile = testUtils.getTestScene('twoSpheres', 'sphere.usda') + cmd = usdUfe.AddReferenceCommand(prim, referencedFile, True) + + cmd.execute() + self.assertTrue(prim.HasAuthoredReferences()) + + cmd.undo() + self.assertFalse(prim.HasAuthoredReferences()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.redo() + self.assertTrue(prim.HasAuthoredReferences()) + + cmd = usdUfe.ClearReferencesCommand(prim) + + cmd.execute() + self.assertFalse(prim.HasAuthoredReferences()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.undo() + self.assertTrue(prim.HasAuthoredReferences()) + + cmd.redo() + self.assertFalse(prim.HasAuthoredReferences()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/test/lib/ufe/testToggleCommands.py b/test/lib/ufe/testToggleCommands.py new file mode 100644 index 0000000000..efbea3d580 --- /dev/null +++ b/test/lib/ufe/testToggleCommands.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python + +import fixturesUtils +from maya import cmds +from maya import standalone +import mayaUsd.ufe +import mayaUtils +import usdUfe +import ufe +import unittest +import usdUtils +from usdUtils import filterUsdStr + +from pxr import Usd + + +##################################################################### +# +# Tests + +class ToggleCommandsTestCase(unittest.TestCase): + 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): + self.assertTrue(self.pluginsLoaded) + + cmds.file(new=True, force=True) + import mayaUsd_createStageWithNewLayer + + # Create the following hierarchy: + # + # proxy shape + # |_ A + # |_ B + # + + psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + self.stage = mayaUsd.lib.GetPrim(psPathStr).GetStage() + self.stage.DefinePrim('/A', 'Xform') + self.stage.DefinePrim('/B', 'Xform') + + psPath = ufe.PathString.path(psPathStr) + psPathSegment = psPath.segments[0] + aPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/A')]) + bPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/B')]) + self.a = ufe.Hierarchy.createItem(aPath) + self.b = ufe.Hierarchy.createItem(bPath) + + cmds.select(clear=True) + + def testToggleActiveCommand(self): + ''' + Test toggle active commands. + ''' + prim = mayaUsd.ufe.ufePathToPrim("|stage1|stageShape1,/A") + + self.assertTrue(prim.IsActive()) + originalRootContents = filterUsdStr(self.stage.GetRootLayer().ExportToString()) + + cmd = usdUfe.ToggleActiveCommand(prim) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertFalse(prim.IsActive()) + + cmd.undo() + self.assertTrue(prim.IsActive()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.redo() + self.assertFalse(prim.IsActive()) + + def testToggleInstanceableCommand(self): + ''' + Test toggle instanceable commands. + ''' + prim = mayaUsd.ufe.ufePathToPrim("|stage1|stageShape1,/A") + + self.assertFalse(prim.IsInstanceable()) + originalRootContents = filterUsdStr(self.stage.GetRootLayer().ExportToString()) + + cmd = usdUfe.ToggleInstanceableCommand(prim) + self.assertIsNotNone(cmd) + + cmd.execute() + self.assertTrue(prim.IsInstanceable()) + + cmd.undo() + self.assertFalse(prim.IsInstanceable()) + self.assertEqual(originalRootContents, filterUsdStr(self.stage.GetRootLayer().ExportToString())) + + cmd.redo() + self.assertTrue(prim.IsInstanceable()) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/test/lib/ufe/testVisibilityCmd.py b/test/lib/ufe/testVisibilityCmd.py index 02a7abf8af..ef278c7796 100644 --- a/test/lib/ufe/testVisibilityCmd.py +++ b/test/lib/ufe/testVisibilityCmd.py @@ -8,14 +8,9 @@ import ufe import unittest import usdUtils +from usdUtils import filterUsdStr from pxr import UsdGeom -def filterUsdStr(usdSceneStr): - '''Remove empty lines and lines starting with pound character.''' - nonBlankLines = filter(None, [l.rstrip() for l in usdSceneStr.splitlines()]) - finalLines = [l for l in nonBlankLines if not l.startswith('#')] - return '\n'.join(finalLines) - def getSessionLayer(context, routingData): prim = context.get('prim') if prim is None: @@ -106,7 +101,7 @@ def testEditRouterForCmd(self): # Check that correct visibility changes were written to the session layer self.assertEqual(filterUsdStr(sessionLayer.ExportToString()), - 'over "B"\n{\n token visibility = "invisible"\n}') + filterUsdStr('over "B"\n{\n token visibility = "invisible"\n}')) def testEditRouterForCmdShowHideMultipleSelection(self): ''' @@ -130,7 +125,7 @@ def testEditRouterForCmdShowHideMultipleSelection(self): # Check visibility was written to the session layer. self.assertEqual(filterUsdStr(sessionLayer.ExportToString()), - 'over "A"\n{\n token visibility = "invisible"\n}') + filterUsdStr('over "A"\n{\n token visibility = "invisible"\n}')) # Hiding a multiple selection with already-hidden A must not error. # Careful: hide command clears the selection, so must add /A again. @@ -141,7 +136,7 @@ def testEditRouterForCmdShowHideMultipleSelection(self): # Check visibility was written to the session layer. self.assertEqual(filterUsdStr(sessionLayer.ExportToString()), - 'over "A"\n{\n token visibility = "invisible"\n}\nover "B"\n{\n token visibility = "invisible"\n}') + filterUsdStr('over "A"\n{\n token visibility = "invisible"\n}\nover "B"\n{\n token visibility = "invisible"\n}')) if __name__ == '__main__': diff --git a/test/testUtils/usdUtils.py b/test/testUtils/usdUtils.py index 7241ada124..8074448501 100644 --- a/test/testUtils/usdUtils.py +++ b/test/testUtils/usdUtils.py @@ -234,3 +234,10 @@ def createLayeredStage(layersCount = 3): return (psPathStr, psPath, ps, layers) +def filterUsdStr(usdSceneStr): + '''Remove empty lines and lines starting with pound character.''' + nonBlankLines = filter(None, [l.strip() for l in usdSceneStr.splitlines()]) + finalLines = [l for l in nonBlankLines if not l.startswith('#')] + return '\n'.join(finalLines) + +