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-108549: Fix undo crash when switching between target layers in a stage #965

Conversation

HamedSabri-adsk
Copy link
Contributor

@HamedSabri-adsk HamedSabri-adsk commented Dec 3, 2020

This PR fixes the crash when switching between target layers in a stage.

@HamedSabri-adsk HamedSabri-adsk added core Related to core library workflows Related to in-context workflows labels Dec 3, 2020
layer->SetStateDelegate(_layerStateDelegate);
}

void UsdUndoManager::trackStatesOnEditTargetChange(const SdfLayerHandle& layer)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit perplexed here. If we set a new state delegate on layer creation, then why do we have to set it on edit target change? Is it because of initialization order and the fact that certain layers may have been created before the UsdUndoManager starts tracking changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time we change the target edit layer, UsdUndoStateDelegate::_OnSetLayer is invoked where it
needs to set the _layer for tracking changes.

We do need to call layer->SetStateDelegate() when we switch between layers otherwise how would the layer know what state delegate needs to use?

Notice that in trackStatesOnEditTargetChange, I am only passing the _layerStateDelegate object that was created on stage set.

More than one layer needs to share the same StateDelegate .

void UsdUndoManager::trackStatesOnEditTargetChange(const SdfLayerHandle& layer) 
{
    layer->SetStateDelegate(_layerStateDelegate);
}

{
layer->SetStateDelegate(UsdUndoStateDelegate::New());
_layerStateDelegate = TfCreateRefPtr(new UsdUndoStateDelegate);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we save this as a data member? Since the UsdUndoManager is a singleton, doesn't that mean that more than one layer can share the same UsdUndoStateDelegate?

Thinking out loud here, could it be that the UsdUndoManager should track a set of layers, and when it sees one that isn't in its set, whether than be through a layer creation notification or an edit target change notification, it will give the unknown layer a newly-created UsdUndoStateDelegate, then will add the layer to its set of known layers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we save this as a data member?

The main reason I need to save _layerStateDelegate as a data member is for undo/redo purposes between layers itself.

Since the UsdUndoManager is a singleton, doesn't that mean that more than one layer can share the same UsdUndoStateDelegate?

Exactly, more than one layer can share the same UsdUndoStateDelegate in a same stage.

it will give the unknown layer a newly-created UsdUndoStateDelegate, then will add the layer to its set of known layers?

Let's have a chat around this. I would like to understand this approach better.

Hamed Sabri added 3 commits December 4, 2020 15:44
@@ -88,7 +88,7 @@ class MAYAUSD_CORE_PUBLIC StagesSubject : public TfWeakBase
void onStageInvalidate(const MayaUsdProxyStageInvalidateNotice& notice);

// Array of Notice::Key for registered listener
#if UFE_PREVIEW_VERSION_NUM >= 2029
#if UFE_PREVIEW_VERSION_NUM >= 2025
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppt-adsk Based on our internal discussion, lowering the version to cover existing shipped PR.

= TfDynamic_cast<UsdUndoStateDelegatePtr>(layer->GetStateDelegate());
if (!usdUndoStateDelegatePtr) {
layer->SetStateDelegate(UsdUndoStateDelegate::New());
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppt-adsk Thanks for great feedback. Using a dynamic_cast to determine if a layer is already registered with our UsdUndoStateDelegate. If the cast fails, that means it needs to be set with a new one. The UsdUndoStateDelegate is stateless and doesn't need to be shared among layers.

Copy link

@kxl-adsk kxl-adsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@HamedSabri-adsk HamedSabri-adsk merged commit 49c5882 into ufe-manipulation Dec 4, 2020
@HamedSabri-adsk HamedSabri-adsk deleted the sabrih/MAYA-108549/fix_undo_crash_switching_layers branch December 4, 2020 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Related to core library workflows Related to in-context workflows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants