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 "KismetCompiler.h"
# include "VariableSetHandler.h"
2014-05-29 16:42:22 -04:00
# include "K2Node_VariableSetRef.h"
2014-07-14 14:20:04 -04:00
# include "BlueprintNodeSpawner.h"
2014-07-16 14:14:48 -04:00
# include "EditorCategoryUtils.h"
2014-08-23 20:16:29 -04:00
# include "BlueprintActionDatabaseRegistrar.h"
2014-09-22 12:23:59 -04:00
# include "BlueprintActionFilter.h"
2014-03-14 14:13:41 -04:00
static FString TargetVarPinName ( TEXT ( " Target " ) ) ;
static FString VarValuePinName ( TEXT ( " Value " ) ) ;
# define LOCTEXT_NAMESPACE "K2Node_VariableSetRef"
class FKCHandler_VariableSetRef : public FKCHandler_VariableSet
{
public :
FKCHandler_VariableSetRef ( FKismetCompilerContext & InCompilerContext )
: FKCHandler_VariableSet ( InCompilerContext )
{
}
2014-06-13 06:14:46 -04:00
virtual void RegisterNets ( FKismetFunctionContext & Context , UEdGraphNode * Node ) override
2014-03-14 14:13:41 -04:00
{
UK2Node_VariableSetRef * VarRefNode = CastChecked < UK2Node_VariableSetRef > ( Node ) ;
UEdGraphPin * ValuePin = VarRefNode - > GetValuePin ( ) ;
ValidateAndRegisterNetIfLiteral ( Context , ValuePin ) ;
}
void InnerAssignment ( FKismetFunctionContext & Context , UEdGraphNode * Node , UEdGraphPin * VariablePin , UEdGraphPin * ValuePin )
{
FBPTerminal * * VariableTerm = Context . NetMap . Find ( VariablePin ) ;
if ( VariableTerm = = NULL )
{
VariableTerm = Context . NetMap . Find ( FEdGraphUtilities : : GetNetFromPin ( VariablePin ) ) ;
}
FBPTerminal * * ValueTerm = Context . LiteralHackMap . Find ( ValuePin ) ;
if ( ValueTerm = = NULL )
{
ValueTerm = Context . NetMap . Find ( FEdGraphUtilities : : GetNetFromPin ( ValuePin ) ) ;
}
if ( ( VariableTerm ! = NULL ) & & ( ValueTerm ! = NULL ) )
{
FBlueprintCompiledStatement & Statement = Context . AppendStatementForNode ( Node ) ;
Statement . Type = KCST_Assignment ;
Statement . LHS = * VariableTerm ;
Statement . RHS . Add ( * ValueTerm ) ;
if ( ! ( * VariableTerm ) - > IsTermWritable ( ) )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " WriteConst_Error " , " Cannot write to const @@ " ) . ToString ( ) , VariablePin ) ;
}
}
else
{
if ( VariablePin ! = ValuePin )
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " ResolveValueIntoVariablePin_Error " , " Failed to resolve term @@ passed into @@ " ) . ToString ( ) , ValuePin , VariablePin ) ;
}
else
{
CompilerContext . MessageLog . Error ( * LOCTEXT ( " ResolveTermPassed_Error " , " Failed to resolve term passed into @@ " ) . ToString ( ) , VariablePin ) ;
}
}
}
2014-06-13 06:14:46 -04:00
virtual void Compile ( FKismetFunctionContext & Context , UEdGraphNode * Node ) override
2014-03-14 14:13:41 -04:00
{
UK2Node_VariableSetRef * VarRefNode = CastChecked < UK2Node_VariableSetRef > ( Node ) ;
UEdGraphPin * VarTargetPin = VarRefNode - > GetTargetPin ( ) ;
UEdGraphPin * ValuePin = VarRefNode - > GetValuePin ( ) ;
InnerAssignment ( Context , Node , VarTargetPin , ValuePin ) ;
// Generate the output impulse from this node
GenerateSimpleThenGoto ( Context , * Node ) ;
}
} ;
2014-10-14 10:29:11 -04:00
UK2Node_VariableSetRef : : UK2Node_VariableSetRef ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
}
void UK2Node_VariableSetRef : : 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 ) ;
CreatePin ( EGPD_Input , K2Schema - > PC_Wildcard , TEXT ( " " ) , NULL , false , true , TargetVarPinName ) ;
UEdGraphPin * ValuePin = CreatePin ( EGPD_Input , K2Schema - > PC_Wildcard , TEXT ( " " ) , NULL , false , false , VarValuePinName ) ;
}
void UK2Node_VariableSetRef : : ReallocatePinsDuringReconstruction ( TArray < UEdGraphPin * > & OldPins )
{
AllocateDefaultPins ( ) ;
// Coerce the type of the node from the old pin, if available
UEdGraphPin * OldTargetPin = NULL ;
for ( auto OldPinIt = OldPins . CreateIterator ( ) ; OldPinIt ; + + OldPinIt )
{
UEdGraphPin * CurrPin = * OldPinIt ;
if ( CurrPin - > PinName = = TargetVarPinName )
{
OldTargetPin = CurrPin ;
break ;
}
}
if ( OldTargetPin )
{
UEdGraphPin * NewTargetPin = GetTargetPin ( ) ;
CoerceTypeFromPin ( OldTargetPin ) ;
}
2014-09-24 14:15:13 -04:00
CachedNodeTitle . MarkDirty ( ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-03 18:14:09 -04:00
FText UK2Node_VariableSetRef : : GetTooltipText ( ) const
2014-03-14 14:13:41 -04:00
{
2014-09-03 18:14:09 -04:00
return NSLOCTEXT ( " K2Node " , " SetValueOfRefVariable " , " Set the value of the connected pass-by-ref variable " ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
FText UK2Node_VariableSetRef : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
const UEdGraphSchema_K2 * Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
UEdGraphPin * TargetPin = GetTargetPin ( ) ;
2014-09-02 19:08:09 -04:00
if ( ( TargetPin = = nullptr ) | | ( TargetPin - > PinType . PinCategory = = Schema - > PC_Wildcard ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:30:37 -04:00
return NSLOCTEXT ( " K2Node " , " SetRefVarNodeTitle " , " Set By-Ref Var " ) ;
}
2015-04-02 11:16:23 -04:00
else if ( CachedNodeTitle . IsOutOfDate ( this ) )
2014-09-02 19:08:09 -04:00
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " PinType " ) , Schema - > TypeToText ( TargetPin - > PinType ) ) ;
// FText::Format() is slow, so we cache this to save on performance
2015-04-02 11:16:23 -04:00
CachedNodeTitle . SetCachedText ( FText : : Format ( NSLOCTEXT ( " K2Node " , " SetRefVarNodeTitle_Typed " , " Set {PinType} " ) , Args ) , this ) ;
2014-09-02 19:08:09 -04:00
}
return CachedNodeTitle ;
2014-04-23 18:30:37 -04:00
}
2014-09-22 12:23:59 -04:00
bool UK2Node_VariableSetRef : : IsActionFilteredOut ( class FBlueprintActionFilter const & Filter )
{
// Default to filtering this node out unless dragging off of a reference output pin
bool bIsFilteredOut = true ;
FBlueprintActionContext const & FilterContext = Filter . Context ;
for ( UEdGraphPin * Pin : FilterContext . Pins )
{
if ( Pin - > Direction = = EGPD_Output & & Pin - > PinType . bIsReference = = true )
{
bIsFilteredOut = false ;
break ;
}
}
return bIsFilteredOut ;
}
2014-03-14 14:13:41 -04:00
void UK2Node_VariableSetRef : : NotifyPinConnectionListChanged ( UEdGraphPin * Pin )
{
Super : : NotifyPinConnectionListChanged ( Pin ) ;
UEdGraphPin * TargetPin = GetTargetPin ( ) ;
UEdGraphPin * ValuePin = GetValuePin ( ) ;
if ( ( Pin = = TargetPin ) | | ( Pin = = ValuePin ) )
{
UEdGraphPin * ConnectedToPin = ( Pin - > LinkedTo . Num ( ) > 0 ) ? Pin - > LinkedTo [ 0 ] : NULL ;
CoerceTypeFromPin ( ConnectedToPin ) ;
}
}
void UK2Node_VariableSetRef : : CoerceTypeFromPin ( const UEdGraphPin * Pin )
{
const UEdGraphSchema_K2 * K2Schema = GetDefault < UEdGraphSchema_K2 > ( ) ;
UEdGraphPin * TargetPin = GetTargetPin ( ) ;
UEdGraphPin * ValuePin = GetValuePin ( ) ;
if ( Pin )
{
check ( ( Pin ! = TargetPin ) | | ( Pin - > PinType . bIsReference & & ! Pin - > PinType . bIsArray ) ) ;
TargetPin - > PinType = Pin - > PinType ;
TargetPin - > PinType . bIsReference = true ;
ValuePin - > PinType = Pin - > PinType ;
ValuePin - > PinType . bIsReference = false ;
}
else
{
// Pin disconnected...revert to wildcard
TargetPin - > PinType . PinCategory = K2Schema - > PC_Wildcard ;
TargetPin - > PinType . PinSubCategory = TEXT ( " " ) ;
TargetPin - > PinType . PinSubCategoryObject = NULL ;
TargetPin - > BreakAllPinLinks ( ) ;
ValuePin - > PinType . PinCategory = K2Schema - > PC_Wildcard ;
ValuePin - > PinType . PinSubCategory = TEXT ( " " ) ;
ValuePin - > PinType . PinSubCategoryObject = NULL ;
ValuePin - > BreakAllPinLinks ( ) ;
2014-09-02 19:08:09 -04:00
CachedNodeTitle . MarkDirty ( ) ;
2014-03-14 14:13:41 -04:00
}
}
UEdGraphPin * UK2Node_VariableSetRef : : GetTargetPin ( ) const
{
return FindPin ( TargetVarPinName ) ;
}
UEdGraphPin * UK2Node_VariableSetRef : : GetValuePin ( ) const
{
return FindPin ( VarValuePinName ) ;
}
FNodeHandlingFunctor * UK2Node_VariableSetRef : : CreateNodeHandler ( FKismetCompilerContext & CompilerContext ) const
{
return new FKCHandler_VariableSetRef ( CompilerContext ) ;
}
2014-08-23 20:16:29 -04:00
void UK2Node_VariableSetRef : : GetMenuActions ( FBlueprintActionDatabaseRegistrar & ActionRegistrar ) const
2014-07-14 14:20:04 -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 14:20:04 -04:00
2014-09-10 17:09:26 -04:00
ActionRegistrar . AddBlueprintAction ( ActionKey , NodeSpawner ) ;
}
2014-07-14 14:20:04 -04:00
}
FText UK2Node_VariableSetRef : : GetMenuCategory ( ) const
{
2014-07-16 14:14:48 -04:00
return FEditorCategoryUtils : : GetCommonCategory ( FCommonEditorCategory : : Variables ) ;
2014-07-14 14:20:04 -04:00
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE