2020-04-23 20:31:16 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "K2Node_AddComponentByClass.h"
2022-08-24 22:45:13 -04:00
2020-04-23 20:31:16 -04:00
# include "Components/ActorComponent.h"
2022-08-24 22:45:13 -04:00
# include "Components/SceneComponent.h"
# include "Containers/EnumAsByte.h"
# include "Containers/UnrealString.h"
# include "EdGraph/EdGraph.h"
# include "EdGraph/EdGraphNode.h"
# include "EdGraph/EdGraphPin.h"
# include "EdGraphSchema_K2.h"
2020-04-23 20:31:16 -04:00
# include "GameFramework/Actor.h"
2022-08-24 22:45:13 -04:00
# include "HAL/Platform.h"
# include "HAL/PlatformCrt.h"
# include "Internationalization/Internationalization.h"
2020-04-23 20:31:16 -04:00
# include "K2Node_CallFunction.h"
2022-08-24 22:45:13 -04:00
# include "Kismet2/CompilerResultsLog.h"
# include "KismetCompiler.h"
# include "KismetCompilerMisc.h"
# include "Misc/AssertionMacros.h"
# include "Templates/Casts.h"
# include "Templates/UnrealTemplate.h"
# include "UObject/Class.h"
# include "UObject/NameTypes.h"
# include "UObject/Object.h"
# include "UObject/WeakObjectPtr.h"
# include "UObject/WeakObjectPtrTemplates.h"
2020-04-23 20:31:16 -04:00
# define LOCTEXT_NAMESPACE "ActorComponent"
struct FK2Node_AddComponentByClassHelper
{
2020-04-29 16:38:20 -04:00
static const FName ClassPinName ;
2020-04-23 20:31:16 -04:00
static const FName TransformPinName ;
static const FName ManualAttachmentPinName ;
static const FName DeferredFinishPinName ;
static const FName ComponentClassPinName ;
static const FName ActorComponentPinName ;
} ;
2020-04-29 16:38:20 -04:00
const FName FK2Node_AddComponentByClassHelper : : ClassPinName ( TEXT ( " Class " ) ) ;
2020-04-23 20:31:16 -04:00
const FName FK2Node_AddComponentByClassHelper : : TransformPinName ( TEXT ( " RelativeTransform " ) ) ;
const FName FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ( TEXT ( " bManualAttachment " ) ) ;
const FName FK2Node_AddComponentByClassHelper : : DeferredFinishPinName ( TEXT ( " bDeferredFinish " ) ) ;
const FName FK2Node_AddComponentByClassHelper : : ComponentClassPinName ( TEXT ( " Class " ) ) ;
const FName FK2Node_AddComponentByClassHelper : : ActorComponentPinName ( TEXT ( " Component " ) ) ;
UK2Node_AddComponentByClass : : UK2Node_AddComponentByClass ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
{
NodeTooltip = LOCTEXT ( " NodeTooltip " , " Adds a component to an actor " ) ;
}
void UK2Node_AddComponentByClass : : AllocateDefaultPins ( )
{
// Create a dummy AActor::AddComponentByClass node to copy pins off of
UK2Node_CallFunction * AddComponentByClassNode = NewObject < UK2Node_CallFunction > ( GetGraph ( ) ) ;
AddComponentByClassNode - > SetFromFunction ( AActor : : StaticClass ( ) - > FindFunctionByName ( GET_FUNCTION_NAME_CHECKED ( AActor , AddComponentByClass ) ) ) ;
AddComponentByClassNode - > AllocateDefaultPins ( ) ;
auto CreatePinCopy = [ & ] ( UEdGraphPin * ProtoPin )
{
const FEdGraphPinType & ProtoPinType = ProtoPin - > PinType ;
UEdGraphNode : : FCreatePinParams PinParams ;
PinParams . ContainerType = ProtoPinType . ContainerType ;
PinParams . ValueTerminalType = ProtoPinType . PinValueType ;
UEdGraphPin * Pin = CreatePin ( ProtoPin - > Direction , ProtoPinType . PinCategory , ProtoPinType . PinSubCategory , ProtoPinType . PinSubCategoryObject . Get ( ) , ProtoPin - > PinName , PinParams ) ;
Pin - > PinToolTip = MoveTemp ( ProtoPin - > PinToolTip ) ;
Pin - > PinFriendlyName = MoveTemp ( ProtoPin - > PinFriendlyName ) ;
return Pin ;
} ;
// Create the self pin first because we want it to come before the class pin
UEdGraphPin * SelfPin = CreatePinCopy ( GetDefault < UEdGraphSchema_K2 > ( ) - > FindSelfPin ( * AddComponentByClassNode , EGPD_Input ) ) ;
Super : : AllocateDefaultPins ( ) ;
// Put the exec pin first in the Pins array so it appears before the self pin
UEdGraphPin * ExecPin = GetExecPin ( ) ;
Pins . Remove ( ExecPin ) ;
Pins . Insert ( ExecPin , 0 ) ;
CreatePinCopy ( AddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ) ) ;
CreatePinCopy ( AddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : TransformPinName ) ) ;
AddComponentByClassNode - > DestroyNode ( ) ;
2020-04-29 16:38:20 -04:00
SetSceneComponentPinsHidden ( true ) ;
2020-04-23 20:31:16 -04:00
}
FText UK2Node_AddComponentByClass : : GetBaseNodeTitle ( ) const
{
return LOCTEXT ( " AddComponent_BaseTitle " , " Add Component by Class " ) ;
}
FText UK2Node_AddComponentByClass : : GetDefaultNodeTitle ( ) const
{
return GetBaseNodeTitle ( ) ;
}
FText UK2Node_AddComponentByClass : : GetNodeTitleFormat ( ) const
{
return LOCTEXT ( " AddComponent " , " Add {ClassName} " ) ;
}
UClass * UK2Node_AddComponentByClass : : GetClassPinBaseClass ( ) const
{
return UActorComponent : : StaticClass ( ) ;
}
2020-04-29 16:38:20 -04:00
void UK2Node_AddComponentByClass : : SetSceneComponentPinsHidden ( const bool bHidden )
{
UEdGraphPin * ManualAttachmentPin = GetManualAttachmentPin ( ) ;
ManualAttachmentPin - > SafeSetHidden ( bHidden ) ;
UEdGraphPin * TransformPin = GetRelativeTransformPin ( ) ;
TransformPin - > SafeSetHidden ( bHidden ) ;
}
void UK2Node_AddComponentByClass : : PinDefaultValueChanged ( UEdGraphPin * ChangedPin )
{
if ( ChangedPin & & ( ChangedPin - > PinName = = FK2Node_AddComponentByClassHelper : : ClassPinName ) )
{
// If the class pin changes set the scene components hidden and then CreatePinsForClass will unhide if appropriate
SetSceneComponentPinsHidden ( true ) ;
}
Super : : PinDefaultValueChanged ( ChangedPin ) ;
}
2020-04-23 20:31:16 -04:00
void UK2Node_AddComponentByClass : : CreatePinsForClass ( UClass * InClass , TArray < UEdGraphPin * > * OutClassPins )
{
Super : : CreatePinsForClass ( InClass , OutClassPins ) ;
// Based on the supplied class we hide the transform and manual attachment pins
const bool bIsSceneComponent = InClass ? InClass - > IsChildOf < USceneComponent > ( ) : false ;
2020-04-29 16:38:20 -04:00
SetSceneComponentPinsHidden ( ! bIsSceneComponent ) ;
2020-04-23 20:31:16 -04:00
}
UEdGraphPin * UK2Node_AddComponentByClass : : GetRelativeTransformPin ( ) const
{
return FindPinChecked ( FK2Node_AddComponentByClassHelper : : TransformPinName ) ;
}
UEdGraphPin * UK2Node_AddComponentByClass : : GetManualAttachmentPin ( ) const
{
return FindPinChecked ( FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ) ;
}
bool UK2Node_AddComponentByClass : : IsSceneComponent ( ) const
{
if ( UEdGraphPin * SpawnClassPin = GetClassPin ( ) )
{
if ( UClass * SpawnClass = Cast < UClass > ( SpawnClassPin - > DefaultObject ) )
{
return SpawnClass - > IsChildOf < USceneComponent > ( ) ;
}
}
return false ;
}
bool UK2Node_AddComponentByClass : : IsSpawnVarPin ( UEdGraphPin * Pin ) const
{
return ( Super : : IsSpawnVarPin ( Pin )
& & Pin - > PinName ! = UEdGraphSchema_K2 : : PN_Self
& & Pin - > PinName ! = FK2Node_AddComponentByClassHelper : : TransformPinName
& & Pin - > PinName ! = FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ) ;
}
void UK2Node_AddComponentByClass : : ExpandNode ( class FKismetCompilerContext & CompilerContext , UEdGraph * SourceGraph )
{
Super : : ExpandNode ( CompilerContext , SourceGraph ) ;
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
UEdGraphPin * SpawnNodeExec = GetExecPin ( ) ;
UEdGraphPin * SpawnOwnerPin = K2Schema - > FindSelfPin ( * this , EGPD_Input ) ;
UEdGraphPin * SpawnClassPin = GetClassPin ( ) ;
UEdGraphPin * SpawnTransformPin = GetRelativeTransformPin ( ) ;
UEdGraphPin * SpawnManualAttachmentPin = GetManualAttachmentPin ( ) ;
UEdGraphPin * SpawnNodeThen = GetThenPin ( ) ;
UEdGraphPin * SpawnNodeResult = GetResultPin ( ) ;
UClass * SpawnClass = ( SpawnClassPin ? Cast < UClass > ( SpawnClassPin - > DefaultObject ) : nullptr ) ;
2020-04-23 21:23:56 -04:00
if ( SpawnClassPin = = nullptr | | ( ( SpawnClass = = nullptr ) & & ( SpawnClassPin - > LinkedTo . Num ( ) = = 0 ) ) )
2020-04-23 20:31:16 -04:00
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " AddComponentByClassNodeMissingClass_Error " , " Spawn node @@ must have a class specified. " ) . ToString ( ) , this ) ;
// we break exec links so this is the only error we get, don't want the AddComponentByClass node being considered and giving 'unexpected node' type warnings
BreakAllNodeLinks ( ) ;
return ;
}
UK2Node_CallFunction * CallAddComponentByClassNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( this , SourceGraph ) ;
CallAddComponentByClassNode - > SetFromFunction ( AActor : : StaticClass ( ) - > FindFunctionByName ( GET_FUNCTION_NAME_CHECKED ( AActor , AddComponentByClass ) ) ) ;
CallAddComponentByClassNode - > AllocateDefaultPins ( ) ;
// store off the class to spawn before we mutate pin connections:
UClass * ClassToSpawn = GetClassToSpawn ( ) ;
UEdGraphPin * CallAddComponentByClassExec = CallAddComponentByClassNode - > GetExecPin ( ) ;
UEdGraphPin * CallAddComponentByClassTypePin = CallAddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : ComponentClassPinName ) ;
UEdGraphPin * CallAddComponentByClassOwnerPin = K2Schema - > FindSelfPin ( * CallAddComponentByClassNode , EGPD_Input ) ;
UEdGraphPin * CallAddComponentByClassTransformPin = CallAddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : TransformPinName ) ;
UEdGraphPin * CallAddComponentByClassManualAttachmentPin = CallAddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ) ;
UEdGraphPin * CallAddComponentByClassResult = CallAddComponentByClassNode - > GetReturnValuePin ( ) ;
// set properties on relative transform pin to allow it to be unconnected
CallAddComponentByClassTransformPin - > bDefaultValueIsIgnored = true ;
CallAddComponentByClassTransformPin - > PinType . bIsReference = false ;
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeExec , * CallAddComponentByClassExec ) ;
CompilerContext . MovePinLinksToIntermediate ( * SpawnClassPin , * CallAddComponentByClassTypePin ) ;
CompilerContext . MovePinLinksToIntermediate ( * SpawnOwnerPin , * CallAddComponentByClassOwnerPin ) ;
CompilerContext . MovePinLinksToIntermediate ( * SpawnTransformPin , * CallAddComponentByClassTransformPin ) ;
CompilerContext . MovePinLinksToIntermediate ( * SpawnManualAttachmentPin , * CallAddComponentByClassManualAttachmentPin ) ;
// Move result connection from spawn node to specific AddComponent function
CallAddComponentByClassResult - > PinType = SpawnNodeResult - > PinType ; // Copy type so it uses the right actor subclass
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeResult , * CallAddComponentByClassResult ) ;
//////////////////////////////////////////////////////////////////////////
// create 'set var' nodes
2024-07-18 14:17:10 -04:00
UEdGraphPin * LastThen = FKismetCompilerUtilities : : GenerateAssignmentNodes ( CompilerContext , SourceGraph , CallAddComponentByClassNode , this , CallAddComponentByClassResult , ClassToSpawn , CallAddComponentByClassTypePin ) ;
2020-04-23 20:31:16 -04:00
2020-09-01 14:07:48 -04:00
if ( LastThen ! = CallAddComponentByClassNode - > GetThenPin ( ) )
2020-04-23 20:31:16 -04:00
{
UEdGraphPin * CallAddComponentByClassDeferredFinishPin = CallAddComponentByClassNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : DeferredFinishPinName ) ;
CallAddComponentByClassDeferredFinishPin - > DefaultValue = TEXT ( " true " ) ;
UK2Node_CallFunction * CallRegisterComponentNode = CompilerContext . SpawnIntermediateNode < UK2Node_CallFunction > ( this , SourceGraph ) ;
CallRegisterComponentNode - > SetFromFunction ( AActor : : StaticClass ( ) - > FindFunctionByName ( GET_FUNCTION_NAME_CHECKED ( AActor , FinishAddComponent ) ) ) ;
CallRegisterComponentNode - > AllocateDefaultPins ( ) ;
// Links execution from last assignment to 'RegisterComponent '
2020-09-01 14:07:48 -04:00
LastThen - > MakeLinkTo ( CallRegisterComponentNode - > GetExecPin ( ) ) ;
2020-04-23 20:31:16 -04:00
// Link the pins to RegisterComponent node
UEdGraphPin * CallRegisterComponentByClassOwnerPin = K2Schema - > FindSelfPin ( * CallRegisterComponentNode , EGPD_Input ) ;
UEdGraphPin * CallRegisterComponentByClassComponentPin = CallRegisterComponentNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : ActorComponentPinName ) ;
UEdGraphPin * CallRegisterComponentByClassTransformPin = CallRegisterComponentNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : TransformPinName ) ;
UEdGraphPin * CallRegisterComponentByClassManualAttachmentPin = CallRegisterComponentNode - > FindPinChecked ( FK2Node_AddComponentByClassHelper : : ManualAttachmentPinName ) ;
// set properties on relative transform pin to allow it to be unconnected
CallRegisterComponentByClassTransformPin - > bDefaultValueIsIgnored = true ;
CallRegisterComponentByClassTransformPin - > PinType . bIsReference = false ;
CompilerContext . CopyPinLinksToIntermediate ( * CallAddComponentByClassOwnerPin , * CallRegisterComponentByClassOwnerPin ) ;
CompilerContext . CopyPinLinksToIntermediate ( * CallAddComponentByClassTransformPin , * CallRegisterComponentByClassTransformPin ) ;
CompilerContext . CopyPinLinksToIntermediate ( * CallAddComponentByClassManualAttachmentPin , * CallRegisterComponentByClassManualAttachmentPin ) ;
CallRegisterComponentByClassComponentPin - > MakeLinkTo ( CallAddComponentByClassResult ) ;
2020-09-01 14:07:48 -04:00
LastThen = CallRegisterComponentNode - > GetThenPin ( ) ;
2020-04-23 20:31:16 -04:00
}
2020-09-01 14:07:48 -04:00
// Move 'then' connection from AddComponent node to the last 'then'
CompilerContext . MovePinLinksToIntermediate ( * SpawnNodeThen , * LastThen ) ;
2020-04-23 20:31:16 -04:00
// Break any links to the expanded node
BreakAllNodeLinks ( ) ;
}
# undef LOCTEXT_NAMESPACE