// Copyright Epic Games, Inc. All Rights Reserved. #include "MVVMBlueprintView.h" #include "Components/Widget.h" #include "Kismet2/BlueprintEditorUtils.h" #include "MVVMBlueprintInstancedViewModel.h" #include "MVVMBlueprintViewConversionFunction.h" #include "MVVMBlueprintViewEvent.h" #include "MVVMBlueprintViewCondition.h" #include "MVVMWidgetBlueprintExtension_View.h" #include "WidgetBlueprint.h" #include "UObject/AssetRegistryTagsContext.h" #include "UObject/FortniteMainBranchObjectVersion.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(MVVMBlueprintView) UMVVMBlueprintView::UMVVMBlueprintView() { Settings = CreateDefaultSubobject("Settings"); CompiledBindingLibraryId = FGuid::NewGuid(); } FMVVMBlueprintViewModelContext* UMVVMBlueprintView::FindViewModel(FGuid ViewModelId) { return AvailableViewModels.FindByPredicate([ViewModelId](const FMVVMBlueprintViewModelContext& Other) { return Other.GetViewModelId() == ViewModelId; }); } const FMVVMBlueprintViewModelContext* UMVVMBlueprintView::FindViewModel(FGuid ViewModelId) const { return const_cast(this)->FindViewModel(ViewModelId); } const FMVVMBlueprintViewModelContext* UMVVMBlueprintView::FindViewModel(FName ViewModel) const { return AvailableViewModels.FindByPredicate([ViewModel](const FMVVMBlueprintViewModelContext& Other) { return Other.GetViewModelName() == ViewModel; }); } void UMVVMBlueprintView::AddViewModel(const FMVVMBlueprintViewModelContext& NewContext) { AvailableViewModels.Add(NewContext); FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); OnViewModelsUpdated.Broadcast(); } namespace UE::MVVM::Private { bool RemoveViewModelInternal(FGuid ViewModelId, TArray& ViewModelContexts) { bool bResult = false; for (int32 Index = ViewModelContexts.Num() - 1; Index >= 0; --Index) { if (ViewModelContexts[Index].GetViewModelId() == ViewModelId) { UMVVMBlueprintInstancedViewModelBase* InstancedViewModel = ViewModelContexts[Index].InstancedViewModel; if (InstancedViewModel) { auto RenameToTransient = [](UObject* ObjectToRename) { FName TrashName = MakeUniqueObjectName(GetTransientPackage(), ObjectToRename->GetClass(), *FString::Printf(TEXT("TRASH_%s"), *ObjectToRename->GetName())); ObjectToRename->Rename(*TrashName.ToString(), GetTransientPackage()); }; if (InstancedViewModel->GetGeneratedClass()) { RenameToTransient(InstancedViewModel->GetGeneratedClass()); } RenameToTransient(InstancedViewModel); } ViewModelContexts.RemoveAt(Index); bResult = true; } } return bResult; } } bool UMVVMBlueprintView::RemoveViewModel(FGuid ViewModelId) { bool bRemoved = UE::MVVM::Private::RemoveViewModelInternal(ViewModelId, AvailableViewModels); if (bRemoved) { FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); OnViewModelsUpdated.Broadcast(); } return bRemoved; } int32 UMVVMBlueprintView::RemoveViewModels(const TArrayView ViewModelIds) { int32 Count = 0; for (const FGuid& ViewModelId : ViewModelIds) { if (UE::MVVM::Private::RemoveViewModelInternal(ViewModelId, AvailableViewModels)) { ++Count; } } if (Count > 0) { FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); OnViewModelsUpdated.Broadcast(); } return Count; } bool UMVVMBlueprintView::RenameViewModel(FName OldViewModelName, FName NewViewModelName) { FMVVMBlueprintViewModelContext* ViewModelContext = AvailableViewModels.FindByPredicate([OldViewModelName](const FMVVMBlueprintViewModelContext& Other) { return Other.GetViewModelName() == OldViewModelName; }); if (ViewModelContext) { ViewModelContext->ViewModelName = NewViewModelName; FBlueprintEditorUtils::ReplaceVariableReferences(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(), OldViewModelName, NewViewModelName); FBlueprintEditorUtils::ValidateBlueprintChildVariables(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(), NewViewModelName); FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); OnViewModelsUpdated.Broadcast(); } return ViewModelContext != nullptr; } bool UMVVMBlueprintView::ReparentViewModel(FGuid ViewModelId, const UClass* ViewModelClass) { if (ViewModelClass && ViewModelClass->ImplementsInterface(UNotifyFieldValueChanged::StaticClass())) { FMVVMBlueprintViewModelContext* ViewModelContext = AvailableViewModels.FindByPredicate([ViewModelId](const FMVVMBlueprintViewModelContext& Other) { return Other.GetViewModelId() == ViewModelId; }); if (ViewModelContext) { ViewModelContext->NotifyFieldValueClass = const_cast(ViewModelClass); TArray ValidCreationTypes = UE::MVVM::GetAllowedContextCreationType(ViewModelClass); if (!ValidCreationTypes.Contains(ViewModelContext->CreationType)) { if (ensureMsgf(ValidCreationTypes.Num() > 0, TEXT("There is no valid creation type for this class."))) { ViewModelContext->CreationType = ValidCreationTypes[0]; } } FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); OnViewModelsUpdated.Broadcast(); return true; } } return false; } const FMVVMBlueprintViewBinding* UMVVMBlueprintView::FindBinding(const UWidget* Widget, const FProperty* Property) const { return const_cast(this)->FindBinding(Widget, Property); } FMVVMBlueprintViewBinding* UMVVMBlueprintView::FindBinding(const UWidget* Widget, const FProperty* Property) { FName WidgetName = Widget->GetFName(); return Bindings.FindByPredicate([WidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(), WidgetName, Property](const FMVVMBlueprintViewBinding& Binding) { return Binding.DestinationPath.GetWidgetName() == WidgetName && Binding.DestinationPath.PropertyPathContains(WidgetBlueprint->GeneratedClass, UE::MVVM::FMVVMConstFieldVariant(Property)); }); } void UMVVMBlueprintView::RemoveBindingAt(int32 Index) { if (Bindings.IsValidIndex(Index)) { if (Bindings[Index].Conversion.SourceToDestinationConversion) { Bindings[Index].Conversion.SourceToDestinationConversion->RemoveWrapperGraph(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } if (Bindings[Index].Conversion.DestinationToSourceConversion) { Bindings[Index].Conversion.DestinationToSourceConversion->RemoveWrapperGraph(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } Bindings.RemoveAt(Index); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } } void UMVVMBlueprintView::RemoveBinding(const FMVVMBlueprintViewBinding* Binding) { int32 Index = 0; for (; Index < Bindings.Num(); ++Index) { if (&Bindings[Index] == Binding) { break; } } RemoveBindingAt(Index); } const FMVVMBlueprintViewBinding* UMVVMBlueprintView::DuplicateBinding(const FMVVMBlueprintViewBinding* Binding) { FMVVMBlueprintViewBinding& NewBinding = Bindings.AddDefaulted_GetRef(); // Copy all existing binding properties except the BindingId NewBinding = *Binding; NewBinding.BindingId = FGuid::NewGuid(); UWidgetBlueprint* WidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); if (UMVVMBlueprintViewConversionFunction* ConversionFunction = Binding->Conversion.SourceToDestinationConversion) { NewBinding.Conversion.SourceToDestinationConversion = DuplicateObject(ConversionFunction, WidgetBlueprint); NewBinding.Conversion.SourceToDestinationConversion->RecreateWrapperGraph(WidgetBlueprint); } if (UMVVMBlueprintViewConversionFunction* ConversionFunction = Binding->Conversion.DestinationToSourceConversion) { NewBinding.Conversion.DestinationToSourceConversion = DuplicateObject(ConversionFunction, WidgetBlueprint); NewBinding.Conversion.DestinationToSourceConversion->RecreateWrapperGraph(WidgetBlueprint); } OnBindingsAdded.Broadcast(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(WidgetBlueprint); return &NewBinding; } FMVVMBlueprintViewBinding& UMVVMBlueprintView::AddDefaultBinding() { FMVVMBlueprintViewBinding& NewBinding = Bindings.AddDefaulted_GetRef(); NewBinding.BindingId = FGuid::NewGuid(); OnBindingsAdded.Broadcast(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); return NewBinding; } FMVVMBlueprintViewBinding* UMVVMBlueprintView::GetBindingAt(int32 Index) { if (Bindings.IsValidIndex(Index)) { return &Bindings[Index]; } return nullptr; } const FMVVMBlueprintViewBinding* UMVVMBlueprintView::GetBindingAt(int32 Index) const { if (Bindings.IsValidIndex(Index)) { return &Bindings[Index]; } return nullptr; } FMVVMBlueprintViewBinding* UMVVMBlueprintView::GetBinding(FGuid Id) { return Bindings.FindByPredicate([Id](const FMVVMBlueprintViewBinding& Binding){ return Id == Binding.BindingId; }); } const FMVVMBlueprintViewBinding* UMVVMBlueprintView::GetBinding(FGuid Id) const { return Bindings.FindByPredicate([Id](const FMVVMBlueprintViewBinding& Binding) { return Id == Binding.BindingId; }); } UMVVMBlueprintViewEvent* UMVVMBlueprintView::AddDefaultEvent() { UMVVMBlueprintViewEvent* Event = NewObject(this); AddEvent(Event); return Event; } void UMVVMBlueprintView::AddEvent(UMVVMBlueprintViewEvent* Event) { Events.Add(Event); OnBindingsAdded.Broadcast(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } void UMVVMBlueprintView::RemoveEvent(UMVVMBlueprintViewEvent* Event) { if (Events.RemoveAll([Event](TObjectPtr& Other){ return Other == Event; }) > 0) { Event->RemoveWrapperGraph(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } } UMVVMBlueprintViewEvent* UMVVMBlueprintView::DuplicateEvent(UMVVMBlueprintViewEvent* Event) { UMVVMBlueprintViewEvent* NewEvent = DuplicateObject(Event, this); NewEvent->RecreateWrapperGraph(); AddEvent(NewEvent); return NewEvent; } UMVVMBlueprintViewCondition* UMVVMBlueprintView::AddDefaultCondition() { UMVVMBlueprintViewCondition* Condition = NewObject(this); AddCondition(Condition); return Condition; } void UMVVMBlueprintView::AddCondition(UMVVMBlueprintViewCondition* Condition) { Conditions.Add(Condition); OnBindingsAdded.Broadcast(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } void UMVVMBlueprintView::RemoveCondition(UMVVMBlueprintViewCondition* Condition) { if (Conditions.RemoveAll([Condition](TObjectPtr& Other) { return Other == Condition; }) > 0) { Condition->RemoveWrapperGraph(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsModified(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()); } } UMVVMBlueprintViewCondition* UMVVMBlueprintView::DuplicateCondition(UMVVMBlueprintViewCondition* Condition) { UMVVMBlueprintViewCondition* NewCondition = DuplicateObject(Condition, this); NewCondition->RecreateWrapperGraph(); AddCondition(NewCondition); return NewCondition; } TArray UMVVMBlueprintView::GetBindingMessages(FGuid Id, UE::MVVM::EBindingMessageType InMessageType) const { TArray Results; if (BindingMessages.Contains(Id)) { const TArray& AllBindingMessages = BindingMessages[Id]; for (const UE::MVVM::FBindingMessage& Message : AllBindingMessages) { if (Message.MessageType == InMessageType) { Results.Add(Message.MessageText); } } } return Results; } bool UMVVMBlueprintView::HasBindingMessage(FGuid Id, UE::MVVM::EBindingMessageType InMessageType) const { if (const TArray* FoundBindingMessages = BindingMessages.Find(Id)) { for (const UE::MVVM::FBindingMessage& Message : *FoundBindingMessages) { if (Message.MessageType == InMessageType) { return true; } } } return false; } void UMVVMBlueprintView::AddMessageToBinding(FGuid Id, UE::MVVM::FBindingMessage MessageToAdd) { TArray& FoundBindingMessages = BindingMessages.FindOrAdd(Id); FoundBindingMessages.Add(MessageToAdd); } void UMVVMBlueprintView::ResetBindingMessages() { BindingMessages.Reset(); } void UMVVMBlueprintView::Serialize(FArchive& Ar) { Super::Serialize(Ar); Ar.UsingCustomVersion(FFortniteMainBranchObjectVersion::GUID); } #if WITH_EDITOR namespace UE::MVVM::Private { enum EConditionPath { ConditionPath, DestinationPath }; template void ForEachPropertyPath_Update(UMVVMBlueprintView* BlueprintView, Predicate Pred, bool bGenerateGraph) { UWidgetBlueprint* WidgetBlueprint = BlueprintView->GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); auto PredPin = [&Pred](const FMVVMBlueprintPin& Pin) -> TOptional { if (Pin.UsedPathAsValue()) { FMVVMBlueprintPropertyPath NewPinPath = Pin.GetPath(); if (Pred(NewPinPath)) { return NewPinPath; } } return TOptional(); }; for (FMVVMBlueprintViewBinding& Binding : BlueprintView->GetBindings()) { Pred(Binding.SourcePath); Pred(Binding.DestinationPath); if (Binding.Conversion.DestinationToSourceConversion) { Binding.Conversion.DestinationToSourceConversion->ConditionalPostLoad(); for (const FMVVMBlueprintPin& Pin : Binding.Conversion.DestinationToSourceConversion->GetPins()) { TOptional NewPath = PredPin(Pin); if (NewPath.IsSet()) { if (bGenerateGraph) { Binding.Conversion.DestinationToSourceConversion->SetGraphPin(WidgetBlueprint, Pin.GetId(), NewPath.GetValue()); } else { const_cast(Pin).SetPath(NewPath.GetValue()); } } } } if (Binding.Conversion.SourceToDestinationConversion) { Binding.Conversion.SourceToDestinationConversion->ConditionalPostLoad(); for (const FMVVMBlueprintPin& Pin : Binding.Conversion.SourceToDestinationConversion->GetPins()) { TOptional NewPath = PredPin(Pin); if (NewPath.IsSet()) { if (bGenerateGraph) { Binding.Conversion.SourceToDestinationConversion->SetGraphPin(WidgetBlueprint, Pin.GetId(), NewPath.GetValue()); } else { const_cast(Pin).SetPath(NewPath.GetValue()); } } } } } for (UMVVMBlueprintViewEvent* Event : BlueprintView->GetEvents()) { if (Event) { auto PredEventPath = [Event, &Pred, bGenerateGraph](const FMVVMBlueprintPropertyPath& PropertyPath, bool bEventPath) { FMVVMBlueprintPropertyPath NewPropertyPath = PropertyPath; if (Pred(NewPropertyPath)) { if (bGenerateGraph) { if (bEventPath) { Event->SetEventPath(NewPropertyPath); } else { Event->SetDestinationPath(NewPropertyPath); } } else { const_cast(PropertyPath) = NewPropertyPath; } } }; TArray> NewPins; for (const FMVVMBlueprintPin& Pin : Event->GetPins()) { TOptional NewPath = PredPin(Pin); if (NewPath.IsSet()) { NewPins.Emplace(Pin.GetId(), MoveTemp(NewPath.GetValue())); } } PredEventPath(Event->GetEventPath(), true); PredEventPath(Event->GetDestinationPath(), false); for (TTuple& Pin : NewPins) { if (bGenerateGraph) { Event->SetPinPath(Pin.Get<0>(), Pin.Get<1>()); } else { Event->SetPinPathNoGraphGeneration(Pin.Get<0>(), Pin.Get<1>()); } } } } for (UMVVMBlueprintViewCondition* Condition : BlueprintView->GetConditions()) { if (Condition) { auto PredConditionPath = [Condition, &Pred, bGenerateGraph](const FMVVMBlueprintPropertyPath& PropertyPath, EConditionPath TypePath) { FMVVMBlueprintPropertyPath NewPropertyPath = PropertyPath; if (Pred(NewPropertyPath)) { if (bGenerateGraph) { if (TypePath == EConditionPath::ConditionPath) { Condition->SetConditionPath(NewPropertyPath); } else if (TypePath == EConditionPath::DestinationPath) { Condition->SetDestinationPath(NewPropertyPath); } } else { const_cast(PropertyPath) = NewPropertyPath; } } }; TArray> NewPins; for (const FMVVMBlueprintPin& Pin : Condition->GetPins()) { TOptional NewPath = PredPin(Pin); if (NewPath.IsSet()) { NewPins.Emplace(Pin.GetId(), MoveTemp(NewPath.GetValue())); } } PredConditionPath(Condition->GetConditionPath(), EConditionPath::ConditionPath); PredConditionPath(Condition->GetDestinationPath(), EConditionPath::DestinationPath); for (TTuple& Pin : NewPins) { if (bGenerateGraph) { Condition->SetPinPath(Pin.Get<0>(), Pin.Get<1>()); } else { Condition->SetPinPathNoGraphGeneration(Pin.Get<0>(), Pin.Get<1>()); } } } } } } void UMVVMBlueprintView::PostLoad() { Super::PostLoad(); for (FMVVMBlueprintViewBinding& Binding : Bindings) { if (!Binding.BindingId.IsValid()) { Binding.BindingId = FGuid::NewGuid(); } } GetOuterUMVVMWidgetBlueprintExtension_View()->ConditionalPostLoad(); GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint()->ConditionalPostLoad(); // Make sure all bindings uses the skeletal class if (GetLinkerCustomVersion(FFortniteMainBranchObjectVersion::GUID) < FFortniteMainBranchObjectVersion::MVVMConvertPropertyPathToSkeletalClass) { const UWidgetBlueprint* ThisWidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); for (FMVVMBlueprintViewBinding& Binding : Bindings) { for (const FMVVMBlueprintFieldPath& FieldPath : Binding.SourcePath.GetFieldPaths()) { const_cast(FieldPath).SetDeprecatedSelfReference(ThisWidgetBlueprint); } for (const FMVVMBlueprintFieldPath& FieldPath : Binding.DestinationPath.GetFieldPaths()) { const_cast(FieldPath).SetDeprecatedSelfReference(ThisWidgetBlueprint); } } } for (FMVVMBlueprintViewBinding& Binding : Bindings) { Binding.Conversion.DeprecateViewConversionFunction(GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(), Binding); } if (GetLinkerCustomVersion(FFortniteMainBranchObjectVersion::GUID) < FFortniteMainBranchObjectVersion::MVVMPropertyPathSelf) { const UWidgetBlueprint* ThisWidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); auto DeprecateSelfPath = [ThisWidgetBlueprint](FMVVMBlueprintPropertyPath& Path) -> bool { Path.GetSource(ThisWidgetBlueprint); return true; }; UE::MVVM::Private::ForEachPropertyPath_Update(this, DeprecateSelfPath, false); } } void UMVVMBlueprintView::PreSave(FObjectPreSaveContext Context) { UWidgetBlueprint* WidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); for (FMVVMBlueprintViewBinding& Binding : Bindings) { Binding.Conversion.SavePinValues(WidgetBlueprint); } for (UMVVMBlueprintViewEvent* Event : Events) { Event->SavePinValues(); } Super::PreSave(Context); } void UMVVMBlueprintView::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); if (PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, Bindings)) { OnBindingsUpdated.Broadcast(); } if (PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, AvailableViewModels)) { OnViewModelsUpdated.Broadcast(); } if (PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, Events)) { OnEventsUpdated.Broadcast(); } } void UMVVMBlueprintView::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChainEvent) { Super::PostEditChangeChainProperty(PropertyChainEvent); if (PropertyChainEvent.PropertyChain.Contains(UMVVMBlueprintView::StaticClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, Bindings)))) { OnBindingsUpdated.Broadcast(); } if (PropertyChainEvent.PropertyChain.Contains(UMVVMBlueprintView::StaticClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, AvailableViewModels)))) { OnViewModelsUpdated.Broadcast(); } if (PropertyChainEvent.PropertyChain.Contains(UMVVMBlueprintView::StaticClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UMVVMBlueprintView, Events)))) { OnEventsUpdated.Broadcast(); } } void UMVVMBlueprintView::PostEditUndo() { Super::PostEditUndo(); OnBindingsUpdated.Broadcast(); OnViewModelsUpdated.Broadcast(); OnEventsUpdated.Broadcast(); OnConditionsUpdated.Broadcast(); } void UMVVMBlueprintView::AddAssetTags(TArray& OutTags) const { } void UMVVMBlueprintView::AddAssetTags(FAssetRegistryTagsContext Context) const { } void UMVVMBlueprintView::OnFieldRenamed(UClass* FieldOwnerClass, FName OldObjectName, FName NewObjectName) { bool bRenamed = false; UWidgetBlueprint* WidgetBlueprint = GetOuterUMVVMWidgetBlueprintExtension_View()->GetWidgetBlueprint(); auto UpdatePaths = [WidgetBlueprint, FieldOwnerClass, &bRenamed, OldObjectName, NewObjectName](FMVVMBlueprintPropertyPath& PropertyPath) -> bool { const bool bDidPathContainField = PropertyPath.OnFieldRenamed(WidgetBlueprint, FieldOwnerClass, OldObjectName, NewObjectName); bRenamed |= bDidPathContainField; return bDidPathContainField; }; UE::MVVM::Private::ForEachPropertyPath_Update(this, UpdatePaths, true); if (bRenamed) { Modify(); OnBindingsUpdated.Broadcast(); FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(WidgetBlueprint); } } #endif