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::FinishDestroy() { Super::FinishDestroy(); if(!IsTemplate()) { EmptyTable(); // Free memory when UObject goes away } }
CSortResultHashTable::~CSortResultHashTable() { EmptyTable(); CSortResult *s,*sr; s=SRstack; while(s) { sr=s; s=s->next; delete sr; } SRstack=0; }
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::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(); }
void UCurveTable::FinishDestroy() { Super::FinishDestroy(); EmptyTable(); // Free memory when UObject goes away }
TArray<FString> UCurveTable::CreateTableFromJSONString(const FString& InString, ERichCurveInterpMode InterpMode) { // Array used to store problems about table creation TArray<FString> OutProblems; if (InString.IsEmpty()) { OutProblems.Add(TEXT("Input data is empty.")); return OutProblems; } TArray< TSharedPtr<FJsonValue> > ParsedTableRows; { const TSharedRef< TJsonReader<TCHAR> > JsonReader = TJsonReaderFactory<TCHAR>::Create(InString); if (!FJsonSerializer::Deserialize(JsonReader, ParsedTableRows) || ParsedTableRows.Num() == 0) { OutProblems.Add(FString::Printf(TEXT("Failed to parse the JSON data. Error: %s"), *JsonReader->GetErrorMessage())); return OutProblems; } } // Empty existing data EmptyTable(); // Iterate over rows for (int32 RowIdx = 0; RowIdx < ParsedTableRows.Num(); ++RowIdx) { const TSharedPtr<FJsonValue>& ParsedTableRowValue = ParsedTableRows[RowIdx]; TSharedPtr<FJsonObject> ParsedTableRowObject = ParsedTableRowValue->AsObject(); if (!ParsedTableRowObject.IsValid()) { OutProblems.Add(FString::Printf(TEXT("Row '%d' is not a valid JSON object."), RowIdx)); continue; } // Get row name static const FString RowNameJsonKey = TEXT("Name"); const FName RowName = MakeValidName(ParsedTableRowObject->GetStringField(RowNameJsonKey)); // Check its not 'none' if (RowName == NAME_None) { OutProblems.Add(FString::Printf(TEXT("Row '%d' missing a name."), RowIdx)); continue; } // Check its not a duplicate if (RowMap.Find(RowName) != NULL) { OutProblems.Add(FString::Printf(TEXT("Duplicate row name '%s'."), *RowName.ToString())); continue; } // Add a key for each entry in this row FRichCurve* NewCurve = new FRichCurve(); for (const auto& ParsedTableRowEntry : ParsedTableRowObject->Values) { // Skip the name entry if (ParsedTableRowEntry.Key == RowNameJsonKey) { continue; } // Make sure we have a valid float key float EntryKey = 0.0f; if (!LexicalConversion::TryParseString(EntryKey, *ParsedTableRowEntry.Key)) { OutProblems.Add(FString::Printf(TEXT("Key '%s' on row '%s' is not a float and cannot be parsed."), *ParsedTableRowEntry.Key, *RowName.ToString())); continue; } // Make sure we have a valid float value double EntryValue = 0.0; if (!ParsedTableRowEntry.Value->TryGetNumber(EntryValue)) { OutProblems.Add(FString::Printf(TEXT("Entry '%s' on row '%s' is not a float and cannot be parsed."), *ParsedTableRowEntry.Key, *RowName.ToString())); continue; } FKeyHandle KeyHandle = NewCurve->AddKey(EntryKey, static_cast<float>(EntryValue)); NewCurve->SetKeyInterpMode(KeyHandle, InterpMode); } RowMap.Add(RowName, NewCurve); } Modify(true); return OutProblems; }
TArray<FString> UCurveTable::CreateTableFromCSVString(const FString& InString, ERichCurveInterpMode InterpMode) { // Array used to store problems about table creation TArray<FString> OutProblems; const FCsvParser Parser(InString); const FCsvParser::FRows& Rows = Parser.GetRows(); // Must have at least 2 rows (x values + y values for at least one row) if(Rows.Num() <= 1) { OutProblems.Add(FString(TEXT("Too few rows."))); return OutProblems; } // Empty existing data EmptyTable(); TArray<float> XValues; GetCurveValues(Rows[0], &XValues); // Iterate over rows for(int32 RowIdx = 1; RowIdx < Rows.Num(); RowIdx++) { const TArray<const TCHAR*>& Row = Rows[RowIdx]; // Need at least 1 cells (row name) if(Row.Num() < 1) { OutProblems.Add(FString::Printf(TEXT("Row '%d' has too few cells."), RowIdx)); continue; } // Get row name FName RowName = MakeValidName(Row[0]); // Check its not 'none' if(RowName == NAME_None) { OutProblems.Add(FString::Printf(TEXT("Row '%d' missing a name."), RowIdx)); continue; } // Check its not a duplicate if(RowMap.Find(RowName) != NULL) { OutProblems.Add(FString::Printf(TEXT("Duplicate row name '%s'."), *RowName.ToString())); continue; } TArray<float> YValues; GetCurveValues(Row, &YValues); if(XValues.Num() != YValues.Num()) { OutProblems.Add(FString::Printf(TEXT("Row '%s' does not have the right number of columns."), *RowName.ToString())); continue; } FRichCurve* NewCurve = new FRichCurve(); // Now iterate over cells (skipping first cell, that was row name) for(int32 ColumnIdx = 0; ColumnIdx < XValues.Num(); ColumnIdx++) { FKeyHandle KeyHandle = NewCurve->AddKey(XValues[ColumnIdx], YValues[ColumnIdx]); NewCurve->SetKeyInterpMode(KeyHandle, InterpMode); } RowMap.Add(RowName, NewCurve); } Modify(true); return OutProblems; }