Skip to content

Commit

Permalink
Merge pull request #942 from Autodesk/sabrih/MAYA-106089/usd_undo_ser…
Browse files Browse the repository at this point in the history
…vice_support

MAYA-106089: Undo/Redo support for USD data model.
  • Loading branch information
Krystian Ligenza authored Nov 30, 2020
2 parents 192ef72 + 0c2794a commit 5ba3e43
Show file tree
Hide file tree
Showing 31 changed files with 1,735 additions and 24 deletions.
2 changes: 2 additions & 0 deletions cmake/compiler_config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ set(MSVC_FLAGS
/wd4506
/wd4996
/wd4180
# exporting STL classes
/wd4251
)

set(MSVC_DEFINITIONS
Expand Down
Binary file added doc/images/ufe_commands.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/mayaUsd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ add_subdirectory(resources)
if(UFE_FOUND)
add_subdirectory(ufe)
endif()
add_subdirectory(undo)
add_subdirectory(utils)

if(BUILD_HDMAYA)
Expand Down
4 changes: 3 additions & 1 deletion lib/mayaUsd/base/debugCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ TF_DEBUG_CODES(
PXRUSDMAYA_DIAGNOSTICS,
PXRUSDMAYA_TRANSLATORS,
USDMAYA_PROXYSHAPEBASE,
USDMAYA_PROXYACCESSOR);
USDMAYA_PROXYACCESSOR,
USDMAYA_UNDOSTACK,
USDMAYA_UNDOSTATEDELEGATE);

PXR_NAMESPACE_CLOSE_SCOPE

Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ target_sources(${PYTHON_TARGET_NAME}
wrapUserTaggedAttribute.cpp
wrapWriteUtil.cpp
wrapXformStack.cpp
wrapUsdUndoManager.cpp
)

# -----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ TF_WRAP_MODULE
TF_WRAP(UserTaggedAttribute);
TF_WRAP(WriteUtil);
TF_WRAP(XformStack);
TF_WRAP(UsdUndoManager);
}
89 changes: 89 additions & 0 deletions lib/mayaUsd/python/wrapUsdUndoManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// Copyright 2020 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 <mayaUsd/undo/UsdUndoBlock.h>
#include <mayaUsd/undo/UsdUndoManager.h>
#include <mayaUsd/undo/UsdUndoableItem.h>

#include <pxr/base/tf/pyContainerConversions.h>
#include <pxr/base/tf/pyNoticeWrapper.h>
#include <pxr/pxr.h>
#include <pxr/usd/sdf/layer.h>

#include <boost/python.hpp>

#include <memory>

using namespace boost::python;

PXR_NAMESPACE_USING_DIRECTIVE

namespace {
class PythonUndoBlock
{
public:
PythonUndoBlock()
: _block(nullptr)
{
}

~PythonUndoBlock() { }

void enter()
{
if (!TF_VERIFY(_block == nullptr)) {
return;
}
_block = std::make_unique<MayaUsd::UsdUndoBlock>();
}

void exit(object, object, object)
{
if (!TF_VERIFY(_block != nullptr)) {
return;
}
_block.reset();
}

private:
std::unique_ptr<MayaUsd::UsdUndoBlock> _block;
};

void _trackLayerStates(const SdfLayerHandle& layer)
{
MayaUsd::UsdUndoManager::instance().trackLayerStates(layer);
}

} // namespace

void wrapUsdUndoManager()
{
// UsdUndoManager
{
typedef MayaUsd::UsdUndoManager This;
class_<This, boost::noncopyable>("UsdUndoManager", no_init)
.def("trackLayerStates", &_trackLayerStates)
.staticmethod("trackLayerStates");
}

// UsdUndoBlock
{
typedef PythonUndoBlock This;
class_<This, boost::noncopyable>("UsdUndoBlock", init<>())
.def("__enter__", &This::enter)
.def("__exit__", &This::exit);
}
}
39 changes: 37 additions & 2 deletions lib/mayaUsd/ufe/StagesSubject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <mayaUsd/ufe/ProxyShapeHandler.h>
#include <mayaUsd/ufe/UsdStageMap.h>
#include <mayaUsd/ufe/Utils.h>
#if UFE_PREVIEW_VERSION_NUM >= 2029
#include <mayaUsd/undo/UsdUndoManager.h>
#endif

