Ok, I got rid of earlier errors (which was caused by .h and .cpp files mismatch). Now, I get following errors:
MainFrameActions: Packaging (Windows (64-bit)): UnrealBuildTool: C:\Program Files\Epic Games\4.9\Engine\Source\Runtime\Engine\Classes\Engine/DataTable.h(205) : error C2146: syntax error : missing ';' before identifier 'FDataTableRowHandle'
MainFrameActions: Packaging (Windows (64-bit)): UnrealBuildTool: C:\Program Files\Epic Games\4.9\Engine\Source\Runtime\Engine\Classes\Engine/DataTable.h(205) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
MainFrameActions: Packaging (Windows (64-bit)): UnrealBuildTool: C:\Program Files\Epic Games\4.9\Engine\Source\Runtime\Engine\Classes\Engine/DataTable.h(248) : error C2143: syntax error : missing ';' before 'const'
MainFrameActions: Packaging (Windows (64-bit)): UnrealBuildTool: C:\Program Files\Epic Games\4.9\Engine\Source\Runtime\Engine\Classes\Engine/DataTable.h(248) : error C4430: missing type specifier - int assumed. Note: C++ does not support defaul
Which corresponds to following line in DataTable.h file:
GENERATED_USTRUCT_BODY()
DataTable.h
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "DataTableUtils.h" // Needed here for LogDataTable
#include "DataTable.generated.h"
// forward declare JSON writer
template <class CharType>
struct TPrettyJsonPrintPolicy;
template <class CharType, class PrintPolicy>
class TJsonWriter;
/**
* Base class for all table row structs to inherit from.
*/
USTRUCT()
struct FTableRowBase
{
GENERATED_USTRUCT_BODY()
FTableRowBase() { }
};
/**
* Imported spreadsheet table.
*/
UCLASS()
class UDataTable
: public UObject
{
GENERATED_UCLASS_BODY()
/** Structure to use for each row of the table, must inherit from FTableRowBase */
UPROPERTY()
UScriptStruct* RowStruct;
/** Map of name of row to row data structure. */
TMap<FName, uint8*> RowMap;
// Begin UObject interface.
ENGINE_API virtual void FinishDestroy() override;
ENGINE_API virtual void Serialize(FArchive& Ar) override;
ENGINE_API static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
ENGINE_API virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
ENGINE_API virtual void PostInitProperties() override;
ENGINE_API virtual void PostLoad() override;
UPROPERTY(VisibleAnywhere, Instanced, Category=ImportSettings)
class UAssetImportData* AssetImportData;
/** The filename imported to create this object. Relative to this object's package, BaseDir() or absolute */
UPROPERTY()
FString ImportPath_DEPRECATED;
// End UObject interface
// Begin UDataTable interface
/** Function to find the row of a table given its name. */
template <class T>
T* FindRow(FName RowName, const FString& ContextString, bool bWarnIfRowMissing = true) const
{
if(RowStruct == nullptr)
{
UE_LOG(LogDataTable, Error, TEXT("UDataTable::FindRow : DataTable '%s' has no RowStruct specified (%s)."), *GetPathName(), *ContextString);
return nullptr;
}
if(!RowStruct->IsChildOf(T::StaticStruct()))
{
UE_CLOG(bWarnIfRowMissing, LogDataTable, Error, TEXT("UDataTable::FindRow : Incorrect type specified for DataTable '%s' (%s)."), *GetPathName(), *ContextString);
return nullptr;
}
if(RowName == NAME_None)
{
UE_CLOG(bWarnIfRowMissing, LogDataTable, Warning, TEXT("UDataTable::FindRow : NAME_None is invalid row name for DataTable '%s' (%s)."), *GetPathName(), *ContextString);
return nullptr;
}
uint8* const* RowDataPtr = RowMap.Find(RowName);
if (RowDataPtr == nullptr)
{
if (bWarnIfRowMissing)
{
UE_LOG(LogDataTable, Warning, TEXT("UDataTable::FindRow : Row '%s' not found in DataTable '%s' (%s)."), *RowName.ToString(), *GetPathName(), *ContextString);
}
return nullptr;
}
uint8* RowData = *RowDataPtr;
check(RowData);
return (T*)RowData;
}
/** Returns the column property where PropertyName matches the name of the column property. Returns nullptr if no match is found or the match is not a supported table property */
ENGINE_API UProperty* FindTableProperty(const FName& PropertyName) const;
uint8* FindRowUnchecked(FName RowName, bool MustExist=false) const
{
if(RowStruct == nullptr)
{
//UE_CLOG(MustExist, LogDataTable, Error, TEXT("UDataTable::FindRow : DataTable '%s' has no RowStruct specified (%s)."), *GetPathName(), *ContextString);
return nullptr;
}
if(RowName == NAME_None)
{
//UE_CLOG(MustExist, LogDataTable, Warning, TEXT("UDataTable::FindRow : NAME_None is invalid row name for DataTable '%s' (%s)."), *GetPathName(), *ContextString);
return nullptr;
}
uint8* const* RowDataPtr = RowMap.Find(RowName);
if(RowDataPtr == nullptr)
{
return nullptr;
}
uint8* RowData = *RowDataPtr;
check(RowData);
return RowData;
}
/** Empty the table info (will not clear RowStruct) */
ENGINE_API void EmptyTable();
ENGINE_API TArray<FName> GetRowNames() const;
private:
//when RowStruct is being modified, row data is stored serialized with tags
TArray<uint8> RowsSerializedWithTags;
TSet<UObject*> TemporarilyReferencedObjects;
public:
ENGINE_API void CleanBeforeStructChange();
ENGINE_API void RestoreAfterStructChange();
/** Output entire contents of table as a string */
ENGINE_API FString GetTableAsString() const;
/** Output entire contents of table as CSV */
ENGINE_API FString GetTableAsCSV() const;
/** Output entire contents of table as JSON */
ENGINE_API FString GetTableAsJSON() const;
/** Output entire contents of table as JSON */
ENGINE_API bool WriteTableAsJSON(const TSharedRef< TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR> > >& JsonWriter) const;
/** Output the fields from a particular row (use RowMap to get RowData) to an existing JsonWriter */
ENGINE_API bool WriteRowAsJSON(const TSharedRef< TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR> > >& JsonWriter, const void* RowData) const;
/**
* Create table from CSV style comma-separated string.
* RowStruct must be defined before calling this function.
* @return Set of problems encountered while processing input
*/
ENGINE_API TArray<FString> CreateTableFromCSVString(const FString& InString);
/**
* Create table from JSON style string.
* RowStruct must be defined before calling this function.
* @return Set of problems encountered while processing input
*/
ENGINE_API TArray<FString> CreateTableFromJSONString(const FString& InString);
/** Get an array of all the column titles, using the friendly display name from the property */
ENGINE_API TArray<FString> GetColumnTitles() const;
/** Get an array of all the column titles, using the unique name from the property */
ENGINE_API TArray<FString> GetUniqueColumnTitles() const;
TArray<UProperty*> GetTablePropertyArray(const TArray<const TCHAR*>& Cells, UStruct* RowStruct, TArray<FString>& OutProblems);
/** Get array for each row in the table. The first row is the titles*/
ENGINE_API TArray< TArray<FString> > GetTableData() const;
// End UDataTable interface
private:
void SaveStructData(FArchive& Ar);
void LoadStructData(FArchive& Ar);
};
/** Handle to a particular row in a table*/
USTRUCT()
struct ENGINE_API FDataTableRowHandle
{
GENERATED_USTRUCT_BODY()
FDataTableRowHandle()
: DataTable(nullptr)
, RowName(NAME_None)
{
}
/** Pointer to table we want a row from */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=DataTableRowHandle)
const class UDataTable* DataTable;
/** Name of row in the table that we want */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=DataTableRowHandle)
FName RowName;
static const FString Unknown;
/** Get the row straight from the row handle */
template <class T>
T* GetRow(const FString& ContextString = Unknown) const
{
if(DataTable == nullptr)
{
if (RowName != NAME_None)
{
UE_LOG(LogDataTable, Warning, TEXT("FDataTableRowHandle::FindRow : No DataTable for row %s (%s)."), *RowName.ToString(), *ContextString);
}
return nullptr;
}
return DataTable->FindRow<T>(RowName, ContextString);
}
};
/** Handle to a particular row in a table*/
USTRUCT()
struct ENGINE_API FDataTableCategoryHandle
{
GENERATED_USTRUCT_BODY()
/** Pointer to table we want a row from */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=DataTableCategoryHandle)
const class UDataTable* DataTable;
/** Name of column in the table that we want */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=DataTableCategoryHandle)
FName ColumnName;
/** Contents of rows in the table that we want */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=DataTableCategoryHandle)
FName RowContents;
static const FString Unknown;
/** Searches DataTable for all rows that contain entries with RowContents in the column named ColumnName and returns them. */
template <class T>
void GetRows(TArray<T*>& OutRows, const FString& ContextString = Unknown) const
{
OutRows.Empty();
if (DataTable == nullptr)
{
if (RowContents != NAME_None)
{
UE_LOG(LogDataTable, Warning, TEXT("FDataTableCategoryHandle::FindRow : No DataTable for row %s (%s)."), *RowContents.ToString(), *ContextString);
}
return;
}
if (ColumnName == NAME_None)
{
if (RowContents != NAME_None)
{
UE_LOG(LogDataTable, Warning, TEXT("FDataTableCategoryHandle::FindRow : No Column selected for row %s (%s)."), *RowContents.ToString(), *ContextString);
}
return;
}
// Find the property that matches the desired column (ColumnName)
UProperty* Property = DataTable->FindTableProperty(ColumnName);
if (Property == nullptr)
{
return;
}
// check each row to see if the value in the Property element is the one we're looking for (RowContents). If it is, add the row to OutRows
FString RowContentsAsString = RowContents.ToString();
for (auto RowIt = DataTable->RowMap.CreateConstIterator(); RowIt; ++RowIt)
{
uint8* RowData = RowIt.Value();
FString PropertyValue(TEXT(""));
Property->ExportText_InContainer(0, PropertyValue, RowData, RowData, nullptr, PPF_None);
if (RowContentsAsString == PropertyValue)
{
OutRows.Add((T*)RowData);
}
}
return;
}
};
/** Macro to call GetRow with a correct error info. Assumed to be called from within a UObject */
#define GETROW_REPORTERROR(Handle, Template) Handle.GetRow<Template>(FString::Printf(TEXT("%s.%s"), *GetPathName(), TEXT(#Handle)))
#define GETROWOBJECT_REPORTERROR(Object, Handle, Template) Handle.GetRow<Template>(FString::Printf(TEXT("%s.%s"), *Object->GetPathName(), TEXT(#Handle)))
DataTable.cpp
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "EnginePrivate.h"
#include "Engine/DataTable.h"
#include "DataTableCSV.h"
#include "DataTableJSON.h"
#include "EditorFramework/AssetImportData.h"
ENGINE_API const FString FDataTableRowHandle::Unknown(TEXT("UNKNOWN"));
ENGINE_API const FString FDataTableCategoryHandle::Unknown(TEXT("UNKNOWN"));
namespace
{
void GatherDataTableForLocalization(const UObject* const Object, TArray<FGatherableTextData>& GatherableTextDataArray)
{
const UDataTable* const DataTable = CastChecked<UDataTable>(Object);
const FString PathToObject = DataTable->GetPathName();
for (const auto& Pair : DataTable->RowMap)
{
const FString PathToRow = PathToObject + TEXT(".") + Pair.Key.ToString();
for (TFieldIterator<UProperty> PropIt(DataTable->RowStruct, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated, EFieldIteratorFlags::IncludeInterfaces); PropIt; ++PropIt)
{
FPropertyLocalizationDataGatherer PropertyLocalizationDataGatherer(GatherableTextDataArray);
PropertyLocalizationDataGatherer.GatherLocalizationDataFromChildTextProperies(PathToRow, *PropIt, PropIt->ContainerPtrToValuePtr<void>(Pair.Value));
}
}
}
}
UDataTable::UDataTable(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
struct FAutomaticRegistrationOfLocalizationGatherer
{
FAutomaticRegistrationOfLocalizationGatherer()
{
UPackage::GetTypeSpecificLocalizationDataGatheringCallbacks().Add(UDataTable::StaticClass(), &GatherDataTableForLocalization);
}
} AutomaticRegistrationOfLocalizationGatherer;
}
void UDataTable::LoadStructData(FArchive& Ar)
{
UScriptStruct* LoadUsingStruct = RowStruct;
if (LoadUsingStruct == NULL)
{
UE_LOG(LogDataTable, Error, TEXT("Missing RowStruct while loading DataTable '%s'!"), *GetPathName());
LoadUsingStruct = FTableRowBase::StaticStruct();
}
int32 NumRows;
Ar << NumRows;
for (int32 RowIdx = 0; RowIdx < NumRows; RowIdx++)
{
// Load row name
FName RowName;
Ar << RowName;
// Load row data
uint8* RowData = (uint8*)FMemory::Malloc(LoadUsingStruct->PropertiesSize);
LoadUsingStruct->InitializeStruct(RowData);
// And be sure to call DestroyScriptStruct later
LoadUsingStruct->SerializeTaggedProperties(Ar, RowData, LoadUsingStruct, NULL);
// Add to map
RowMap.Add(RowName, RowData);
}
}
void UDataTable::SaveStructData(FArchive& Ar)
{
// Don't even try to save rows if no RowStruct
if (RowStruct != NULL)
{
int32 NumRows = RowMap.Num();
Ar << NumRows;
// Now iterate over rows in the map
for (auto RowIt = RowMap.CreateIterator(); RowIt; ++RowIt)
{
// Save out name
FName RowName = RowIt.Key();
Ar << RowName;
// Save out data
uint8* RowData = RowIt.Value();
RowStruct->SerializeTaggedProperties(Ar, RowData, RowStruct, NULL);
}
}
}
void UDataTable::Serialize( FArchive& Ar )
{
Super::Serialize(Ar); // When loading, this should load our RowStruct!
if (RowStruct && RowStruct->HasAnyFlags(RF_NeedLoad))
{
auto RowStructLinker = RowStruct->GetLinker();
if (RowStructLinker)
{
RowStructLinker->Preload(RowStruct);
}
}
if(Ar.IsLoading())
{
EmptyTable();
LoadStructData(Ar);
}
else if(Ar.IsSaving())
{
SaveStructData(Ar);
}
}
void UDataTable::AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector)
{
UDataTable* This = CastChecked<UDataTable>(InThis);
// Need to emit references for referenced rows
if(This->RowStruct != NULL)
{
// Now iterate over rows in the map
for ( auto RowIt = This->RowMap.CreateIterator(); RowIt; ++RowIt )
{
uint8* RowData = RowIt.Value();
if (RowData)
{
// Serialize all of the properties to make sure they get in the collector
FSimpleObjectReferenceCollectorArchive ObjectReferenceCollector( This, Collector );
This->RowStruct->SerializeBin(ObjectReferenceCollector, RowData);
}
}
}
Collector.AddReferencedObjects(This->TemporarilyReferencedObjects);
Super::AddReferencedObjects( This, Collector );
}
void UDataTable::FinishDestroy()
{
Super::FinishDestroy();
if(!IsTemplate())
{
EmptyTable(); // Free memory when UObject goes away
}
}
void UDataTable::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
{
if (AssetImportData)
{
OutTags.Add( FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden) );
}
Super::GetAssetRegistryTags(OutTags);
}
void UDataTable::PostInitProperties()
{
if (!HasAnyFlags(RF_ClassDefaultObject))
{
AssetImportData = NewObject<UAssetImportData>(this, TEXT("AssetImportData"));
}
Super::PostInitProperties();
}
void UDataTable::PostLoad()
{
Super::PostLoad();
if (!ImportPath_DEPRECATED.IsEmpty() && AssetImportData)
{
FAssetImportInfo Info;
Info.Insert(FAssetImportInfo::FSourceFile(ImportPath_DEPRECATED));
AssetImportData->SourceData = MoveTemp(Info);
}
}
void UDataTable::EmptyTable()
{
UScriptStruct* LoadUsingStruct = RowStruct;
if (LoadUsingStruct == NULL)
{
UE_LOG(LogDataTable, Error, TEXT("Missing RowStruct while emptying DataTable '%s'!"), *GetPathName());
LoadUsingStruct = FTableRowBase::StaticStruct();
}
// Iterate over all rows in table and free mem
for (auto RowIt = RowMap.CreateIterator(); RowIt; ++RowIt)
{
uint8* RowData = RowIt.Value();
LoadUsingStruct->DestroyStruct(RowData);
FMemory::Free(RowData);
}
// Finally empty the map
RowMap.Empty();
}
/** Returns the column property where PropertyName matches the name of the column property. Returns NULL if no match is found or the match is not a supported table property */
UProperty* UDataTable::FindTableProperty(const FName& PropertyName) const
{
UProperty* Property = NULL;
for (TFieldIterator<UProperty> It(RowStruct); It; ++It)
{
Property = *It;
check(Property != NULL);
if (PropertyName == Property->GetFName())
{
break;
}
}
if (!DataTableUtils::IsSupportedTableProperty(Property))
{
Property = NULL;
}
return Property;
}
void UDataTable::CleanBeforeStructChange()
{
RowsSerializedWithTags.Reset();
TemporarilyReferencedObjects.Empty();
{
class FRawStructWriter : public FObjectWriter
{
TSet<UObject*>& TemporarilyReferencedObjects;
public:
FRawStructWriter(TArray<uint8>& InBytes, TSet<UObject*>& InTemporarilyReferencedObjects)
: FObjectWriter(InBytes), TemporarilyReferencedObjects(InTemporarilyReferencedObjects) {}
virtual FArchive& operator<<(class UObject*& Res) override
{
FObjectWriter::operator<<(Res);
TemporarilyReferencedObjects.Add(Res);
return *this;
}
};
FRawStructWriter MemoryWriter(RowsSerializedWithTags, TemporarilyReferencedObjects);
SaveStructData(MemoryWriter);
}
EmptyTable();
Modify();
}
void UDataTable::RestoreAfterStructChange()
{
EmptyTable();
{
class FRawStructReader : public FObjectReader
{
public:
FRawStructReader(TArray<uint8>& InBytes) : FObjectReader(InBytes) {}
virtual FArchive& operator<<(class UObject*& Res) override
{
UObject* Object = NULL;
FObjectReader::operator<<(Object);
FWeakObjectPtr WeakObjectPtr = Object;
Res = WeakObjectPtr.Get();
return *this;
}
};
FRawStructReader MemoryReader(RowsSerializedWithTags);
LoadStructData(MemoryReader);
}
TemporarilyReferencedObjects.Empty();
RowsSerializedWithTags.Empty();
}
FString UDataTable::GetTableAsString() const
{
FString Result;
if(RowStruct != NULL)
{
Result += FString::Printf(TEXT("Using RowStruct: %s
"), *RowStruct->GetPathName());
// First build array of properties
TArray<UProperty*> StructProps;
for (TFieldIterator<UProperty> It(RowStruct); It; ++It)
{
UProperty* Prop = *It;
check(Prop != NULL);
StructProps.Add(Prop);
}
// First row, column titles, taken from properties
Result += TEXT("---");
for(int32 PropIdx=0; PropIdx<StructProps.Num(); PropIdx++)
{
Result += TEXT(",");
Result += StructProps[PropIdx]->GetName();
}
Result += TEXT("
");
// Now iterate over rows
for ( auto RowIt = RowMap.CreateConstIterator(); RowIt; ++RowIt )
{
FName RowName = RowIt.Key();
Result += RowName.ToString();
uint8* RowData = RowIt.Value();
for(int32 PropIdx=0; PropIdx<StructProps.Num(); PropIdx++)
{
Result += TEXT(",");
Result += DataTableUtils::GetPropertyValueAsString(StructProps[PropIdx], RowData);
}
Result += TEXT("
");
}
}
else
{
Result += FString(TEXT("Missing RowStruct!
"));
}
return Result;
}
FString UDataTable::GetTableAsCSV() const
{
FString Result;
if (!FDataTableExporterCSV(*this, Result).WriteTable())
{
Result = TEXT("Missing RowStruct!
");
}
return Result;
}
FString UDataTable::GetTableAsJSON() const
{
FString Result;
if (!FDataTableExporterJSON(*this, Result).WriteTable())
{
Result = TEXT("Missing RowStruct!
");
}
return Result;
}
bool UDataTable::WriteRowAsJSON(const TSharedRef< TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR> > >& JsonWriter, const void* RowData) const
{
return FDataTableExporterJSON(*this, JsonWriter).WriteRow(RowData);
}
bool UDataTable::WriteTableAsJSON(const TSharedRef< TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR> > >& JsonWriter) const
{
return FDataTableExporterJSON(*this, JsonWriter).WriteTable();
}
/** Get array of UProperties that corresponds to columns in the table */
TArray<UProperty*> UDataTable::GetTablePropertyArray(const TArray<const TCHAR*>& Cells, UStruct* InRowStruct, TArray<FString>& OutProblems)
{
TArray<UProperty*> ColumnProps;
// Get list of all expected properties from the struct
TArray<FName> ExpectedPropNames = DataTableUtils::GetStructPropertyNames(InRowStruct);
// Need at least 2 columns, first column is skipped, will contain row names
if(Cells.Num() > 1)
{
ColumnProps.AddZeroed( Cells.Num() );
// first element always NULL - as first column is row names
for (int32 ColIdx = 1; ColIdx < Cells.Num(); ++ColIdx)
{
const TCHAR* ColumnValue = Cells[ColIdx];
FName PropName = DataTableUtils::MakeValidName(ColumnValue);
if(PropName == NAME_None)
{
OutProblems.Add(FString::Printf(TEXT("Missing name for column %d."), ColIdx));
}
else
{
UProperty* ColumnProp = FindField<UProperty>(InRowStruct, PropName);
for (TFieldIterator<UProperty> It(InRowStruct); It && !ColumnProp; ++It)
{
const auto DisplayName = DataTableUtils::GetPropertyDisplayName(*It, FString());
ColumnProp = (!DisplayName.IsEmpty() && DisplayName == ColumnValue) ? *It : NULL;
}
// Didn't find a property with this name, problem..
if(ColumnProp == NULL)
{
OutProblems.Add(FString::Printf(TEXT("Cannot find Property for column '%s' in struct '%s'."), *PropName.ToString(), *InRowStruct->GetName()));
}
// Found one!
else
{
// Check we don't have this property already
if(ColumnProps.Contains(ColumnProp))
{
OutProblems.Add(FString::Printf(TEXT("Duplicate column '%s'."), *ColumnProp->GetName()));
}
// Check we support this property type
else if( !DataTableUtils::IsSupportedTableProperty(ColumnProp) )
{
OutProblems.Add(FString::Printf(TEXT("Unsupported Property type for struct member '%s'."), *ColumnProp->GetName()));
}
// Looks good, add to array
else
{
ColumnProps[ColIdx] = ColumnProp;
}
// Track that we found this one
ExpectedPropNames.Remove(ColumnProp->GetFName());
}
}
}
}
// Generate warning for any properties in struct we are not filling in
for(int32 PropIdx=0; PropIdx < ExpectedPropNames.Num(); PropIdx++)
{
const UProperty* const ColumnProp = FindField<UProperty>(InRowStruct, ExpectedPropNames[PropIdx]);
const FString DisplayName = DataTableUtils::GetPropertyDisplayName(ColumnProp, ExpectedPropNames[PropIdx].ToString());
OutProblems.Add(FString::Printf(TEXT("Expected column '%s' not found in input."), *DisplayName));
}
return ColumnProps;
}
TArray<FString> UDataTable::CreateTableFromCSVString(const FString& InString)
{
// Array used to store problems about table creation
TArray<FString> OutProblems;
FDataTableImporterCSV(*this, InString, OutProblems).ReadTable();
return OutProblems;
}
TArray<FString> UDataTable::CreateTableFromJSONString(const FString& InString)
{
// Array used to store problems about table creation
TArray<FString> OutProblems;
FDataTableImporterJSON(*this, InString, OutProblems).ReadTable();
return OutProblems;
}
TArray<FString> UDataTable::GetColumnTitles() const
{
TArray<FString> Result;
Result.Add(TEXT("Name"));
for (TFieldIterator<UProperty> It(RowStruct); It; ++It)
{
UProperty* Prop = *It;
check(Prop != NULL);
const FString DisplayName = DataTableUtils::GetPropertyDisplayName(Prop, Prop->GetName());
Result.Add(DisplayName);
}
return Result;
}
TArray<FString> UDataTable::GetUniqueColumnTitles() const
{
TArray<FString> Result;
Result.Add(TEXT("Name"));
for (TFieldIterator<UProperty> It(RowStruct); It; ++It)
{
UProperty* Prop = *It;
check(Prop != NULL);
const FString DisplayName = Prop->GetName();
Result.Add(DisplayName);
}
return Result;
}
TArray< TArray<FString> > UDataTable::GetTableData() const
{
TArray< TArray<FString> > Result;
Result.Add(GetColumnTitles());
// First build array of properties
TArray<UProperty*> StructProps;
for (TFieldIterator<UProperty> It(RowStruct); It; ++It)
{
UProperty* Prop = *It;
check(Prop != NULL);
StructProps.Add(Prop);
}
// Now iterate over rows
for ( auto RowIt = RowMap.CreateConstIterator(); RowIt; ++RowIt )
{
TArray<FString> RowResult;
FName RowName = RowIt.Key();
RowResult.Add(RowName.ToString());
uint8* RowData = RowIt.Value();
for(int32 PropIdx=0; PropIdx<StructProps.Num(); PropIdx++)
{
RowResult.Add(DataTableUtils::GetPropertyValueAsString(StructProps[PropIdx], RowData));
}
Result.Add(RowResult);
}
return Result;
}
TArray<FName> UDataTable::GetRowNames() const
{
TArray<FName> Keys;
RowMap.GetKeys(Keys);
return Keys;
}