2023-04-26 14:13:43 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "MVVMDebugSnapshot.h"
|
|
|
|
|
#include "MVVMDebugView.h"
|
|
|
|
|
#include "MVVMDebugViewClass.h"
|
|
|
|
|
|
|
|
|
|
#include "Bindings/MVVMCompiledBindingLibrary.h"
|
|
|
|
|
#include "Blueprint/UserWidget.h"
|
|
|
|
|
#include "Engine/LocalPlayer.h"
|
|
|
|
|
#include "Engine/World.h"
|
|
|
|
|
#include "Templates/ValueOrError.h"
|
|
|
|
|
#include "MVVMDebugView.h"
|
|
|
|
|
#include "MVVMDebugViewModel.h"
|
|
|
|
|
#include "MVVMViewModelBase.h"
|
|
|
|
|
#include "UObject/UObjectIterator.h"
|
|
|
|
|
#include "View/MVVMView.h"
|
|
|
|
|
#include "View/MVVMViewClass.h"
|
|
|
|
|
|
|
|
|
|
namespace UE::MVVM
|
|
|
|
|
{
|
|
|
|
|
namespace Private
|
|
|
|
|
{
|
2023-12-01 11:13:35 -05:00
|
|
|
|
|
|
|
|
FMVVMViewSourceDebugEntry CreateSourceInstanceEntry(const UMVVMView* View, const FMVVMView_Source& ViewSource)
|
2023-04-26 14:13:43 -04:00
|
|
|
{
|
|
|
|
|
FMVVMViewSourceDebugEntry Result;
|
2023-12-01 11:13:35 -05:00
|
|
|
Result.SourceInstanceName = View->GetViewClass()->GetSource(ViewSource.ClassKey).GetName();
|
2023-04-26 14:13:43 -04:00
|
|
|
Result.SourceAsset = ViewSource.Source ? FAssetData(ViewSource.Source->GetClass()) : FAssetData();
|
|
|
|
|
Result.ViewModelDebugId = FGuid::NewGuid();
|
|
|
|
|
Result.LiveSource = ViewSource.Source;
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-01 11:13:35 -05:00
|
|
|
FMVVMViewBindingDebugEntry CreateViewBindingDebugEntry(const UMVVMViewClass* ViewClass, const FMVVMViewClass_Binding& Binding, int32 Index)
|
2023-04-26 14:13:43 -04:00
|
|
|
{
|
|
|
|
|
FMVVMViewBindingDebugEntry Result;
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
Result.BlueprintViewBindingId = Binding.GetEditorId();
|
|
|
|
|
#endif
|
2023-06-09 10:26:25 -04:00
|
|
|
if (ViewClass->GetBindingLibrary().IsLoaded())
|
2023-04-26 14:13:43 -04:00
|
|
|
{
|
2023-06-09 10:26:25 -04:00
|
|
|
if (Binding.GetBinding().GetSourceFieldPath().IsValid())
|
|
|
|
|
{
|
|
|
|
|
TValueOrError<FString, FString> SourceFieldPathValue = ViewClass->GetBindingLibrary().FieldPathToString(Binding.GetBinding().GetSourceFieldPath(), false);
|
|
|
|
|
Result.SourceFieldPath = SourceFieldPathValue.HasValue() ? SourceFieldPathValue.StealValue() : SourceFieldPathValue.StealError();
|
|
|
|
|
}
|
|
|
|
|
if (Binding.GetBinding().GetDestinationFieldPath().IsValid())
|
|
|
|
|
{
|
|
|
|
|
TValueOrError<FString, FString> DestinationFieldPathValue = ViewClass->GetBindingLibrary().FieldPathToString(Binding.GetBinding().GetDestinationFieldPath(), false);
|
|
|
|
|
Result.DestinationFieldPath = DestinationFieldPathValue.HasValue() ? DestinationFieldPathValue.StealValue() : DestinationFieldPathValue.StealError();
|
|
|
|
|
}
|
|
|
|
|
if (Binding.GetBinding().GetConversionFunctionFieldPath().IsValid())
|
|
|
|
|
{
|
|
|
|
|
TValueOrError<FString, FString> ConversionFieldPathValue = ViewClass->GetBindingLibrary().FieldPathToString(Binding.GetBinding().GetConversionFunctionFieldPath(), false);
|
|
|
|
|
Result.ConversionFunctionFieldPath = ConversionFieldPathValue.HasValue() ? ConversionFieldPathValue.StealValue() : ConversionFieldPathValue.StealError();
|
|
|
|
|
}
|
2023-04-26 14:13:43 -04:00
|
|
|
}
|
|
|
|
|
Result.CompiledBindingIndex = Index;
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FMVVMViewModelFieldBoundDebugEntry CreateViewModelFieldBoundDebugEntry(const UE::FieldNotification::FFieldMulticastDelegate::FDelegateView& DelegateView)
|
|
|
|
|
{
|
|
|
|
|
FMVVMViewModelFieldBoundDebugEntry Result;
|
2023-05-26 12:02:21 -04:00
|
|
|
Result.KeyObjectName = DelegateView.KeyObject ? DelegateView.KeyObject->GetFName() : FName();
|
|
|
|
|
Result.KeyFieldId = FFieldNotificationId(DelegateView.KeyField.GetName());
|
|
|
|
|
Result.BindingFunctionName = DelegateView.BindingFunctionName;
|
|
|
|
|
Result.BindingObjectPathName = DelegateView.BindingObject ? DelegateView.BindingObject->GetPathName() : FString();
|
|
|
|
|
Result.LiveInstanceKeyObject = DelegateView.KeyObject;
|
|
|
|
|
Result.LiveInstanceBindingObject = DelegateView.BindingObject;
|
2023-04-26 14:13:43 -04:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
}//namespace private
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FMVVMViewDebugEntry> FDebugSnapshot::FindView(FGuid Id) const
|
|
|
|
|
{
|
|
|
|
|
const TSharedPtr<FMVVMViewDebugEntry>* Result = Views.FindByPredicate([Id](const TSharedPtr<FMVVMViewDebugEntry>& Other){ return Other->ViewInstanceDebugId == Id; });
|
|
|
|
|
return Result ? *Result : TSharedPtr<FMVVMViewDebugEntry>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FMVVMViewModelDebugEntry> FDebugSnapshot::FindViewModel(FGuid Id) const
|
|
|
|
|
{
|
|
|
|
|
const TSharedPtr<FMVVMViewModelDebugEntry>* Result = ViewModels.FindByPredicate([Id](const TSharedPtr<FMVVMViewModelDebugEntry>& Other) { return Other->ViewModelDebugId == Id; });
|
|
|
|
|
return Result ? *Result : TSharedPtr<FMVVMViewModelDebugEntry>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FDebugSnapshot> FDebugSnapshot::CreateSnapshot()
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FDebugSnapshot> Snapshot = MakeShared<FDebugSnapshot>();
|
|
|
|
|
|
|
|
|
|
for (FThreadSafeObjectIterator It(UMVVMView::StaticClass()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
if (It->IsTemplate(RF_ClassDefaultObject))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UMVVMView* View = CastChecked<UMVVMView>(*It);
|
|
|
|
|
UUserWidget* UserWidget = View->GetOuterUUserWidget();
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FMVVMViewDebugEntry> DebugEntry = MakeShared<FMVVMViewDebugEntry>();
|
|
|
|
|
if (UserWidget)
|
|
|
|
|
{
|
|
|
|
|
DebugEntry->UserWidgetInstanceName = UserWidget->GetFName();
|
|
|
|
|
ULocalPlayer* LocalPlayer = UserWidget->GetOwningLocalPlayer();
|
|
|
|
|
DebugEntry->LocalPlayerName = LocalPlayer ? LocalPlayer->GetFName() : FName();
|
|
|
|
|
UWorld* World = UserWidget->GetWorld();
|
|
|
|
|
DebugEntry->WorldName = World ? World->GetFName() : FName();
|
|
|
|
|
DebugEntry->UserWidgetAsset = FAssetData(UserWidget->GetClass());
|
|
|
|
|
}
|
2023-12-01 11:13:35 -05:00
|
|
|
|
|
|
|
|
for (const FMVVMView_Source& ViewSource : View->GetSources())
|
2023-04-26 14:13:43 -04:00
|
|
|
{
|
2023-12-01 11:13:35 -05:00
|
|
|
DebugEntry->Sources.Add(Private::CreateSourceInstanceEntry(View, ViewSource));
|
2023-04-26 14:13:43 -04:00
|
|
|
}
|
|
|
|
|
DebugEntry->ViewClassDebugId = Snapshot->FindOrAddViewClassEntry(View->GetViewClass())->ViewClassDebugId;
|
|
|
|
|
DebugEntry->ViewInstanceDebugId = FGuid::NewGuid();
|
|
|
|
|
DebugEntry->LiveView = View;
|
|
|
|
|
|
|
|
|
|
Snapshot->Views.Add(DebugEntry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (FThreadSafeObjectIterator It(UMVVMViewModelBase::StaticClass()); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
if (It->IsTemplate(RF_ClassDefaultObject))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UMVVMViewModelBase* ViewModel = CastChecked<UMVVMViewModelBase>(*It);
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FMVVMViewModelDebugEntry> DebugEntry = MakeShared<FMVVMViewModelDebugEntry>();
|
|
|
|
|
DebugEntry->Name = ViewModel->GetFName();
|
2023-05-26 12:02:21 -04:00
|
|
|
DebugEntry->PathName = ViewModel->GetPathName();
|
2023-04-26 14:13:43 -04:00
|
|
|
DebugEntry->ViewModelAsset = FAssetData(ViewModel->GetClass());
|
|
|
|
|
for (const UE::FieldNotification::FFieldMulticastDelegate::FDelegateView& DelegateView : ViewModel->GetNotificationDelegateView())
|
|
|
|
|
{
|
2023-12-01 11:13:35 -05:00
|
|
|
DebugEntry->FieldBound.Add(Private::CreateViewModelFieldBoundDebugEntry(DelegateView));
|
2023-04-26 14:13:43 -04:00
|
|
|
}
|
|
|
|
|
//DebugEntry.PropertyBag;
|
|
|
|
|
DebugEntry->ViewModelDebugId = FGuid::NewGuid();
|
|
|
|
|
DebugEntry->LiveViewModel = ViewModel;
|
|
|
|
|
|
|
|
|
|
Snapshot->ViewModels.Add(DebugEntry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Snapshot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedRef<FMVVMViewClassDebugEntry> FDebugSnapshot::FindOrAddViewClassEntry(const UMVVMViewClass* ViewClass)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FMVVMViewClassDebugEntry>* Entry = ViewClasses.FindByPredicate([ViewClass](const TSharedPtr<FMVVMViewClassDebugEntry>& Entry) { return Entry->LiveViewClass == ViewClass; });
|
|
|
|
|
if (Entry)
|
|
|
|
|
{
|
|
|
|
|
return Entry->ToSharedRef();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef<FMVVMViewClassDebugEntry> NewEntry = MakeShared<FMVVMViewClassDebugEntry>();
|
|
|
|
|
ViewClasses.Add(NewEntry);
|
|
|
|
|
NewEntry->ViewClassDebugId = FGuid::NewGuid();
|
|
|
|
|
NewEntry->LiveViewClass = ViewClass;
|
|
|
|
|
|
|
|
|
|
int32 Index = 0;
|
2023-12-01 11:13:35 -05:00
|
|
|
for (const FMVVMViewClass_Binding& Binding : ViewClass->GetBindings())
|
2023-04-26 14:13:43 -04:00
|
|
|
{
|
|
|
|
|
NewEntry->Bindings.Add(Private::CreateViewBindingDebugEntry(ViewClass, Binding, Index));
|
|
|
|
|
++Index;
|
|
|
|
|
}
|
|
|
|
|
return NewEntry;
|
|
|
|
|
}
|
|
|
|
|
}//namespace UE::MVVM
|