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"
|
|
|
|
|
|
2014-10-14 22:50:06 -04:00
|
|
|
#include "SlateBasics.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
#include "../../../Runtime/Engine/Classes/Kismet/KismetArrayLibrary.h"
|
|
|
|
|
#include "ScopedTransaction.h"
|
|
|
|
|
#include "KismetCompiler.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-09-04 13:00:27 -04:00
|
|
|
#include "EdGraph/EdGraphNodeUtils.h" // for FNodeTextCache
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
static const FString OutputPinName = FString(TEXT("Array"));
|
|
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MakeArrayNode"
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
|
// FKCHandler_MakeArray
|
|
|
|
|
class FKCHandler_MakeArray : public FNodeHandlingFunctor
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FKCHandler_MakeArray(FKismetCompilerContext& InCompilerContext)
|
|
|
|
|
: FNodeHandlingFunctor(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_MakeArray* ArrayNode = CastChecked<UK2Node_MakeArray>(Node);
|
|
|
|
|
UEdGraphPin* OutputPin = ArrayNode->GetOutputPin();
|
|
|
|
|
|
|
|
|
|
FNodeHandlingFunctor::RegisterNets(Context, Node);
|
|
|
|
|
|
|
|
|
|
// Create a local term to drop the array into
|
2014-09-26 11:32:41 -04:00
|
|
|
FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(OutputPin, Context.NetNameMap->MakeValidName(OutputPin));
|
2014-03-14 14:13:41 -04:00
|
|
|
Term->bPassedByReference = false;
|
|
|
|
|
Term->Source = Node;
|
|
|
|
|
Context.NetMap.Add(OutputPin, Term);
|
|
|
|
|
}
|
|
|
|
|
|
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_MakeArray* ArrayNode = CastChecked<UK2Node_MakeArray>(Node);
|
|
|
|
|
UEdGraphPin* OutputPin = ArrayNode->GetOutputPin();
|
|
|
|
|
|
|
|
|
|
FBPTerminal** ArrayTerm = Context.NetMap.Find(OutputPin);
|
|
|
|
|
check(ArrayTerm);
|
|
|
|
|
|
|
|
|
|
FBlueprintCompiledStatement& CreateArrayStatement = Context.AppendStatementForNode(Node);
|
|
|
|
|
CreateArrayStatement.Type = KCST_CreateArray;
|
|
|
|
|
CreateArrayStatement.LHS = *ArrayTerm;
|
|
|
|
|
|
|
|
|
|
for(auto PinIt = Node->Pins.CreateIterator(); PinIt; ++PinIt)
|
|
|
|
|
{
|
|
|
|
|
UEdGraphPin* Pin = *PinIt;
|
|
|
|
|
if(Pin && Pin->Direction == EGPD_Input)
|
|
|
|
|
{
|
|
|
|
|
FBPTerminal** InputTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(Pin));
|
|
|
|
|
if( InputTerm )
|
|
|
|
|
{
|
|
|
|
|
CreateArrayStatement.RHS.Add(*InputTerm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
|
// UK2Node_MakeArray
|
|
|
|
|
|
2014-10-14 10:29:11 -04:00
|
|
|
UK2Node_MakeArray::UK2Node_MakeArray(const FObjectInitializer& ObjectInitializer)
|
|
|
|
|
: Super(ObjectInitializer)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
NumInputs = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FNodeHandlingFunctor* UK2Node_MakeArray::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
|
|
|
|
|
{
|
|
|
|
|
return new FKCHandler_MakeArray(CompilerContext);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-23 18:30:37 -04:00
|
|
|
FText UK2Node_MakeArray::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-04-23 18:30:37 -04:00
|
|
|
return LOCTEXT("NodeTitle", "Make Array");
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UEdGraphPin* UK2Node_MakeArray::GetOutputPin() const
|
|
|
|
|
{
|
|
|
|
|
return FindPin(OutputPinName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::AllocateDefaultPins()
|
|
|
|
|
{
|
|
|
|
|
// Create the output pin
|
2014-11-17 09:46:35 -05:00
|
|
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, TEXT(""), NULL, true, false, *OutputPinName);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
// Create the input pins to create the arrays from
|
|
|
|
|
for (int32 i = 0; i < NumInputs; ++i)
|
|
|
|
|
{
|
2014-11-17 09:46:35 -05:00
|
|
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, TEXT(""), NULL, false, false, *FString::Printf(TEXT("[%d]"), i));
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-17 09:46:35 -05:00
|
|
|
bool UK2Node_MakeArray::CanResetToWildcard() const
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
bool bClearPinsToWildcard = true;
|
|
|
|
|
|
|
|
|
|
// Check to see if we want to clear the wildcards.
|
2014-11-17 09:46:35 -05:00
|
|
|
for (const UEdGraphPin* Pin : Pins)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-11-17 09:46:35 -05:00
|
|
|
if( Pin->LinkedTo.Num() > 0 )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
// One of the pins is still linked, we will not be clearing the types.
|
|
|
|
|
bClearPinsToWildcard = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-17 09:46:35 -05:00
|
|
|
return bClearPinsToWildcard;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::ClearPinTypeToWildcard()
|
|
|
|
|
{
|
|
|
|
|
if( CanResetToWildcard() )
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
UEdGraphPin* OutputPin = GetOutputPin();
|
2014-11-17 09:46:35 -05:00
|
|
|
OutputPin->PinType.PinCategory = UEdGraphSchema_K2::PC_Wildcard;
|
2014-03-14 14:13:41 -04:00
|
|
|
OutputPin->PinType.PinSubCategory = TEXT("");
|
|
|
|
|
OutputPin->PinType.PinSubCategoryObject = NULL;
|
|
|
|
|
|
|
|
|
|
PropagatePinType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::NotifyPinConnectionListChanged(UEdGraphPin* Pin)
|
|
|
|
|
{
|
|
|
|
|
Super::NotifyPinConnectionListChanged(Pin);
|
|
|
|
|
|
|
|
|
|
// Was this the first or last connection?
|
|
|
|
|
int32 NumPinsWithLinks = 0;
|
|
|
|
|
// Array to cache the input pins we might want to find these if we are removing the last link
|
|
|
|
|
TArray< UEdGraphPin* > InputPins;
|
|
|
|
|
for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
|
|
|
|
|
{
|
|
|
|
|
NumPinsWithLinks += (Pins[PinIndex]->LinkedTo.Num() > 0) ? 1 : 0;
|
|
|
|
|
if( Pins[PinIndex]->Direction == EGPD_Input )
|
|
|
|
|
{
|
|
|
|
|
InputPins.Add(Pins[PinIndex]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UEdGraphPin* OutputPin = GetOutputPin();
|
|
|
|
|
|
|
|
|
|
if (Pin->LinkedTo.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
// Just made a connection, was it the first?
|
|
|
|
|
if (NumPinsWithLinks == 1)
|
|
|
|
|
{
|
|
|
|
|
// Update the types on all the pins
|
|
|
|
|
OutputPin->PinType = Pin->LinkedTo[0]->PinType;
|
|
|
|
|
OutputPin->PinType.bIsArray = true;
|
|
|
|
|
PropagatePinType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Just broke a connection, was it the last?
|
|
|
|
|
if (NumPinsWithLinks == 0)
|
|
|
|
|
{
|
|
|
|
|
// Return to wildcard if theres nothing in any of the input pins
|
|
|
|
|
bool bResetOutputPin = true;
|
|
|
|
|
for (int32 PinIndex = 0; PinIndex < InputPins.Num(); ++PinIndex)
|
|
|
|
|
{
|
|
|
|
|
if( InputPins[PinIndex]->GetDefaultAsString().IsEmpty() == false )
|
|
|
|
|
{
|
|
|
|
|
bResetOutputPin = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( bResetOutputPin == true )
|
|
|
|
|
{
|
2014-11-17 09:46:35 -05:00
|
|
|
OutputPin->PinType.PinCategory = UEdGraphSchema_K2::PC_Wildcard;
|
2014-03-14 14:13:41 -04:00
|
|
|
OutputPin->PinType.PinSubCategory = TEXT("");
|
|
|
|
|
OutputPin->PinType.PinSubCategoryObject = NULL;
|
|
|
|
|
|
|
|
|
|
PropagatePinType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::PropagatePinType()
|
|
|
|
|
{
|
|
|
|
|
const UEdGraphPin* OutputPin = GetOutputPin();
|
|
|
|
|
|
|
|
|
|
if (OutputPin)
|
|
|
|
|
{
|
|
|
|
|
UClass const* CallingContext = NULL;
|
|
|
|
|
if (UBlueprint const* Blueprint = GetBlueprint())
|
|
|
|
|
{
|
|
|
|
|
CallingContext = Blueprint->GeneratedClass;
|
|
|
|
|
if (CallingContext == NULL)
|
|
|
|
|
{
|
|
|
|
|
CallingContext = Blueprint->ParentClass;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
|
bool bWantRefresh = false;
|
|
|
|
|
// Propagate pin type info (except for array info!) to pins with dependent types
|
|
|
|
|
for (TArray<UEdGraphPin*>::TIterator it(Pins); it; ++it)
|
|
|
|
|
{
|
|
|
|
|
UEdGraphPin* CurrentPin = *it;
|
|
|
|
|
|
|
|
|
|
if (CurrentPin != OutputPin)
|
|
|
|
|
{
|
2015-03-10 18:34:29 -04:00
|
|
|
// sub pins will be updated by their parent pin, so if we have a parent pin just do nothing
|
|
|
|
|
if (CurrentPin->ParentPin == nullptr)
|
|
|
|
|
{
|
|
|
|
|
bWantRefresh = true;
|
|
|
|
|
|
|
|
|
|
// if we've reset to wild card or the parentpin no longer matches we need to collapse the split pin(s)
|
|
|
|
|
// otherwise everything should be OK:
|
|
|
|
|
if (CurrentPin->SubPins.Num() != 0 &&
|
|
|
|
|
( CurrentPin->PinType.PinCategory != OutputPin->PinType.PinCategory ||
|
|
|
|
|
CurrentPin->PinType.PinSubCategory != OutputPin->PinType.PinSubCategory ||
|
|
|
|
|
CurrentPin->PinType.PinSubCategoryObject != OutputPin->PinType.PinSubCategoryObject )
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
// this is a little dicey, but should be fine.. relies on the fact that RecombinePin will only remove pins that
|
|
|
|
|
// are placed after CurrentPin in the Pins member:
|
|
|
|
|
Schema->RecombinePin(CurrentPin->SubPins[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CurrentPin->PinType.PinCategory = OutputPin->PinType.PinCategory;
|
|
|
|
|
CurrentPin->PinType.PinSubCategory = OutputPin->PinType.PinSubCategory;
|
|
|
|
|
CurrentPin->PinType.PinSubCategoryObject = OutputPin->PinType.PinSubCategoryObject;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-11-17 09:46:35 -05:00
|
|
|
if (CurrentPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard)
|
|
|
|
|
{
|
|
|
|
|
CurrentPin->ResetDefaultValue();
|
|
|
|
|
}
|
2014-11-26 18:11:01 -05:00
|
|
|
else if (CurrentPin->GetDefaultAsString().IsEmpty() == true)
|
2014-11-17 09:46:35 -05:00
|
|
|
{
|
2014-11-26 18:11:01 -05:00
|
|
|
// Only reset default value if there isn't one set. Otherwise this deletes data!
|
2014-11-17 09:46:35 -05:00
|
|
|
Schema->SetPinDefaultValueBasedOnType(CurrentPin);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
// Verify that all previous connections to this pin are still valid with the new type
|
|
|
|
|
for (TArray<UEdGraphPin*>::TIterator ConnectionIt(CurrentPin->LinkedTo); ConnectionIt; ++ConnectionIt)
|
|
|
|
|
{
|
|
|
|
|
UEdGraphPin* ConnectedPin = *ConnectionIt;
|
|
|
|
|
if (!Schema->ArePinsCompatible(CurrentPin, ConnectedPin, CallingContext))
|
|
|
|
|
{
|
|
|
|
|
CurrentPin->BreakLinkTo(ConnectedPin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If we have a valid graph we should refresh it now to refelect any changes we made
|
|
|
|
|
if( (bWantRefresh == true ) && ( OutputPin->GetOwningNode() != NULL ) && ( OutputPin->GetOwningNode()->GetGraph() != NULL ) )
|
|
|
|
|
{
|
|
|
|
|
OutputPin->GetOwningNode()->GetGraph()->NotifyGraphChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UFunction* UK2Node_MakeArray::GetArrayClearFunction() const
|
|
|
|
|
{
|
|
|
|
|
UClass* ArrayLibClass = UKismetArrayLibrary::StaticClass();
|
|
|
|
|
UFunction* ReturnFunction = ArrayLibClass->FindFunctionByName(FName(TEXT("Array_Clear")));
|
|
|
|
|
check(ReturnFunction);
|
|
|
|
|
return ReturnFunction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UFunction* UK2Node_MakeArray::GetArrayAddFunction() const
|
|
|
|
|
{
|
|
|
|
|
UClass* ArrayLibClass = UKismetArrayLibrary::StaticClass();
|
|
|
|
|
UFunction* ReturnFunction = ArrayLibClass->FindFunctionByName(FName(TEXT("Array_Add")));
|
|
|
|
|
check(ReturnFunction);
|
|
|
|
|
return ReturnFunction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::PostReconstructNode()
|
|
|
|
|
{
|
|
|
|
|
// Find a pin that has connections to use to jumpstart the wildcard process
|
|
|
|
|
for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
|
|
|
|
|
{
|
|
|
|
|
if (Pins[PinIndex]->LinkedTo.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
// The pin is linked, continue to use its type as the type for all pins.
|
|
|
|
|
|
|
|
|
|
// Update the types on all the pins
|
|
|
|
|
UEdGraphPin* OutputPin = GetOutputPin();
|
|
|
|
|
OutputPin->PinType = Pins[PinIndex]->LinkedTo[0]->PinType;
|
|
|
|
|
OutputPin->PinType.bIsArray = true;
|
|
|
|
|
PropagatePinType();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if(!Pins[PinIndex]->GetDefaultAsString().IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
// The pin has user data in it, continue to use its type as the type for all pins.
|
|
|
|
|
|
|
|
|
|
// Update the types on all the pins
|
|
|
|
|
UEdGraphPin* OutputPin = GetOutputPin();
|
|
|
|
|
OutputPin->PinType = Pins[PinIndex]->PinType;
|
|
|
|
|
OutputPin->PinType.bIsArray = true;
|
|
|
|
|
PropagatePinType();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-03 18:14:09 -04:00
|
|
|
FText UK2Node_MakeArray::GetTooltipText() const
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-09-03 18:14:09 -04:00
|
|
|
return LOCTEXT("MakeArrayTooltip", "Create an array from a series of items.");
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::AddInputPin()
|
|
|
|
|
{
|
|
|
|
|
FScopedTransaction Transaction( LOCTEXT("AddPinTx", "AddPin") );
|
|
|
|
|
Modify();
|
|
|
|
|
|
|
|
|
|
++NumInputs;
|
2014-12-10 12:38:55 -05:00
|
|
|
FEdGraphPinType OutputPinType = GetOutputPin()->PinType;
|
|
|
|
|
CreatePin(EGPD_Input, OutputPinType.PinCategory, OutputPinType.PinSubCategory, OutputPinType.PinSubCategoryObject.Get(), false, false, *FString::Printf(TEXT("[%d]"), (NumInputs-1)));
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
const bool bIsCompiling = GetBlueprint()->bBeingCompiled;
|
|
|
|
|
if( !bIsCompiling )
|
|
|
|
|
{
|
|
|
|
|
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::RemoveInputPin(UEdGraphPin* Pin)
|
|
|
|
|
{
|
|
|
|
|
FScopedTransaction Transaction( LOCTEXT("RemovePinTx", "RemovePin") );
|
|
|
|
|
Modify();
|
|
|
|
|
|
|
|
|
|
check(Pin->Direction == EGPD_Input);
|
|
|
|
|
|
|
|
|
|
int32 PinRemovalIndex = INDEX_NONE;
|
|
|
|
|
if (Pins.Find(Pin, /*out*/ PinRemovalIndex))
|
|
|
|
|
{
|
|
|
|
|
for (int32 PinIndex = PinRemovalIndex + 1; PinIndex < Pins.Num(); ++PinIndex)
|
|
|
|
|
{
|
|
|
|
|
Pins[PinIndex]->Modify();
|
|
|
|
|
Pins[PinIndex]->PinName = FString::Printf(TEXT("[%d]"), PinIndex - 2); // -1 to shift back one, -1 to account for the output pin at the 0th position
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Pins.RemoveAt(PinRemovalIndex);
|
|
|
|
|
Pin->Modify();
|
|
|
|
|
Pin->BreakAllPinLinks();
|
|
|
|
|
|
|
|
|
|
--NumInputs;
|
|
|
|
|
|
|
|
|
|
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UK2Node_MakeArray::GetContextMenuActions(const FGraphNodeContextMenuBuilder& Context) const
|
|
|
|
|
{
|
|
|
|
|
Super::GetContextMenuActions(Context);
|
|
|
|
|
|
|
|
|
|
if (!Context.bIsDebugging)
|
|
|
|
|
{
|
2014-11-17 09:46:35 -05:00
|
|
|
Context.MenuBuilder->BeginSection("K2NodeMakeArray", NSLOCTEXT("K2Nodes", "MakeArrayHeader", "MakeArray"));
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
if (Context.Pin != NULL)
|
|
|
|
|
{
|
|
|
|
|
// we only do this for normal BlendList/BlendList by enum, BlendList by Bool doesn't support add/remove pins
|
|
|
|
|
if (Context.Pin->Direction == EGPD_Input)
|
|
|
|
|
{
|
|
|
|
|
//@TODO: Only offer this option on arrayed pins
|
2014-11-17 09:46:35 -05:00
|
|
|
Context.MenuBuilder->AddMenuEntry(
|
|
|
|
|
LOCTEXT("RemovePin", "Remove array element pin"),
|
|
|
|
|
LOCTEXT("RemovePinTooltip", "Remove this array element pin"),
|
|
|
|
|
FSlateIcon(),
|
|
|
|
|
FUIAction(
|
|
|
|
|
FExecuteAction::CreateUObject(this, &UK2Node_MakeArray::RemoveInputPin, const_cast<UEdGraphPin*>(Context.Pin))
|
|
|
|
|
)
|
|
|
|
|
);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-17 09:46:35 -05:00
|
|
|
Context.MenuBuilder->AddMenuEntry(
|
|
|
|
|
LOCTEXT("AddPin", "Add array element pin"),
|
|
|
|
|
LOCTEXT("AddPinTooltip", "Add another array element pin"),
|
|
|
|
|
FSlateIcon(),
|
|
|
|
|
FUIAction(
|
|
|
|
|
FExecuteAction::CreateUObject(this, &UK2Node_MakeArray::AddInputPin)
|
|
|
|
|
)
|
|
|
|
|
);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-11-17 09:46:35 -05:00
|
|
|
|
|
|
|
|
Context.MenuBuilder->AddMenuEntry(
|
|
|
|
|
LOCTEXT("ResetToWildcard", "Reset to wildcard"),
|
|
|
|
|
LOCTEXT("ResetToWildcardTooltip", "Reset the node to have wildcard input/outputs. Requires no pins are connected."),
|
|
|
|
|
FSlateIcon(),
|
|
|
|
|
FUIAction(
|
|
|
|
|
FExecuteAction::CreateUObject(this, &UK2Node_MakeArray::ClearPinTypeToWildcard),
|
|
|
|
|
FCanExecuteAction::CreateUObject(this, &UK2Node_MakeArray::CanResetToWildcard)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Context.MenuBuilder->EndSection();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UK2Node_MakeArray::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
|
|
|
|
{
|
|
|
|
|
if(OtherPin->PinType.bIsArray == true && MyPin->Direction == EGPD_Input)
|
|
|
|
|
{
|
|
|
|
|
OutReason = NSLOCTEXT("K2Node", "MakeArray_InputIsArray", "Cannot make an array with an input of an array!").ToString();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-23 16:57:59 -04:00
|
|
|
auto Schema = Cast<const UEdGraphSchema_K2>(GetSchema());
|
|
|
|
|
if (!ensure(Schema) || (ensure(OtherPin) && Schema->IsExecPin(*OtherPin)))
|
|
|
|
|
{
|
|
|
|
|
OutReason = NSLOCTEXT("K2Node", "MakeArray_InputIsExec", "Cannot make an array with an execution input!").ToString();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-23 16:57:59 -04:00
|
|
|
void UK2Node_MakeArray::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
|
|
|
|
|
{
|
|
|
|
|
auto Schema = Cast<const UEdGraphSchema_K2>(GetSchema());
|
|
|
|
|
auto OutputPin = GetOutputPin();
|
|
|
|
|
if (!ensure(Schema) || !ensure(OutputPin) || Schema->IsExecPin(*OutputPin))
|
|
|
|
|
{
|
|
|
|
|
MessageLog.Error(*NSLOCTEXT("K2Node", "MakeArray_OutputIsExec", "Uaccepted array type in @@").ToString(), this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-23 20:16:29 -04:00
|
|
|
void UK2Node_MakeArray::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)
|
|
|
|
|
// 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_MakeArray::GetMenuCategory() const
|
|
|
|
|
{
|
2014-09-04 13:00:27 -04:00
|
|
|
static FNodeTextCache CachedCategory;
|
2015-04-02 11:16:23 -04:00
|
|
|
if (CachedCategory.IsOutOfDate(this))
|
2014-09-04 13:00:27 -04:00
|
|
|
{
|
|
|
|
|
// FText::Format() is slow, so we cache this to save on performance
|
2015-04-02 11:16:23 -04:00
|
|
|
CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "Array")), this);
|
2014-09-04 13:00:27 -04:00
|
|
|
}
|
|
|
|
|
return CachedCategory;
|
2014-07-14 16:05:25 -04:00
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
#undef LOCTEXT_NAMESPACE
|