You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb #rnx ============================ MAJOR FEATURES & CHANGES ============================ Change 4289396 by Marc.Audy Fix get data table row result pin not properly updating if it was split. #jira UE-62896 Change 4289407 by Marc.Audy Don't allow set member input pin to be split at all #jira UE-62924 Change 4291871 by Mieszko.Zielinski Exporting EnvQueryGenerator_SimpleGrid with AIMODULE_API #UE4 #jira UE-62697 Change 4292078 by Marc.Audy Fix GetDataTableRow title not updating when changing type #jira UE-62896 Change 4292770 by Dan.Oconnor Interpreter Optimization 7 of N: CPF_ZeroConstructor assigned for struct properties that that are User Defined Structs Change 4293207 by Dan.Oconnor Interpreter Optimization 8 of N: CPF_IsPlainOldData and CPF_NoDestructor assigned for struct properties that that are User Defined Structs Change 4297023 by Marc.Audy Remove dumb returns Change 4298303 by Dan.Oconnor Fix for issues compiling blueprints after changing a UserDefinedStructure #jira UE-63002 Change 4301603 by Phillip.Kavan Fix incorrect code generation at cook time when Blueprint nativization is enabled for objects instanced through the editor and assigned to an instanced object reference property. Change summary: - Modified FEmitDefaultValueHelper::HandleSpecialTypes() to emit runtime code to look for an existing instance of a default subobject only if the 'RF_DefaultSubObject' flag is set on the source instance. This works around instances that return 'true' for IsDefaultSubobject() but were not created with CreateDefaultSubobject() (e.g. - instanced in the editor UI). #jira UE-62883 Change 4302720 by Dan.Oconnor Prevent user from entering 'None' as parameter name on a blueprint function #jira UE-63033 Change 4303695 by Fred.Kimberley Don't allow the user to attempt to import a csv unless they've specified the rowstruct for datatables or the interpolation for curve tables. #jira UE-62856 Change 4304633 by Ben.Zeigler #jira UE-63173 Fix crash ending PIE while a level is waiting to load, SetShouldForceUnloadStreamingLevels now actually force unloads levels Change 4313208 by Dan.Oconnor Warn users when the outputs of a node that is pruned are used #jira UE-44518 Change 4313339 by Dan.Oconnor Interpreter Optimization 9 of N: Mark ubergraph function as final so that calls to it don't need to search the target object Change 4313652 by Dan.Oconnor Don't warn when a non-pure node that is connected only via its exec is orphaned - fixes overzealous warnings EngineTest #jira None Change 4313661 by Dan.Oconnor Comment typo fixes Change 4313729 by Dan.Oconnor Avoid crashing when running the help command for the GenerateBlueprintAPICommandlet #jira UE-63283 Change 4318175 by Marc.Audy PR #5024: Require BlueprintAssignable delegate parameters to be supported by blueprints (Contributed by slonopotamus) #jira UE-635250 Change 4318302 by Marc.Audy Use define instead of duplicating text Change 4318681 by Fred.Kimberley Don't allow users to try to rename rows to emtpy strings, whitespace only, or names that have invalid characters. #jira UE-63058 Change 4318683 by Fred.Kimberley Don't reorder the rowmap when removing a row. #jira UE-62754 Change 4318686 by Fred.Kimberley Get rid of the failed to import message when cancelling the import of a csv or json file. #jira UE-62625 Change 4318689 by Fred.Kimberley Back out changelist 4281972 Change 4318713 by Marc.Audy Validate CommutativeAssociativeBinaryOperator metadata in UHT and also at the K2Node level in case the function changes to an invalid construct later #jira UE-60186 Change 4319363 by Dan.Oconnor Warnings and errors generated by macro expansion now include a link back to the macro instance that created the suspect nodes #jira None Change 4319559 by Dan.Oconnor PR #5028: UE-63225: Use correct source BP when retrieving the tooltip text (Contributed by projectgheist) #jira UE-63225 Change 4323740 by Marc.Audy Don't crash if an ICH is (somewhat surprisingly) missing #jira UE-63305 Change 4328877 by mason.seay BP for pin bug Change 4336999 by Fred.Kimberley Unshelved from pending changelist '4299645': PR #5003: Changed SendGameplayEvent()'s category from "Abilities" to "Ability" for consistency (Contributed by rlabrecque) #jira UE-63067 Change 4337645 by Marc.Audy PR #5049: Make GetPlayerControllerID pure (Contributed by KristofMorva) #jira UE-63472 Change 4338211 by Phillip.Kavan Fix missing backend support for initializing a container variable (including unconnected function output pins) to a default (literal) value term in nativized Blueprint C++ code. Change summary: - Added a 'CoerceProperty' argument to FBlueprintCompilerCppBackEnd::TermToText() and FEmitHelper::LiteralTerm(). This is passed through as the LHS term's associated property when compiling 'KCST_Assignment' statements. - Modified FEmitHelper::LiteralTerm() to emit an initialization list to C++. This occurs when the RHS of a variable assignment statement is a literal container term, which includes the initialization of K2Node_FunctionResult pins to a default (empty) value. - Added FBlueprintCompilerCppBackEnd::TermToText() and FEmitHelper::LiteralTerm() methods that accept a struct value for specifying arguments rather than increasing the number of parameters with default values. Modified the implementations to match. #jira UE-48397 Change 4338908 by Marc.Audy Don't check when fetching world settings from IsPaused as it is already set up to handle it coming back null #jira UE-63583 Change 4339262 by Marc.Audy Add comments to ERedirectType Change 4339718 by Mieszko.Zielinski Clearing editor world's EnvironmentQueryManager instace's LocalContextMap whenever a BP finished compiling #UE4 #jira UE-63481 Change 4340548 by Marc.Audy ChildActor's need to be spawned from the ChildActorTemplate otherwise any non-replicated customized properties will be incorrect on the Client. #jira UE-63427 Change 4340756 by Marc.Audy Don't allow a new pin to be matched twice #jira UE-63504 Change 4342704 by mason.seay Updated Pin Testing blueprints Change 4319930 by Marc.Audy Mark FPartyState as a BlueprintType Change 4329176 by Dan.Oconnor Add optional message identifier to tokenized message, use message identifier to facilitate suppressing a new warning in the blueprint compiler, remove the unused (and unusable) FTokenizedMiscData #jira None Change 4337859 by Fred.Kimberley Fixing misc restricted gameplay tag UI bugs #jira UE-63600, UE-63602, UE-63603 #ROBOMERGE-OWNER: jason.bestimt #ROBOMERGE-SOURCE: CL 4344176 in //UE4/Main/... #ROBOMERGE-BOT: DEVVR (Main -> Dev-VR) [CL 4344180 by marc audy in Dev-VR branch]
504 lines
17 KiB
C++
504 lines
17 KiB
C++
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "K2Node_GetDataTableRow.h"
|
|
#include "Engine/DataTable.h"
|
|
#include "EdGraphSchema_K2.h"
|
|
#include "K2Node_CallFunction.h"
|
|
#include "K2Node_IfThenElse.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
#include "KismetCompiler.h"
|
|
#include "DataTableEditorUtils.h"
|
|
#include "Kismet/DataTableFunctionLibrary.h"
|
|
#include "BlueprintNodeSpawner.h"
|
|
#include "EditorCategoryUtils.h"
|
|
#include "BlueprintActionDatabaseRegistrar.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "K2Node_GetDataTableRow"
|
|
|
|
struct UK2Node_GetDataTableRowHelper
|
|
{
|
|
static FName DataTablePinName;
|
|
static FName RowNamePinName;
|
|
static FName RowNotFoundPinName;
|
|
};
|
|
|
|
FName UK2Node_GetDataTableRowHelper::DataTablePinName(*LOCTEXT("DataTablePinName","DataTable").ToString());
|
|
FName UK2Node_GetDataTableRowHelper::RowNotFoundPinName(*LOCTEXT("RowNotFoundPinName","RowNotFound").ToString());
|
|
FName UK2Node_GetDataTableRowHelper::RowNamePinName(*LOCTEXT("RowNamePinName","RowName").ToString());
|
|
|
|
UK2Node_GetDataTableRow::UK2Node_GetDataTableRow(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
NodeTooltip = LOCTEXT("NodeTooltip", "Attempts to retrieve a TableRow from a DataTable via it's RowName");
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::AllocateDefaultPins()
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
// Add execution pins
|
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
|
UEdGraphPin* RowFoundPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
|
RowFoundPin->PinFriendlyName = LOCTEXT("GetDataTableRow Row Found Exec pin", "Row Found");
|
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UK2Node_GetDataTableRowHelper::RowNotFoundPinName);
|
|
|
|
// Add DataTable pin
|
|
UEdGraphPin* DataTablePin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, UDataTable::StaticClass(), UK2Node_GetDataTableRowHelper::DataTablePinName);
|
|
SetPinToolTip(*DataTablePin, LOCTEXT("DataTablePinDescription", "The DataTable you want to retreive a row from"));
|
|
|
|
// Row Name pin
|
|
UEdGraphPin* RowNamePin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Name, UK2Node_GetDataTableRowHelper::RowNamePinName);
|
|
SetPinToolTip(*RowNamePin, LOCTEXT("RowNamePinDescription", "The name of the row to retrieve from the DataTable"));
|
|
|
|
// Result pin
|
|
UEdGraphPin* ResultPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, UEdGraphSchema_K2::PN_ReturnValue);
|
|
ResultPin->PinFriendlyName = LOCTEXT("GetDataTableRow Output Row", "Out Row");
|
|
SetPinToolTip(*ResultPin, LOCTEXT("ResultPinDescription", "The returned TableRow, if found"));
|
|
|
|
Super::AllocateDefaultPins();
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::SetPinToolTip(UEdGraphPin& MutatablePin, const FText& PinDescription) const
|
|
{
|
|
MutatablePin.PinToolTip = UEdGraphSchema_K2::TypeToText(MutatablePin.PinType).ToString();
|
|
|
|
UEdGraphSchema_K2 const* const K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema());
|
|
if (K2Schema != nullptr)
|
|
{
|
|
MutatablePin.PinToolTip += TEXT(" ");
|
|
MutatablePin.PinToolTip += K2Schema->GetPinDisplayName(&MutatablePin).ToString();
|
|
}
|
|
|
|
MutatablePin.PinToolTip += FString(TEXT("\n")) + PinDescription.ToString();
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::RefreshOutputPinType()
|
|
{
|
|
UScriptStruct* OutputType = GetDataTableRowStructType();
|
|
SetReturnTypeForStruct(OutputType);
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::RefreshRowNameOptions()
|
|
{
|
|
// When the DataTable pin gets a new value assigned, we need to update the Slate UI so that SGraphNodeCallParameterCollectionFunction will update the ParameterName drop down
|
|
UEdGraph* Graph = GetGraph();
|
|
Graph->NotifyGraphChanged();
|
|
}
|
|
|
|
|
|
void UK2Node_GetDataTableRow::SetReturnTypeForStruct(UScriptStruct* NewRowStruct)
|
|
{
|
|
UScriptStruct* OldRowStruct = GetReturnTypeForStruct();
|
|
if (NewRowStruct != OldRowStruct)
|
|
{
|
|
UEdGraphPin* ResultPin = GetResultPin();
|
|
|
|
if (ResultPin->SubPins.Num() > 0)
|
|
{
|
|
GetSchema()->RecombinePin(ResultPin);
|
|
}
|
|
|
|
// NOTE: purposefully not disconnecting the ResultPin (even though it changed type)... we want the user to see the old
|
|
// connections, and incompatible connections will produce an error (plus, some super-struct connections may still be valid)
|
|
ResultPin->PinType.PinSubCategoryObject = NewRowStruct;
|
|
ResultPin->PinType.PinCategory = (NewRowStruct == nullptr) ? UEdGraphSchema_K2::PC_Wildcard : UEdGraphSchema_K2::PC_Struct;
|
|
|
|
CachedNodeTitle.Clear();
|
|
}
|
|
}
|
|
|
|
UScriptStruct* UK2Node_GetDataTableRow::GetReturnTypeForStruct()
|
|
{
|
|
UScriptStruct* ReturnStructType = (UScriptStruct*)(GetResultPin()->PinType.PinSubCategoryObject.Get());
|
|
|
|
return ReturnStructType;
|
|
}
|
|
|
|
UScriptStruct* UK2Node_GetDataTableRow::GetDataTableRowStructType() const
|
|
{
|
|
UScriptStruct* RowStructType = nullptr;
|
|
|
|
UEdGraphPin* DataTablePin = GetDataTablePin();
|
|
if(DataTablePin && DataTablePin->DefaultObject != nullptr && DataTablePin->LinkedTo.Num() == 0)
|
|
{
|
|
if (DataTablePin->DefaultObject->IsA(UDataTable::StaticClass()))
|
|
{
|
|
UDataTable* DataTable = (UDataTable*)DataTablePin->DefaultObject;
|
|
if (DataTable)
|
|
{
|
|
RowStructType = DataTable->RowStruct;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RowStructType == nullptr)
|
|
{
|
|
UEdGraphPin* ResultPin = GetResultPin();
|
|
if (ResultPin && ResultPin->LinkedTo.Num() > 0)
|
|
{
|
|
RowStructType = Cast<UScriptStruct>(ResultPin->LinkedTo[0]->PinType.PinSubCategoryObject.Get());
|
|
for (int32 LinkIndex = 1; LinkIndex < ResultPin->LinkedTo.Num(); ++LinkIndex)
|
|
{
|
|
UEdGraphPin* Link = ResultPin->LinkedTo[LinkIndex];
|
|
UScriptStruct* LinkType = Cast<UScriptStruct>(Link->PinType.PinSubCategoryObject.Get());
|
|
|
|
if (RowStructType->IsChildOf(LinkType))
|
|
{
|
|
RowStructType = LinkType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return RowStructType;
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::OnDataTableRowListChanged(const UDataTable* DataTable)
|
|
{
|
|
UEdGraphPin* DataTablePin = GetDataTablePin();
|
|
if (DataTable && DataTablePin && DataTable == DataTablePin->DefaultObject)
|
|
{
|
|
UEdGraphPin* RowNamePin = GetRowNamePin();
|
|
const bool TryRefresh = RowNamePin && !RowNamePin->LinkedTo.Num();
|
|
const FName CurrentName = RowNamePin ? FName(*RowNamePin->GetDefaultAsString()) : NAME_None;
|
|
if (TryRefresh && RowNamePin && !DataTable->GetRowNames().Contains(CurrentName))
|
|
{
|
|
if (UBlueprint* BP = GetBlueprint())
|
|
{
|
|
FBlueprintEditorUtils::MarkBlueprintAsModified(BP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
|
|
{
|
|
Super::ReallocatePinsDuringReconstruction(OldPins);
|
|
|
|
if (UEdGraphPin* DataTablePin = GetDataTablePin(&OldPins))
|
|
{
|
|
if (UDataTable* DataTable = Cast<UDataTable>(DataTablePin->DefaultObject))
|
|
{
|
|
// make sure to properly load the data-table object so that we can
|
|
// farm the "RowStruct" property from it (below, in GetDataTableRowStructType)
|
|
PreloadObject(DataTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
|
{
|
|
// 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);
|
|
|
|
ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
|
|
}
|
|
}
|
|
|
|
FText UK2Node_GetDataTableRow::GetMenuCategory() const
|
|
{
|
|
return FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Utilities);
|
|
}
|
|
|
|
bool UK2Node_GetDataTableRow::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
|
{
|
|
if (MyPin == GetResultPin() && MyPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard)
|
|
{
|
|
bool bDisallowed = true;
|
|
if (OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Struct)
|
|
{
|
|
if (UScriptStruct* ConnectionType = Cast<UScriptStruct>(OtherPin->PinType.PinSubCategoryObject.Get()))
|
|
{
|
|
bDisallowed = !FDataTableEditorUtils::IsValidTableStruct(ConnectionType);
|
|
}
|
|
}
|
|
else if (OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard)
|
|
{
|
|
bDisallowed = false;
|
|
}
|
|
|
|
if (bDisallowed)
|
|
{
|
|
OutReason = TEXT("Must be a struct that can be used in a DataTable");
|
|
}
|
|
return bDisallowed;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::PinDefaultValueChanged(UEdGraphPin* ChangedPin)
|
|
{
|
|
if (ChangedPin && ChangedPin->PinName == UK2Node_GetDataTableRowHelper::DataTablePinName)
|
|
{
|
|
RefreshOutputPinType();
|
|
|
|
UEdGraphPin* RowNamePin = GetRowNamePin();
|
|
UDataTable* DataTable = Cast<UDataTable>(ChangedPin->DefaultObject);
|
|
if (RowNamePin)
|
|
{
|
|
if (DataTable && (RowNamePin->DefaultValue.IsEmpty() || !DataTable->RowMap.Contains(*RowNamePin->DefaultValue)))
|
|
{
|
|
if (auto Iterator = DataTable->RowMap.CreateConstIterator())
|
|
{
|
|
RowNamePin->DefaultValue = Iterator.Key().ToString();
|
|
}
|
|
}
|
|
|
|
RefreshRowNameOptions();
|
|
}
|
|
}
|
|
}
|
|
|
|
FText UK2Node_GetDataTableRow::GetTooltipText() const
|
|
{
|
|
return NodeTooltip;
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_GetDataTableRow::GetThenPin()const
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
UEdGraphPin* Pin = FindPinChecked(UEdGraphSchema_K2::PN_Then);
|
|
check(Pin->Direction == EGPD_Output);
|
|
return Pin;
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_GetDataTableRow::GetDataTablePin(const TArray<UEdGraphPin*>* InPinsToSearch /*= NULL*/) const
|
|
{
|
|
const TArray<UEdGraphPin*>* PinsToSearch = InPinsToSearch ? InPinsToSearch : &Pins;
|
|
|
|
UEdGraphPin* Pin = nullptr;
|
|
for (UEdGraphPin* TestPin : *PinsToSearch)
|
|
{
|
|
if (TestPin && TestPin->PinName == UK2Node_GetDataTableRowHelper::DataTablePinName)
|
|
{
|
|
Pin = TestPin;
|
|
break;
|
|
}
|
|
}
|
|
check(Pin == nullptr || Pin->Direction == EGPD_Input);
|
|
return Pin;
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_GetDataTableRow::GetRowNamePin() const
|
|
{
|
|
UEdGraphPin* Pin = FindPinChecked(UK2Node_GetDataTableRowHelper::RowNamePinName);
|
|
check(Pin->Direction == EGPD_Input);
|
|
return Pin;
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_GetDataTableRow::GetRowNotFoundPin() const
|
|
{
|
|
UEdGraphPin* Pin = FindPinChecked(UK2Node_GetDataTableRowHelper::RowNotFoundPinName);
|
|
check(Pin->Direction == EGPD_Output);
|
|
return Pin;
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_GetDataTableRow::GetResultPin() const
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
UEdGraphPin* Pin = FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue);
|
|
check(Pin->Direction == EGPD_Output);
|
|
return Pin;
|
|
}
|
|
|
|
FText UK2Node_GetDataTableRow::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
if (TitleType == ENodeTitleType::MenuTitle)
|
|
{
|
|
return LOCTEXT("ListViewTitle", "Get Data Table Row");
|
|
}
|
|
else if (UEdGraphPin* DataTablePin = GetDataTablePin())
|
|
{
|
|
if (DataTablePin->LinkedTo.Num() > 0)
|
|
{
|
|
return NSLOCTEXT("K2Node", "DataTable_Title_Unknown", "Get Data Table Row");
|
|
}
|
|
else if (DataTablePin->DefaultObject == nullptr)
|
|
{
|
|
return NSLOCTEXT("K2Node", "DataTable_Title_None", "Get Data Table Row NONE");
|
|
}
|
|
else if (CachedNodeTitle.IsOutOfDate(this))
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("DataTableName"), FText::FromString(DataTablePin->DefaultObject->GetName()));
|
|
|
|
FText LocFormat = NSLOCTEXT("K2Node", "DataTable", "Get Data Table Row {DataTableName}");
|
|
// FText::Format() is slow, so we cache this to save on performance
|
|
CachedNodeTitle.SetCachedText(FText::Format(LocFormat, Args), this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return NSLOCTEXT("K2Node", "DataTable_Title_None", "Get Data Table Row NONE");
|
|
}
|
|
return CachedNodeTitle;
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
|
{
|
|
Super::ExpandNode(CompilerContext, SourceGraph);
|
|
|
|
UEdGraphPin* OriginalDataTableInPin = GetDataTablePin();
|
|
UDataTable* Table = (OriginalDataTableInPin != NULL) ? Cast<UDataTable>(OriginalDataTableInPin->DefaultObject) : NULL;
|
|
if((nullptr == OriginalDataTableInPin) || (0 == OriginalDataTableInPin->LinkedTo.Num() && nullptr == Table))
|
|
{
|
|
CompilerContext.MessageLog.Error(*LOCTEXT("GetDataTableRowNoDataTable_Error", "GetDataTableRow must have a DataTable specified.").ToString(), this);
|
|
// we break exec links so this is the only error we get
|
|
BreakAllNodeLinks();
|
|
return;
|
|
}
|
|
|
|
// FUNCTION NODE
|
|
const FName FunctionName = GET_FUNCTION_NAME_CHECKED(UDataTableFunctionLibrary, GetDataTableRowFromName);
|
|
UK2Node_CallFunction* GetDataTableRowFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
|
|
GetDataTableRowFunction->FunctionReference.SetExternalMember(FunctionName, UDataTableFunctionLibrary::StaticClass());
|
|
GetDataTableRowFunction->AllocateDefaultPins();
|
|
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *(GetDataTableRowFunction->GetExecPin()));
|
|
|
|
// Connect the input of our GetDataTableRow to the Input of our Function pin
|
|
UEdGraphPin* DataTableInPin = GetDataTableRowFunction->FindPinChecked(TEXT("Table"));
|
|
if(OriginalDataTableInPin->LinkedTo.Num() > 0)
|
|
{
|
|
// Copy the connection
|
|
CompilerContext.MovePinLinksToIntermediate(*OriginalDataTableInPin, *DataTableInPin);
|
|
}
|
|
else
|
|
{
|
|
// Copy literal
|
|
DataTableInPin->DefaultObject = OriginalDataTableInPin->DefaultObject;
|
|
}
|
|
UEdGraphPin* RowNameInPin = GetDataTableRowFunction->FindPinChecked(TEXT("RowName"));
|
|
CompilerContext.MovePinLinksToIntermediate(*GetRowNamePin(), *RowNameInPin);
|
|
|
|
// Get some pins to work with
|
|
UEdGraphPin* OriginalOutRowPin = FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue);
|
|
UEdGraphPin* FunctionOutRowPin = GetDataTableRowFunction->FindPinChecked(TEXT("OutRow"));
|
|
UEdGraphPin* FunctionReturnPin = GetDataTableRowFunction->FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue);
|
|
UEdGraphPin* FunctionThenPin = GetDataTableRowFunction->GetThenPin();
|
|
|
|
// Set the type of the OutRow pin on this expanded mode to match original
|
|
FunctionOutRowPin->PinType = OriginalOutRowPin->PinType;
|
|
FunctionOutRowPin->PinType.PinSubCategoryObject = OriginalOutRowPin->PinType.PinSubCategoryObject;
|
|
|
|
//BRANCH NODE
|
|
UK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
|
|
BranchNode->AllocateDefaultPins();
|
|
// Hook up inputs to branch
|
|
FunctionThenPin->MakeLinkTo(BranchNode->GetExecPin());
|
|
FunctionReturnPin->MakeLinkTo(BranchNode->GetConditionPin());
|
|
|
|
// Hook up outputs
|
|
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *(BranchNode->GetThenPin()));
|
|
CompilerContext.MovePinLinksToIntermediate(*GetRowNotFoundPin(), *(BranchNode->GetElsePin()));
|
|
CompilerContext.MovePinLinksToIntermediate(*OriginalOutRowPin, *FunctionOutRowPin);
|
|
|
|
BreakAllNodeLinks();
|
|
}
|
|
|
|
FSlateIcon UK2Node_GetDataTableRow::GetIconAndTint(FLinearColor& OutColor) const
|
|
{
|
|
OutColor = GetNodeTitleColor();
|
|
static FSlateIcon Icon("EditorStyle", "Kismet.AllClasses.FunctionIcon");
|
|
return Icon;
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::PostReconstructNode()
|
|
{
|
|
Super::PostReconstructNode();
|
|
|
|
RefreshOutputPinType();
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::EarlyValidation(class FCompilerResultsLog& MessageLog) const
|
|
{
|
|
Super::EarlyValidation(MessageLog);
|
|
|
|
const UEdGraphPin* DataTablePin = GetDataTablePin();
|
|
const UEdGraphPin* RowNamePin = GetRowNamePin();
|
|
if (!DataTablePin || !RowNamePin)
|
|
{
|
|
MessageLog.Error(*LOCTEXT("MissingPins", "Missing pins in @@").ToString(), this);
|
|
return;
|
|
}
|
|
|
|
if (DataTablePin->LinkedTo.Num() == 0)
|
|
{
|
|
const UDataTable* DataTable = Cast<UDataTable>(DataTablePin->DefaultObject);
|
|
if (!DataTable)
|
|
{
|
|
MessageLog.Error(*LOCTEXT("NoDataTable", "No DataTable in @@").ToString(), this);
|
|
return;
|
|
}
|
|
|
|
if (!RowNamePin->LinkedTo.Num())
|
|
{
|
|
const FName CurrentName = FName(*RowNamePin->GetDefaultAsString());
|
|
if (!DataTable->GetRowNames().Contains(CurrentName))
|
|
{
|
|
const FString Msg = FText::Format(
|
|
LOCTEXT("WrongRowNameFmt", "'{0}' row name is not stored in '{1}'. @@"),
|
|
FText::FromString(CurrentName.ToString()),
|
|
FText::FromString(GetFullNameSafe(DataTable))
|
|
).ToString();
|
|
MessageLog.Error(*Msg, this);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::PreloadRequiredAssets()
|
|
{
|
|
if (UEdGraphPin* DataTablePin = GetDataTablePin())
|
|
{
|
|
if (UDataTable* DataTable = Cast<UDataTable>(DataTablePin->DefaultObject))
|
|
{
|
|
// make sure to properly load the data-table object so that we can
|
|
// farm the "RowStruct" property from it (below, in GetDataTableRowStructType)
|
|
PreloadObject(DataTable);
|
|
}
|
|
}
|
|
return Super::PreloadRequiredAssets();
|
|
}
|
|
|
|
void UK2Node_GetDataTableRow::NotifyPinConnectionListChanged(UEdGraphPin* Pin)
|
|
{
|
|
Super::NotifyPinConnectionListChanged(Pin);
|
|
|
|
if (Pin == GetResultPin())
|
|
{
|
|
UEdGraphPin* TablePin = GetDataTablePin();
|
|
// this connection would only change the output type if the table pin is undefined
|
|
const bool bIsTypeAuthority = (TablePin->LinkedTo.Num() > 0 || TablePin->DefaultObject == nullptr);
|
|
if (bIsTypeAuthority)
|
|
{
|
|
RefreshOutputPinType();
|
|
}
|
|
}
|
|
else if (Pin == GetDataTablePin())
|
|
{
|
|
const bool bConnectionAdded = Pin->LinkedTo.Num() > 0;
|
|
if (bConnectionAdded)
|
|
{
|
|
// if a connection was made, then we may need to rid ourselves of the row dropdown
|
|
RefreshRowNameOptions();
|
|
// if the output connection was previously, incompatible, it now becomes the authority on this node's output type
|
|
RefreshOutputPinType();
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|