Skip to content

Commit

Permalink
Merge pull request #3625 from Autodesk/bailp/EMSUSD-1017/fix-multi-re…
Browse files Browse the repository at this point in the history
…vert-crash

EMSUSD-1017 Fix reverting multiple files
  • Loading branch information
seando-adsk authored Feb 22, 2024
2 parents 1b7ce9c + 31620d7 commit f8c1d93
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 19 deletions.
45 changes: 45 additions & 0 deletions lib/usd/ui/layerEditor/abstractCommandHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,53 @@ class AbstractCommandHook
// or has an owned root
virtual bool isProxyShapeSharedStage(const std::string& proxyShapePath) = 0;

// Increase the count tracking if command executions are delayed.
void increaseDelayedCommands() { _delayCount += 1; }

// Decrease the count tracking if command executions are delayed.
void decreaseDelayedCommands()
{
_delayCount -= 1;
if (!areCommandsDelayed())
executeDelayedCommands();
}

// Verify if commands are currently delayed.
bool areCommandsDelayed() const { return _delayCount > 0; }

protected:
virtual void executeDelayedCommands() = 0;

SessionState* _sessionState;
int _delayCount { 0 };
};

/**
* @brief When executing multiple commands, it may sometimes be necessary to delay.
* the execution until all commands are issued. For example, when processing
* multiple elements in the slection, but the command itself might change the
* selection.
*/
class DelayAbstractCommandHook
{
public:
DelayAbstractCommandHook(AbstractCommandHook& hook)
: _hook(hook)
{
_hook.increaseDelayedCommands();
}

~DelayAbstractCommandHook()
{
try {
_hook.decreaseDelayedCommands();
} catch (const std::exception&) {
// Ignore exceptions in destructor.
}
}

private:
AbstractCommandHook& _hook;
};

class UndoContext
Expand Down
9 changes: 9 additions & 0 deletions lib/usd/ui/layerEditor/layerTreeView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ LayerItemVector LayerTreeView::getSelectedLayerItems() const

