Add single asset export functionality and enhance README with usage details
This commit is contained in:
@ -196,6 +196,202 @@ void FAssetExporterToJSON::ExportAssetsToJSON()
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Message));
|
||||
}
|
||||
|
||||
void FAssetExporterToJSON::ExportSingleAssetToJSON(const FAssetData& AssetData)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Exporting single asset: %s"), *AssetData.GetObjectPathString());
|
||||
|
||||
UObject* Asset = AssetData.GetAsset();
|
||||
if (!Asset)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Error, TEXT("Failed to load asset: %s"), *AssetData.GetObjectPathString());
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Failed to load asset")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine asset type and export accordingly
|
||||
TArray<TSharedPtr<FJsonValue>> JsonArray;
|
||||
FString AssetTypeName;
|
||||
|
||||
if (UDataTable* DataTable = Cast<UDataTable>(Asset))
|
||||
{
|
||||
AssetTypeName = TEXT("DataTable");
|
||||
TSharedPtr<FJsonObject> DataTableJson = MakeShareable(new FJsonObject);
|
||||
DataTableJson->SetStringField(TEXT("AssetName"), DataTable->GetName());
|
||||
DataTableJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
DataTableJson->SetStringField(TEXT("RowStructure"), DataTable->GetRowStruct() ? DataTable->GetRowStruct()->GetName() : TEXT("None"));
|
||||
|
||||
// Export rows
|
||||
TArray<TSharedPtr<FJsonValue>> RowsArray;
|
||||
const UScriptStruct* RowStruct = DataTable->GetRowStruct();
|
||||
const TMap<FName, uint8*>& RowMap = DataTable->GetRowMap();
|
||||
|
||||
for (const TPair<FName, uint8*>& Row : RowMap)
|
||||
{
|
||||
TSharedPtr<FJsonObject> RowJson = MakeShareable(new FJsonObject);
|
||||
RowJson->SetStringField(TEXT("RowName"), Row.Key.ToString());
|
||||
|
||||
if (RowStruct)
|
||||
{
|
||||
FString RowDataString;
|
||||
if (FJsonObjectConverter::UStructToJsonObjectString(RowStruct, Row.Value, RowDataString, 0, 0))
|
||||
{
|
||||
TSharedPtr<FJsonObject> RowDataJson;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(RowDataString);
|
||||
if (FJsonSerializer::Deserialize(Reader, RowDataJson) && RowDataJson.IsValid())
|
||||
{
|
||||
RowJson->SetObjectField(TEXT("Data"), RowDataJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowsArray.Add(MakeShareable(new FJsonValueObject(RowJson)));
|
||||
}
|
||||
|
||||
DataTableJson->SetArrayField(TEXT("Rows"), RowsArray);
|
||||
JsonArray.Add(MakeShareable(new FJsonValueObject(DataTableJson)));
|
||||
}
|
||||
else if (UBlueprint* Blueprint = Cast<UBlueprint>(Asset))
|
||||
{
|
||||
AssetTypeName = TEXT("Blueprint");
|
||||
TSharedPtr<FJsonObject> BlueprintJson = ExtractBlueprintDetails(Blueprint);
|
||||
if (BlueprintJson.IsValid())
|
||||
{
|
||||
BlueprintJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
JsonArray.Add(MakeShareable(new FJsonValueObject(BlueprintJson)));
|
||||
}
|
||||
}
|
||||
else if (UAnimMontage* AnimMontage = Cast<UAnimMontage>(Asset))
|
||||
{
|
||||
AssetTypeName = TEXT("AnimMontage");
|
||||
TSharedPtr<FJsonObject> MontageJson = MakeShareable(new FJsonObject);
|
||||
MontageJson->SetStringField(TEXT("AssetName"), AnimMontage->GetName());
|
||||
MontageJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
MontageJson->SetNumberField(TEXT("SequenceLength"), static_cast<double>(AnimMontage->GetPlayLength()));
|
||||
MontageJson->SetNumberField(TEXT("RateScale"), static_cast<double>(AnimMontage->RateScale));
|
||||
|
||||
// Export sections
|
||||
TArray<TSharedPtr<FJsonValue>> SectionsArray;
|
||||
for (const FCompositeSection& Section : AnimMontage->CompositeSections)
|
||||
{
|
||||
TSharedPtr<FJsonObject> SectionJson = MakeShareable(new FJsonObject);
|
||||
SectionJson->SetStringField(TEXT("SectionName"), Section.SectionName.ToString());
|
||||
SectionJson->SetNumberField(TEXT("StartTime"), static_cast<double>(Section.GetTime()));
|
||||
SectionJson->SetStringField(TEXT("NextSectionName"), Section.NextSectionName.ToString());
|
||||
SectionsArray.Add(MakeShareable(new FJsonValueObject(SectionJson)));
|
||||
}
|
||||
MontageJson->SetArrayField(TEXT("Sections"), SectionsArray);
|
||||
|
||||
// Note: Simplified export for single asset - full export includes SlotAnimTracks and Notifies
|
||||
JsonArray.Add(MakeShareable(new FJsonValueObject(MontageJson)));
|
||||
}
|
||||
else if (UCurveTable* CurveTable = Cast<UCurveTable>(Asset))
|
||||
{
|
||||
AssetTypeName = TEXT("CurveTable");
|
||||
TSharedPtr<FJsonObject> CurveTableJson = MakeShareable(new FJsonObject);
|
||||
CurveTableJson->SetStringField(TEXT("AssetName"), CurveTable->GetName());
|
||||
CurveTableJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
|
||||
FString ModeStr = TEXT("Unknown");
|
||||
switch (CurveTable->GetCurveTableMode())
|
||||
{
|
||||
case ECurveTableMode::Empty:
|
||||
ModeStr = TEXT("Empty");
|
||||
break;
|
||||
case ECurveTableMode::SimpleCurves:
|
||||
ModeStr = TEXT("SimpleCurves");
|
||||
break;
|
||||
case ECurveTableMode::RichCurves:
|
||||
ModeStr = TEXT("RichCurves");
|
||||
break;
|
||||
}
|
||||
CurveTableJson->SetStringField(TEXT("CurveTableMode"), ModeStr);
|
||||
|
||||
// Export curves (simplified for single asset)
|
||||
TArray<TSharedPtr<FJsonValue>> CurvesArray;
|
||||
if (CurveTable->GetCurveTableMode() == ECurveTableMode::RichCurves)
|
||||
{
|
||||
const TMap<FName, FRichCurve*>& RichCurveMap = CurveTable->GetRichCurveRowMap();
|
||||
for (const TPair<FName, FRichCurve*>& Row : RichCurveMap)
|
||||
{
|
||||
TSharedPtr<FJsonObject> CurveJson = MakeShareable(new FJsonObject);
|
||||
CurveJson->SetStringField(TEXT("CurveName"), Row.Key.ToString());
|
||||
if (FRichCurve* Curve = Row.Value)
|
||||
{
|
||||
TArray<TSharedPtr<FJsonValue>> KeysArray;
|
||||
const TArray<FRichCurveKey>& Keys = Curve->GetConstRefOfKeys();
|
||||
for (const FRichCurveKey& Key : Keys)
|
||||
{
|
||||
TSharedPtr<FJsonObject> KeyJson = MakeShareable(new FJsonObject);
|
||||
KeyJson->SetNumberField(TEXT("Time"), static_cast<double>(Key.Time));
|
||||
KeyJson->SetNumberField(TEXT("Value"), static_cast<double>(Key.Value));
|
||||
KeysArray.Add(MakeShareable(new FJsonValueObject(KeyJson)));
|
||||
}
|
||||
CurveJson->SetArrayField(TEXT("Keys"), KeysArray);
|
||||
}
|
||||
CurvesArray.Add(MakeShareable(new FJsonValueObject(CurveJson)));
|
||||
}
|
||||
}
|
||||
CurveTableJson->SetArrayField(TEXT("Curves"), CurvesArray);
|
||||
JsonArray.Add(MakeShareable(new FJsonValueObject(CurveTableJson)));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Warning, TEXT("Unsupported asset type: %s"), *Asset->GetClass()->GetName());
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(FString::Printf(
|
||||
TEXT("Unsupported asset type: %s\n\nSupported types: DataTable, Blueprint, AnimMontage, CurveTable"),
|
||||
*Asset->GetClass()->GetName()
|
||||
)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (JsonArray.Num() == 0)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Warning, TEXT("No data to export"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create output directory
|
||||
const UAssetExportSettings* Settings = GetDefault<UAssetExportSettings>();
|
||||
FString OutputPath = FPaths::ProjectContentDir();
|
||||
if (Settings && !Settings->OutputDirectory.Path.IsEmpty())
|
||||
{
|
||||
OutputPath = OutputPath / Settings->OutputDirectory.Path;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputPath = OutputPath / TEXT("Exports");
|
||||
}
|
||||
|
||||
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
|
||||
if (!PlatformFile.DirectoryExists(*OutputPath))
|
||||
{
|
||||
PlatformFile.CreateDirectory(*OutputPath);
|
||||
}
|
||||
|
||||
// Create timestamped filename
|
||||
FString Timestamp = FDateTime::Now().ToString(TEXT("%Y%m%d_%H%M%S"));
|
||||
FString SafeAssetName = Asset->GetName().Replace(TEXT(" "), TEXT("_"));
|
||||
FString FileName = FString::Printf(TEXT("%s_%s_%s.json"), *AssetTypeName, *SafeAssetName, *Timestamp);
|
||||
|
||||
// Save JSON
|
||||
if (SaveJsonToFile(JsonArray, FileName, OutputPath))
|
||||
{
|
||||
FString FilePath = OutputPath / FileName;
|
||||
FString Message = FString::Printf(
|
||||
TEXT("Asset exported successfully!\n\n")
|
||||
TEXT("Asset: %s\n")
|
||||
TEXT("Type: %s\n\n")
|
||||
TEXT("Output file:\n%s"),
|
||||
*Asset->GetName(),
|
||||
*AssetTypeName,
|
||||
*FilePath
|
||||
);
|
||||
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Single asset export completed: %s"), *FilePath);
|
||||
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Message));
|
||||
}
|
||||
}
|
||||
|
||||
int32 FAssetExporterToJSON::ExportDataTables(const FString& FolderPath, TArray<TSharedPtr<FJsonValue>>& OutJsonArray)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Exporting DataTables from: %s"), *FolderPath);
|
||||
@ -210,13 +406,22 @@ int32 FAssetExporterToJSON::ExportDataTables(const FString& FolderPath, TArray<T
|
||||
|
||||
AssetRegistryModule.Get().GetAssets(Filter, AssetList);
|
||||
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Found %d DataTables to export"), AssetList.Num());
|
||||
|
||||
int32 Count = 0;
|
||||
int32 TotalCount = AssetList.Num();
|
||||
for (const FAssetData& AssetData : AssetList)
|
||||
{
|
||||
UDataTable* DataTable = Cast<UDataTable>(AssetData.GetAsset());
|
||||
if (!DataTable)
|
||||
continue;
|
||||
|
||||
// Progress logging every 10 assets or for first/last
|
||||
if (Count == 0 || Count % 10 == 0 || Count == TotalCount - 1)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT(" Processing DataTable %d/%d: %s"), Count + 1, TotalCount, *DataTable->GetName());
|
||||
}
|
||||
|
||||
TSharedPtr<FJsonObject> DataTableJson = MakeShareable(new FJsonObject);
|
||||
DataTableJson->SetStringField(TEXT("AssetName"), DataTable->GetName());
|
||||
DataTableJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
@ -275,13 +480,22 @@ int32 FAssetExporterToJSON::ExportBlueprints(const FString& FolderPath, TArray<T
|
||||
|
||||
AssetRegistryModule.Get().GetAssets(Filter, AssetList);
|
||||
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Found %d Blueprints to export"), AssetList.Num());
|
||||
|
||||
int32 Count = 0;
|
||||
int32 TotalCount = AssetList.Num();
|
||||
for (const FAssetData& AssetData : AssetList)
|
||||
{
|
||||
UBlueprint* Blueprint = Cast<UBlueprint>(AssetData.GetAsset());
|
||||
if (!Blueprint || !Blueprint->GeneratedClass)
|
||||
continue;
|
||||
|
||||
// Progress logging every 10 assets or for first/last
|
||||
if (Count == 0 || Count % 10 == 0 || Count == TotalCount - 1)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT(" Processing Blueprint %d/%d: %s"), Count + 1, TotalCount, *Blueprint->GetName());
|
||||
}
|
||||
|
||||
TSharedPtr<FJsonObject> BlueprintJson = ExtractBlueprintDetails(Blueprint);
|
||||
if (BlueprintJson.IsValid())
|
||||
{
|
||||
@ -340,26 +554,125 @@ TArray<TSharedPtr<FJsonValue>> FAssetExporterToJSON::ExtractBlueprintVariables(U
|
||||
if (!DefaultObject)
|
||||
return VariablesArray;
|
||||
|
||||
// Iterate through all properties
|
||||
for (TFieldIterator<FProperty> PropIt(Blueprint->GeneratedClass, EFieldIteratorFlags::ExcludeSuper); PropIt; ++PropIt)
|
||||
// CRITICAL: Export Blueprint custom variables (NewVariables)
|
||||
// This is the most important part for Blueprint analysis
|
||||
for (const FBPVariableDescription& Variable : Blueprint->NewVariables)
|
||||
{
|
||||
TSharedPtr<FJsonObject> VarJson = MakeShareable(new FJsonObject);
|
||||
VarJson->SetStringField(TEXT("Name"), Variable.VarName.ToString());
|
||||
VarJson->SetStringField(TEXT("VarGuid"), Variable.VarGuid.ToString());
|
||||
|
||||
// Export variable type information
|
||||
VarJson->SetStringField(TEXT("Category"), Variable.VarType.PinCategory.ToString());
|
||||
if (Variable.VarType.PinSubCategoryObject.IsValid())
|
||||
{
|
||||
VarJson->SetStringField(TEXT("SubCategoryObject"), Variable.VarType.PinSubCategoryObject->GetName());
|
||||
}
|
||||
if (!Variable.VarType.PinSubCategory.IsNone())
|
||||
{
|
||||
VarJson->SetStringField(TEXT("SubCategory"), Variable.VarType.PinSubCategory.ToString());
|
||||
}
|
||||
|
||||
// Container type (Array, Set, Map)
|
||||
if (Variable.VarType.ContainerType != EPinContainerType::None)
|
||||
{
|
||||
FString ContainerTypeStr;
|
||||
switch (Variable.VarType.ContainerType)
|
||||
{
|
||||
case EPinContainerType::Array:
|
||||
ContainerTypeStr = TEXT("Array");
|
||||
break;
|
||||
case EPinContainerType::Set:
|
||||
ContainerTypeStr = TEXT("Set");
|
||||
break;
|
||||
case EPinContainerType::Map:
|
||||
ContainerTypeStr = TEXT("Map");
|
||||
break;
|
||||
}
|
||||
VarJson->SetStringField(TEXT("ContainerType"), ContainerTypeStr);
|
||||
}
|
||||
|
||||
// Export default value
|
||||
VarJson->SetStringField(TEXT("DefaultValue"), Variable.DefaultValue);
|
||||
|
||||
// Export property flags
|
||||
VarJson->SetBoolField(TEXT("IsEditable"), (Variable.PropertyFlags & CPF_Edit) != 0);
|
||||
VarJson->SetBoolField(TEXT("IsBlueprintVisible"), (Variable.PropertyFlags & CPF_BlueprintVisible) != 0);
|
||||
VarJson->SetBoolField(TEXT("IsBlueprintReadOnly"), (Variable.PropertyFlags & CPF_BlueprintReadOnly) != 0);
|
||||
VarJson->SetBoolField(TEXT("IsExposedOnSpawn"), (Variable.PropertyFlags & CPF_ExposeOnSpawn) != 0);
|
||||
VarJson->SetBoolField(TEXT("IsInstanceEditable"), (Variable.PropertyFlags & CPF_DisableEditOnInstance) == 0);
|
||||
|
||||
// Export category
|
||||
if (!Variable.Category.IsEmpty())
|
||||
{
|
||||
VarJson->SetStringField(TEXT("CategoryName"), Variable.Category.ToString());
|
||||
}
|
||||
|
||||
// Export replication
|
||||
if (Variable.RepNotifyFunc != NAME_None)
|
||||
{
|
||||
VarJson->SetStringField(TEXT("RepNotifyFunc"), Variable.RepNotifyFunc.ToString());
|
||||
}
|
||||
|
||||
// Export metadata
|
||||
if (Variable.MetaDataArray.Num() > 0)
|
||||
{
|
||||
TSharedPtr<FJsonObject> MetaDataJson = MakeShareable(new FJsonObject);
|
||||
|
||||
for (const FBPVariableMetaDataEntry& MetaDataEntry : Variable.MetaDataArray)
|
||||
{
|
||||
MetaDataJson->SetStringField(MetaDataEntry.DataKey.ToString(), MetaDataEntry.DataValue);
|
||||
}
|
||||
|
||||
if (MetaDataJson->Values.Num() > 0)
|
||||
{
|
||||
VarJson->SetObjectField(TEXT("MetaData"), MetaDataJson);
|
||||
}
|
||||
}
|
||||
|
||||
VarJson->SetStringField(TEXT("Source"), TEXT("Blueprint"));
|
||||
VariablesArray.Add(MakeShareable(new FJsonValueObject(VarJson)));
|
||||
}
|
||||
|
||||
// Extract parent class properties with Category = "WorldStalker"
|
||||
// This captures important C++ properties like ActivationOrderGroup
|
||||
for (TFieldIterator<FProperty> PropIt(Blueprint->GeneratedClass); PropIt; ++PropIt)
|
||||
{
|
||||
FProperty* Property = *PropIt;
|
||||
if (!Property)
|
||||
continue;
|
||||
|
||||
// Check if this property has Category metadata set to "WorldStalker"
|
||||
const FString* CategoryMeta = Property->FindMetaData(TEXT("Category"));
|
||||
if (!CategoryMeta || !CategoryMeta->Equals(TEXT("WorldStalker")))
|
||||
continue;
|
||||
|
||||
// This is a WorldStalker category property - export it!
|
||||
TSharedPtr<FJsonObject> VarJson = MakeShareable(new FJsonObject);
|
||||
VarJson->SetStringField(TEXT("Name"), Property->GetName());
|
||||
VarJson->SetStringField(TEXT("Type"), Property->GetCPPType());
|
||||
|
||||
// Get default value
|
||||
// Get default value from CDO
|
||||
FString DefaultValue;
|
||||
const void* ValuePtr = Property->ContainerPtrToValuePtr<void>(DefaultObject);
|
||||
Property->ExportTextItem_Direct(DefaultValue, ValuePtr, nullptr, nullptr, PPF_None);
|
||||
VarJson->SetStringField(TEXT("DefaultValue"), DefaultValue);
|
||||
|
||||
// Additional metadata
|
||||
// Property flags
|
||||
VarJson->SetBoolField(TEXT("IsEditable"), Property->HasAnyPropertyFlags(CPF_Edit));
|
||||
VarJson->SetBoolField(TEXT("IsBlueprintVisible"), Property->HasAnyPropertyFlags(CPF_BlueprintVisible));
|
||||
VarJson->SetBoolField(TEXT("IsBlueprintReadOnly"), Property->HasAnyPropertyFlags(CPF_BlueprintReadOnly));
|
||||
VarJson->SetBoolField(TEXT("IsEditDefaultsOnly"), Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance));
|
||||
|
||||
// Category and source
|
||||
VarJson->SetStringField(TEXT("CategoryName"), TEXT("WorldStalker"));
|
||||
VarJson->SetStringField(TEXT("Source"), TEXT("C++ParentClass"));
|
||||
|
||||
// Get owning class name for clarity
|
||||
if (Property->GetOwnerClass())
|
||||
{
|
||||
VarJson->SetStringField(TEXT("OwnerClass"), Property->GetOwnerClass()->GetName());
|
||||
}
|
||||
|
||||
VariablesArray.Add(MakeShareable(new FJsonValueObject(VarJson)));
|
||||
}
|
||||
@ -598,12 +911,17 @@ int32 FAssetExporterToJSON::ExportAnimMontages(const FString& FolderPath, TArray
|
||||
|
||||
AssetRegistryModule.Get().GetAssets(Filter, AssetList);
|
||||
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Found %d AnimMontages to export"), AssetList.Num());
|
||||
|
||||
// Track exported assets to avoid duplicates
|
||||
TSet<FString> ExportedPaths;
|
||||
|
||||
int32 Count = 0;
|
||||
int32 TotalCount = AssetList.Num();
|
||||
int32 ProcessedCount = 0;
|
||||
for (const FAssetData& AssetData : AssetList)
|
||||
{
|
||||
ProcessedCount++;
|
||||
FString AssetPath = AssetData.GetObjectPathString();
|
||||
|
||||
// Skip if already exported
|
||||
@ -617,6 +935,12 @@ int32 FAssetExporterToJSON::ExportAnimMontages(const FString& FolderPath, TArray
|
||||
if (!AnimMontage)
|
||||
continue;
|
||||
|
||||
// Progress logging every 10 assets or for first/last
|
||||
if (Count == 0 || Count % 10 == 0 || ProcessedCount == TotalCount)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT(" Processing AnimMontage %d/%d: %s"), ProcessedCount, TotalCount, *AnimMontage->GetName());
|
||||
}
|
||||
|
||||
ExportedPaths.Add(AssetPath);
|
||||
|
||||
TSharedPtr<FJsonObject> MontageJson = MakeShareable(new FJsonObject);
|
||||
@ -785,13 +1109,22 @@ int32 FAssetExporterToJSON::ExportCurveTables(const FString& FolderPath, TArray<
|
||||
|
||||
AssetRegistryModule.Get().GetAssets(Filter, AssetList);
|
||||
|
||||
UE_LOG(LogAssetExporter, Log, TEXT("Found %d CurveTables to export"), AssetList.Num());
|
||||
|
||||
int32 Count = 0;
|
||||
int32 TotalCount = AssetList.Num();
|
||||
for (const FAssetData& AssetData : AssetList)
|
||||
{
|
||||
UCurveTable* CurveTable = Cast<UCurveTable>(AssetData.GetAsset());
|
||||
if (!CurveTable)
|
||||
continue;
|
||||
|
||||
// Progress logging every 10 assets or for first/last
|
||||
if (Count == 0 || Count % 10 == 0 || Count == TotalCount - 1)
|
||||
{
|
||||
UE_LOG(LogAssetExporter, Log, TEXT(" Processing CurveTable %d/%d: %s"), Count + 1, TotalCount, *CurveTable->GetName());
|
||||
}
|
||||
|
||||
TSharedPtr<FJsonObject> CurveTableJson = MakeShareable(new FJsonObject);
|
||||
CurveTableJson->SetStringField(TEXT("AssetName"), CurveTable->GetName());
|
||||
CurveTableJson->SetStringField(TEXT("AssetPath"), AssetData.GetObjectPathString());
|
||||
|
||||
Reference in New Issue
Block a user