125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | #include "K2Node_CSCancellableAsyncAction.h"
 | ||
|  | 
 | ||
|  | #include "BlueprintActionDatabaseRegistrar.h"
 | ||
|  | #include "BlueprintFunctionNodeSpawner.h"
 | ||
|  | #include "BlueprintNodeSpawner.h"
 | ||
|  | #include "Delegates/Delegate.h"
 | ||
|  | #include "EdGraph/EdGraphNode.h"
 | ||
|  | #include "Extensions/BlueprintActions/CSCancellableAsyncAction.h"
 | ||
|  | #include "HAL/Platform.h"
 | ||
|  | #include "Misc/AssertionMacros.h"
 | ||
|  | #include "Templates/Casts.h"
 | ||
|  | #include "Templates/SubclassOf.h"
 | ||
|  | #include "TypeGenerator/CSClass.h"
 | ||
|  | #include "UObject/Class.h"
 | ||
|  | #include "UObject/Field.h"
 | ||
|  | #include "UObject/NameTypes.h"
 | ||
|  | #include "UObject/ObjectPtr.h"
 | ||
|  | #include "UObject/UnrealType.h"
 | ||
|  | #include "UObject/WeakObjectPtrTemplates.h"
 | ||
|  | 
 | ||
|  | #define LOCTEXT_NAMESPACE "K2Node"
 | ||
|  | 
 | ||
|  | UK2Node_CSCancellableAsyncAction::UK2Node_CSCancellableAsyncAction() | ||
|  | { | ||
|  | 	ProxyActivateFunctionName = GET_FUNCTION_NAME_CHECKED(UCSCancellableAsyncAction, Activate); | ||
|  | } | ||
|  | 
 | ||
|  | void UK2Node_CSCancellableAsyncAction::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const | ||
|  | { | ||
|  | 	struct GetMenuActions_Utils | ||
|  | 	{ | ||
|  | 		static bool IsFactoryMethod(const UFunction* Function, const UClass* InTargetType) | ||
|  | 		{ | ||
|  | 			if (!Function->HasAnyFunctionFlags(FUNC_Static)) | ||
|  | 			{ | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (!Function->GetOwnerClass()->HasAnyClassFlags(CLASS_Deprecated | CLASS_NewerVersionExists)) | ||
|  | 			{ | ||
|  | 				FObjectProperty* ReturnProperty = CastField<FObjectProperty>(Function->GetReturnProperty()); | ||
|  | 				// see if the function is a static factory method
 | ||
|  | 				bool const bIsFactoryMethod = (ReturnProperty != nullptr) && (ReturnProperty->PropertyClass != nullptr) && | ||
|  | 					ReturnProperty->PropertyClass->IsChildOf(InTargetType); | ||
|  | 
 | ||
|  | 				return bIsFactoryMethod; | ||
|  | 			} | ||
|  | 			else | ||
|  | 			{ | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		static void SetNodeFunc(UEdGraphNode* NewNode, bool /*bIsTemplateNode*/, TWeakObjectPtr<UFunction> FunctionPtr) | ||
|  | 		{ | ||
|  | 			UK2Node_CSCancellableAsyncAction* AsyncTaskNode = CastChecked<UK2Node_CSCancellableAsyncAction>(NewNode); | ||
|  | 			if (FunctionPtr.IsValid()) | ||
|  | 			{ | ||
|  | 				UFunction* Func = FunctionPtr.Get(); | ||
|  | 				FObjectProperty* ReturnProp = CastFieldChecked<FObjectProperty>(Func->GetReturnProperty()); | ||
|  | 						 | ||
|  | 				AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); | ||
|  | 				AsyncTaskNode->ProxyFactoryClass        = Func->GetOuterUClass(); | ||
|  | 				AsyncTaskNode->ProxyClass               = ReturnProp->PropertyClass; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		static UBlueprintNodeSpawner* MakeAction(UClass* NodeClass, const UFunction* FactoryFunc) | ||
|  | 		{ | ||
|  | 			UClass* FactoryClass = FactoryFunc ? FactoryFunc->GetOwnerClass() : nullptr; | ||
|  | 			if (FactoryClass && FactoryClass->HasMetaData(TEXT("HasDedicatedAsyncNode"))) | ||
|  | 			{ | ||
|  | 				// Wants to use a more specific blueprint node to handle the async action
 | ||
|  | 				return nullptr; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(FactoryFunc); | ||
|  | 			check(NodeSpawner != nullptr); | ||
|  | 			NodeSpawner->NodeClass = NodeClass; | ||
|  | 
 | ||
|  | 			TWeakObjectPtr<UFunction> FunctionPtr = MakeWeakObjectPtr(const_cast<UFunction*>(FactoryFunc)); | ||
|  | 			NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(GetMenuActions_Utils::SetNodeFunc, FunctionPtr); | ||
|  | 
 | ||
|  | 			return NodeSpawner; | ||
|  | 		} | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	UClass* NodeClass = GetClass(); | ||
|  | 	UClass* TargetType = UCSCancellableAsyncAction::StaticClass(); | ||
|  | 
 | ||
|  | 	for (TObjectIterator<UCSClass> ClassIt; ClassIt; ++ClassIt) | ||
|  | 	{ | ||
|  | 		UCSClass* Class = *ClassIt; | ||
|  | 		if (Class->HasAnyClassFlags(CLASS_Abstract) || !Class->IsChildOf(TargetType)) | ||
|  | 		{ | ||
|  | 			continue; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt) | ||
|  | 		{ | ||
|  | 			UFunction* Function = *FuncIt; | ||
|  | 			if (!GetMenuActions_Utils::IsFactoryMethod(Function, TargetType)) | ||
|  | 			{ | ||
|  | 				continue; | ||
|  | 			} | ||
|  | 			else if (UBlueprintNodeSpawner* NewAction = GetMenuActions_Utils::MakeAction(NodeClass, Function)) | ||
|  | 			{ | ||
|  | 				ActionRegistrar.AddBlueprintAction(Class, NewAction); | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void UK2Node_CSCancellableAsyncAction::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) | ||
|  | { | ||
|  | 	if (ProxyClass->bLayoutChanging) | ||
|  | 	{ | ||
|  | 		return; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	Super::ExpandNode(CompilerContext, SourceGraph); | ||
|  | } | ||
|  | 
 | ||
|  | #undef LOCTEXT_NAMESPACE
 |