#include <pxr/usd/usdGeom/tokens.h>
#include <pxr/usd/usdGeom/xformOp.h>
Expand Down Expand Up @@ -165,7 +168,11 @@ void StagesSubject::afterOpen()
std::for_each(
std::begin(fStageListeners),
std::end(fStageListeners),
[](StageListenerMap::value_type element) { TfNotice::Revoke(element.second); });
[](StageListenerMap::value_type element) {
for (auto& noticeKey : element.second) {
TfNotice::Revoke(noticeKey);
}
});
fStageListeners.clear();

// Set up our stage to proxy shape UFE path (and reverse)
Expand Down Expand Up @@ -294,8 +301,28 @@ void StagesSubject::stageChanged(
}
}

#if UFE_PREVIEW_VERSION_NUM >= 2029
void StagesSubject::stageEditTargetChanged(
UsdNotice::StageEditTargetChanged const& notice,
UsdStageWeakPtr const& sender)
{
// Track the edit target layer's state
UsdUndoManager::instance().trackLayerStates(notice.GetStage()->GetEditTarget().GetLayer());
}
#endif

void StagesSubject::onStageSet(const MayaUsdProxyStageSetNotice& notice)
{
#if UFE_PREVIEW_VERSION_NUM >= 2029
auto noticeStage = notice.GetStage();
// Check if stage received from notice is valid. We could have cases where a ProxyShape has an
// invalid stage.
if (noticeStage) {
// Track the edit target layer's state
UsdUndoManager::instance().trackLayerStates(noticeStage->GetEditTarget().GetLayer());
}
#endif

// Handle re-entrant onStageSet
bool expectedState = false;
if (stageSetGuardCount.compare_exchange_strong(expectedState, true)) {
Expand All @@ -305,8 +332,16 @@ void StagesSubject::onStageSet(const MayaUsdProxyStageSetNotice& notice)

StagesSubject::Ptr me(this);
for (auto stage : ProxyShapeHandler::getAllStages()) {
fStageListeners[stage] = TfNotice::Register(me, &StagesSubject::stageChanged, stage);

NoticeKeys noticeKeys;

noticeKeys[0] = TfNotice::Register(me, &StagesSubject::stageChanged, stage);
#if UFE_PREVIEW_VERSION_NUM >= 2029
noticeKeys[1] = TfNotice::Register(me, &StagesSubject::stageEditTargetChanged, stage);
#endif
fStageListeners[stage] = noticeKeys;
}

stageSetGuardCount = false;
}
}
Expand Down
18 changes: 16 additions & 2 deletions lib/mayaUsd/ufe/StagesSubject.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,30 @@ class MAYAUSD_CORE_PUBLIC StagesSubject : public TfWeakBase
//! Call the stageChanged() methods on stage observers.
void stageChanged(UsdNotice::ObjectsChanged const& notice, UsdStageWeakPtr const& sender);

#if UFE_PREVIEW_VERSION_NUM >= 2029
//! Call the stageEditTargetChanged() methods on stage observers.
void stageEditTargetChanged(
UsdNotice::StageEditTargetChanged const& notice,
UsdStageWeakPtr const& sender);
#endif

private:
// Notice listener method for proxy stage set
void onStageSet(const MayaUsdProxyStageSetNotice& notice);

// Notice listener method for proxy stage invalidate.
void onStageInvalidate(const MayaUsdProxyStageInvalidateNotice& notice);

// Array of Notice::Key for registered listener
#if UFE_PREVIEW_VERSION_NUM >= 2029
using NoticeKeys = std::array<TfNotice::Key, 2>;
#else
using NoticeKeys = std::array<TfNotice::Key, 1>;
#endif

// Map of per-stage listeners, indexed by stage.
typedef TfHashMap<UsdStageWeakPtr, TfNotice::Key, TfHash> StageListenerMap;
StageListenerMap fStageListeners;
typedef TfHashMap<UsdStageWeakPtr, NoticeKeys, TfHash> StageListenerMap;
StageListenerMap fStageListeners;

bool fBeforeNewCallback = false;

Expand Down
35 changes: 34 additions & 1 deletion lib/mayaUsd/ufe/UsdUndoAddNewPrimCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include <mayaUsd/ufe/Global.h>
#include <mayaUsd/ufe/Utils.h>

#if UFE_PREVIEW_VERSION_NUM >= 2029
#include <mayaUsd/undo/UsdUndoBlock.h>
#endif

namespace {

Ufe::Path appendToPath(const Ufe::Path& path, const std::string& name)
Expand Down Expand Up @@ -72,6 +76,35 @@ UsdUndoAddNewPrimCommand::UsdUndoAddNewPrimCommand(
}
}

#if UFE_PREVIEW_VERSION_NUM >= 2029
void UsdUndoAddNewPrimCommand::execute()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

UsdUndoBlock undoBlock(&_undoableItem);