void LayerTreeView::onAddParentLayer(const QString& undoName) const
{
DelayAbstractCommandHook delayed(*_model->sessionState()->commandHook());

auto selection = getSelectedLayerItems();

CallMethodParams params;
Expand Down Expand Up @@ -322,6 +324,8 @@ void LayerTreeView::onAddParentLayer(const QString& undoName) const

void LayerTreeView::onMuteLayer(const QString& undoName) const
{
DelayAbstractCommandHook delayed(*_model->sessionState()->commandHook());

auto selection = getSelectedLayerItems();

CallMethodParams params;
Expand All @@ -339,6 +343,7 @@ void LayerTreeView::onMuteLayer(const QString& undoName) const

void LayerTreeView::onLockLayer(const QString& undoName) const
{
DelayAbstractCommandHook delayed(*_model->sessionState()->commandHook());

auto selection = getSelectedLayerItems();

Expand All @@ -357,6 +362,8 @@ void LayerTreeView::onLockLayer(const QString& undoName) const

void LayerTreeView::callMethodOnSelection(const QString& undoName, simpleLayerMethod method)
{
DelayAbstractCommandHook delayed(*_model->sessionState()->commandHook());

CallMethodParams params;
auto selection = getSelectedLayerItems();
params.selection = &selection;
Expand Down Expand Up @@ -486,6 +493,8 @@ void LayerTreeView::mouseReleaseEvent(QMouseEvent* event)

void LayerTreeView::keyPressEvent(QKeyEvent* event)
{
DelayAbstractCommandHook delayed(*_model->sessionState()->commandHook());

if (event->type() == QEvent::KeyPress) {
if (event->key() == Qt::Key_Delete) {
CallMethodParams params;
Expand Down
72 changes: 53 additions & 19 deletions lib/usd/ui/layerEditor/mayaCommandHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,6 @@ namespace {

std::string quote(const std::string& string) { return STR(" \"") + string + STR("\""); }

MString executeMel(const std::string& commandString)
{
// executes maya command with display and undo set to true so that it logs
MStringArray result;
MGlobal::executeCommand(
MString(commandString.c_str()),
result,
/*display*/ true,
/*undo*/ true);
if (result.length() > 0)
return result[0];
else
return "";
}

// maya doesn't support spaces in undo chunk names...
MString cleanChunkName(QString name) { return quote(name.replace(" ", "_").toStdString()).c_str(); }

Expand Down Expand Up @@ -195,8 +180,11 @@ UsdLayer MayaCommandHook::addAnonymousSubLayer(UsdLayer usdLayer, std::string ne
cmd = "mayaUsdLayerEditor -edit -addAnonymous ";
cmd += quote(newName);
cmd += quote(usdLayer->GetIdentifier());
std::string result = executeMel(cmd).asChar();
return PXR_NS::SdfLayer::FindOrOpen(result);
std::string result = executeMel(cmd);
if (result.size() > 0)
return PXR_NS::SdfLayer::FindOrOpen(result);
else
return {};
}

// mute or unmute the given layer
Expand All @@ -207,7 +195,7 @@ void MayaCommandHook::muteSubLayer(UsdLayer usdLayer, bool muteIt)
cmd += muteIt ? "1" : "0";
cmd += quote(proxyShapePath());
cmd += quote(usdLayer->GetIdentifier());
executeMel(cmd).asChar();
executeMel(cmd);
}

// lock, system-lock or unlock the given layer
Expand Down Expand Up @@ -236,7 +224,7 @@ void MayaCommandHook::lockSubLayer(UsdLayer usdLayer, MayaUsd::LayerLockType loc

cmd += quote(proxyShapePath());
cmd += quote(usdLayer->GetIdentifier());
executeMel(cmd).asChar();
executeMel(cmd);
}

// Help menu callback
Expand Down Expand Up @@ -295,4 +283,50 @@ bool MayaCommandHook::isProxyShapeSharedStage(const std::string& proxyShapePath)
return getBooleanAttributeOnProxyShape(proxyShapePath, "shareStage");
}

std::string MayaCommandHook::executeMel(const std::string& commandString)
{
if (areCommandsDelayed()) {
_delayedCommands.push_back({ commandString, false });
} else {
// executes maya command with display and undo set to true so that it logs
MStringArray result;
MGlobal::executeCommand(
MString(commandString.c_str()),
result,
/*display*/ true,
/*undo*/ true);
if (result.length() > 0)
return result[0].asChar();
}
return "";
}

void MayaCommandHook::executePython(const std::string& commandString)
{
if (areCommandsDelayed()) {
_delayedCommands.push_back({ commandString, true });
} else {
MGlobal::executePythonCommand(commandString.c_str());
}
}

void MayaCommandHook::executeDelayedCommands()
{
if (areCommandsDelayed())
return;

// In case the execution of commands add new commands,
// make a copy and clear the delayed commands.
std::vector<DelayedCommand> cmds = _delayedCommands;
_delayedCommands.clear();

for (const auto& cmd : cmds) {
if (cmd.isPython) {
executePython(cmd.command);
} else {
executeMel(cmd.command);
}
}
}

} // namespace UsdLayerEditor
21 changes: 21 additions & 0 deletions lib/usd/ui/layerEditor/mayaCommandHook.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "abstractCommandHook.h"

#include <vector>

namespace UsdLayerEditor {

/**
Expand Down Expand Up @@ -87,6 +89,25 @@ class MayaCommandHook : public AbstractCommandHook

protected:
std::string proxyShapePath();

std::string executeMel(const std::string& commandString);
void executePython(const std::string& commandString);

void executeDelayedCommands() override;

struct DelayedCommand
{
DelayedCommand(const std::string& cmd, bool isP)
: command(cmd)
, isPython(isP)
{
}

std::string command;
bool isPython { false };
};

std::vector<DelayedCommand> _delayedCommands;
};

} // namespace UsdLayerEditor
Expand Down

0 comments on commit f8c1d93

Please sign in to comment.