2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "BlueprintGraphPrivatePCH.h"
# include "CompilerResultsLog.h"
# include "KismetCompiler.h"
2014-07-14 14:09:47 -04:00
# include "BlueprintNodeSpawner.h"
2014-08-23 23:06:59 -04:00
# include "BlueprintActionDatabaseRegistrar.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "UK2Node_BaseAsyncTask"
2014-10-14 10:29:11 -04:00
UK2Node_BaseAsyncTask : : UK2Node_BaseAsyncTask ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
, ProxyFactoryFunctionName ( NAME_None )
, ProxyFactoryClass ( NULL )
, ProxyClass ( NULL )
2014-04-23 19:30:38 -04:00
, ProxyActivateFunctionName ( NAME_None )
2014-03-14 14:13:41 -04:00
{
}
2014-09-03 18:14:09 -04:00
FText UK2Node_BaseAsyncTask : : GetTooltipText ( ) const
2014-03-14 14:13:41 -04:00
{
2014-04-23 19:30:38 -04:00
const FString FunctionToolTipText = UK2Node_CallFunction : : GetDefaultTooltipForFunction ( GetFactoryFunction ( ) ) ;
2014-09-03 18:14:09 -04:00
return FText : : FromString ( FunctionToolTipText ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:30:38 -04:00
FText UK2Node_BaseAsyncTask : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2015-03-27 14:07:28 -04:00
if ( GetFactoryFunction ( ) = = nullptr )
{
return FText ( LOCTEXT ( " UK2Node_BaseAsyncTaskGetNodeTitle " , " Async Task: Missing Function " ) ) ;
}
2015-03-27 12:54:58 -04:00
const FText FunctionToolTipText = UK2Node_CallFunction : : GetUserFacingFunctionName ( GetFactoryFunction ( ) ) ;
return FunctionToolTipText ;
2014-03-14 14:13:41 -04:00
}
2014-08-04 12:39:34 -04:00
bool UK2Node_BaseAsyncTask : : IsCompatibleWithGraph ( const UEdGraph * TargetGraph ) const
2014-07-30 21:01:24 -04:00
{
2014-10-16 14:38:52 -04:00
bool bIsCompatible = false ;
// Can only place events in ubergraphs and macros (other code will help prevent macros with latents from ending up in functions), and basicasync task creates an event node:
EGraphType GraphType = TargetGraph - > GetSchema ( ) - > GetGraphType ( TargetGraph ) ;
if ( GraphType = = EGraphType : : GT_Ubergraph | | GraphType = = EGraphType : : GT_Macro )
2014-07-30 21:01:24 -04:00
{
2014-10-16 14:38:52 -04:00
bIsCompatible = true ;
2014-07-30 21:01:24 -04:00
}
2014-08-04 12:39:34 -04:00
return bIsCompatible & & Super : : IsCompatibleWithGraph ( TargetGraph ) ;
2014-07-30 21:01:24 -04:00
}
2014-03-14 14:13:41 -04:00
void UK2Node_BaseAsyncTask : : AllocateDefaultPins ( )
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
CreatePin ( EGPD_Input , K2Schema - > PC_Exec , TEXT ( " " ) , NULL , false , false , K2Schema - > PN_Execute ) ;
CreatePin ( EGPD_Output , K2Schema - > PC_Exec , TEXT ( " " ) , NULL , false , false , K2Schema - > PN_Then ) ;
UFunction * DelegateSignatureFunction = NULL ;
for ( TFieldIterator < UProperty > PropertyIt ( ProxyClass , EFieldIteratorFlags : : ExcludeSuper ) ; PropertyIt ; + + PropertyIt )
{
2014-04-23 19:30:38 -04:00
if ( UMulticastDelegateProperty * Property = Cast < UMulticastDelegateProperty > ( * PropertyIt ) )
2014-03-14 14:13:41 -04:00
{
2014-06-16 10:30:41 -04:00
CreatePin ( EGPD_Output , K2Schema - > PC_Exec , TEXT ( " " ) , NULL , false , false , * Property - > GetName ( ) ) ;
if ( ! DelegateSignatureFunction )
{
DelegateSignatureFunction = Property - > SignatureFunction ;
2014-03-14 14:13:41 -04:00
}
}
2014-06-16 10:30:41 -04:00
}
2014-03-14 14:13:41 -04:00
if ( DelegateSignatureFunction )
{
for ( TFieldIterator < UProperty > PropIt ( DelegateSignatureFunction ) ; PropIt & & ( PropIt - > PropertyFlags & CPF_Parm ) ; + + PropIt )
{
UProperty * Param = * PropIt ;
const bool bIsFunctionInput = ! Param - > HasAnyPropertyFlags ( CPF_OutParm ) | | Param - > HasAnyPropertyFlags ( CPF_ReferenceParm ) ;
if ( bIsFunctionInput )
{
UEdGraphPin * Pin = CreatePin ( EGPD_Output , TEXT ( " " ) , TEXT ( " " ) , NULL , false , false , Param - > GetName ( ) ) ;
K2Schema - > ConvertPropertyToPinType ( Param , /*out*/ Pin - > PinType ) ;
}
}
}
bool bAllPinsGood = true ;
UFunction * Function = ProxyFactoryClass - > FindFunctionByName ( ProxyFactoryFunctionName ) ;
if ( Function )
{
TSet < FString > PinsToHide ;
[UE-2345] BP - enforce const-correctness in native const class method overrides
this change introduces enforcement of 'const-correctness' into implemented function graphs.
summary:
if you have a function declared in C++ like this:
UFUNCTION(BlueprintImplementableEvent)
int32 MyFunctionThatReturnsSomeValue() const;
if you implement that (BPIE) function in a Blueprint that's parented to that native class, it will now be flagged as 'const'. this makes any properties of 'self' read-only within the context of that graph, which means the compiler will emit an error if you try to set a property or otherwise call a non-const, non-static function with 'self' as the target.
if there happens to already be an implemented const function in a Blueprint that was in place prior to this change, the compiler will emit a warning instead of an error, in order to allow existing Blueprints that may currently be "violating" const within the context of a const BPIE function to still compile, while still alerting to issues that should probably be addressed.
notes:
1) this also applies to BlueprintNativeEvent (BPNE) implementations, and also when implementing BPIE/BPNE interface methods that are also declared as const
2) a const BPIE/BPNE function with no return value and no output parameters will be implemented as a "normal" impure function, and not as an event as in the non-const case
3) a const BPIE/BPNE function with a return value and/or output parameters will currently be implemented as a pure function, regardless of whether or not BlueprintCallable is specified
4) this CL also retains some consolidation of static function validation code that i had previously done, mostly to allow static functions to more easily be whitelisted for const function graphs
#codereview Nick.Whiting, Michael.Noland
[CL 2368059 by Phillip Kavan in Main branch]
2014-11-21 17:47:17 -05:00
FBlueprintEditorUtils : : GetHiddenPinsForFunction ( GetGraph ( ) , Function , PinsToHide ) ;
2014-03-14 14:13:41 -04:00
for ( TFieldIterator < UProperty > PropIt ( Function ) ; PropIt & & ( PropIt - > PropertyFlags & CPF_Parm ) ; + + PropIt )
{
UProperty * Param = * PropIt ;
const bool bIsFunctionInput = ! Param - > HasAnyPropertyFlags ( CPF_OutParm ) | | Param - > HasAnyPropertyFlags ( CPF_ReferenceParm ) ;
if ( ! bIsFunctionInput )
{
// skip function output, it's internal node data
continue ;
}
const bool bIsRefParam = Param - > HasAnyPropertyFlags ( CPF_ReferenceParm ) & & bIsFunctionInput ;
UEdGraphPin * Pin = CreatePin ( EGPD_Input , TEXT ( " " ) , TEXT ( " " ) , NULL , false , bIsRefParam , Param - > GetName ( ) ) ;
const bool bPinGood = ( Pin ! = NULL ) & & K2Schema - > ConvertPropertyToPinType ( Param , /*out*/ Pin - > PinType ) ;
if ( bPinGood )
{
//Flag pin as read only for const reference property
2014-06-17 13:25:57 -04:00
Pin - > bDefaultValueIsIgnored = Param - > HasAllPropertyFlags ( CPF_ConstParm | CPF_ReferenceParm ) & & ( ! Function - > HasMetaData ( FBlueprintMetadata : : MD_AutoCreateRefTerm ) | | Pin - > PinType . bIsArray ) ;
2014-03-14 14:13:41 -04:00
const bool bAdvancedPin = Param - > HasAllPropertyFlags ( CPF_AdvancedDisplay ) ;
Pin - > bAdvancedView = bAdvancedPin ;
if ( bAdvancedPin & & ( ENodeAdvancedPins : : NoPins = = AdvancedPinDisplay ) )
{
AdvancedPinDisplay = ENodeAdvancedPins : : Hidden ;
}
2014-06-16 10:30:41 -04:00
K2Schema - > SetPinDefaultValue ( Pin , Function , Param ) ;
2014-03-14 14:13:41 -04:00
if ( PinsToHide . Contains ( Pin - > PinName ) )
{
Pin - > bHidden = true ;
Pin - > DefaultValue = TEXT ( " 0 " ) ;
}
}
bAllPinsGood = bAllPinsGood & & bPinGood ;
}
}
Super : : AllocateDefaultPins ( ) ;
}
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
bool UK2Node_BaseAsyncTask : : FBaseAsyncTaskHelper : : ValidDataPin ( const UEdGraphPin * Pin , EEdGraphPinDirection Direction , const UEdGraphSchema_K2 * Schema )
{
check ( Schema ) ;
const bool bValidDataPin = Pin
& & ( Pin - > PinName ! = Schema - > PN_Execute )
& & ( Pin - > PinName ! = Schema - > PN_Then )
& & ( Pin - > PinType . PinCategory ! = Schema - > PC_Exec ) ;
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
const bool bProperDirection = Pin & & ( Pin - > Direction = = Direction ) ;
return bValidDataPin & & bProperDirection ;
2014-06-16 10:30:41 -04:00
}
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
bool UK2Node_BaseAsyncTask : : FBaseAsyncTaskHelper : : CreateDelegateForNewFunction ( UEdGraphPin * DelegateInputPin , FName FunctionName , UK2Node * CurrentNode , UEdGraph * SourceGraph , FKismetCompilerContext & CompilerContext )
{
2014-06-16 10:30:41 -04:00
const UEdGraphSchema_K2 * Schema = CompilerContext . GetSchema ( ) ;
2014-07-03 10:59:02 -04:00
check ( DelegateInputPin & & Schema & & CurrentNode & & SourceGraph & & ( FunctionName ! = NAME_None ) ) ;
bool bResult = true ;
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
// WORKAROUND, so we can create delegate from nonexistent function by avoiding check at expanding step
// instead simply: Schema->TryCreateConnection(AddDelegateNode->GetDelegatePin(), CurrentCENode->FindPinChecked(UK2Node_CustomEvent::DelegateOutputName));
UK2Node_Self * SelfNode = CompilerContext . SpawnIntermediateNode < UK2Node_Self > ( CurrentNode , SourceGraph ) ;
SelfNode - > AllocateDefaultPins ( ) ;
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
UK2Node_CreateDelegate * CreateDelegateNode = CompilerContext . SpawnIntermediateNode < UK2Node_CreateDelegate > ( CurrentNode , SourceGraph ) ;
CreateDelegateNode - > AllocateDefaultPins ( ) ;
bResult & = Schema - > TryCreateConnection ( DelegateInputPin , CreateDelegateNode - > GetDelegateOutPin ( ) ) ;
bResult & = Schema - > TryCreateConnection ( SelfNode - > FindPinChecked ( Schema - > PN_Self ) , CreateDelegateNode - > GetObjectInPin ( ) ) ;
CreateDelegateNode - > SetFunction ( FunctionName ) ;
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
return bResult ;
}
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
bool UK2Node_BaseAsyncTask : : FBaseAsyncTaskHelper : : CopyEventSignature ( UK2Node_CustomEvent * CENode , UFunction * Function , const UEdGraphSchema_K2 * Schema )
{
check ( CENode & & Function & & Schema ) ;
bool bResult = true ;
for ( TFieldIterator < UProperty > PropIt ( Function ) ; PropIt & & ( PropIt - > PropertyFlags & CPF_Parm ) ; + + PropIt )
2014-04-23 18:50:20 -04:00
{
2014-07-03 10:59:02 -04:00
const UProperty * Param = * PropIt ;
if ( ! Param - > HasAnyPropertyFlags ( CPF_OutParm ) | | Param - > HasAnyPropertyFlags ( CPF_ReferenceParm ) )
2014-04-23 18:50:20 -04:00
{
2014-07-03 10:59:02 -04:00
FEdGraphPinType PinType ;
bResult & = Schema - > ConvertPropertyToPinType ( Param , /*out*/ PinType ) ;
2015-03-31 10:32:10 -04:00
bResult & = ( NULL ! = CENode - > CreateUserDefinedPin ( Param - > GetName ( ) , PinType , EGPD_Output ) ) ;
2014-04-23 18:50:20 -04:00
}
2014-06-16 10:30:41 -04:00
}
2014-07-03 10:59:02 -04:00
return bResult ;
}
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
bool UK2Node_BaseAsyncTask : : FBaseAsyncTaskHelper : : HandleDelegateImplementation (
UMulticastDelegateProperty * CurrentProperty , const TArray < FBaseAsyncTaskHelper : : FOutputPinAndLocalVariable > & VariableOutputs ,
UEdGraphPin * ProxyObjectPin , UEdGraphPin * & InOutLastThenPin ,
UK2Node * CurrentNode , UEdGraph * SourceGraph , FKismetCompilerContext & CompilerContext )
{
bool bIsErrorFree = true ;
const UEdGraphSchema_K2 * Schema = CompilerContext . GetSchema ( ) ;
check ( CurrentProperty & & ProxyObjectPin & & InOutLastThenPin & & CurrentNode & & SourceGraph & & Schema ) ;
UEdGraphPin * PinForCurrentDelegateProperty = CurrentNode - > FindPin ( CurrentProperty - > GetName ( ) ) ;
if ( ! PinForCurrentDelegateProperty | | ( Schema - > PC_Exec ! = PinForCurrentDelegateProperty - > PinType . PinCategory ) )
{
FText ErrorMessage = FText : : Format ( LOCTEXT ( " WrongDelegateProperty " , " BaseAsyncTask: Cannot find execution pin for delegate " ) , FText : : FromString ( CurrentProperty - > GetName ( ) ) ) ;
CompilerContext . MessageLog . Error ( * ErrorMessage . ToString ( ) , CurrentNode ) ;
return false ;
2014-04-23 18:50:20 -04:00
}
2014-07-03 10:59:02 -04:00
UK2Node_CustomEvent * CurrentCENode = CompilerContext . SpawnIntermediateNode < UK2Node_CustomEvent > ( CurrentNode , SourceGraph ) ;
2014-04-23 18:50:20 -04:00
{
2014-07-03 10:59:02 -04:00
UK2Node_AddDelegate * AddDelegateNode = CompilerContext . SpawnIntermediateNode < UK2Node_AddDelegate > ( CurrentNode , SourceGraph ) ;
AddDelegateNode - > SetFromProperty ( CurrentProperty , false ) ;
AddDelegateNode - > AllocateDefaultPins ( ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( AddDelegateNode - > FindPinChecked ( Schema - > PN_Self ) , ProxyObjectPin ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( InOutLastThenPin , AddDelegateNode - > FindPinChecked ( Schema - > PN_Execute ) ) ;
InOutLastThenPin = AddDelegateNode - > FindPinChecked ( Schema - > PN_Then ) ;
CurrentCENode - > CustomFunctionName = * FString : : Printf ( TEXT ( " %s_%s " ) , * CurrentProperty - > GetName ( ) , * CurrentCENode - > NodeGuid . ToString ( ) ) ;
CurrentCENode - > AllocateDefaultPins ( ) ;
2014-04-23 18:50:20 -04:00
2014-07-03 10:59:02 -04:00
bIsErrorFree & = FBaseAsyncTaskHelper : : CreateDelegateForNewFunction ( AddDelegateNode - > GetDelegatePin ( ) , CurrentCENode - > GetFunctionName ( ) , CurrentNode , SourceGraph , CompilerContext ) ;
bIsErrorFree & = FBaseAsyncTaskHelper : : CopyEventSignature ( CurrentCENode , AddDelegateNode - > GetDelegateSignature ( ) , Schema ) ;
}
UEdGraphPin * LastActivatedNodeThen = CurrentCENode - > FindPinChecked ( Schema - > PN_Then ) ;
for ( auto OutputPair : VariableOutputs ) // CREATE CHAIN OF ASSIGMENTS
{
UEdGraphPin * PinWithData = CurrentCENode - > FindPin ( OutputPair . OutputPin - > PinName ) ;
if ( PinWithData = = NULL )
{
FText ErrorMessage = FText : : Format ( LOCTEXT ( " MissingDataPin " , " ICE: Pin @@ was expecting a data output pin named {0} on @@ (each delegate must have the same signature) " ) , FText : : FromString ( OutputPair . OutputPin - > PinName ) ) ;
CompilerContext . MessageLog . Error ( * ErrorMessage . ToString ( ) , OutputPair . OutputPin , CurrentCENode ) ;
2014-04-23 18:50:20 -04:00
return false ;
}
2014-07-03 10:59:02 -04:00
UK2Node_AssignmentStatement * AssignNode = CompilerContext . SpawnIntermediateNode < UK2Node_AssignmentStatement > ( CurrentNode , SourceGraph ) ;
AssignNode - > AllocateDefaultPins ( ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( LastActivatedNodeThen , AssignNode - > GetExecPin ( ) ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( OutputPair . TempVar - > GetVariablePin ( ) , AssignNode - > GetVariablePin ( ) ) ;
AssignNode - > NotifyPinConnectionListChanged ( AssignNode - > GetVariablePin ( ) ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( AssignNode - > GetValuePin ( ) , PinWithData ) ;
AssignNode - > NotifyPinConnectionListChanged ( AssignNode - > GetValuePin ( ) ) ;
LastActivatedNodeThen = AssignNode - > GetThenPin ( ) ;
}
bIsErrorFree & = CompilerContext . MovePinLinksToIntermediate ( * PinForCurrentDelegateProperty , * LastActivatedNodeThen ) . CanSafeConnect ( ) ;
return bIsErrorFree ;
}
2014-04-23 18:50:20 -04:00
2014-03-14 14:13:41 -04:00
void UK2Node_BaseAsyncTask : : ExpandNode ( class FKismetCompilerContext & CompilerContext , UEdGraph * SourceGraph )
{
2014-07-03 10:59:02 -04:00
Super : : ExpandNode ( CompilerContext , SourceGraph ) ;
2014-06-16 10:30:41 -04:00
2014-03-14 14:13:41 -04:00
const UEdGraphSchema_K2 * Schema = CompilerContext . GetSchema ( ) ;
2014-04-23 19:30:38 -04:00
check ( SourceGraph & & Schema ) ;
2014-04-23 18:50:20 -04:00
bool bIsErrorFree = true ;
2014-03-14 14:13:41 -04:00
2014-04-23 19:30:38 -04:00
// Create a call to factory the proxy object
UK2Node_CallFunction * const CallCreateProxyObjectNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( this , SourceGraph ) ;
CallCreateProxyObjectNode - > FunctionReference . SetExternalMember ( ProxyFactoryFunctionName , ProxyFactoryClass ) ;
CallCreateProxyObjectNode - > AllocateDefaultPins ( ) ;
2015-03-27 14:07:28 -04:00
if ( CallCreateProxyObjectNode - > GetTargetFunction ( ) = = nullptr )
{
const FString ClassName = ProxyFactoryClass ? ProxyFactoryClass - > GetName ( ) : LOCTEXT ( " MissingClassString " , " Unknown Class " ) . ToString ( ) ;
const FString RawMessage = LOCTEXT ( " AsyncTaskError " , " BaseAsyncTask: Missing function %s from class %s for async task @@ " ) . ToString ( ) ;
const FString FormattedMessage = FString : : Printf ( * RawMessage , * ProxyFactoryFunctionName . GetPlainNameString ( ) , * ClassName ) ;
CompilerContext . MessageLog . Error ( * FormattedMessage , this ) ;
return ;
}
2014-04-23 19:30:38 -04:00
bIsErrorFree & = CompilerContext . MovePinLinksToIntermediate ( * FindPinChecked ( Schema - > PN_Execute ) , * CallCreateProxyObjectNode - > FindPinChecked ( Schema - > PN_Execute ) ) . CanSafeConnect ( ) ;
2015-03-27 14:07:28 -04:00
2014-04-23 19:30:38 -04:00
for ( auto CurrentPin : Pins )
2015-03-27 14:07:28 -04:00
{
2014-06-16 10:30:41 -04:00
if ( FBaseAsyncTaskHelper : : ValidDataPin ( CurrentPin , EGPD_Input , Schema ) )
2015-03-27 14:07:28 -04:00
{
2014-04-23 19:30:38 -04:00
UEdGraphPin * DestPin = CallCreateProxyObjectNode - > FindPin ( CurrentPin - > PinName ) ; // match function inputs, to pass data to function from CallFunction node
2014-04-23 18:50:20 -04:00
bIsErrorFree & = DestPin & & CompilerContext . MovePinLinksToIntermediate ( * CurrentPin , * DestPin ) . CanSafeConnect ( ) ;
}
2015-03-27 14:07:28 -04:00
}
2014-06-16 10:30:41 -04:00
2014-04-23 18:50:20 -04:00
// GATHER OUTPUT PARAMETERS AND PAIR THEM WITH LOCAL VARIABLES
TArray < FBaseAsyncTaskHelper : : FOutputPinAndLocalVariable > VariableOutputs ;
2014-04-23 19:30:38 -04:00
for ( auto CurrentPin : Pins )
2014-04-23 18:50:20 -04:00
{
if ( FBaseAsyncTaskHelper : : ValidDataPin ( CurrentPin , EGPD_Output , Schema ) )
{
const FEdGraphPinType & PinType = CurrentPin - > PinType ;
UK2Node_TemporaryVariable * TempVarOutput = CompilerContext . SpawnInternalVariable (
2014-04-23 19:30:38 -04:00
this , PinType . PinCategory , PinType . PinSubCategory , PinType . PinSubCategoryObject . Get ( ) , PinType . bIsArray ) ;
2014-04-23 18:50:20 -04:00
bIsErrorFree & = TempVarOutput - > GetVariablePin ( ) & & CompilerContext . MovePinLinksToIntermediate ( * CurrentPin , * TempVarOutput - > GetVariablePin ( ) ) . CanSafeConnect ( ) ;
VariableOutputs . Add ( FBaseAsyncTaskHelper : : FOutputPinAndLocalVariable ( CurrentPin , TempVarOutput ) ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-04-23 18:50:20 -04:00
// FOR EACH DELEGATE DEFINE EVENT, CONNECT IT TO DELEGATE AND IMPLEMENT A CHAIN OF ASSIGMENTS
2014-04-23 19:30:38 -04:00
UEdGraphPin * LastThenPin = CallCreateProxyObjectNode - > FindPinChecked ( Schema - > PN_Then ) ;
UEdGraphPin * const ProxyObjectPin = CallCreateProxyObjectNode - > GetReturnValuePin ( ) ;
for ( TFieldIterator < UMulticastDelegateProperty > PropertyIt ( ProxyClass , EFieldIteratorFlags : : ExcludeSuper ) ; PropertyIt & & bIsErrorFree ; + + PropertyIt )
2015-03-27 14:07:28 -04:00
{
2014-04-23 19:30:38 -04:00
bIsErrorFree & = FBaseAsyncTaskHelper : : HandleDelegateImplementation ( * PropertyIt , VariableOutputs , ProxyObjectPin , LastThenPin , this , SourceGraph , CompilerContext ) ;
2014-04-23 18:50:20 -04:00
}
2014-04-23 19:30:38 -04:00
if ( CallCreateProxyObjectNode - > FindPinChecked ( Schema - > PN_Then ) = = LastThenPin )
2015-03-27 14:07:28 -04:00
{
2014-04-23 19:30:38 -04:00
CompilerContext . MessageLog . Error ( * LOCTEXT ( " MissingDelegateProperties " , " BaseAsyncTask: Proxy has no delegates defined. @@ " ) . ToString ( ) , this ) ;
2014-03-14 14:13:41 -04:00
return ;
2015-03-27 14:07:28 -04:00
}
2014-03-14 14:13:41 -04:00
2014-04-23 19:30:38 -04:00
// Create a call to activate the proxy object if necessary
if ( ProxyActivateFunctionName ! = NAME_None )
2014-03-14 14:13:41 -04:00
{
2014-04-23 19:30:38 -04:00
UK2Node_CallFunction * const CallActivateProxyObjectNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( this , SourceGraph ) ;
CallActivateProxyObjectNode - > FunctionReference . SetExternalMember ( ProxyActivateFunctionName , ProxyClass ) ;
CallActivateProxyObjectNode - > AllocateDefaultPins ( ) ;
// Hook up the self connection
UEdGraphPin * ActivateCallSelfPin = Schema - > FindSelfPin ( * CallActivateProxyObjectNode , EGPD_Input ) ;
check ( ActivateCallSelfPin ) ;
bIsErrorFree & = Schema - > TryCreateConnection ( ProxyObjectPin , ActivateCallSelfPin ) ;
2014-06-16 10:30:41 -04:00
2014-04-23 19:30:38 -04:00
// Hook the activate node up in the exec chain
UEdGraphPin * ActivateExecPin = CallActivateProxyObjectNode - > FindPinChecked ( Schema - > PN_Execute ) ;
UEdGraphPin * ActivateThenPin = CallActivateProxyObjectNode - > FindPinChecked ( Schema - > PN_Then ) ;
2014-04-23 19:43:20 -04:00
bIsErrorFree & = Schema - > TryCreateConnection ( LastThenPin , ActivateExecPin ) ;
2014-04-23 19:30:38 -04:00
LastThenPin = ActivateThenPin ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:30:38 -04:00
// Move the connections from the original node then pin to the last internal then pin
bIsErrorFree & = CompilerContext . MovePinLinksToIntermediate ( * FindPinChecked ( Schema - > PN_Then ) , * LastThenPin ) . CanSafeConnect ( ) ;
if ( ! bIsErrorFree )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " InternalConnectionError " , " BaseAsyncTask: Internal connection error. @@ " ) . ToString ( ) , this ) ;
2015-03-27 14:07:28 -04:00
}
2014-04-23 19:30:38 -04:00
// Make sure we caught everything
BreakAllNodeLinks ( ) ;
2015-03-27 14:07:28 -04:00
}
2014-03-14 14:13:41 -04:00
2015-04-25 17:47:39 -04:00
bool UK2Node_BaseAsyncTask : : HasExternalDependencies ( TArray < class UStruct * > * OptionalOutput ) const
2014-03-14 14:13:41 -04:00
{
const UBlueprint * SourceBlueprint = GetBlueprint ( ) ;
2015-04-25 17:47:39 -04:00
const bool bProxyFactoryResult = ( ProxyFactoryClass ! = NULL ) & & ( ProxyFactoryClass - > ClassGeneratedBy ! = SourceBlueprint ) ;
2014-03-14 14:13:41 -04:00
if ( bProxyFactoryResult & & OptionalOutput )
{
2015-04-25 17:47:39 -04:00
OptionalOutput - > AddUnique ( ProxyFactoryClass ) ;
2014-03-14 14:13:41 -04:00
}
2015-04-25 17:47:39 -04:00
const bool bProxyResult = ( ProxyClass ! = NULL ) & & ( ProxyClass - > ClassGeneratedBy ! = SourceBlueprint ) ;
2014-03-14 14:13:41 -04:00
if ( bProxyResult & & OptionalOutput )
{
2015-04-25 17:47:39 -04:00
OptionalOutput - > AddUnique ( ProxyClass ) ;
2014-03-14 14:13:41 -04:00
}
2015-04-25 17:47:39 -04:00
const bool bSuperResult = Super : : HasExternalDependencies ( OptionalOutput ) ;
return bProxyFactoryResult | | bProxyResult | | bSuperResult ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:30:38 -04:00
FName UK2Node_BaseAsyncTask : : GetCornerIcon ( ) const
2014-07-14 14:09:47 -04:00
{
2014-04-23 19:30:38 -04:00
return TEXT ( " Graph.Latent.LatentIcon " ) ;
2014-07-14 14:09:47 -04:00
}
FText UK2Node_BaseAsyncTask : : GetMenuCategory ( ) const
{
UFunction * TargetFunction = GetFactoryFunction ( ) ;
2014-08-28 17:40:36 -04:00
return FText : : FromString ( UK2Node_CallFunction : : GetDefaultCategoryForFunction ( TargetFunction , TEXT ( " " ) ) ) ;
2014-07-14 14:09:47 -04:00
}
2014-08-23 23:06:59 -04:00
void UK2Node_BaseAsyncTask : : GetMenuActions ( FBlueprintActionDatabaseRegistrar & ActionRegistrar ) const
2014-07-14 14:09:47 -04:00
{
2014-09-10 17:09:26 -04:00
// actions get registered under specific object-keys; the idea is that
// actions might have to be updated (or deleted) if their object-key is
// mutated (or removed)... here we use the node's class (so if the node
// type disappears, then the action should go with it)
UClass * ActionKey = GetClass ( ) ;
// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
// check to make sure that the registrar is looking for actions of this type
// (could be regenerating actions for a specific asset, and therefore the
// registrar would only accept actions corresponding to that asset)
if ( ActionRegistrar . IsOpenForRegistration ( ActionKey ) )
{
UBlueprintNodeSpawner * NodeSpawner = UBlueprintNodeSpawner : : Create ( GetClass ( ) ) ;
check ( NodeSpawner ! = nullptr ) ;
ActionRegistrar . AddBlueprintAction ( ActionKey , NodeSpawner ) ;
}
2014-07-14 14:09:47 -04:00
}
2014-04-23 19:30:38 -04:00
UFunction * UK2Node_BaseAsyncTask : : GetFactoryFunction ( ) const
{
2014-09-18 16:46:00 -04:00
if ( ProxyFactoryClass = = nullptr )
{
2015-03-27 14:07:28 -04:00
UE_LOG ( LogBlueprint , Error , TEXT ( " ProxyFactoryClass null in %s. Was a class deleted or saved on a non promoted build? " ) , * GetFullName ( ) ) ;
2014-09-18 16:46:00 -04:00
return nullptr ;
}
2014-04-23 19:30:38 -04:00
UFunction * FactoryFunction = ProxyFactoryClass - > FindFunctionByName ( ProxyFactoryFunctionName ) ;
check ( FactoryFunction ) ;
return FactoryFunction ;
}
2014-10-16 14:38:52 -04:00
void UK2Node_BaseAsyncTask : : ValidateNodeDuringCompilation ( class FCompilerResultsLog & MessageLog ) const
{
UEdGraphSchema_K2 const * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
if ( UObject const * SourceObject = MessageLog . FindSourceObject ( this ) )
{
// Lets check if it's a result of macro expansion, to give a helpful error
if ( UK2Node_MacroInstance const * MacroInstance = Cast < UK2Node_MacroInstance > ( SourceObject ) )
{
// Since it's not possible to check the graph's type, just check if this is a ubergraph using the schema's name for it
if ( ! ( GetGraph ( ) - > HasAnyFlags ( RF_Transient ) & & GetGraph ( ) - > GetName ( ) . StartsWith ( K2Schema - > FN_ExecuteUbergraphBase . ToString ( ) ) ) )
{
MessageLog . Error ( * LOCTEXT ( " AsyncTaskInFunctionFromMacro " , " @@ is being used in Function '@@' resulting from expansion of Macro '@@' " ) . ToString ( ) , this , GetGraph ( ) , MacroInstance ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE