diff --git a/lib/usd/ui/layerEditor/layerTreeModel.cpp b/lib/usd/ui/layerEditor/layerTreeModel.cpp index 38a10f1523..953255ff75 100644 --- a/lib/usd/ui/layerEditor/layerTreeModel.cpp +++ b/lib/usd/ui/layerEditor/layerTreeModel.cpp @@ -233,7 +233,7 @@ void LayerTreeModel::setSessionState(SessionState* in_sessionState) in_sessionState, &SessionState::autoHideSessionLayerSignal, this, - &LayerTreeModel::sessionStageChanged); + &LayerTreeModel::autoHideSessionLayerChanged); } void LayerTreeModel::rebuildModelOnIdle() diff --git a/lib/usd/ui/layerEditor/mayaLayerEditorWindow.cpp b/lib/usd/ui/layerEditor/mayaLayerEditorWindow.cpp index 938261c28c..8f599cafe6 100644 --- a/lib/usd/ui/layerEditor/mayaLayerEditorWindow.cpp +++ b/lib/usd/ui/layerEditor/mayaLayerEditorWindow.cpp @@ -232,11 +232,10 @@ void MayaLayerEditorWindow::selectPrimsWithSpec() void MayaLayerEditorWindow::selectProxyShape(const char* shapePath) { - auto prim = UsdMayaQuery::GetPrim(shapePath); - if (prim) { - auto stage = prim.GetStage(); - if (stage != nullptr) { - _sessionState.setStage(stage); + SessionState::StageEntry entry; + if (_sessionState.getStageEntry(&entry, shapePath)) { + if (entry._stage != nullptr) { + _sessionState.setStageEntry(entry); } } } diff --git a/lib/usd/ui/layerEditor/mayaSessionState.cpp b/lib/usd/ui/layerEditor/mayaSessionState.cpp index c1392b1aa4..467b51c67a 100644 --- a/lib/usd/ui/layerEditor/mayaSessionState.cpp +++ b/lib/usd/ui/layerEditor/mayaSessionState.cpp @@ -19,7 +19,7 @@ #include "saveLayersDialog.h" #include "stringResources.h" -#include +#include #include #include @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include #include #include @@ -59,25 +61,29 @@ MayaSessionState::~MayaSessionState() // } -void MayaSessionState::setStage(PXR_NS::UsdStageRefPtr const& in_stage) +void MayaSessionState::setStageEntry(StageEntry const& inEntry) { - PARENT_CLASS::setStage(in_stage); - if (in_stage) { - auto stageList = allStages(); - for (auto const& entry : stageList) { - if (entry._stage == in_stage) { - _currentProxyShapePath = entry._proxyShapePath; - break; - } - } - } else { - _currentProxyShapePath.clear(); + PARENT_CLASS::setStageEntry(inEntry); + if (!inEntry._stage) { + _currentStageEntry.clear(); } } bool MayaSessionState::getStageEntry(StageEntry* out_stageEntry, const MString& shapePath) { - auto prim = UsdMayaQuery::GetPrim(shapePath.asChar()); + pxr::UsdPrim prim; + + MObject shapeObj; + MStatus status = UsdMayaUtil::GetMObjectByName(shapePath.asChar(), shapeObj); + CHECK_MSTATUS_AND_RETURN(status, false); + MFnDagNode dagNode(shapeObj, &status); + CHECK_MSTATUS_AND_RETURN(status, false); + + if (const UsdMayaUsdPrimProvider* usdPrimProvider + = dynamic_cast(dagNode.userNode())) { + prim = usdPrimProvider->usdPrim(); + } + if (prim) { auto stage = prim.GetStage(); // debatable, but we remove the path|to|shape @@ -89,6 +95,7 @@ bool MayaSessionState::getStageEntry(StageEntry* out_stageEntry, const MString& } else { niceName = tokenList[0]; } + out_stageEntry->_id = dagNode.uuid().asString().asChar(); out_stageEntry->_stage = stage; out_stageEntry->_displayName = niceName.toStdString(); out_stageEntry->_proxyShapePath = shapePath.asChar(); @@ -155,25 +162,23 @@ void MayaSessionState::unregisterNotifications() void MayaSessionState::mayaUsdStageReset(const MayaUsdProxyStageSetNotice& notice) { - auto shapePath = notice.GetShapePath(); - auto stage = notice.GetStage(); - if (shapePath == _currentProxyShapePath) { - QTimer::singleShot(0, this, [this, stage]() { setStage(stage); }); - } else { - auto shapePath = notice.GetShapePath(); - QTimer::singleShot( - 0, this, [this, shapePath, stage]() { mayaUsdStageResetCBOnIdle(shapePath, stage); }); + auto shapePath = notice.GetShapePath(); + StageEntry entry; + if (getStageEntry(&entry, shapePath.c_str())) { + if (entry._proxyShapePath == _currentStageEntry._proxyShapePath) { + QTimer::singleShot(0, this, [this, entry]() { + mayaUsdStageResetCBOnIdle(entry); + setStageEntry(entry); + }); + } else { + QTimer::singleShot(0, this, [this, entry]() { mayaUsdStageResetCBOnIdle(entry); }); + } } } -void MayaSessionState::mayaUsdStageResetCBOnIdle( - const std::string& shapePath, - PXR_NS::UsdStageRefPtr const& stage) +void MayaSessionState::mayaUsdStageResetCBOnIdle(StageEntry const& entry) { - StageEntry entry; - if (getStageEntry(&entry, shapePath.c_str())) { - Q_EMIT stageResetSignal(entry._proxyShapePath, stage); - } + Q_EMIT stageResetSignal(entry); } /* static */ @@ -195,7 +200,7 @@ void MayaSessionState::proxyShapeAddedCBOnIdle(const MObject& obj) auto shapePath = dagPath.fullPathName(); StageEntry entry; if (getStageEntry(&entry, shapePath)) { - Q_EMIT stageListChangedSignal(entry._stage); + Q_EMIT stageListChangedSignal(entry); } } @@ -213,11 +218,12 @@ void MayaSessionState::nodeRenamedCB(MObject& obj, const MString& oldName, void* auto THIS = static_cast(clientData); // doing it on idle give time to the Load Stage to set a file name - QTimer::singleShot(0, [THIS, obj]() { THIS->nodeRenamedCBOnIdle(obj); }); + QTimer::singleShot( + 0, [THIS, obj, oldName]() { THIS->nodeRenamedCBOnIdle(oldName.asChar(), obj); }); } } -void MayaSessionState::nodeRenamedCBOnIdle(const MObject& obj) +void MayaSessionState::nodeRenamedCBOnIdle(std::string const& oldName, const MObject& obj) { // this does not work: // if OpenMaya.MFnDependencyNode(obj).typeName == PROXY_NODE_TYPE @@ -228,7 +234,12 @@ void MayaSessionState::nodeRenamedCBOnIdle(const MObject& obj) StageEntry entry; if (getStageEntry(&entry, shapePath)) { - Q_EMIT stageRenamedSignal(entry._displayName, entry._stage); + // Need to update the current Entry also + if (_currentStageEntry._id == entry._id) { + _currentStageEntry = entry; + } + + Q_EMIT stageRenamedSignal(entry); } } } @@ -325,10 +336,10 @@ std::string MayaSessionState::defaultLoadPath() const // in this case, the stage needs to be re-created on the new file void MayaSessionState::rootLayerPathChanged(std::string const& in_path) { - if (!_currentProxyShapePath.empty()) { + if (!_currentStageEntry._proxyShapePath.empty()) { MString script; - MString proxyShape(_currentProxyShapePath.c_str()); + MString proxyShape(_currentStageEntry._proxyShapePath.c_str()); MString newValue(in_path.c_str()); script.format("setAttr -type \"string\" ^1s.filePath \"^2s\"", proxyShape, newValue); MGlobal::executeCommand( diff --git a/lib/usd/ui/layerEditor/mayaSessionState.h b/lib/usd/ui/layerEditor/mayaSessionState.h index 4b83f6659a..70be8b9fc6 100644 --- a/lib/usd/ui/layerEditor/mayaSessionState.h +++ b/lib/usd/ui/layerEditor/mayaSessionState.h @@ -50,7 +50,7 @@ class MayaSessionState ~MayaSessionState(); // API implementation - void setStage(PXR_NS::UsdStageRefPtr const& in_stage) override; + void setStageEntry(StageEntry const& in_entry) override; void setAutoHideSessionLayer(bool hide) override; AbstractCommandHook* commandHook() override; std::vector allStages() const override; @@ -69,7 +69,7 @@ class MayaSessionState // in this case, the stage needs to be re-created on the new file void rootLayerPathChanged(std::string const& in_path) override; - std::string proxyShapePath() { return _currentProxyShapePath; } + std::string proxyShapePath() { return _currentStageEntry._proxyShapePath; } Q_SIGNALS: void clearUIOnSceneResetSignal(); @@ -78,10 +78,10 @@ class MayaSessionState void registerNotifications(); void unregisterNotifications(); -protected: // get the stage and proxy name for a path static bool getStageEntry(StageEntry* out_stageEntry, const MString& shapePath); +protected: // maya callback handers static void proxyShapeAddedCB(MObject& node, void* clientData); static void proxyShapeRemovedCB(MObject& node, void* clientData); @@ -89,15 +89,14 @@ class MayaSessionState static void sceneClosingCB(void* clientData); void proxyShapeAddedCBOnIdle(const MObject& node); - void nodeRenamedCBOnIdle(const MObject& obj); + void nodeRenamedCBOnIdle(std::string const& oldName, const MObject& obj); // Notice listener method for proxy stage set void mayaUsdStageReset(const MayaUsdProxyStageSetNotice& notice); - void mayaUsdStageResetCBOnIdle(const std::string& shapePath, UsdStageRefPtr const& stage); + void mayaUsdStageResetCBOnIdle(StageEntry const& entry); std::vector _callbackIds; TfNotice::Key _stageResetNoticeKey; - std::string _currentProxyShapePath; MayaCommandHook _mayaCommandHook; }; diff --git a/lib/usd/ui/layerEditor/saveLayersDialog.cpp b/lib/usd/ui/layerEditor/saveLayersDialog.cpp index eaba1ce1a4..ca454d30f2 100644 --- a/lib/usd/ui/layerEditor/saveLayersDialog.cpp +++ b/lib/usd/ui/layerEditor/saveLayersDialog.cpp @@ -275,19 +275,11 @@ SaveLayersDialog::SaveLayersDialog(SessionState* in_sessionState, QWidget* in_pa MString msg; QString dialogTitle = StringResources::getAsQString(StringResources::kSaveStage); if (TF_VERIFY(nullptr != _sessionState)) { - auto stage = _sessionState->stage(); - - auto stageList = _sessionState->allStages(); - for (auto const& entry : stageList) { - if (entry._stage == stage) { - std::string stageName = entry._displayName; - msg.format( - StringResources::getAsMString(StringResources::kSaveName), stageName.c_str()); - dialogTitle = MQtUtil::toQString(msg); - getLayersToSave(stage, stageName); - break; - } - } + auto stageEntry = _sessionState->stageEntry(); + std::string stageName = stageEntry._displayName; + msg.format(StringResources::getAsMString(StringResources::kSaveName), stageName.c_str()); + dialogTitle = MQtUtil::toQString(msg); + getLayersToSave(stageEntry._stage, stageName); } setWindowTitle(dialogTitle); diff --git a/lib/usd/ui/layerEditor/sessionState.cpp b/lib/usd/ui/layerEditor/sessionState.cpp index 1b5d2710b0..31cdbdccd0 100644 --- a/lib/usd/ui/layerEditor/sessionState.cpp +++ b/lib/usd/ui/layerEditor/sessionState.cpp @@ -23,18 +23,19 @@ void SessionState::setAutoHideSessionLayer(bool hideIt) Q_EMIT autoHideSessionLayerSignal(_autoHideSessionLayer); } -void SessionState::setStage(PXR_NS::UsdStageRefPtr const& in_stage) +void SessionState::setStageEntry(StageEntry const& in_entry) { - if (in_stage != _stage) { - _stage = in_stage; + if (_currentStageEntry != in_entry) { + auto oldEntry = _currentStageEntry; + _currentStageEntry = in_entry; Q_EMIT currentStageChangedSignal(); } } PXR_NS::SdfLayerRefPtr SessionState::targetLayer() const { - if (_stage != nullptr) { - const auto& target = _stage->GetEditTarget(); + if (_currentStageEntry._stage != nullptr) { + const auto& target = _currentStageEntry._stage->GetEditTarget(); return target.GetLayer(); } else { return nullptr; diff --git a/lib/usd/ui/layerEditor/sessionState.h b/lib/usd/ui/layerEditor/sessionState.h index a52addd65d..e6c46713e3 100644 --- a/lib/usd/ui/layerEditor/sessionState.h +++ b/lib/usd/ui/layerEditor/sessionState.h @@ -45,17 +45,43 @@ class SessionState : public QObject struct StageEntry { + std::string _id; PXR_NS::UsdStageRefPtr _stage; std::string _displayName; std::string _proxyShapePath; + + StageEntry() + { + _id = ""; + _stage = PXR_NS::UsdStageRefPtr(); + _displayName = ""; + _proxyShapePath = ""; + } + + bool operator==(const StageEntry& entry) const + { + return ( + _id == entry._id && _stage == entry._stage && _displayName == entry._displayName + && _proxyShapePath == entry._proxyShapePath); + } + + bool operator!=(const StageEntry& entry) const { return !(*this == entry); } + + void clear() + { + _stage = PXR_NS::UsdStageRefPtr(); + _displayName = ""; + _proxyShapePath = ""; + } }; // properties virtual bool autoHideSessionLayer() const { return _autoHideSessionLayer; } virtual void setAutoHideSessionLayer(bool hide); - PXR_NS::UsdStageRefPtr const& stage() const { return _stage; } + PXR_NS::UsdStageRefPtr const& stage() const { return _currentStageEntry._stage; } + StageEntry const& stageEntry() const { return _currentStageEntry; } PXR_NS::SdfLayerRefPtr targetLayer() const; - virtual void setStage(PXR_NS::UsdStageRefPtr const& in_stage); + virtual void setStageEntry(StageEntry const& in_entry); virtual AbstractCommandHook* commandHook() = 0; virtual std::vector allStages() const = 0; // path to default load layer dialogs to @@ -73,18 +99,21 @@ class SessionState : public QObject // in this case, the stage needs to be re-created on the new file virtual void rootLayerPathChanged(std::string const& in_path) = 0; - bool isValid() { return _stage && _stage->GetRootLayer(); } + bool isValid() + { + return _currentStageEntry._stage && _currentStageEntry._stage->GetRootLayer(); + } Q_SIGNALS: void currentStageChangedSignal(); - void stageListChangedSignal(PXR_NS::UsdStageRefPtr const& toSelect = PXR_NS::UsdStageRefPtr()); - void stageRenamedSignal(std::string const& name, PXR_NS::UsdStageRefPtr const& stage); + void stageListChangedSignal(StageEntry const& toSelect = StageEntry()); + void stageRenamedSignal(StageEntry const& renamedEntry); void autoHideSessionLayerSignal(bool hideIt); - void stageResetSignal(const std::string& proxyPath, PXR_NS::UsdStageRefPtr const& stage); + void stageResetSignal(StageEntry const& entry); protected: - PXR_NS::UsdStageRefPtr _stage; - bool _autoHideSessionLayer = true; + StageEntry _currentStageEntry; + bool _autoHideSessionLayer = true; }; } // namespace UsdLayerEditor diff --git a/lib/usd/ui/layerEditor/stageSelectorWidget.cpp b/lib/usd/ui/layerEditor/stageSelectorWidget.cpp index e34ff7b3e5..e36f07fb7e 100644 --- a/lib/usd/ui/layerEditor/stageSelectorWidget.cpp +++ b/lib/usd/ui/layerEditor/stageSelectorWidget.cpp @@ -16,6 +16,7 @@ #include "stageSelectorWidget.h" #include "qtUtils.h" +#include "sessionState.h" #include "stringResources.h" #include @@ -25,7 +26,25 @@ #include #include -Q_DECLARE_METATYPE(PXR_NS::UsdStageRefPtr); +Q_DECLARE_METATYPE(UsdLayerEditor::SessionState::StageEntry); + +namespace { +int getEntryIndexById( + UsdLayerEditor::SessionState::StageEntry const& entry, + std::vector const& stages) +{ + auto it = std::find_if( + stages.begin(), stages.end(), [entry](UsdLayerEditor::SessionState::StageEntry stageEntry) { + return (entry._id == stageEntry._id); + }); + + if (it != stages.end()) { + return std::distance(stages.begin(), it); + } + + return -1; +} +} // namespace namespace UsdLayerEditor { @@ -71,31 +90,30 @@ void StageSelectorWidget::setSessionState(SessionState* in_sessionState) updateFromSessionState(); } -PXR_NS::UsdStageRefPtr StageSelectorWidget::selectedStage() +SessionState::StageEntry const StageSelectorWidget::selectedStage() { if (_dropDown->currentIndex() != -1) { auto const& data = _dropDown->currentData(); - return data.value(); + return data.value(); } - return PXR_NS::UsdStageRefPtr(); + return SessionState::StageEntry(); } // repopulates the combo based on the session stage list -void StageSelectorWidget::updateFromSessionState(PXR_NS::UsdStageRefPtr const& stageToSelect) +void StageSelectorWidget::updateFromSessionState(SessionState::StageEntry const& entryToSelect) { QSignalBlocker blocker(_dropDown); _dropDown->clear(); auto allStages = _sessionState->allStages(); - for (auto const& stage : allStages) { - _dropDown->addItem(QString(stage._displayName.c_str()), QVariant::fromValue(stage._stage)); + for (auto const& stageEntry : allStages) { + _dropDown->addItem( + QString(stageEntry._displayName.c_str()), QVariant::fromValue(stageEntry)); } - if (!stageToSelect) { - const auto& newStage = selectedStage(); - if (newStage != _sessionState->stage()) { - _sessionState->setStage(newStage); - } + if (!entryToSelect._stage) { + const auto& newEntry = selectedStage(); + _sessionState->setStageEntry(newEntry); } else { - _sessionState->setStage(stageToSelect); + _sessionState->setStageEntry(entryToSelect); } } @@ -103,7 +121,7 @@ void StageSelectorWidget::updateFromSessionState(PXR_NS::UsdStageRefPtr const& s void StageSelectorWidget::selectedIndexChanged(int index) { _internalChange = true; - _sessionState->setStage(selectedStage()); + _sessionState->setStageEntry(selectedStage()); _internalChange = false; } @@ -112,7 +130,7 @@ void StageSelectorWidget::selectedIndexChanged(int index) void StageSelectorWidget::sessionStageChanged() { if (!_internalChange) { - auto index = _dropDown->findData(QVariant::fromValue(_sessionState->stage())); + auto index = getEntryIndexById(_sessionState->stageEntry(), _sessionState->allStages()); if (index != -1) { QSignalBlocker blocker(_dropDown); _dropDown->setCurrentIndex(index); @@ -120,17 +138,16 @@ void StageSelectorWidget::sessionStageChanged() } } -void StageSelectorWidget::stageRenamed(std::string const& name, PXR_NS::UsdStageRefPtr const& stage) +void StageSelectorWidget::stageRenamed(SessionState::StageEntry const& renamedEntry) { - auto index = _dropDown->findData(QVariant::fromValue(stage)); + auto index = getEntryIndexById(renamedEntry, _sessionState->allStages()); if (index != -1) { - _dropDown->setItemText(index, name.c_str()); + _dropDown->setItemText(index, renamedEntry._displayName.c_str()); + _dropDown->setItemData(index, QVariant::fromValue(renamedEntry)); } } -void StageSelectorWidget::stageReset( - const std::string& proxyPath, - PXR_NS::UsdStageRefPtr const& stage) +void StageSelectorWidget::stageReset(SessionState::StageEntry const& entry) { // Individual combo box entries have a short display name and a reference to a stage, // which is not a unique combination. By construction the combo box indices do line @@ -142,19 +159,9 @@ void StageSelectorWidget::stageReset( return; } - std::vector allStages = _sessionState->allStages(); - auto it = std::find_if( - allStages.begin(), allStages.end(), [proxyPath](SessionState::StageEntry entry) { - return (proxyPath == entry._proxyShapePath); - }); - - if (it != allStages.end()) { - auto index = (it - allStages.begin()); - if (index < count) { - if (_dropDown->itemText(index) == QString::fromStdString((*it)._displayName)) { - _dropDown->setItemData(index, QVariant::fromValue(stage)); - } - } + auto index = getEntryIndexById(entry, _sessionState->allStages()); + if (index >= 0 && index < count) { + _dropDown->setItemData(index, QVariant::fromValue(entry)); } } diff --git a/lib/usd/ui/layerEditor/stageSelectorWidget.h b/lib/usd/ui/layerEditor/stageSelectorWidget.h index c3ba22a56b..3b900055d3 100644 --- a/lib/usd/ui/layerEditor/stageSelectorWidget.h +++ b/lib/usd/ui/layerEditor/stageSelectorWidget.h @@ -26,8 +26,6 @@ namespace UsdLayerEditor { -class SessionState; - /** * @brief Drop down list that allows selecting a stage. Owned by the LayerEditorWidget * @@ -39,14 +37,14 @@ class StageSelectorWidget : public QWidget StageSelectorWidget(SessionState* in_sessionState, QWidget* in_parent); protected: - void setSessionState(SessionState* in_sessionState); - PXR_NS::UsdStageRefPtr selectedStage(); + void setSessionState(SessionState* in_sessionState); + SessionState::StageEntry const selectedStage(); // slot: - void - updateFromSessionState(PXR_NS::UsdStageRefPtr const& stageToSelect = PXR_NS::UsdStageRefPtr()); - void stageRenamed(std::string const& name, PXR_NS::UsdStageRefPtr const& stage); - void stageReset(const std::string& proxyPath, PXR_NS::UsdStageRefPtr const& stage); + void updateFromSessionState( + SessionState::StageEntry const& entryToSelect = SessionState::StageEntry()); + void stageRenamed(SessionState::StageEntry const& renamedEntry); + void stageReset(SessionState::StageEntry const& entry); void sessionStageChanged(); void selectedIndexChanged(int index);