Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAYA-129538 move commands out of context op implementation #3179

Merged
merged 6 commits into from
Jul 4, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
MAYA-129538 move commands out of context op implementation
Move the commands that implement the menu items in their own file as reusable
UFE commands.

- Fix undo of add reference and payload that were adding a delete to the prim
  lists instead of reverting the addition.
- Wrap all move commands in Python
- Add unit test for all commands that were moved into their own file.
- Chang all commands to use UsdUndoableItem and UsdUndoBlock to ensure perfect
  undo.
pierrebai-adsk committed Jun 20, 2023
commit fb5f1cdf2c394ded32e911085a940d9e69c89a35
1 change: 1 addition & 0 deletions lib/mayaUsd/python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ target_sources(${PYTHON_TARGET_NAME}
wrapAdaptor.cpp
wrapBlockSceneModificationContext.cpp
wrapColorSpace.cpp
wrapCommands.cpp
wrapConverter.cpp
wrapDiagnosticDelegate.cpp
wrapMeshWriteUtils.cpp
1 change: 1 addition & 0 deletions lib/mayaUsd/python/module.cpp
Original file line number Diff line number Diff line change
@@ -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);
56 changes: 56 additions & 0 deletions lib/mayaUsd/python/wrapCommands.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// Copyright 2021 Autodesk
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved
//
// 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 <mayaUsd/ufe/UsdUndoPayloadCommand.h>

#include <boost/python.hpp>
#include <boost/python/def.hpp>

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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("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);
}
}
2 changes: 2 additions & 0 deletions lib/mayaUsd/ufe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
362 changes: 23 additions & 339 deletions lib/mayaUsd/ufe/UsdContextOps.cpp

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions lib/mayaUsd/ufe/UsdUndoPayloadCommand.cpp
Original file line number Diff line number Diff line change
@@ -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 <mayaUsd/nodes/proxyShapeStageExtraData.h>

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
69 changes: 69 additions & 0 deletions lib/mayaUsd/ufe/UsdUndoPayloadCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Copyright 2019 Autodesk
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved
//
// 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
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved

#include <mayaUsd/base/api.h>

#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/payloads.h>
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/stage.h>

#include <ufe/undoableCommand.h>

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
1 change: 1 addition & 0 deletions lib/usdUfe/python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ target_sources(${PYTHON_TARGET_NAME}
wrapGlobal.cpp
wrapTokens.cpp
wrapUtils.cpp
wrapCommands.cpp
)

# -----------------------------------------------------------------------------
1 change: 1 addition & 0 deletions lib/usdUfe/python/module.cpp
Original file line number Diff line number Diff line change
@@ -24,4 +24,5 @@ TF_WRAP_MODULE
TF_WRAP(Global);
TF_WRAP(Tokens);
TF_WRAP(Utils);
TF_WRAP(Commands);
}
114 changes: 114 additions & 0 deletions lib/usdUfe/python/wrapCommands.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// Copyright 2021 Autodesk
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved
//
// 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 <usdUfe/ufe/UsdUndoAddPayloadCommand.h>
#include <usdUfe/ufe/UsdUndoAddReferenceCommand.h>
#include <usdUfe/ufe/UsdUndoClearPayloadsCommand.h>
#include <usdUfe/ufe/UsdUndoClearReferencesCommand.h>
#include <usdUfe/ufe/UsdUndoToggleActiveCommand.h>
#include <usdUfe/ufe/UsdUndoToggleInstanceableCommand.h>

#include <boost/python.hpp>
#include <boost/python/def.hpp>

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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("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_<This, boost::noncopyable>("ToggleInstanceableCommand", no_init)
.def("__init__", make_constructor(ToggleInstanceableCommandInit))
.def("execute", &UsdUfe::UsdUndoToggleInstanceableCommand::execute)
.def("undo", &UsdUfe::UsdUndoToggleInstanceableCommand::undo)
.def("redo", &UsdUfe::UsdUndoToggleInstanceableCommand::redo);
}
}
13 changes: 13 additions & 0 deletions lib/usdUfe/ufe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -21,10 +21,16 @@ 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
UsdUndoSetKindCommand.cpp
UsdUndoToggleActiveCommand.cpp
UsdUndoToggleInstanceableCommand.cpp
UsdUndoVisibleCommand.cpp
)
endif()
@@ -56,10 +62,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()
7 changes: 7 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.cpp
Original file line number Diff line number Diff line change
@@ -145,4 +145,11 @@ UsdUndoAddNewPrimCommand::Ptr UsdUndoAddNewPrimCommand::create(
return std::make_shared<UsdUndoAddNewPrimCommand>(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
5 changes: 5 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddNewPrimCommand.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
#include <usdUfe/undo/UsdUndoableItem.h>

#include <ufe/path.h>
#include <ufe/selection.h>
#include <ufe/undoableCommand.h>

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);
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved

} // namespace USDUFE_NS_DEF

#endif
51 changes: 51 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddPayloadCommand.cpp
Original file line number Diff line number Diff line change
@@ -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 <pxr/base/tf/stringUtils.h>
#include <pxr/usd/sdf/path.h>

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
52 changes: 52 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddPayloadCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/usd/payloads.h>
#include <pxr/usd/usd/prim.h>

#include <ufe/undoableCommand.h>

#include <string>

