2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "BlueprintGraphPrivatePCH.h"
# include "KismetCompiler.h"
# include "Runtime/Engine/Classes/Kismet/GameplayStatics.h"
2014-07-14 16:05:25 -04:00
# include "BlueprintNodeSpawner.h"
# include "EditorCategoryUtils.h"
2014-08-23 20:16:29 -04:00
# include "BlueprintActionDatabaseRegistrar.h"
2014-03-14 14:13:41 -04:00
struct FK2Node_SpawnActorFromClassHelper
{
static FString WorldContextPinName ;
static FString ClassPinName ;
static FString SpawnTransformPinName ;
static FString NoCollisionFailPinName ;
} ;
FString FK2Node_SpawnActorFromClassHelper : : WorldContextPinName ( TEXT ( " WorldContextObject " ) ) ;
FString FK2Node_SpawnActorFromClassHelper : : ClassPinName ( TEXT ( " Class " ) ) ;
FString FK2Node_SpawnActorFromClassHelper : : SpawnTransformPinName ( TEXT ( " SpawnTransform " ) ) ;
FString FK2Node_SpawnActorFromClassHelper : : NoCollisionFailPinName ( TEXT ( " SpawnEvenIfColliding " ) ) ;
# define LOCTEXT_NAMESPACE "K2Node_SpawnActorFromClass"
UK2Node_SpawnActorFromClass : : UK2Node_SpawnActorFromClass ( const class FPostConstructInitializeProperties & PCIP )
: Super ( PCIP )
{
2014-09-03 18:14:09 -04:00
NodeTooltip = LOCTEXT ( " NodeTooltip " , " Attempts to spawn a new Actor with the specified transform " ) ;
2014-03-14 14:13:41 -04:00
}
void UK2Node_SpawnActorFromClass : : AllocateDefaultPins ( )
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
// Add execution pins
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 ) ;
// If required add the world context pin
2014-09-10 15:23:52 -04:00
if ( GetBlueprint ( ) - > ParentClass - > HasMetaData ( FBlueprintMetadata : : MD_ShowWorldContextPin ) )
2014-03-14 14:13:41 -04:00
{
CreatePin ( EGPD_Input , K2Schema - > PC_Object , TEXT ( " " ) , UObject : : StaticClass ( ) , false , false , FK2Node_SpawnActorFromClassHelper : : WorldContextPinName ) ;
}
// Add blueprint pin
UEdGraphPin * ClassPin = CreatePin ( EGPD_Input , K2Schema - > PC_Class , TEXT ( " " ) , AActor : : StaticClass ( ) , false , false , FK2Node_SpawnActorFromClassHelper : : ClassPinName ) ;
2014-09-05 13:06:18 -04:00
K2Schema - > ConstructBasicPinTooltip ( * ClassPin , LOCTEXT ( " ClassPinDescription " , " The Actor class you want to spawn " ) , ClassPin - > PinToolTip ) ;
2014-03-14 14:13:41 -04:00
// Transform pin
UScriptStruct * TransformStruct = FindObjectChecked < UScriptStruct > ( UObject : : StaticClass ( ) , TEXT ( " Transform " ) ) ;
UEdGraphPin * TransformPin = CreatePin ( EGPD_Input , K2Schema - > PC_Struct , TEXT ( " " ) , TransformStruct , false , false , FK2Node_SpawnActorFromClassHelper : : SpawnTransformPinName ) ;
2014-09-05 13:06:18 -04:00
K2Schema - > ConstructBasicPinTooltip ( * TransformPin , LOCTEXT ( " TransformPinDescription " , " The transform to spawn the Actor with " ) , TransformPin - > PinToolTip ) ;
2014-03-14 14:13:41 -04:00
// bNoCollisionFail pin
UEdGraphPin * NoCollisionFailPin = CreatePin ( EGPD_Input , K2Schema - > PC_Boolean , TEXT ( " " ) , NULL , false , false , FK2Node_SpawnActorFromClassHelper : : NoCollisionFailPinName ) ;
2014-09-05 13:06:18 -04:00
K2Schema - > ConstructBasicPinTooltip ( * NoCollisionFailPin , LOCTEXT ( " NoCollisionFailPinDescription " , " Determines if the Actor should be spawned when the location is blocked by a collision " ) , NoCollisionFailPin - > PinToolTip ) ;
2014-03-14 14:13:41 -04:00
// Result pin
UEdGraphPin * ResultPin = CreatePin ( EGPD_Output , K2Schema - > PC_Object , TEXT ( " " ) , AActor : : StaticClass ( ) , false , false , K2Schema - > PN_ReturnValue ) ;
2014-09-05 13:06:18 -04:00
K2Schema - > ConstructBasicPinTooltip ( * ResultPin , LOCTEXT ( " ResultPinDescription " , " The spawned Actor " ) , ResultPin - > PinToolTip ) ;
2014-03-14 14:13:41 -04:00
Super : : AllocateDefaultPins ( ) ;
}
void UK2Node_SpawnActorFromClass : : CreatePinsForClass ( UClass * InClass )
{
check ( InClass ! = NULL ) ;
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
2014-07-23 11:45:37 -04:00
const UObject * const ClassDefaultObject = InClass - > GetDefaultObject ( false ) ;
2014-03-14 14:13:41 -04:00
for ( TFieldIterator < UProperty > PropertyIt ( InClass , EFieldIteratorFlags : : IncludeSuper ) ; PropertyIt ; + + PropertyIt )
{
UProperty * Property = * PropertyIt ;
UClass * PropertyClass = CastChecked < UClass > ( Property - > GetOuter ( ) ) ;
const bool bIsDelegate = Property - > IsA ( UMulticastDelegateProperty : : StaticClass ( ) ) ;
2014-04-02 18:09:23 -04:00
const bool bIsExposedToSpawn = UEdGraphSchema_K2 : : IsPropertyExposedOnSpawn ( Property ) ;
2014-04-23 17:34:52 -04:00
const bool bIsSettableExternally = ! Property - > HasAnyPropertyFlags ( CPF_DisableEditOnInstance ) ;
2014-03-14 14:13:41 -04:00
if ( bIsExposedToSpawn & &
! Property - > HasAnyPropertyFlags ( CPF_Parm ) & &
bIsSettableExternally & &
Property - > HasAllPropertyFlags ( CPF_BlueprintVisible ) & &
2014-07-14 17:15:42 -04:00
! bIsDelegate & &
( NULL = = FindPin ( Property - > GetName ( ) ) ) )
2014-03-14 14:13:41 -04:00
{
UEdGraphPin * Pin = CreatePin ( EGPD_Input , TEXT ( " " ) , TEXT ( " " ) , NULL , false , false , Property - > GetName ( ) ) ;
2014-07-14 17:15:42 -04:00
const bool bPinGood = ( Pin ! = NULL ) & & K2Schema - > ConvertPropertyToPinType ( Property , /*out*/ Pin - > PinType ) ;
2014-07-23 11:45:37 -04:00
if ( ClassDefaultObject & & K2Schema - > PinDefaultValueIsEditable ( * Pin ) )
2014-07-14 17:15:42 -04:00
{
FString DefaultValueAsString ;
2014-07-23 11:45:37 -04:00
const bool bDefaultValueSet = FBlueprintEditorUtils : : PropertyValueToString ( Property , reinterpret_cast < const uint8 * > ( ClassDefaultObject ) , DefaultValueAsString ) ;
2014-07-14 17:15:42 -04:00
check ( bDefaultValueSet ) ;
K2Schema - > TrySetDefaultValue ( * Pin , DefaultValueAsString ) ;
}
2014-03-14 14:13:41 -04:00
}
}
// Change class of output pin
UEdGraphPin * ResultPin = GetResultPin ( ) ;
ResultPin - > PinType . PinSubCategoryObject = InClass ;
}
UClass * UK2Node_SpawnActorFromClass : : GetClassToSpawn ( const TArray < UEdGraphPin * > * InPinsToSearch /*=NULL*/ ) const
{
UClass * UseSpawnClass = NULL ;
const TArray < UEdGraphPin * > * PinsToSearch = InPinsToSearch ? InPinsToSearch : & Pins ;
UEdGraphPin * ClassPin = GetClassPin ( PinsToSearch ) ;
if ( ClassPin & & ClassPin - > DefaultObject ! = NULL & & ClassPin - > LinkedTo . Num ( ) = = 0 )
{
UseSpawnClass = CastChecked < UClass > ( ClassPin - > DefaultObject ) ;
}
2014-10-02 05:33:25 -04:00
else if ( ClassPin & & ( 1 = = ClassPin - > LinkedTo . Num ( ) ) )
{
auto SourcePin = ClassPin - > LinkedTo [ 0 ] ;
UseSpawnClass = SourcePin ? Cast < UClass > ( SourcePin - > PinType . PinSubCategoryObject . Get ( ) ) : NULL ;
}
2014-03-14 14:13:41 -04:00
return UseSpawnClass ;
}
void UK2Node_SpawnActorFromClass : : ReallocatePinsDuringReconstruction ( TArray < UEdGraphPin * > & OldPins )
{
AllocateDefaultPins ( ) ;
UClass * UseSpawnClass = GetClassToSpawn ( & OldPins ) ;
if ( UseSpawnClass ! = NULL )
{
CreatePinsForClass ( UseSpawnClass ) ;
}
}
bool UK2Node_SpawnActorFromClass : : IsSpawnVarPin ( UEdGraphPin * Pin )
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
2014-07-08 10:18:59 -04:00
UEdGraphPin * ParentPin = Pin - > ParentPin ;
while ( ParentPin )
{
if ( ParentPin - > PinName = = FK2Node_SpawnActorFromClassHelper : : SpawnTransformPinName )
{
return false ;
}
ParentPin = ParentPin - > ParentPin ;
}
2014-03-14 14:13:41 -04:00
return ( Pin - > PinName ! = K2Schema - > PN_Execute & &
Pin - > PinName ! = K2Schema - > PN_Then & &
Pin - > PinName ! = K2Schema - > PN_ReturnValue & &
Pin - > PinName ! = FK2Node_SpawnActorFromClassHelper : : ClassPinName & &
Pin - > PinName ! = FK2Node_SpawnActorFromClassHelper : : WorldContextPinName & &
Pin - > PinName ! = FK2Node_SpawnActorFromClassHelper : : NoCollisionFailPinName & &
Pin - > PinName ! = FK2Node_SpawnActorFromClassHelper : : SpawnTransformPinName ) ;
}
2014-10-02 05:33:25 -04:00
void UK2Node_SpawnActorFromClass : : OnClassPinChanged ( )
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
// Because the archetype has changed, we break the output link as the output pin type will change
UEdGraphPin * ResultPin = GetResultPin ( ) ;
ResultPin - > BreakAllPinLinks ( ) ;
// Remove all pins related to archetype variables
TArray < UEdGraphPin * > OldPins = Pins ;
for ( int32 i = 0 ; i < OldPins . Num ( ) ; i + + )
{
UEdGraphPin * OldPin = OldPins [ i ] ;
if ( IsSpawnVarPin ( OldPin ) )
{
OldPin - > BreakAllPinLinks ( ) ;
Pins . Remove ( OldPin ) ;
}
}
CachedNodeTitle . MarkDirty ( ) ;
UClass * UseSpawnClass = GetClassToSpawn ( ) ;
if ( UseSpawnClass ! = NULL )
{
CreatePinsForClass ( UseSpawnClass ) ;
}
2014-10-09 12:04:45 -04:00
K2Schema - > ConstructBasicPinTooltip ( * ResultPin , LOCTEXT ( " ResultPinDescription " , " The spawned Actor " ) , ResultPin - > PinToolTip ) ;
2014-10-02 05:33:25 -04:00
// Refresh the UI for the graph so the pin changes show up
UEdGraph * Graph = GetGraph ( ) ;
Graph - > NotifyGraphChanged ( ) ;
// Mark dirty
FBlueprintEditorUtils : : MarkBlueprintAsModified ( GetBlueprint ( ) ) ;
}
void UK2Node_SpawnActorFromClass : : PinConnectionListChanged ( UEdGraphPin * ChangedPin )
{
if ( ChangedPin & & ( ChangedPin - > PinName = = FK2Node_SpawnActorFromClassHelper : : ClassPinName ) )
{
OnClassPinChanged ( ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-04-23 19:31:03 -04:00
void UK2Node_SpawnActorFromClass : : PinDefaultValueChanged ( UEdGraphPin * ChangedPin )
2014-03-14 14:13:41 -04:00
{
2014-10-02 05:33:25 -04:00
if ( ChangedPin & & ( ChangedPin - > PinName = = FK2Node_SpawnActorFromClassHelper : : ClassPinName ) )
2014-03-14 14:13:41 -04:00
{
2014-10-02 05:33:25 -04:00
OnClassPinChanged ( ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-09-03 18:14:09 -04:00
FText UK2Node_SpawnActorFromClass : : GetTooltipText ( ) const
2014-03-14 14:13:41 -04:00
{
return NodeTooltip ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetThenPin ( ) const
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
UEdGraphPin * Pin = FindPinChecked ( K2Schema - > PN_Then ) ;
check ( Pin - > Direction = = EGPD_Output ) ;
return Pin ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetClassPin ( const TArray < UEdGraphPin * > * InPinsToSearch /*= NULL*/ ) const
{
const TArray < UEdGraphPin * > * PinsToSearch = InPinsToSearch ? InPinsToSearch : & Pins ;
UEdGraphPin * Pin = NULL ;
for ( auto PinIt = PinsToSearch - > CreateConstIterator ( ) ; PinIt ; + + PinIt )
{
UEdGraphPin * TestPin = * PinIt ;
if ( TestPin & & TestPin - > PinName = = FK2Node_SpawnActorFromClassHelper : : ClassPinName )
{
Pin = TestPin ;
break ;
}
}
check ( Pin = = NULL | | Pin - > Direction = = EGPD_Input ) ;
return Pin ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetSpawnTransformPin ( ) const
{
UEdGraphPin * Pin = FindPinChecked ( FK2Node_SpawnActorFromClassHelper : : SpawnTransformPinName ) ;
check ( Pin - > Direction = = EGPD_Input ) ;
return Pin ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetNoCollisionFailPin ( ) const
{
UEdGraphPin * Pin = FindPinChecked ( FK2Node_SpawnActorFromClassHelper : : NoCollisionFailPinName ) ;
check ( Pin - > Direction = = EGPD_Input ) ;
return Pin ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetWorldContextPin ( ) const
{
UEdGraphPin * Pin = FindPin ( FK2Node_SpawnActorFromClassHelper : : WorldContextPinName ) ;
check ( Pin = = NULL | | Pin - > Direction = = EGPD_Input ) ;
return Pin ;
}
UEdGraphPin * UK2Node_SpawnActorFromClass : : GetResultPin ( ) const
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
UEdGraphPin * Pin = FindPinChecked ( K2Schema - > PN_ReturnValue ) ;
check ( Pin - > Direction = = EGPD_Output ) ;
return Pin ;
}
FLinearColor UK2Node_SpawnActorFromClass : : GetNodeTitleColor ( ) const
{
return Super : : GetNodeTitleColor ( ) ;
}
2014-04-23 18:30:37 -04:00
FText UK2Node_SpawnActorFromClass : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2014-07-14 16:05:25 -04:00
FText NodeTitle = NSLOCTEXT ( " K2Node " , " SpawnActor_BaseTitle " , " Spawn Actor from Class " ) ;
2014-09-16 15:01:38 -04:00
if ( TitleType ! = ENodeTitleType : : MenuTitle )
2014-04-23 18:30:37 -04:00
{
2014-07-14 16:05:25 -04:00
FText SpawnString = NSLOCTEXT ( " K2Node " , " None " , " NONE " ) ;
if ( UEdGraphPin * ClassPin = GetClassPin ( ) )
2014-04-23 18:30:37 -04:00
{
2014-09-02 19:08:09 -04:00
if ( ClassPin - > LinkedTo . Num ( ) > 0 )
2014-07-14 16:05:25 -04:00
{
// Blueprint will be determined dynamically, so we don't have the name in this case
2014-09-02 19:08:09 -04:00
NodeTitle = NSLOCTEXT ( " K2Node " , " SpawnActor_Title_Unknown " , " SpawnActor " ) ;
2014-07-14 16:05:25 -04:00
}
2014-09-02 19:08:09 -04:00
else if ( ClassPin - > DefaultObject = = nullptr )
2014-07-14 16:05:25 -04:00
{
2014-09-02 19:08:09 -04:00
NodeTitle = NSLOCTEXT ( " K2Node " , " SpawnActor_Title_NONE " , " SpawnActor NONE " ) ;
2014-07-14 16:05:25 -04:00
}
2014-09-02 19:08:09 -04:00
else
{
if ( CachedNodeTitle . IsOutOfDate ( ) )
{
2014-10-09 12:04:45 -04:00
FText ClassName ;
if ( UClass * PickedClass = Cast < UClass > ( ClassPin - > DefaultObject ) )
{
ClassName = PickedClass - > GetDisplayNameText ( ) ;
}
2014-09-02 19:08:09 -04:00
FFormatNamedArguments Args ;
2014-10-09 12:04:45 -04:00
Args . Add ( TEXT ( " ClassName " ) , ClassName ) ;
2014-09-02 19:08:09 -04:00
// FText::Format() is slow, so we cache this to save on performance
CachedNodeTitle = FText : : Format ( NSLOCTEXT ( " K2Node " , " SpawnActor " , " SpawnActor {ClassName} " ) , Args ) ;
}
NodeTitle = CachedNodeTitle ;
}
}
else
{
NodeTitle = NSLOCTEXT ( " K2Node " , " SpawnActor_Title_NONE " , " SpawnActor NONE " ) ;
2014-04-23 18:30:37 -04:00
}
}
2014-07-14 16:05:25 -04:00
return NodeTitle ;
2014-04-23 18:30:37 -04:00
}
2014-08-04 12:39:34 -04:00
bool UK2Node_SpawnActorFromClass : : IsCompatibleWithGraph ( const UEdGraph * TargetGraph ) const
2014-03-14 14:13:41 -04:00
{
2014-08-04 12:39:34 -04:00
UBlueprint * Blueprint = FBlueprintEditorUtils : : FindBlueprintForGraph ( TargetGraph ) ;
return Super : : IsCompatibleWithGraph ( TargetGraph ) & & ( ! Blueprint | | FBlueprintEditorUtils : : FindUserConstructionScript ( Blueprint ) ! = TargetGraph ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-06 18:51:05 -04:00
void UK2Node_SpawnActorFromClass : : GetNodeAttributes ( TArray < TKeyValuePair < FString , FString > > & OutNodeAttributes ) const
{
UClass * ClassToSpawn = GetClassToSpawn ( ) ;
const FString ClassToSpawnStr = ClassToSpawn ? ClassToSpawn - > GetName ( ) : TEXT ( " InvalidClass " ) ;
OutNodeAttributes . Add ( TKeyValuePair < FString , FString > ( TEXT ( " Type " ) , TEXT ( " SpawnActorFromClass " ) ) ) ;
OutNodeAttributes . Add ( TKeyValuePair < FString , FString > ( TEXT ( " Class " ) , GetClass ( ) - > GetName ( ) ) ) ;
OutNodeAttributes . Add ( TKeyValuePair < FString , FString > ( TEXT ( " Name " ) , GetName ( ) ) ) ;
OutNodeAttributes . Add ( TKeyValuePair < FString , FString > ( TEXT ( " ActorClass " ) , ClassToSpawnStr ) ) ;
}
2014-08-23 20:16:29 -04:00
void UK2Node_SpawnActorFromClass : : GetMenuActions ( FBlueprintActionDatabaseRegistrar & ActionRegistrar ) const
2014-07-14 16:05:25 -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 ) ;
2014-07-14 16:05:25 -04:00
2014-09-10 17:09:26 -04:00
ActionRegistrar . AddBlueprintAction ( ActionKey , NodeSpawner ) ;
}
2014-07-14 16:05:25 -04:00
}
FText UK2Node_SpawnActorFromClass : : GetMenuCategory ( ) const
{
return FEditorCategoryUtils : : GetCommonCategory ( FCommonEditorCategory : : Gameplay ) ;
}
2014-07-28 12:24:56 -04:00
FNodeHandlingFunctor * UK2Node_SpawnActorFromClass : : CreateNodeHandler ( FKismetCompilerContext & CompilerContext ) const
{
return new FNodeHandlingFunctor ( CompilerContext ) ;
}
2014-03-14 14:13:41 -04:00
void UK2Node_SpawnActorFromClass : : ExpandNode ( class FKismetCompilerContext & CompilerContext , UEdGraph * SourceGraph )
{
Super : : ExpandNode ( CompilerContext , SourceGraph ) ;
if ( CompilerContext . bIsFullCompile )
{
static FName BeginSpawningBlueprintFuncName = GET_FUNCTION_NAME_CHECKED ( UGameplayStatics , BeginSpawningActorFromClass ) ;
static FString ActorClassParamName = FString ( TEXT ( " ActorClass " ) ) ;
static FString WorldContextParamName = FString ( TEXT ( " WorldContextObject " ) ) ;
static FName FinishSpawningFuncName = GET_FUNCTION_NAME_CHECKED ( UGameplayStatics , FinishSpawningActor ) ;
static FString ActorParamName = FString ( TEXT ( " Actor " ) ) ;
static FString TransformParamName = FString ( TEXT ( " SpawnTransform " ) ) ;
static FString NoCollisionFailParamName = FString ( TEXT ( " bNoCollisionFail " ) ) ;
static FString ObjectParamName = FString ( TEXT ( " Object " ) ) ;
static FString ValueParamName = FString ( TEXT ( " Value " ) ) ;
static FString PropertyNameParamName = FString ( TEXT ( " PropertyName " ) ) ;
UK2Node_SpawnActorFromClass * SpawnNode = this ;
UEdGraphPin * SpawnNodeExec = SpawnNode - > GetExecPin ( ) ;
UEdGraphPin * SpawnNodeTransform = SpawnNode - > GetSpawnTransformPin ( ) ;
UEdGraphPin * SpawnNodeNoCollisionFail = GetNoCollisionFailPin ( ) ;
UEdGraphPin * SpawnWorldContextPin = SpawnNode - > GetWorldContextPin ( ) ;
UEdGraphPin * SpawnClassPin = SpawnNode - > GetClassPin ( ) ;
UEdGraphPin * SpawnNodeThen = SpawnNode - > GetThenPin ( ) ;
UEdGraphPin * SpawnNodeResult = SpawnNode - > GetResultPin ( ) ;
UClass * SpawnClass = ( SpawnClassPin ! = NULL ) ? Cast < UClass > ( SpawnClassPin - > DefaultObject ) : NULL ;
if ( ( 0 = = SpawnClassPin - > LinkedTo . Num ( ) ) & & ( NULL = = SpawnClass ) )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " SpawnActorNodeMissingClass_Error " , " Spawn node @@ must have a class specified. " ) . ToString ( ) , SpawnNode ) ;
// we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings
SpawnNode - > BreakAllNodeLinks ( ) ;
return ;
}
//////////////////////////////////////////////////////////////////////////
// create 'begin spawn' call node
UK2Node_CallFunction * CallBeginSpawnNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( SpawnNode , SourceGraph ) ;
CallBeginSpawnNode - > FunctionReference . SetExternalMember ( BeginSpawningBlueprintFuncName , UGameplayStatics : : StaticClass ( ) ) ;
CallBeginSpawnNode - > AllocateDefaultPins ( ) ;
UEdGraphPin * CallBeginExec = CallBeginSpawnNode - > GetExecPin ( ) ;
UEdGraphPin * CallBeginWorldContextPin = CallBeginSpawnNode - > FindPinChecked ( WorldContextParamName ) ;
UEdGraphPin * CallBeginActorClassPin = CallBeginSpawnNode - > FindPinChecked ( ActorClassParamName ) ;
UEdGraphPin * CallBeginTransform = CallBeginSpawnNode - > FindPinChecked ( TransformParamName ) ;
UEdGraphPin * CallBeginNoCollisionFail = CallBeginSpawnNode - > FindPinChecked ( NoCollisionFailParamName ) ;
UEdGraphPin * CallBeginResult = CallBeginSpawnNode - > GetReturnValuePin ( ) ;
// Move 'exec' connection from spawn node to 'begin spawn'
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeExec , * CallBeginExec ) ;
2014-03-14 14:13:41 -04:00
if ( SpawnClassPin - > LinkedTo . Num ( ) > 0 )
{
// Copy the 'blueprint' connection from the spawn node to 'begin spawn'
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnClassPin , * CallBeginActorClassPin ) ;
2014-03-14 14:13:41 -04:00
}
else
{
// Copy blueprint literal onto begin spawn call
CallBeginActorClassPin - > DefaultObject = SpawnClass ;
}
// Copy the world context connection from the spawn node to 'begin spawn' if necessary
if ( SpawnWorldContextPin )
{
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnWorldContextPin , * CallBeginWorldContextPin ) ;
2014-03-14 14:13:41 -04:00
}
// Copy the 'transform' connection from the spawn node to 'begin spawn'
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeTransform , * CallBeginTransform ) ;
2014-03-14 14:13:41 -04:00
// Copy the 'bNoCollisionFail' connection from the spawn node to 'begin spawn'
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeNoCollisionFail , * CallBeginNoCollisionFail ) ;
2014-03-14 14:13:41 -04:00
//////////////////////////////////////////////////////////////////////////
// create 'finish spawn' call node
UK2Node_CallFunction * CallFinishSpawnNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( SpawnNode , SourceGraph ) ;
CallFinishSpawnNode - > FunctionReference . SetExternalMember ( FinishSpawningFuncName , UGameplayStatics : : StaticClass ( ) ) ;
CallFinishSpawnNode - > AllocateDefaultPins ( ) ;
UEdGraphPin * CallFinishExec = CallFinishSpawnNode - > GetExecPin ( ) ;
UEdGraphPin * CallFinishThen = CallFinishSpawnNode - > GetThenPin ( ) ;
UEdGraphPin * CallFinishActor = CallFinishSpawnNode - > FindPinChecked ( ActorParamName ) ;
UEdGraphPin * CallFinishTransform = CallFinishSpawnNode - > FindPinChecked ( TransformParamName ) ;
UEdGraphPin * CallFinishResult = CallFinishSpawnNode - > GetReturnValuePin ( ) ;
// Move 'then' connection from spawn node to 'finish spawn'
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeThen , * CallFinishThen ) ;
2014-03-14 14:13:41 -04:00
// Copy transform connection
2014-04-23 17:45:37 -04:00
CompilerContext . CopyPinLinksToIntermediate ( * CallBeginTransform , * CallFinishTransform ) ;
2014-03-14 14:13:41 -04:00
// Connect output actor from 'begin' to 'finish'
CallBeginResult - > MakeLinkTo ( CallFinishActor ) ;
// Move result connection from spawn node to 'finish spawn'
CallFinishResult - > PinType = SpawnNodeResult - > PinType ; // Copy type so it uses the right actor subclass
2014-04-23 17:45:37 -04:00
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeResult , * CallFinishResult ) ;
2014-03-14 14:13:41 -04:00
//////////////////////////////////////////////////////////////////////////
// create 'set var' nodes
// Get 'result' pin from 'begin spawn', this is the actual actor we want to set properties on
2014-07-14 17:15:42 -04:00
UEdGraphPin * LastThen = FKismetCompilerUtilities : : GenerateAssignmentNodes ( CompilerContext , SourceGraph , CallBeginSpawnNode , SpawnNode , CallBeginResult , GetClassToSpawn ( ) ) ;
2014-06-30 16:06:49 -04:00
2014-03-14 14:13:41 -04:00
// Make exec connection between 'then' on last node and 'finish'
LastThen - > MakeLinkTo ( CallFinishExec ) ;
// Break any links to the expanded node
SpawnNode - > BreakAllNodeLinks ( ) ;
}
}
bool UK2Node_SpawnActorFromClass : : HasExternalBlueprintDependencies ( TArray < class UStruct * > * OptionalOutput ) const
{
UClass * SourceClass = GetClassToSpawn ( ) ;
const UBlueprint * SourceBlueprint = GetBlueprint ( ) ;
const bool bResult = ( SourceClass ! = NULL ) & & ( SourceClass - > ClassGeneratedBy ! = NULL ) & & ( SourceClass - > ClassGeneratedBy ! = SourceBlueprint ) ;
if ( bResult & & OptionalOutput )
{
OptionalOutput - > Add ( SourceClass ) ;
}
2014-04-23 20:18:55 -04:00
return bResult | | Super : : HasExternalBlueprintDependencies ( OptionalOutput ) ;
2014-03-14 14:13:41 -04:00
}
# undef LOCTEXT_NAMESPACE