2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "BlueprintGraphPrivatePCH.h"
# include "KismetCompiler.h"
2014-04-23 20:18:55 -04:00
# include "Editor/UnrealEd/Public/Kismet2/StructureEditorUtils.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "K2Node_MakeStruct"
//////////////////////////////////////////////////////////////////////////
// FKCHandler_MakeStruct
class FKCHandler_MakeStruct : public FNodeHandlingFunctor
{
public :
UEdGraphPin * FindOutputStructPinChecked ( UEdGraphNode * Node )
{
check ( NULL ! = Node ) ;
UEdGraphPin * OutputPin = NULL ;
for ( int32 PinIndex = 0 ; PinIndex < Node - > Pins . Num ( ) ; + + PinIndex )
{
UEdGraphPin * Pin = Node - > Pins [ PinIndex ] ;
if ( Pin & & ( EGPD_Output = = Pin - > Direction ) & & ! CompilerContext . GetSchema ( ) - > IsMetaPin ( * Pin ) )
{
OutputPin = Pin ;
break ;
}
}
check ( NULL ! = OutputPin ) ;
return OutputPin ;
}
FKCHandler_MakeStruct ( FKismetCompilerContext & InCompilerContext )
: FNodeHandlingFunctor ( InCompilerContext )
{
}
virtual void RegisterNets ( FKismetFunctionContext & Context , UEdGraphNode * InNode ) OVERRIDE
{
UK2Node_MakeStruct * Node = CastChecked < UK2Node_MakeStruct > ( InNode ) ;
if ( NULL = = Node - > StructType )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " MakeStruct_UnknownStructure_Error " , " Unknown structure to break for @@ " ) . ToString ( ) , Node ) ;
return ;
}
if ( ! UK2Node_MakeStruct : : CanBeMade ( Node - > StructType ) )
{
CompilerContext . MessageLog . Warning ( * LOCTEXT ( " MakeStruct_Error " , " The structure contains read-only members @@. Try use specialized 'make' function if available. " ) . ToString ( ) , Node ) ;
}
FNodeHandlingFunctor : : RegisterNets ( Context , Node ) ;
UEdGraphPin * OutputPin = FindOutputStructPinChecked ( Node ) ;
UEdGraphPin * Net = FEdGraphUtilities : : GetNetFromPin ( OutputPin ) ;
check ( NULL ! = Net ) ;
FBPTerminal * * FoundTerm = Context . NetMap . Find ( Net ) ;
FBPTerminal * Term = FoundTerm ? * FoundTerm : NULL ;
check ( NULL ! = Term ) ;
UStruct * StructInTerm = Cast < UStruct > ( Term - > Type . PinSubCategoryObject . Get ( ) ) ;
if ( NULL = = StructInTerm | | ! StructInTerm - > IsChildOf ( Node - > StructType ) )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " MakeStruct_NoMatch_Error " , " Structures don't match for @@ " ) . ToString ( ) , Node ) ;
}
}
virtual void RegisterNet ( FKismetFunctionContext & Context , UEdGraphPin * Net ) OVERRIDE
{
FBPTerminal * Term = new ( Context . IsEventGraph ( ) ? Context . EventGraphLocals : Context . Locals ) FBPTerminal ( ) ;
Term - > CopyFromPin ( Net , Context . NetNameMap - > MakeValidName ( Net ) ) ;
Context . NetMap . Add ( Net , Term ) ;
}
virtual void Compile ( FKismetFunctionContext & Context , UEdGraphNode * InNode ) OVERRIDE
{
UK2Node_MakeStruct * Node = CastChecked < UK2Node_MakeStruct > ( InNode ) ;
if ( NULL = = Node - > StructType )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " MakeStruct_UnknownStructure_Error " , " Unknown structure to break for @@ " ) . ToString ( ) , Node ) ;
return ;
}
UEdGraphPin * OutputStructNet = FEdGraphUtilities : : GetNetFromPin ( FindOutputStructPinChecked ( Node ) ) ;
FBPTerminal * * FoundTerm = Context . NetMap . Find ( OutputStructNet ) ;
FBPTerminal * OutputStructTerm = FoundTerm ? * FoundTerm : NULL ;
check ( NULL ! = OutputStructTerm ) ;
for ( int32 PinIndex = 0 ; PinIndex < Node - > Pins . Num ( ) ; + + PinIndex )
{
UEdGraphPin * Pin = Node - > Pins [ PinIndex ] ;
if ( Pin & & ! CompilerContext . GetSchema ( ) - > IsMetaPin ( * Pin ) & & ( Pin - > Direction = = EGPD_Input ) )
{
FBPTerminal * * FoundSrcTerm = Context . NetMap . Find ( FEdGraphUtilities : : GetNetFromPin ( Pin ) ) ;
FBPTerminal * SrcTerm = FoundSrcTerm ? * FoundSrcTerm : NULL ;
check ( NULL ! = SrcTerm ) ;
UProperty * BoundProperty = FindField < UProperty > ( Node - > StructType , * ( Pin - > PinName ) ) ;
check ( NULL ! = BoundProperty ) ;
FBPTerminal * DstTerm = new ( Context . IsEventGraph ( ) ? Context . EventGraphLocals : Context . Locals ) FBPTerminal ( ) ;
DstTerm - > CopyFromPin ( Pin , Context . NetNameMap - > MakeValidName ( Pin ) ) ;
DstTerm - > AssociatedVarProperty = BoundProperty ;
DstTerm - > Context = OutputStructTerm ;
FBlueprintCompiledStatement & Statement = Context . AppendStatementForNode ( Node ) ;
Statement . Type = KCST_Assignment ;
Statement . LHS = DstTerm ;
Statement . RHS . Add ( SrcTerm ) ;
}
}
if ( ! Node - > IsNodePure ( ) )
{
GenerateSimpleThenGoto ( Context , * Node ) ;
}
}
} ;
//////////////////////////////////////////////////////////////////////////
// UK2Node_MakeStruct
2014-04-23 20:18:55 -04:00
UK2Node_MakeStruct : : FMakeStructPinManager : : FMakeStructPinManager ( const uint8 * InSampleStructMemory )
: FStructOperationOptionalPinManager ( ) , SampleStructMemory ( InSampleStructMemory )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
void UK2Node_MakeStruct : : FMakeStructPinManager : : CustomizePinData ( UEdGraphPin * Pin , FName SourcePropertyName , int32 ArrayIndex , UProperty * Property ) const
{
struct FPinDefaultValueHelper
2014-03-14 14:13:41 -04:00
{
2014-05-29 16:52:50 -04:00
static void Set ( UEdGraphPin & InPin , const FString & Value , bool bIsText )
2014-03-14 14:13:41 -04:00
{
2014-05-29 16:52:50 -04:00
InPin . AutogeneratedDefaultValue = Value ;
2014-04-23 20:18:55 -04:00
if ( bIsText )
2014-03-14 14:13:41 -04:00
{
2014-05-29 16:52:50 -04:00
InPin . DefaultTextValue = FText : : FromString ( Value ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 20:18:55 -04:00
else
2014-03-14 14:13:41 -04:00
{
2014-05-29 16:52:50 -04:00
InPin . DefaultValue = Value ;
2014-04-23 20:18:55 -04:00
}
}
} ;
UK2Node_StructOperation : : FStructOperationOptionalPinManager : : CustomizePinData ( Pin , SourcePropertyName , ArrayIndex , Property ) ;
if ( Pin & & Property )
{
const UEdGraphSchema_K2 * Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
check ( Schema ) ;
const bool bIsText = Property - > IsA < UTextProperty > ( ) ;
checkSlow ( bIsText = = ( Schema - > PC_Text = = Pin - > PinType . PinCategory ) ) ;
const FString & MetadataDefaultValue = Property - > GetMetaData ( TEXT ( " MakeStructureDefaultValue " ) ) ;
if ( ! MetadataDefaultValue . IsEmpty ( ) )
{
FPinDefaultValueHelper : : Set ( * Pin , MetadataDefaultValue , bIsText ) ;
return ;
}
if ( NULL ! = SampleStructMemory )
{
FString NewDefaultValue ;
if ( Property - > ExportText_InContainer ( 0 , NewDefaultValue , SampleStructMemory , SampleStructMemory , NULL , PPF_None ) )
{
if ( Schema - > IsPinDefaultValid ( Pin , NewDefaultValue , NULL , FText : : GetEmpty ( ) ) . IsEmpty ( ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
FPinDefaultValueHelper : : Set ( * Pin , NewDefaultValue , bIsText ) ;
return ;
2014-03-14 14:13:41 -04:00
}
}
}
2014-04-23 20:18:55 -04:00
Schema - > SetPinDefaultValueBasedOnType ( Pin ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 20:18:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
bool UK2Node_MakeStruct : : FMakeStructPinManager : : CanTreatPropertyAsOptional ( UProperty * TestProperty ) const
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
return UK2Node_MakeStruct : : CanBeExposed ( TestProperty ) ;
}
2014-03-14 14:13:41 -04:00
UK2Node_MakeStruct : : UK2Node_MakeStruct ( const class FPostConstructInitializeProperties & PCIP )
: Super ( PCIP )
{
}
void UK2Node_MakeStruct : : AllocateDefaultPins ( )
{
const UEdGraphSchema_K2 * Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
if ( Schema & & StructType )
{
CreatePin ( EGPD_Output , Schema - > PC_Struct , TEXT ( " " ) , StructType , false , false , StructType - > GetName ( ) ) ;
{
2014-05-29 17:02:19 -04:00
FStructOnScope StructOnScope ( Cast < UScriptStruct > ( StructType ) ) ;
2014-03-14 14:13:41 -04:00
FMakeStructPinManager OptionalPinManager ( StructOnScope . GetStructMemory ( ) ) ;
OptionalPinManager . RebuildPropertyList ( ShowPinForProperties , StructType ) ;
OptionalPinManager . CreateVisiblePins ( ShowPinForProperties , StructType , EGPD_Input , this ) ;
}
// When struct has a lot of fields, mark their pins as advanced
if ( Pins . Num ( ) > 5 )
{
if ( ENodeAdvancedPins : : NoPins = = AdvancedPinDisplay )
{
AdvancedPinDisplay = ENodeAdvancedPins : : Hidden ;
}
for ( int32 PinIndex = 3 ; PinIndex < Pins . Num ( ) ; + + PinIndex )
{
if ( UEdGraphPin * EdGraphPin = Pins [ PinIndex ] )
{
EdGraphPin - > bAdvancedView = true ;
}
}
}
}
}
void UK2Node_MakeStruct : : ValidateNodeDuringCompilation ( class FCompilerResultsLog & MessageLog ) const
{
if ( ! StructType )
{
MessageLog . Error ( * LOCTEXT ( " NoStruct_Error " , " No Struct in @@ " ) . ToString ( ) , this ) ;
}
}
2014-04-23 18:30:37 -04:00
FText UK2Node_MakeStruct : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:30:37 -04:00
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " StructName " ) , FText : : FromString ( StructType ? StructType - > GetName ( ) : FString ( ) ) ) ;
return FText : : Format ( LOCTEXT ( " MakeNodeTitle " , " Make {StructName} " ) , Args ) ;
}
FString UK2Node_MakeStruct : : GetNodeNativeTitle ( ENodeTitleType : : Type TitleType ) const
{
// Do not setup this function for localization, intentionally left unlocalized!
2014-03-14 14:13:41 -04:00
return FString ( TEXT ( " Make " ) ) + ( StructType ? StructType - > GetName ( ) : FString ( ) ) ;
}
FString UK2Node_MakeStruct : : GetTooltip ( ) const
{
return FString : : Printf (
* LOCTEXT ( " MakeStruct_Tooltip " , " Adds a node that create a '%s' from its members " ) . ToString ( ) ,
* ( StructType ? StructType - > GetName ( ) : FString ( ) )
) ;
}
FLinearColor UK2Node_MakeStruct : : GetNodeTitleColor ( ) const
{
if ( const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) )
{
FEdGraphPinType PinType ;
PinType . PinCategory = K2Schema - > PC_Struct ;
PinType . PinSubCategoryObject = StructType ;
return K2Schema - > GetPinTypeColor ( PinType ) ;
}
return UK2Node : : GetNodeTitleColor ( ) ;
}
bool UK2Node_MakeStruct : : CanBeExposed ( const UProperty * Property )
{
if ( Property )
{
const UEdGraphSchema_K2 * Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
check ( Schema ) ;
FEdGraphPinType DumbGraphPinType ;
const bool bConvertable = Schema - > ConvertPropertyToPinType ( Property , /*out*/ DumbGraphPinType ) ;
const bool bVisible = Property - > HasAnyPropertyFlags ( CPF_BlueprintVisible | CPF_Edit ) ;
const bool bBlueprintReadOnly = Property - > HasAllPropertyFlags ( CPF_BlueprintReadOnly ) ;
if ( bVisible & & bConvertable & & ! bBlueprintReadOnly )
{
return true ;
}
}
return false ;
}
bool UK2Node_MakeStruct : : CanBeMade ( const UScriptStruct * Struct )
{
if ( ! Struct - > GetBoolMetaData ( TEXT ( " HasNativeMakeBreak " ) ) )
{
for ( TFieldIterator < UProperty > It ( Struct ) ; It ; + + It )
{
if ( CanBeExposed ( * It ) )
{
return true ;
}
}
}
return false ;
}
FNodeHandlingFunctor * UK2Node_MakeStruct : : CreateNodeHandler ( FKismetCompilerContext & CompilerContext ) const
{
return new FKCHandler_MakeStruct ( CompilerContext ) ;
}
UK2Node : : ERedirectType UK2Node_MakeStruct : : DoPinsMatchForReconstruction ( const UEdGraphPin * NewPin , int32 NewPinIndex , const UEdGraphPin * OldPin , int32 OldPinIndex ) const
{
ERedirectType Result = UK2Node : : DoPinsMatchForReconstruction ( NewPin , NewPinIndex , OldPin , OldPinIndex ) ;
2014-04-23 20:18:55 -04:00
if ( ( ERedirectType_None = = Result ) & & DoRenamedPinsMatch ( NewPin , OldPin , false ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
Result = ERedirectType_Custom ;
2014-03-14 14:13:41 -04:00
}
return Result ;
}
# undef LOCTEXT_NAMESPACE