namespace USDUFE_NS_DEF {

//! \brief Command to add a payload to a prim.
class USDUFE_PUBLIC UsdUndoAddPayloadCommand : public UsdUndoableCommand<Ufe::UndoableCommand>
{
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 */
50 changes: 50 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddReferenceCommand.cpp
Original file line number Diff line number Diff line change
@@ -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 <pxr/base/tf/stringUtils.h>
#include <pxr/usd/sdf/path.h>

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
52 changes: 52 additions & 0 deletions lib/usdUfe/ufe/UsdUndoAddReferenceCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/references.h>

#include <ufe/undoableCommand.h>

#include <string>

namespace USDUFE_NS_DEF {

//! \brief Command to add a reference to a prim.
class USDUFE_PUBLIC UsdUndoAddReferenceCommand : public UsdUndoableCommand<Ufe::UndoableCommand>
{
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 */
36 changes: 36 additions & 0 deletions lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.cpp
Original file line number Diff line number Diff line change
@@ -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 <pxr/usd/usd/payloads.h>

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
43 changes: 43 additions & 0 deletions lib/usdUfe/ufe/UsdUndoClearPayloadsCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/usd/prim.h>

#include <ufe/undoableCommand.h>

namespace USDUFE_NS_DEF {

//! \brief Command to clear (remove all) payloads from a prim.
class USDUFE_PUBLIC UsdUndoClearPayloadsCommand : public UsdUndoableCommand<Ufe::UndoableCommand>
{
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 */
36 changes: 36 additions & 0 deletions lib/usdUfe/ufe/UsdUndoClearReferencesCommand.cpp
Original file line number Diff line number Diff line change
@@ -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 <pxr/usd/usd/references.h>

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
43 changes: 43 additions & 0 deletions lib/usdUfe/ufe/UsdUndoClearReferencesCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/usd/prim.h>

#include <ufe/undoableCommand.h>

namespace USDUFE_NS_DEF {

//! \brief Command to clear (remove all) references from a prim.
class USDUFE_PUBLIC UsdUndoClearReferencesCommand : public UsdUndoableCommand<Ufe::UndoableCommand>
{
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 */
7 changes: 7 additions & 0 deletions lib/usdUfe/ufe/UsdUndoInsertChildCommand.cpp
Original file line number Diff line number Diff line change
@@ -333,4 +333,11 @@ void UsdUndoInsertChildCommand::redo()
_ufeDstItem = sendReparentNotification(_ufeSrcPath, _ufeDstPath);
}

Ufe::Selection USDUFE_PUBLIC getNewSelectionFromCommand(const Ufe::InsertChildCommand& cmd)
{
Ufe::Selection newSelection;
newSelection.append(cmd.insertedChild());
return newSelection;
}

} // namespace USDUFE_NS_DEF
1 change: 1 addition & 0 deletions lib/usdUfe/ufe/UsdUndoInsertChildCommand.h
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
#include <pxr/usd/usd/prim.h>

#include <ufe/hierarchy.h>
#include <ufe/selection.h>

namespace USDUFE_NS_DEF {

87 changes: 87 additions & 0 deletions lib/usdUfe/ufe/UsdUndoSelectAfterCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// 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 <usdUfe/ufe/UsdUndoAddNewPrimCommand.h>
#include <usdUfe/ufe/UsdUndoInsertChildCommand.h>

#include <ufe/globalSelection.h>
#include <ufe/selection.h>
#include <ufe/undoableCommand.h>

namespace USDUFE_NS_DEF {

//! \brief Add post-command selection to another command.
template <class OTHER_COMMAND> class UsdUndoSelectAfterCommand : public OTHER_COMMAND
{
public:
using OtherCommand = OTHER_COMMAND;
using Ptr = std::shared_ptr<UsdUndoSelectAfterCommand<OtherCommand>>;

// 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 <class... ARGS>
static UsdUndoSelectAfterCommand<OtherCommand>::Ptr create(ARGS... args)
{
return std::make_shared<UsdUndoSelectAfterCommand<OtherCommand>>(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);
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved

} // namespace USDUFE_NS_DEF

#endif /* UFE_USD_SELECT_AFTER_COMMAND */
42 changes: 42 additions & 0 deletions lib/usdUfe/ufe/UsdUndoToggleActiveCommand.cpp
Original file line number Diff line number Diff line change
@@ -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
46 changes: 46 additions & 0 deletions lib/usdUfe/ufe/UsdUndoToggleActiveCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/stage.h>

#include <ufe/undoableCommand.h>

namespace USDUFE_NS_DEF {

//! \brief Undoable command to toggle the active flag of a prim.
class USDUFE_PUBLIC UsdUndoToggleActiveCommand : public UsdUndoableCommand<Ufe::UndoableCommand>
{
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
39 changes: 39 additions & 0 deletions lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.cpp
Original file line number Diff line number Diff line change
@@ -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
47 changes: 47 additions & 0 deletions lib/usdUfe/ufe/UsdUndoToggleInstanceableCommand.h
Original file line number Diff line number Diff line change
@@ -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 <usdUfe/base/api.h>
#include <usdUfe/ufe/UsdUndoableCommand.h>

#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/stage.h>

#include <ufe/undoableCommand.h>

namespace USDUFE_NS_DEF {

//! \brief Undoable command to toggle the instanceable flag of a prim.
class USDUFE_PUBLIC UsdUndoToggleInstanceableCommand
: public UsdUndoableCommand<Ufe::UndoableCommand>
{
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
3 changes: 3 additions & 0 deletions test/lib/ufe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
157 changes: 157 additions & 0 deletions test/lib/ufe/testPayloadCommands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/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 pxr import Usd

#####################################################################
#
# 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)


#####################################################################
#
# 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)
106 changes: 106 additions & 0 deletions test/lib/ufe/testReferenceCommands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/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

#####################################################################
#
# 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)
pierrebai-adsk marked this conversation as resolved.
Show resolved Hide resolved


#####################################################################
#
# 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)
117 changes: 117 additions & 0 deletions test/lib/ufe/testToggleCommands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/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 pxr import Usd

#####################################################################
#
# 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)


#####################################################################
#
# 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)