if (_stage) {
MayaUsd::ufe::InAddOrDeleteOperation ad;
auto prim = _stage->DefinePrim(_primPath, _primToken);
if (!prim.IsValid())
TF_RUNTIME_ERROR("Failed to create new prim type: %s", _primToken.GetText());
}
}

void UsdUndoAddNewPrimCommand::undo()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

_undoableItem.undo();
}

void UsdUndoAddNewPrimCommand::redo()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

_undoableItem.redo();
}
#else
void UsdUndoAddNewPrimCommand::undo()
{
if (_stage) {
Expand All @@ -89,6 +122,7 @@ void UsdUndoAddNewPrimCommand::redo()
TF_RUNTIME_ERROR("Failed to create new prim type: %s", _primToken.GetText());
}
}
#endif

const Ufe::Path& UsdUndoAddNewPrimCommand::newUfePath() const { return _newUfePath; }

Expand All @@ -101,7 +135,6 @@ PXR_NS::UsdPrim UsdUndoAddNewPrimCommand::newPrim() const
return _stage->GetPrimAtPath(_primPath);
}

/*static*/
UsdUndoAddNewPrimCommand::Ptr UsdUndoAddNewPrimCommand::create(
const UsdSceneItem::Ptr& usdSceneItem,
const std::string& name,
Expand Down
11 changes: 10 additions & 1 deletion lib/mayaUsd/ufe/UsdUndoAddNewPrimCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include <mayaUsd/base/api.h>
#include <mayaUsd/ufe/UsdSceneItem.h>

#if UFE_PREVIEW_VERSION_NUM >= 2029
#include <mayaUsd/undo/UsdUndoableItem.h>
#endif

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

Expand All @@ -37,7 +41,9 @@ class MAYAUSD_CORE_PUBLIC UsdUndoAddNewPrimCommand : public Ufe::UndoableCommand
const UsdSceneItem::Ptr& usdSceneItem,
const std::string& name,
const std::string& type);

#if UFE_PREVIEW_VERSION_NUM >= 2029
void execute() override;
#endif
void undo() override;
void redo() override;

Expand All @@ -52,6 +58,9 @@ class MAYAUSD_CORE_PUBLIC UsdUndoAddNewPrimCommand : public Ufe::UndoableCommand
PXR_NS::SdfPath _primPath;
PXR_NS::TfToken _primToken;
Ufe::Path _newUfePath;
#if UFE_PREVIEW_VERSION_NUM >= 2029
UsdUndoableItem _undoableItem;
#endif

}; // UsdUndoAddNewPrimCommand

Expand Down
37 changes: 32 additions & 5 deletions lib/mayaUsd/ufe/UsdUndoDeleteCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,63 @@

#include "private/UfeNotifGuard.h"

#if UFE_PREVIEW_VERSION_NUM >= 2029
#include <mayaUsd/undo/UsdUndoBlock.h>
#endif

namespace MAYAUSD_NS_DEF {
namespace ufe {

UsdUndoDeleteCommand::UsdUndoDeleteCommand(const UsdPrim& prim)
: Ufe::UndoableCommand()
#if UFE_PREVIEW_VERSION_NUM >= 2029
, _prim(prim)
#else
, fPrim(prim)
#endif
{
}

UsdUndoDeleteCommand::~UsdUndoDeleteCommand() { }

/*static*/
UsdUndoDeleteCommand::Ptr UsdUndoDeleteCommand::create(const UsdPrim& prim)
{
return std::make_shared<UsdUndoDeleteCommand>(prim);
}

#if UFE_PREVIEW_VERSION_NUM >= 2029
void UsdUndoDeleteCommand::execute()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

UsdUndoBlock undoBlock(&_undoableItem);
_prim.SetActive(false);
}

void UsdUndoDeleteCommand::undo()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

_undoableItem.undo();
}

void UsdUndoDeleteCommand::redo()
{
MayaUsd::ufe::InAddOrDeleteOperation ad;

_undoableItem.redo();
}
#else
void UsdUndoDeleteCommand::perform(bool state)
{
MayaUsd::ufe::InAddOrDeleteOperation ad;
fPrim.SetActive(state);
}

//------------------------------------------------------------------------------
// UsdUndoDeleteCommand overrides
//------------------------------------------------------------------------------

void UsdUndoDeleteCommand::undo() { perform(true); }

void UsdUndoDeleteCommand::redo() { perform(false); }
#endif

} // namespace ufe
} // namespace MAYAUSD_NS_DEF
Loading

0 comments on commit 5ba3e43

Please sign in to comment.