You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
[FYI] Patrick.Boutot Original CL Desc ----------------------------------------------------------------- MVVM: Big rework of the MVVM view compiler. It add supports for conversion function to go from complex to simple. Supports pin split on simple conversion function. Add ability to to support setter function with more than one argument. Build the list of all the sources. #jira UE-200602, UE-200602, UE-200602, UE-200602, UE-200602 #rb editor-ui-systems [CL 29801739 by bob tellez in ue5-main branch]
314 lines
9.5 KiB
C++
314 lines
9.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MVVMBlueprintViewConversionFunction.h"
|
|
#include "MVVMDeveloperProjectSettings.h"
|
|
|
|
#include "Bindings/MVVMConversionFunctionHelper.h"
|
|
#include "Bindings/MVVMBindingHelper.h"
|
|
#include "Engine/Blueprint.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
|
|
#include "EdGraphSchema_K2.h"
|
|
#include "EdGraph/EdGraphPin.h"
|
|
#include "K2Node_CallFunction.h"
|
|
#include "K2Node_FunctionEntry.h"
|
|
#include "K2Node_FunctionResult.h"
|
|
#include "KismetCompiler.h"
|
|
|
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(MVVMBlueprintViewConversionFunction)
|
|
|
|
namespace UE::MVVM::Private
|
|
{
|
|
static FLazyName DefaultConversionFunctionName = TEXT("__ConversionFunction");
|
|
}
|
|
|
|
const UFunction* UMVVMBlueprintViewConversionFunction::GetCompiledFunction(const UClass* SelfContext) const
|
|
{
|
|
if (NeedsWrapperGraph())
|
|
{
|
|
FMemberReference CompiledFunction;
|
|
CompiledFunction.SetSelfMember(GraphName);
|
|
return CompiledFunction.ResolveMember<UFunction>(const_cast<UClass*>(SelfContext));
|
|
}
|
|
return FunctionReference.ResolveMember<UFunction>(const_cast<UClass*>(SelfContext));
|
|
}
|
|
|
|
FName UMVVMBlueprintViewConversionFunction::GetCompiledFunctionName() const
|
|
{
|
|
if (NeedsWrapperGraph())
|
|
{
|
|
return GraphName;
|
|
}
|
|
return FunctionReference.GetMemberName();
|
|
}
|
|
|
|
TVariant<const UFunction*, TSubclassOf<UK2Node>> UMVVMBlueprintViewConversionFunction::GetConversionFunction(const UClass* SelfContext) const
|
|
{
|
|
if (FunctionNode.Get())
|
|
{
|
|
return TVariant<const UFunction*, TSubclassOf<UK2Node>>( TInPlaceType<TSubclassOf<UK2Node>>(), FunctionNode);
|
|
}
|
|
else
|
|
{
|
|
const UFunction* ConversionFunction = FunctionReference.ResolveMember<UFunction>(const_cast<UClass*>(SelfContext));
|
|
return TVariant<const UFunction*, TSubclassOf<UK2Node>>( TInPlaceType<const UFunction*>(), ConversionFunction);
|
|
}
|
|
//return FunctionReference.ResolveMember<UFunction>(WidgetBlueprint->SkeletonGeneratedClass);
|
|
//UK2Node_CallFunction* CallFunctionNode = GetConversionFunctionNode(WidgetBlueprint, Binding, bSourceToDestination);
|
|
//if (CallFunctionNode)
|
|
//{
|
|
// return CallFunctionNode->GetTargetFunction();
|
|
//}
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::Reset()
|
|
{
|
|
FunctionReference = FMemberReference();
|
|
FunctionNode = TSubclassOf<UK2Node>();
|
|
GraphName = FName();
|
|
bWrapperGraphTransient = false;
|
|
SavedPins.Reset();
|
|
CachedWrapperGraph = nullptr;
|
|
CachedWrapperNode = nullptr;
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::InitFromFunction(UBlueprint* InContext, const UFunction* InFunction)
|
|
{
|
|
InitFromFunction(InContext, InFunction, UE::MVVM::Private::DefaultConversionFunctionName.Resolve());
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::InitFromFunction(UBlueprint* InContext, const UFunction* InFunction, FName InGraphName)
|
|
{
|
|
Reset();
|
|
|
|
if (InFunction)
|
|
{
|
|
UClass* OwnerClass = InFunction->GetOuterUClass();
|
|
FGuid MemberGuid;
|
|
UBlueprint::GetGuidFromClassByFieldName<UFunction>(OwnerClass, InFunction->GetFName(), MemberGuid);
|
|
|
|
bool bIsSelf = (InContext->GeneratedClass && InContext->GeneratedClass->IsChildOf(OwnerClass))
|
|
|| (InContext->SkeletonGeneratedClass && InContext->SkeletonGeneratedClass->IsChildOf(OwnerClass));
|
|
if (bIsSelf)
|
|
{
|
|
FunctionReference.SetSelfMember(InFunction->GetFName(), MemberGuid);
|
|
}
|
|
else
|
|
{
|
|
if (UBlueprint* VariableOwnerBP = Cast<UBlueprint>(OwnerClass->ClassGeneratedBy))
|
|
{
|
|
OwnerClass = VariableOwnerBP->SkeletonGeneratedClass;
|
|
}
|
|
|
|
FunctionReference.SetExternalMember(InFunction->GetFName(), OwnerClass, MemberGuid);
|
|
}
|
|
// used to be SetFromField<UFunction>(Function, SelfContext->SkeletonGeneratedClass);
|
|
|
|
if (UE::MVVM::ConversionFunctionHelper::RequiresWrapper(InFunction))
|
|
{
|
|
GraphName = InGraphName;
|
|
bWrapperGraphTransient = !GetDefault<UMVVMDeveloperProjectSettings>()->bAllowConversionFunctionGeneratedGraphInEditor;
|
|
GetOrCreateWrapperGraphInternal(InContext, InFunction);
|
|
SavePinValues(InContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::InitializeFromWrapperGraph(UBlueprint* SelfContext, UEdGraph* Graph)
|
|
{
|
|
Reset();
|
|
|
|
if (UK2Node* WrapperNode = UE::MVVM::ConversionFunctionHelper::GetWrapperNode(Graph))
|
|
{
|
|
if (UK2Node_CallFunction* CallFunction = Cast<UK2Node_CallFunction>(WrapperNode))
|
|
{
|
|
FunctionReference = CallFunction->FunctionReference;
|
|
}
|
|
else
|
|
{
|
|
FunctionNode = WrapperNode->GetClass();
|
|
}
|
|
CachedWrapperGraph = WrapperNode->GetGraph();
|
|
check(CachedWrapperGraph);
|
|
|
|
GraphName = CachedWrapperGraph->GetFName();
|
|
bWrapperGraphTransient = !GetDefault<UMVVMDeveloperProjectSettings>()->bAllowConversionFunctionGeneratedGraphInEditor;
|
|
|
|
CachedWrapperNode = WrapperNode;
|
|
SavePinValues(SelfContext);
|
|
|
|
if (bWrapperGraphTransient && CachedWrapperNode)
|
|
{
|
|
SelfContext->FunctionGraphs.RemoveSingle(CachedWrapperGraph);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::InitializeFromMemberReference(UBlueprint* SelfContext, FMemberReference MemberReference)
|
|
{
|
|
Reset();
|
|
|
|
FunctionReference = MemberReference;
|
|
}
|
|
|
|
UEdGraph* UMVVMBlueprintViewConversionFunction::GetOrCreateIntermediateWrapperGraph(FKismetCompilerContext& Context) const
|
|
{
|
|
if (!NeedsWrapperGraph())
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if (CachedWrapperGraph)
|
|
{
|
|
return CachedWrapperGraph;
|
|
}
|
|
|
|
if (IsWrapperGraphTransient())
|
|
{
|
|
if (FunctionNode.Get())
|
|
{
|
|
ensure(false); // not supported for now
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
const UFunction* ConversionFunction = FunctionReference.ResolveMember<UFunction>(Context.NewClass);
|
|
return GetOrCreateWrapperGraphInternal(Context, ConversionFunction);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TObjectPtr<UEdGraph>* Found = Context.Blueprint->FunctionGraphs.FindByPredicate([GraphName = GetWrapperGraphName()](const UEdGraph* Other) { return Other->GetFName() == GraphName; });
|
|
if (Found)
|
|
{
|
|
CachedWrapperGraph = *Found;
|
|
CachedWrapperNode = UE::MVVM::ConversionFunctionHelper::GetWrapperNode(CachedWrapperGraph);
|
|
}
|
|
return CachedWrapperGraph;
|
|
}
|
|
}
|
|
|
|
UEdGraph* UMVVMBlueprintViewConversionFunction::GetOrCreateWrapperGraph(UBlueprint* Blueprint) const
|
|
{
|
|
if (!NeedsWrapperGraph())
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if (CachedWrapperGraph)
|
|
{
|
|
return CachedWrapperGraph;
|
|
}
|
|
|
|
if (IsWrapperGraphTransient())
|
|
{
|
|
if (FunctionNode.Get())
|
|
{
|
|
ensure(false); // not supported for now
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
const UFunction* ConversionFunction = FunctionReference.ResolveMember<UFunction>(Blueprint->SkeletonGeneratedClass);
|
|
return GetOrCreateWrapperGraphInternal(Blueprint, ConversionFunction);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TObjectPtr<UEdGraph>* Found = Blueprint->FunctionGraphs.FindByPredicate([GraphName = GetWrapperGraphName()](const UEdGraph* Other) { return Other->GetFName() == GraphName; });
|
|
if (Found)
|
|
{
|
|
CachedWrapperGraph = *Found;
|
|
CachedWrapperNode = UE::MVVM::ConversionFunctionHelper::GetWrapperNode(CachedWrapperGraph);
|
|
}
|
|
return CachedWrapperGraph;
|
|
}
|
|
}
|
|
|
|
UEdGraphPin* UMVVMBlueprintViewConversionFunction::GetOrCreateGraphPin(UBlueprint* Blueprint, FName PinName) const
|
|
{
|
|
GetOrCreateWrapperGraph(Blueprint);
|
|
if (CachedWrapperNode)
|
|
{
|
|
return CachedWrapperNode->FindPin(PinName);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
UEdGraph* UMVVMBlueprintViewConversionFunction::GetOrCreateWrapperGraphInternal(FKismetCompilerContext& Context, const UFunction* Function) const
|
|
{
|
|
return GetOrCreateWrapperGraphInternal(Context.Blueprint, Function);
|
|
}
|
|
|
|
UEdGraph* UMVVMBlueprintViewConversionFunction::GetOrCreateWrapperGraphInternal(UBlueprint* Blueprint, const UFunction* Function) const
|
|
{
|
|
bool bConst = true;
|
|
TPair<UEdGraph*, UK2Node*> Result = UE::MVVM::ConversionFunctionHelper::CreateGraph(Blueprint, GraphName, nullptr, Function, bConst, bWrapperGraphTransient);
|
|
CachedWrapperGraph = Result.Get<0>();
|
|
CachedWrapperNode = Result.Get<1>();
|
|
LoadPinValuesInternal(Blueprint);
|
|
return CachedWrapperGraph;
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::RemoveWrapperGraph(UBlueprint* Blueprint)
|
|
{
|
|
TObjectPtr<UEdGraph>* Result = Blueprint->FunctionGraphs.FindByPredicate([WrapperName = GraphName](const UEdGraph* GraphPtr) { return GraphPtr->GetFName() == WrapperName; });
|
|
if (Result)
|
|
{
|
|
FBlueprintEditorUtils::RemoveGraph(Blueprint, Result->Get());
|
|
}
|
|
CachedWrapperGraph = nullptr;
|
|
CachedWrapperNode = nullptr;
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::SetGraphPin(UBlueprint* Blueprint, FName PinName, const FMVVMBlueprintPropertyPath& Path)
|
|
{
|
|
if (!NeedsWrapperGraph())
|
|
{
|
|
return;
|
|
}
|
|
|
|
UEdGraphPin* GraphPin = GetOrCreateGraphPin(Blueprint, PinName);
|
|
|
|
// Set the value and make the blueprint as dirty before creating the pin.
|
|
//A property may not be created yet and the skeletal needs to be recreated.
|
|
FMVVMBlueprintPin* Pin = SavedPins.FindByPredicate([PinName](const FMVVMBlueprintPin& Other) { return PinName == Other.GetName(); });
|
|
if (!Pin)
|
|
{
|
|
Pin = &SavedPins.Add_GetRef(FMVVMBlueprintPin::CreateFromPin(Blueprint, GraphPin));
|
|
}
|
|
Pin->SetPath(Path);
|
|
|
|
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);
|
|
|
|
UE::MVVM::ConversionFunctionHelper::SetPropertyPathForPin(Blueprint, Path, GraphPin);
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::SavePinValues(UBlueprint* Blueprint)
|
|
{
|
|
if (CachedWrapperNode)
|
|
{
|
|
SavedPins.Reset();
|
|
for (UEdGraphPin* Pin : CachedWrapperNode->Pins)
|
|
{
|
|
if (Pin->PinName != UEdGraphSchema_K2::PN_Self && Pin->PinName != UEdGraphSchema_K2::PN_Execute && Pin->Direction == EGPD_Input)
|
|
{
|
|
SavedPins.Add(FMVVMBlueprintPin::CreateFromPin(Blueprint, Pin));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMVVMBlueprintViewConversionFunction::LoadPinValuesInternal(UBlueprint* Blueprint) const
|
|
{
|
|
if (CachedWrapperNode)
|
|
{
|
|
for (const FMVVMBlueprintPin& Pin : SavedPins)
|
|
{
|
|
if (UEdGraphPin* GraphPin = CachedWrapperNode->FindPin(Pin.GetName()))
|
|
{
|
|
Pin.CopyTo(Blueprint, GraphPin);
|
|
}
|
|
}
|
|
}
|
|
} |