From 7ed3b78018cecca24ec3241a46ef131d9d606392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20By=C5=A1ka?= Date: Sat, 3 Apr 2021 13:49:08 +0200 Subject: [PATCH 1/8] Adds support for cross references in TArrays. --- .../Private/Prefab/PrefabTools.cpp | 99 ++++++++++++++----- .../Public/Asset/PrefabricatorAsset.h | 3 +- 2 files changed, 74 insertions(+), 28 deletions(-) diff --git a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp index 8bd792df..ec79a69a 100644 --- a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp +++ b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp @@ -385,6 +385,24 @@ namespace { } } + // JB: Added SerializeObjectProperty method to reuse the code. + bool SerializeObjectProperty(const FObjectPropertyBase* ObjProperty, const void* PropertyValueAddress, int32 Index, UPrefabricatorProperty* PrefabProperty, const FPrefabActorLookup& CrossReferences) + { + UObject* PropertyObjectValue = ObjProperty->GetObjectPropertyValue(PropertyValueAddress); + if (PropertyObjectValue == nullptr || PropertyObjectValue->HasAnyFlags(RF_DefaultSubObject | RF_ArchetypeObject)) { + return false; + } + + FString ObjectPath = PropertyObjectValue->GetPathName(); + FGuid CrossRefPrefabItem; + if (CrossReferences.GetPrefabItemId(ObjectPath, CrossRefPrefabItem)) { + PrefabProperty->bIsCrossReferencedActor = true; + PrefabProperty->CrossReferencePrefabActorIdMap.Add(Index, CrossRefPrefabItem); + return true; + } + return false; + } + void SerializeFields(UObject* ObjToSerialize, UObject* ObjTemplate, APrefabActor* PrefabActor, const FPrefabActorLookup& CrossReferences, TArray& OutProperties) { if (!ObjToSerialize || !PrefabActor) { return; @@ -445,23 +463,22 @@ namespace { // Check for cross actor references bool bFoundCrossReference = false; - - if (const FObjectProperty* ObjProperty = CastField(Property)) { - UObject* PropertyObjectValue = ObjProperty->GetObjectPropertyValue_InContainer(ObjToSerialize); - if (PropertyObjectValue) { - if (PropertyObjectValue->HasAnyFlags(RF_DefaultSubObject | RF_ArchetypeObject)) { - continue; - } - - FString ObjectPath = PropertyObjectValue->GetPathName(); - FGuid CrossRefPrefabItem; - if (CrossReferences.GetPrefabItemId(ObjectPath, CrossRefPrefabItem)) { - PrefabProperty->bIsCrossReferencedActor = true; - PrefabProperty->CrossReferencePrefabActorId = CrossRefPrefabItem; - bFoundCrossReference = true; + // JB: Added support for TArrays (TODO: Adds support for sets and maps). + if (const FArrayProperty* ArrayProperty = CastField(Property)) + { + if (const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, ObjToSerialize); + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + bFoundCrossReference |= SerializeObjectProperty(ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); } } } + // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references. + else if (const FObjectPropertyBase* ObjProperty = CastField(Property)) { + bFoundCrossReference = SerializeObjectProperty(ObjProperty, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), 0, PrefabProperty, CrossReferences); + } // Save as usual if no cross reference was found if (!bFoundCrossReference) { @@ -925,29 +942,57 @@ void FPrefabTools::LoadStateFromPrefabAsset(APrefabActor* PrefabActor, const FPr } } -void FPrefabTools::FixupCrossReferences(const TArray& PrefabProperties, UObject* ObjToWrite, TMap& PrefabItemToActorMap) +// JB: Added FixupCrossReferences_Helper method to be able to easily reuse the code. +namespace { - for (UPrefabricatorProperty* PrefabProperty : PrefabProperties) { - if (!PrefabProperty || !PrefabProperty->bIsCrossReferencedActor) continue; - - FProperty* Property = ObjToWrite->GetClass()->FindPropertyByName(*PrefabProperty->PropertyName); - - const FObjectProperty* ObjectProperty = CastField(Property); - if (!ObjectProperty) continue; - - AActor** SearchResult = PrefabItemToActorMap.Find(PrefabProperty->CrossReferencePrefabActorId); - if (!SearchResult) continue; + void FixupCrossReferences_Helper(UPrefabricatorProperty* PrefabProperty, const FObjectPropertyBase* ObjectProperty, void* PropertyValueAddress, int32 Index, TMap& PrefabItemToActorMap) + { + FGuid* Guid = PrefabProperty->CrossReferencePrefabActorIdMap.Find(Index); + if (!Guid) return; + AActor** SearchResult = PrefabItemToActorMap.Find(*Guid); + if (!SearchResult) return; AActor* CrossReference = *SearchResult; - ObjectProperty->SetObjectPropertyValue_InContainer(ObjToWrite, CrossReference); + ObjectProperty->SetObjectPropertyValue(PropertyValueAddress, CrossReference); //////// FString ActorName = CrossReference ? CrossReference->GetName() : "[NONE]"; - UE_LOG(LogPrefabTools, Log, TEXT("Cross Reference: %s -> %s"), *PrefabProperty->CrossReferencePrefabActorId.ToString(), *ActorName); + UE_LOG(LogPrefabTools, Log, TEXT("Cross Reference: %s -> %s"), *Guid->ToString(), *ActorName); //////// } } +void FPrefabTools::FixupCrossReferences(const TArray& PrefabProperties, UObject* ObjToWrite, TMap& PrefabItemToActorMap) +{ + for (UPrefabricatorProperty* PrefabProperty : PrefabProperties) { + if (!PrefabProperty || !PrefabProperty->bIsCrossReferencedActor) continue; + + FProperty* Property = ObjToWrite->GetClass()->FindPropertyByName(*PrefabProperty->PropertyName); + + // JB: Added support for TArrays (TODO: Adds support for sets and maps). + if (const FArrayProperty* ArrayProperty = CastField(Property)) + { + if (const FObjectPropertyBase* ObjectProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, ObjToWrite); + // The array may have different length by default. + if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) + { + Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); + } + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); + } + } + } + // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references + else if (const FObjectPropertyBase* ObjectProperty = CastField(Property)) { + FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), 0, PrefabItemToActorMap); + } + } +} + void FPrefabVersionControl::UpgradeToLatestVersion(UPrefabricatorAsset* PrefabAsset) { if (PrefabAsset->Version == (int32)EPrefabricatorAssetVersion::InitialVersion) { diff --git a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h index bd44c88f..de2acebd 100644 --- a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h +++ b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h @@ -38,8 +38,9 @@ class PREFABRICATORRUNTIME_API UPrefabricatorProperty : public UObject { UPROPERTY() bool bIsCrossReferencedActor = false; + // JB: The cross-references per index in array. UPROPERTY() - FGuid CrossReferencePrefabActorId; + TMap CrossReferencePrefabActorIdMap; void SaveReferencedAssetValues(); void LoadReferencedAssetValues(); From f4a045da24f51701597a85075bae009c72b58833 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 11:11:41 -0500 Subject: [PATCH 2/8] add suport for structs containing TSoftObjectPtr cross references --- .../ConstructionSystemEditor.Build.cs | 2 +- .../ConstructionSystemRuntime.Build.cs | 2 +- .../PrefabricatorEditor.Build.cs | 7 +- .../PrefabricatorEditorPostInit.Build.cs | 7 +- .../PrefabricatorRuntime.Build.cs | 7 +- .../Private/Prefab/PrefabTools.cpp | 204 +++++++++++++++--- .../Public/Asset/PrefabricatorAsset.h | 1 - 7 files changed, 189 insertions(+), 41 deletions(-) diff --git a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs index 3b3dfed4..020cde95 100644 --- a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs +++ b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs @@ -8,7 +8,7 @@ public ConstructionSystemEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs index d4f8276c..21b75c5e 100644 --- a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs +++ b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs @@ -8,7 +8,7 @@ public ConstructionSystemRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs index 5226ae28..0eeea6f9 100644 --- a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs +++ b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs @@ -8,7 +8,12 @@ public PrefabricatorEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + + + OptimizeCode = CodeOptimization.Never; + + + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs index c9e5ae05..7b3b1d9c 100644 --- a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs +++ b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs @@ -8,7 +8,12 @@ public PrefabricatorEditorPostInit(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + + + OptimizeCode = CodeOptimization.Never; + + + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs index d686a32f..516ae279 100644 --- a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs +++ b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs @@ -8,7 +8,12 @@ public PrefabricatorRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + + + OptimizeCode = CodeOptimization.Never; + + + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp index ce5a8e47..005a2979 100644 --- a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp +++ b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp @@ -385,7 +385,7 @@ namespace { } } - // JB: Added SerializeObjectProperty method to reuse the code. + // SerializeObjectProperty method to reuse the code. bool SerializeObjectProperty(const FObjectPropertyBase* ObjProperty, const void* PropertyValueAddress, int32 Index, UPrefabricatorProperty* PrefabProperty, const FPrefabActorLookup& CrossReferences) { UObject* PropertyObjectValue = ObjProperty->GetObjectPropertyValue(PropertyValueAddress); @@ -403,6 +403,70 @@ namespace { return false; } + bool SerializeStructField( + void* Ptr + , const FPrefabActorLookup& CrossReferences + , UPrefabricatorProperty* PrefabProperty + , const FStructProperty* StructProperty); + + bool SerializeArrayField( + void* Ptr + , const FPrefabActorLookup& CrossReferences + , UPrefabricatorProperty* PrefabProperty + , const FArrayProperty* ArrayProperty) + { + bool bFoundCrossReference = false; + // TODO: Array of arrays + if (const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + bFoundCrossReference |= SerializeObjectProperty(ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); + } + } + else if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + bFoundCrossReference |= SerializeStructField(Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, StructProperty); + } + } + + return bFoundCrossReference; + } + + bool SerializeStructField( + void* Ptr + , const FPrefabActorLookup& CrossReferences + , UPrefabricatorProperty* PrefabProperty + , const FStructProperty* StructProperty + ) + { + bool bFoundCrossReference = false; + for (TFieldIterator It(StructProperty->Struct); It; ++It) { + FProperty* InnerProperty = *It; + + if (const FStructProperty* StructProperty = CastField(InnerProperty)) { + void* PropPtr = StructProperty->ContainerPtrToValuePtr(Ptr, 0); + bFoundCrossReference |= SerializeStructField(PropPtr, CrossReferences, PrefabProperty, StructProperty); + } + // JB: Added support for TArrays (TODO: Adds support for sets and maps). + else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) + { + bFoundCrossReference |= SerializeArrayField(Ptr, CrossReferences, PrefabProperty, ArrayProperty); + } + // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references. + else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) { + void* PropPtr = ObjProperty->ContainerPtrToValuePtr(Ptr, 0); + bFoundCrossReference |= SerializeObjectProperty(ObjProperty, PropPtr, 0, PrefabProperty, CrossReferences); + } + } + + return bFoundCrossReference; + } + void SerializeFields(UObject* ObjToSerialize, UObject* ObjTemplate, APrefabActor* PrefabActor, const FPrefabActorLookup& CrossReferences, TArray& OutProperties) { if (!ObjToSerialize || !PrefabActor) { return; @@ -463,28 +527,26 @@ namespace { // Check for cross actor references bool bFoundCrossReference = false; - // JB: Added support for TArrays (TODO: Adds support for sets and maps). - if (const FArrayProperty* ArrayProperty = CastField(Property)) + // Support for USTRUCT + if (const FStructProperty* StructProperty = CastField(Property)) { + void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToSerialize, 0); + bFoundCrossReference |= SerializeStructField(StructPtr, CrossReferences, PrefabProperty, StructProperty); + } + // Support for TArrays (TODO: Adds support for sets and maps). + else if (const FArrayProperty* ArrayProperty = CastField(Property)) { - if (const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner)) - { - FScriptArrayHelper_InContainer Helper(ArrayProperty, ObjToSerialize); - for (int32 Index = 0; Index < Helper.Num(); Index++) - { - bFoundCrossReference |= SerializeObjectProperty(ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); - } - } + bFoundCrossReference |= SerializeArrayField(ObjToSerialize, CrossReferences, PrefabProperty, ArrayProperty); } - // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references. + // FObjectPropertyBase instead of FObjectProperty to also support soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(Property)) { bFoundCrossReference = SerializeObjectProperty(ObjProperty, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), 0, PrefabProperty, CrossReferences); } - // Save as usual if no cross reference was found - if (!bFoundCrossReference) { - GetPropertyData(Property, ObjToSerialize, ObjTemplate, PrefabProperty->ExportedValue); - PrefabProperty->SaveReferencedAssetValues(); - } + // Save as usual even if cross reference was found + // This is is to supprot fields present in a struct which have nothing to do with + // object reference + GetPropertyData(Property, ObjToSerialize, ObjTemplate, PrefabProperty->ExportedValue); + PrefabProperty->SaveReferencedAssetValues(); OutProperties.Add(PrefabProperty); } @@ -943,10 +1005,15 @@ void FPrefabTools::LoadStateFromPrefabAsset(APrefabActor* PrefabActor, const FPr } } -// JB: Added FixupCrossReferences_Helper method to be able to easily reuse the code. namespace { - void FixupCrossReferences_Helper(UPrefabricatorProperty* PrefabProperty, const FObjectPropertyBase* ObjectProperty, void* PropertyValueAddress, int32 Index, TMap& PrefabItemToActorMap) + void FixupCrossReferences_Helper( + UPrefabricatorProperty* PrefabProperty + , const FObjectPropertyBase* ObjectProperty + , void* PropertyValueAddress + , int32 Index + , TMap& PrefabItemToActorMap + ) { FGuid* Guid = PrefabProperty->CrossReferencePrefabActorIdMap.Find(Index); if (!Guid) return; @@ -961,6 +1028,78 @@ namespace UE_LOG(LogPrefabTools, Log, TEXT("Cross Reference: %s -> %s"), *Guid->ToString(), *ActorName); //////// } + + void FixupCrossReferences_StructHelper( + void* StructPtr + , UPrefabricatorProperty* PrefabProperty + , const FStructProperty* StructProperty + , int32 Index + , TMap& PrefabItemToActorMap + ); + + void FixupCrossReferences_ArrayHelper( + void* Ptr + , UPrefabricatorProperty* PrefabProperty + , const FArrayProperty* ArrayProperty + , TMap& PrefabItemToActorMap + ) + { + if (const FObjectPropertyBase* ObjectProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + // The array may have different length by default. + if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) + { + Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); + } + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); + } + } + else if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + // The array may have different length by default. + if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) + { + Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); + } + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + FixupCrossReferences_StructHelper(Helper.GetRawPtr(Index), PrefabProperty, StructProperty, Index, PrefabItemToActorMap); + } + } + } + + void FixupCrossReferences_StructHelper( + void* StructPtr + , UPrefabricatorProperty* PrefabProperty + , const FStructProperty* StructProperty + , int32 Index + , TMap& PrefabItemToActorMap + ) + { + for (TFieldIterator It(StructProperty->Struct); It; ++It) { + FProperty* InnerProperty = *It; + + if (const FStructProperty* StructProperty = CastField(InnerProperty)) { + void* PropPtr = StructProperty->ContainerPtrToValuePtr(StructPtr, 0); + FixupCrossReferences_StructHelper(PropPtr, PrefabProperty, StructProperty, Index, PrefabItemToActorMap); + } + // Support for TArrays (TODO: Adds support for sets and maps). + else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) + { + FixupCrossReferences_ArrayHelper(StructPtr, PrefabProperty, ArrayProperty, PrefabItemToActorMap); + } + // Changed from FObjectProperty to FObjectPropertyBase to support also soft references. + else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) + { + void* PropPtr = ObjProperty->ContainerPtrToValuePtr(StructPtr, 0); + FixupCrossReferences_Helper(PrefabProperty, ObjProperty, PropPtr, 0, PrefabItemToActorMap); + } + } + } } void FPrefabTools::FixupCrossReferences(const TArray& PrefabProperties, UObject* ObjToWrite, TMap& PrefabItemToActorMap) @@ -970,27 +1109,22 @@ void FPrefabTools::FixupCrossReferences(const TArray& P FProperty* Property = ObjToWrite->GetClass()->FindPropertyByName(*PrefabProperty->PropertyName); - // JB: Added support for TArrays (TODO: Adds support for sets and maps). - if (const FArrayProperty* ArrayProperty = CastField(Property)) + // Support for TArrays (TODO: Adds support for sets and maps). + if (const FStructProperty* StructProperty = CastField(Property)) { - if (const FObjectPropertyBase* ObjectProperty = CastField(ArrayProperty->Inner)) - { - FScriptArrayHelper_InContainer Helper(ArrayProperty, ObjToWrite); - // The array may have different length by default. - if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) - { - Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); - } - for (int32 Index = 0; Index < Helper.Num(); Index++) - { - FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); - } - } + void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToWrite, 0); + FixupCrossReferences_StructHelper(StructPtr, PrefabProperty, StructProperty, 0, PrefabItemToActorMap); + } + else if (const FArrayProperty* ArrayProperty = CastField(Property)) + { + FixupCrossReferences_ArrayHelper(ObjToWrite, PrefabProperty, ArrayProperty, PrefabItemToActorMap); } - // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references + // FObjectProperty instead of FObjectPropertyBase to support also soft references else if (const FObjectPropertyBase* ObjectProperty = CastField(Property)) { FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), 0, PrefabItemToActorMap); } + // Note: there cannot be more than array, structs, and straight up object deemed as cross ref + // Nothing to do here } } diff --git a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h index 464d9f9e..cd9e27ed 100644 --- a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h +++ b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h @@ -40,7 +40,6 @@ class PREFABRICATORRUNTIME_API UPrefabricatorProperty : public UObject { UPROPERTY() bool bIsCrossReferencedActor = false; - // JB: The cross-references per index in array. UPROPERTY() TMap CrossReferencePrefabActorIdMap; From 456370f1bd5805e44b49722108cc396bb7683cb8 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 11:16:59 -0500 Subject: [PATCH 3/8] restore build files --- .../ConstructionSystemEditor.Build.cs | 2 +- .../ConstructionSystemRuntime.Build.cs | 2 +- Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs | 7 +------ .../PrefabricatorEditorPostInit.Build.cs | 7 +------ Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs | 5 ----- 5 files changed, 4 insertions(+), 19 deletions(-) diff --git a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs index 020cde95..3b3dfed4 100644 --- a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs +++ b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs @@ -8,7 +8,7 @@ public ConstructionSystemEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs index 21b75c5e..d4f8276c 100644 --- a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs +++ b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs @@ -8,7 +8,7 @@ public ConstructionSystemRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs index 0eeea6f9..5226ae28 100644 --- a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs +++ b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs @@ -8,12 +8,7 @@ public PrefabricatorEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - - - OptimizeCode = CodeOptimization.Never; - - - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs index 7b3b1d9c..c9e5ae05 100644 --- a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs +++ b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs @@ -8,12 +8,7 @@ public PrefabricatorEditorPostInit(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - - - OptimizeCode = CodeOptimization.Never; - - - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs index 516ae279..2a064d55 100644 --- a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs +++ b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs @@ -8,11 +8,6 @@ public PrefabricatorRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - - - OptimizeCode = CodeOptimization.Never; - - PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... From 3045a697d3496e101a6db7386a8a20bc86fe4150 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 11:17:25 -0500 Subject: [PATCH 4/8] restore build files --- Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs index 2a064d55..d686a32f 100644 --- a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs +++ b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs @@ -8,7 +8,7 @@ public PrefabricatorRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } From d4514ecf94d94bb8de86e0a55acefb5b50f9de74 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 11:18:16 -0500 Subject: [PATCH 5/8] fix typo --- Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp index 005a2979..b804c41f 100644 --- a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp +++ b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp @@ -543,8 +543,7 @@ namespace { } // Save as usual even if cross reference was found - // This is is to supprot fields present in a struct which have nothing to do with - // object reference + // This is is to support fields present in a struct which have nothing to do with objects GetPropertyData(Property, ObjToSerialize, ObjTemplate, PrefabProperty->ExportedValue); PrefabProperty->SaveReferencedAssetValues(); From 87a3dd06e5825a82b696dfb451df3246b2641df8 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 14:27:31 -0500 Subject: [PATCH 6/8] fixed array not being initialized with the right size --- .../Private/Prefab/PrefabTools.cpp | 180 +++++++++++------- .../Public/Asset/PrefabricatorAsset.h | 19 +- 2 files changed, 132 insertions(+), 67 deletions(-) diff --git a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp index b804c41f..0735037e 100644 --- a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp +++ b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp @@ -358,7 +358,9 @@ namespace { if (!InObjToDeserialize) return; for (UPrefabricatorProperty* PrefabProperty : InProperties) { - if (!PrefabProperty || PrefabProperty->bIsCrossReferencedActor) continue; + // If its a struct property, still let us use the value found in PrefabProperty->ExportedValue + // as a starting point, only the object reference will be fixed-up. + if (!PrefabProperty || (PrefabProperty->bIsCrossReferencedActor && !PrefabProperty->bContainsStructProperty)) continue; FString PropertyName = PrefabProperty->PropertyName; if (PropertyName == "AssetUserData") continue; // Skip this as assignment is very slow and is not needed @@ -386,7 +388,14 @@ namespace { } // SerializeObjectProperty method to reuse the code. - bool SerializeObjectProperty(const FObjectPropertyBase* ObjProperty, const void* PropertyValueAddress, int32 Index, UPrefabricatorProperty* PrefabProperty, const FPrefabActorLookup& CrossReferences) + bool SerializePreProcessForReference_ObjectHelper( + UObject* ObjPtr + , const FObjectPropertyBase* ObjProperty + , const void* PropertyValueAddress + , int32 Index + , UPrefabricatorProperty* PrefabProperty + , const FPrefabActorLookup& CrossReferences + ) { UObject* PropertyObjectValue = ObjProperty->GetObjectPropertyValue(PropertyValueAddress); if (PropertyObjectValue == nullptr || PropertyObjectValue->HasAnyFlags(RF_DefaultSubObject | RF_ArchetypeObject)) { @@ -397,74 +406,97 @@ namespace { FGuid CrossRefPrefabItem; if (CrossReferences.GetPrefabItemId(ObjectPath, CrossRefPrefabItem)) { PrefabProperty->bIsCrossReferencedActor = true; - PrefabProperty->CrossReferencePrefabActorIdMap.Add(Index, CrossRefPrefabItem); - return true; + // Obtain property path relative to object provided + FString NestedPropertyName = ObjProperty->GetPathName(ObjPtr); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + if(!NestedPropertyData) + { + NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NestedPropertyName, FPrefabricatorNestedPropertyData()); + } + + if (ensure(NestedPropertyData)) + { + NestedPropertyData->CrossReferencePrefabActorIdMap.Add(Index, CrossRefPrefabItem); + return true; + } } return false; } - bool SerializeStructField( - void* Ptr + void SerializePreProcessForReference_StructHelper( + UObject* ObjPtr + , void* ContainerPtr , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty); - bool SerializeArrayField( - void* Ptr + void SerializePreProcessForReference_ArrayHelper( + UObject* ObjPtr + , void* ContainerPtr , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty , const FArrayProperty* ArrayProperty) - { - bool bFoundCrossReference = false; - // TODO: Array of arrays - if (const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner)) + { + const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner); + const FStructProperty* StructProperty = CastField(ArrayProperty->Inner); + + if (ObjProperty || StructProperty) { - FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); - for (int32 Index = 0; Index < Helper.Num(); Index++) + FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); + FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); + FPrefabricatorNestedPropertyData* NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + if (!NestedPropertyData) { - bFoundCrossReference |= SerializeObjectProperty(ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); + NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NestedPropertyName, FPrefabricatorNestedPropertyData()); } - } - else if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) - { - FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); - for (int32 Index = 0; Index < Helper.Num(); Index++) + + NestedPropertyData->ArrayLength = Helper.Num(); + + // TODO: Array of arrays + if (ObjProperty) { - bFoundCrossReference |= SerializeStructField(Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, StructProperty); + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + SerializePreProcessForReference_ObjectHelper(ObjPtr, ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); + } + } + else if (StructProperty) + { + for (int32 Index = 0; Index < Helper.Num(); Index++) + { + SerializePreProcessForReference_StructHelper(ObjPtr, Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, StructProperty); + } } } - - return bFoundCrossReference; } - bool SerializeStructField( - void* Ptr + void SerializePreProcessForReference_StructHelper( + UObject* ObjPtr + , void* ContainerPtr , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty ) { - bool bFoundCrossReference = false; + PrefabProperty->bContainsStructProperty = true; for (TFieldIterator It(StructProperty->Struct); It; ++It) { FProperty* InnerProperty = *It; if (const FStructProperty* StructProperty = CastField(InnerProperty)) { - void* PropPtr = StructProperty->ContainerPtrToValuePtr(Ptr, 0); - bFoundCrossReference |= SerializeStructField(PropPtr, CrossReferences, PrefabProperty, StructProperty); + void* PropPtr = StructProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + SerializePreProcessForReference_StructHelper(ObjPtr, PropPtr, CrossReferences, PrefabProperty, StructProperty); } - // JB: Added support for TArrays (TODO: Adds support for sets and maps). + // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) { - bFoundCrossReference |= SerializeArrayField(Ptr, CrossReferences, PrefabProperty, ArrayProperty); + SerializePreProcessForReference_ArrayHelper(ObjPtr, ContainerPtr, CrossReferences, PrefabProperty, ArrayProperty); } - // JB: Changed from FObjectProperty to FObjectPropertyBase to support also soft references. + // FObjectPropertyBase instead of FObjectProperty to also support soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) { - void* PropPtr = ObjProperty->ContainerPtrToValuePtr(Ptr, 0); - bFoundCrossReference |= SerializeObjectProperty(ObjProperty, PropPtr, 0, PrefabProperty, CrossReferences); + void* PropPtr = ObjProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + SerializePreProcessForReference_ObjectHelper(ObjPtr, ObjProperty, PropPtr, 0, PrefabProperty, CrossReferences); } } - - return bFoundCrossReference; } void SerializeFields(UObject* ObjToSerialize, UObject* ObjTemplate, APrefabActor* PrefabActor, const FPrefabActorLookup& CrossReferences, TArray& OutProperties) { @@ -524,28 +556,29 @@ namespace { PrefabProperty = NewObject(PrefabAsset); PrefabProperty->PropertyName = PropertyName; - - // Check for cross actor references - bool bFoundCrossReference = false; + // Support for USTRUCT if (const FStructProperty* StructProperty = CastField(Property)) { void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToSerialize, 0); - bFoundCrossReference |= SerializeStructField(StructPtr, CrossReferences, PrefabProperty, StructProperty); + SerializePreProcessForReference_StructHelper(ObjToSerialize, StructPtr, CrossReferences, PrefabProperty, StructProperty); } // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(Property)) { - bFoundCrossReference |= SerializeArrayField(ObjToSerialize, CrossReferences, PrefabProperty, ArrayProperty); + SerializePreProcessForReference_ArrayHelper(ObjToSerialize, ObjToSerialize, CrossReferences, PrefabProperty, ArrayProperty); } // FObjectPropertyBase instead of FObjectProperty to also support soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(Property)) { - bFoundCrossReference = SerializeObjectProperty(ObjProperty, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), 0, PrefabProperty, CrossReferences); + SerializePreProcessForReference_ObjectHelper(ObjToSerialize, ObjProperty, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), 0, PrefabProperty, CrossReferences); } // Save as usual even if cross reference was found // This is is to support fields present in a struct which have nothing to do with objects - GetPropertyData(Property, ObjToSerialize, ObjTemplate, PrefabProperty->ExportedValue); - PrefabProperty->SaveReferencedAssetValues(); + if (!PrefabProperty->bIsCrossReferencedActor || PrefabProperty->bContainsStructProperty) + { + GetPropertyData(Property, ObjToSerialize, ObjTemplate, PrefabProperty->ExportedValue); + PrefabProperty->SaveReferencedAssetValues(); + } OutProperties.Add(PrefabProperty); } @@ -1007,14 +1040,19 @@ void FPrefabTools::LoadStateFromPrefabAsset(APrefabActor* PrefabActor, const FPr namespace { void FixupCrossReferences_Helper( - UPrefabricatorProperty* PrefabProperty + UObject* ObjPtr + , UPrefabricatorProperty* PrefabProperty , const FObjectPropertyBase* ObjectProperty , void* PropertyValueAddress , int32 Index , TMap& PrefabItemToActorMap ) { - FGuid* Guid = PrefabProperty->CrossReferencePrefabActorIdMap.Find(Index); + FString NestedPropertyName = ObjectProperty->GetPathName(ObjPtr); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + if (!NestedPropertyData) return; + + FGuid* Guid = NestedPropertyData->CrossReferencePrefabActorIdMap.Find(Index); if (!Guid) return; AActor** SearchResult = PrefabItemToActorMap.Find(*Guid); if (!SearchResult) return; @@ -1029,15 +1067,16 @@ namespace } void FixupCrossReferences_StructHelper( - void* StructPtr + UObject* ObjPtr + , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty - , int32 Index , TMap& PrefabItemToActorMap ); void FixupCrossReferences_ArrayHelper( - void* Ptr + UObject* ObjPtr + , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FArrayProperty* ArrayProperty , TMap& PrefabItemToActorMap @@ -1045,37 +1084,46 @@ namespace { if (const FObjectPropertyBase* ObjectProperty = CastField(ArrayProperty->Inner)) { - FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); + FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + if (!NestedPropertyData) + return; // The array may have different length by default. - if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) + if (Helper.Num() < NestedPropertyData->ArrayLength) { - Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); + Helper.AddValues(NestedPropertyData->ArrayLength - Helper.Num()); } for (int32 Index = 0; Index < Helper.Num(); Index++) { - FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); + FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); } } else if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) { - FScriptArrayHelper_InContainer Helper(ArrayProperty, Ptr); + FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); + FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + if (!NestedPropertyData) + return; + // The array may have different length by default. - if (Helper.Num() < PrefabProperty->CrossReferencePrefabActorIdMap.Num()) + if (Helper.Num() < NestedPropertyData->ArrayLength) { - Helper.AddValues(PrefabProperty->CrossReferencePrefabActorIdMap.Num() - Helper.Num()); + Helper.AddValues(NestedPropertyData->ArrayLength - Helper.Num()); } for (int32 Index = 0; Index < Helper.Num(); Index++) { - FixupCrossReferences_StructHelper(Helper.GetRawPtr(Index), PrefabProperty, StructProperty, Index, PrefabItemToActorMap); + FixupCrossReferences_StructHelper(ObjPtr, Helper.GetRawPtr(Index), PrefabProperty, StructProperty, PrefabItemToActorMap); } } } void FixupCrossReferences_StructHelper( - void* StructPtr + UObject* ObjPtr + , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty - , int32 Index , TMap& PrefabItemToActorMap ) { @@ -1083,19 +1131,19 @@ namespace FProperty* InnerProperty = *It; if (const FStructProperty* StructProperty = CastField(InnerProperty)) { - void* PropPtr = StructProperty->ContainerPtrToValuePtr(StructPtr, 0); - FixupCrossReferences_StructHelper(PropPtr, PrefabProperty, StructProperty, Index, PrefabItemToActorMap); + void* PropPtr = StructProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + FixupCrossReferences_StructHelper(ObjPtr, PropPtr, PrefabProperty, StructProperty, PrefabItemToActorMap); } // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) { - FixupCrossReferences_ArrayHelper(StructPtr, PrefabProperty, ArrayProperty, PrefabItemToActorMap); + FixupCrossReferences_ArrayHelper(ObjPtr, ContainerPtr, PrefabProperty, ArrayProperty, PrefabItemToActorMap); } // Changed from FObjectProperty to FObjectPropertyBase to support also soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) { - void* PropPtr = ObjProperty->ContainerPtrToValuePtr(StructPtr, 0); - FixupCrossReferences_Helper(PrefabProperty, ObjProperty, PropPtr, 0, PrefabItemToActorMap); + void* PropPtr = ObjProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjProperty, PropPtr, 0, PrefabItemToActorMap); } } } @@ -1112,15 +1160,15 @@ void FPrefabTools::FixupCrossReferences(const TArray& P if (const FStructProperty* StructProperty = CastField(Property)) { void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToWrite, 0); - FixupCrossReferences_StructHelper(StructPtr, PrefabProperty, StructProperty, 0, PrefabItemToActorMap); + FixupCrossReferences_StructHelper(ObjToWrite, StructPtr, PrefabProperty, StructProperty, PrefabItemToActorMap); } else if (const FArrayProperty* ArrayProperty = CastField(Property)) { - FixupCrossReferences_ArrayHelper(ObjToWrite, PrefabProperty, ArrayProperty, PrefabItemToActorMap); + FixupCrossReferences_ArrayHelper(ObjToWrite, ObjToWrite, PrefabProperty, ArrayProperty, PrefabItemToActorMap); } // FObjectProperty instead of FObjectPropertyBase to support also soft references else if (const FObjectPropertyBase* ObjectProperty = CastField(Property)) { - FixupCrossReferences_Helper(PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), 0, PrefabItemToActorMap); + FixupCrossReferences_Helper(ObjToWrite, PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), 0, PrefabItemToActorMap); } // Note: there cannot be more than array, structs, and straight up object deemed as cross ref // Nothing to do here diff --git a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h index cd9e27ed..beb3fe69 100644 --- a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h +++ b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h @@ -24,6 +24,20 @@ struct PREFABRICATORRUNTIME_API FPrefabricatorPropertyAssetMapping { bool bUseQuotes = false; }; + +USTRUCT() +struct PREFABRICATORRUNTIME_API FPrefabricatorNestedPropertyData +{ + GENERATED_BODY() + + /// Array length is used to initialize array inside FixupCrossReferences phase of serialization + UPROPERTY() + int32 ArrayLength = -1; + + UPROPERTY() + TMap CrossReferencePrefabActorIdMap; +}; + UCLASS() class PREFABRICATORRUNTIME_API UPrefabricatorProperty : public UObject { GENERATED_BODY() @@ -41,7 +55,10 @@ class PREFABRICATORRUNTIME_API UPrefabricatorProperty : public UObject { bool bIsCrossReferencedActor = false; UPROPERTY() - TMap CrossReferencePrefabActorIdMap; + bool bContainsStructProperty = false; + + UPROPERTY() + TMap NestedPropertyData; void SaveReferencedAssetValues(); void LoadReferencedAssetValues(); From 1ce2c248b2681e16f5600238b5250981601ed783 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 20:41:40 -0500 Subject: [PATCH 7/8] fix nested property data not saving correctly --- .../ConstructionSystemEditor.Build.cs | 1 + .../ConstructionSystemRuntime.Build.cs | 3 +- .../PrefabricatorEditor.Build.cs | 3 +- .../PrefabricatorEditorPostInit.Build.cs | 3 +- .../PrefabricatorRuntime.Build.cs | 3 +- .../Private/Prefab/PrefabTools.cpp | 120 +++++++++++------- .../Public/Asset/PrefabricatorAsset.h | 3 +- 7 files changed, 88 insertions(+), 48 deletions(-) diff --git a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs index 3b3dfed4..15becb49 100644 --- a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs +++ b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs @@ -8,6 +8,7 @@ public ConstructionSystemEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + OptimizeCode = CodeOptimization.Never; PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... diff --git a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs index d4f8276c..fdcec759 100644 --- a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs +++ b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs @@ -8,7 +8,8 @@ public ConstructionSystemRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + OptimizeCode = CodeOptimization.Never; + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs index 5226ae28..96ed7dcf 100644 --- a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs +++ b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs @@ -8,7 +8,8 @@ public PrefabricatorEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + OptimizeCode = CodeOptimization.Never; + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs index c9e5ae05..bacbe75d 100644 --- a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs +++ b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs @@ -8,7 +8,8 @@ public PrefabricatorEditorPostInit(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + OptimizeCode = CodeOptimization.Never; + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs index d686a32f..8cc918a3 100644 --- a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs +++ b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs @@ -8,7 +8,8 @@ public PrefabricatorRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicIncludePaths.AddRange( + OptimizeCode = CodeOptimization.Never; + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp index 0735037e..016f9dba 100644 --- a/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp +++ b/Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp @@ -387,14 +387,25 @@ namespace { } } + FString GetNestedPropertyPath(const FString& PropertyPath, const FProperty* Property, int32 PropertyElementIndex=-1) + { + FString NestedPropertyName = Property->GetName(); + FString NewPropertyPath(PropertyPath); + NewPropertyPath += PropertyElementIndex < 0 ? + FString::Format(TEXT("|{0}"), { NestedPropertyName }) : + FString::Format(TEXT("|{0}[{1}]"), { NestedPropertyName, PropertyElementIndex }); + return NewPropertyPath; + } + // SerializeObjectProperty method to reuse the code. bool SerializePreProcessForReference_ObjectHelper( UObject* ObjPtr - , const FObjectPropertyBase* ObjProperty , const void* PropertyValueAddress - , int32 Index - , UPrefabricatorProperty* PrefabProperty , const FPrefabActorLookup& CrossReferences + , UPrefabricatorProperty* PrefabProperty + , const FObjectPropertyBase* ObjProperty + , const FString& PropertyPath + , int32 PropertyElementIndex=-1 ) { UObject* PropertyObjectValue = ObjProperty->GetObjectPropertyValue(PropertyValueAddress); @@ -407,16 +418,17 @@ namespace { if (CrossReferences.GetPrefabItemId(ObjectPath, CrossRefPrefabItem)) { PrefabProperty->bIsCrossReferencedActor = true; // Obtain property path relative to object provided - FString NestedPropertyName = ObjProperty->GetPathName(ObjPtr); - auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, ObjProperty, PropertyElementIndex); + + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NewPropertyPath); if(!NestedPropertyData) { - NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NestedPropertyName, FPrefabricatorNestedPropertyData()); + NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NewPropertyPath, FPrefabricatorNestedPropertyData()); } if (ensure(NestedPropertyData)) { - NestedPropertyData->CrossReferencePrefabActorIdMap.Add(Index, CrossRefPrefabItem); + NestedPropertyData->CrossReferencePrefabActorId = CrossRefPrefabItem; return true; } } @@ -428,26 +440,32 @@ namespace { , void* ContainerPtr , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty - , const FStructProperty* StructProperty); + , const FStructProperty* StructProperty + , const FString& PropertyPath + , int32 PropertyElementIndex=-1); void SerializePreProcessForReference_ArrayHelper( UObject* ObjPtr , void* ContainerPtr , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty - , const FArrayProperty* ArrayProperty) + , const FArrayProperty* ArrayProperty + , const FString& PropertyPath + , int32 PropertyElementIndex=-1 + ) { const FObjectPropertyBase* ObjProperty = CastField(ArrayProperty->Inner); const FStructProperty* StructProperty = CastField(ArrayProperty->Inner); if (ObjProperty || StructProperty) { - FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); - FPrefabricatorNestedPropertyData* NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, ArrayProperty, PropertyElementIndex); + + FPrefabricatorNestedPropertyData* NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NewPropertyPath); if (!NestedPropertyData) { - NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NestedPropertyName, FPrefabricatorNestedPropertyData()); + NestedPropertyData = &PrefabProperty->NestedPropertyData.Add(NewPropertyPath, FPrefabricatorNestedPropertyData()); } NestedPropertyData->ArrayLength = Helper.Num(); @@ -457,14 +475,14 @@ namespace { { for (int32 Index = 0; Index < Helper.Num(); Index++) { - SerializePreProcessForReference_ObjectHelper(ObjPtr, ObjProperty, Helper.GetRawPtr(Index), Index, PrefabProperty, CrossReferences); + SerializePreProcessForReference_ObjectHelper(ObjPtr, Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, ObjProperty, NewPropertyPath, Index); } } else if (StructProperty) { for (int32 Index = 0; Index < Helper.Num(); Index++) { - SerializePreProcessForReference_StructHelper(ObjPtr, Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, StructProperty); + SerializePreProcessForReference_StructHelper(ObjPtr, Helper.GetRawPtr(Index), CrossReferences, PrefabProperty, StructProperty, NewPropertyPath, Index); } } } @@ -476,25 +494,29 @@ namespace { , const FPrefabActorLookup& CrossReferences , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty + , const FString& PropertyPath + , int32 PropertyElementIndex ) { PrefabProperty->bContainsStructProperty = true; + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, StructProperty, PropertyElementIndex); + for (TFieldIterator It(StructProperty->Struct); It; ++It) { FProperty* InnerProperty = *It; if (const FStructProperty* StructProperty = CastField(InnerProperty)) { - void* PropPtr = StructProperty->ContainerPtrToValuePtr(ContainerPtr, 0); - SerializePreProcessForReference_StructHelper(ObjPtr, PropPtr, CrossReferences, PrefabProperty, StructProperty); + void* PropValuePtr = StructProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + SerializePreProcessForReference_StructHelper(ObjPtr, PropValuePtr, CrossReferences, PrefabProperty, StructProperty, NewPropertyPath); } // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) { - SerializePreProcessForReference_ArrayHelper(ObjPtr, ContainerPtr, CrossReferences, PrefabProperty, ArrayProperty); + SerializePreProcessForReference_ArrayHelper(ObjPtr, ContainerPtr, CrossReferences, PrefabProperty, ArrayProperty, NewPropertyPath); } // FObjectPropertyBase instead of FObjectProperty to also support soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) { - void* PropPtr = ObjProperty->ContainerPtrToValuePtr(ContainerPtr, 0); - SerializePreProcessForReference_ObjectHelper(ObjPtr, ObjProperty, PropPtr, 0, PrefabProperty, CrossReferences); + void* PropValuePtr = ObjProperty->ContainerPtrToValuePtr(ContainerPtr, 0); + SerializePreProcessForReference_ObjectHelper(ObjPtr, PropValuePtr, CrossReferences, PrefabProperty, ObjProperty, NewPropertyPath); } } } @@ -556,20 +578,22 @@ namespace { PrefabProperty = NewObject(PrefabAsset); PrefabProperty->PropertyName = PropertyName; - + + FString PropertyPath = ""; + // Support for USTRUCT if (const FStructProperty* StructProperty = CastField(Property)) { void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToSerialize, 0); - SerializePreProcessForReference_StructHelper(ObjToSerialize, StructPtr, CrossReferences, PrefabProperty, StructProperty); + SerializePreProcessForReference_StructHelper(ObjToSerialize, StructPtr, CrossReferences, PrefabProperty, StructProperty, PropertyPath); } // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(Property)) { - SerializePreProcessForReference_ArrayHelper(ObjToSerialize, ObjToSerialize, CrossReferences, PrefabProperty, ArrayProperty); + SerializePreProcessForReference_ArrayHelper(ObjToSerialize, ObjToSerialize, CrossReferences, PrefabProperty, ArrayProperty, PropertyPath); } // FObjectPropertyBase instead of FObjectProperty to also support soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(Property)) { - SerializePreProcessForReference_ObjectHelper(ObjToSerialize, ObjProperty, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), 0, PrefabProperty, CrossReferences); + SerializePreProcessForReference_ObjectHelper(ObjToSerialize, ObjProperty->ContainerPtrToValuePtr(ObjToSerialize), CrossReferences, PrefabProperty, ObjProperty, PropertyPath); } // Save as usual even if cross reference was found @@ -1044,17 +1068,17 @@ namespace , UPrefabricatorProperty* PrefabProperty , const FObjectPropertyBase* ObjectProperty , void* PropertyValueAddress + , const FString& PropertyPath , int32 Index , TMap& PrefabItemToActorMap ) { - FString NestedPropertyName = ObjectProperty->GetPathName(ObjPtr); - auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, ObjectProperty, Index); + + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NewPropertyPath); if (!NestedPropertyData) return; - FGuid* Guid = NestedPropertyData->CrossReferencePrefabActorIdMap.Find(Index); - if (!Guid) return; - AActor** SearchResult = PrefabItemToActorMap.Find(*Guid); + AActor** SearchResult = PrefabItemToActorMap.Find(NestedPropertyData->CrossReferencePrefabActorId); if (!SearchResult) return; AActor* CrossReference = *SearchResult; @@ -1062,7 +1086,7 @@ namespace //////// FString ActorName = CrossReference ? CrossReference->GetName() : "[NONE]"; - UE_LOG(LogPrefabTools, Log, TEXT("Cross Reference: %s -> %s"), *Guid->ToString(), *ActorName); + UE_LOG(LogPrefabTools, Log, TEXT("Cross Reference: %s -> %s"), *NestedPropertyData->CrossReferencePrefabActorId.ToString(), *ActorName); //////// } @@ -1071,6 +1095,8 @@ namespace , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty + , const FString& PropertyPath + , int32 PropertyElementIndex , TMap& PrefabItemToActorMap ); @@ -1079,16 +1105,20 @@ namespace , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FArrayProperty* ArrayProperty + , const FString& PropertyPath + , int32 PropertyElementIndex , TMap& PrefabItemToActorMap ) { + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, ArrayProperty, PropertyElementIndex); + if (const FObjectPropertyBase* ObjectProperty = CastField(ArrayProperty->Inner)) { - FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); - FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); - auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NewPropertyPath); if (!NestedPropertyData) return; + + FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); // The array may have different length by default. if (Helper.Num() < NestedPropertyData->ArrayLength) { @@ -1096,17 +1126,16 @@ namespace } for (int32 Index = 0; Index < Helper.Num(); Index++) { - FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), Index, PrefabItemToActorMap); + FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjectProperty, Helper.GetRawPtr(Index), NewPropertyPath, Index, PrefabItemToActorMap); } } else if (const FStructProperty* StructProperty = CastField(ArrayProperty->Inner)) { - FString NestedPropertyName = ArrayProperty->GetPathName(ObjPtr); - FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); - auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NestedPropertyName); + auto NestedPropertyData = PrefabProperty->NestedPropertyData.Find(NewPropertyPath); if (!NestedPropertyData) return; + FScriptArrayHelper_InContainer Helper(ArrayProperty, ContainerPtr); // The array may have different length by default. if (Helper.Num() < NestedPropertyData->ArrayLength) { @@ -1114,7 +1143,7 @@ namespace } for (int32 Index = 0; Index < Helper.Num(); Index++) { - FixupCrossReferences_StructHelper(ObjPtr, Helper.GetRawPtr(Index), PrefabProperty, StructProperty, PrefabItemToActorMap); + FixupCrossReferences_StructHelper(ObjPtr, Helper.GetRawPtr(Index), PrefabProperty, StructProperty, NewPropertyPath, Index, PrefabItemToActorMap); } } } @@ -1124,26 +1153,30 @@ namespace , void* ContainerPtr , UPrefabricatorProperty* PrefabProperty , const FStructProperty* StructProperty + , const FString& PropertyPath + , int32 PropertyElementIndex , TMap& PrefabItemToActorMap ) { + FString NewPropertyPath = GetNestedPropertyPath(PropertyPath, StructProperty, PropertyElementIndex); + for (TFieldIterator It(StructProperty->Struct); It; ++It) { FProperty* InnerProperty = *It; if (const FStructProperty* StructProperty = CastField(InnerProperty)) { void* PropPtr = StructProperty->ContainerPtrToValuePtr(ContainerPtr, 0); - FixupCrossReferences_StructHelper(ObjPtr, PropPtr, PrefabProperty, StructProperty, PrefabItemToActorMap); + FixupCrossReferences_StructHelper(ObjPtr, PropPtr, PrefabProperty, StructProperty, NewPropertyPath, -1, PrefabItemToActorMap); } // Support for TArrays (TODO: Adds support for sets and maps). else if (const FArrayProperty* ArrayProperty = CastField(InnerProperty)) { - FixupCrossReferences_ArrayHelper(ObjPtr, ContainerPtr, PrefabProperty, ArrayProperty, PrefabItemToActorMap); + FixupCrossReferences_ArrayHelper(ObjPtr, ContainerPtr, PrefabProperty, ArrayProperty, NewPropertyPath, -1, PrefabItemToActorMap); } // Changed from FObjectProperty to FObjectPropertyBase to support also soft references. else if (const FObjectPropertyBase* ObjProperty = CastField(InnerProperty)) { void* PropPtr = ObjProperty->ContainerPtrToValuePtr(ContainerPtr, 0); - FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjProperty, PropPtr, 0, PrefabItemToActorMap); + FixupCrossReferences_Helper(ObjPtr, PrefabProperty, ObjProperty, PropPtr, NewPropertyPath, -1, PrefabItemToActorMap); } } } @@ -1155,20 +1188,21 @@ void FPrefabTools::FixupCrossReferences(const TArray& P if (!PrefabProperty || !PrefabProperty->bIsCrossReferencedActor) continue; FProperty* Property = ObjToWrite->GetClass()->FindPropertyByName(*PrefabProperty->PropertyName); + FString PropertyPath = ""; // Support for TArrays (TODO: Adds support for sets and maps). if (const FStructProperty* StructProperty = CastField(Property)) { void* StructPtr = StructProperty->ContainerPtrToValuePtr(ObjToWrite, 0); - FixupCrossReferences_StructHelper(ObjToWrite, StructPtr, PrefabProperty, StructProperty, PrefabItemToActorMap); + FixupCrossReferences_StructHelper(ObjToWrite, StructPtr, PrefabProperty, StructProperty, PropertyPath, -1, PrefabItemToActorMap); } else if (const FArrayProperty* ArrayProperty = CastField(Property)) { - FixupCrossReferences_ArrayHelper(ObjToWrite, ObjToWrite, PrefabProperty, ArrayProperty, PrefabItemToActorMap); + FixupCrossReferences_ArrayHelper(ObjToWrite, ObjToWrite, PrefabProperty, ArrayProperty, PropertyPath, -1, PrefabItemToActorMap); } // FObjectProperty instead of FObjectPropertyBase to support also soft references else if (const FObjectPropertyBase* ObjectProperty = CastField(Property)) { - FixupCrossReferences_Helper(ObjToWrite, PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), 0, PrefabItemToActorMap); + FixupCrossReferences_Helper(ObjToWrite, PrefabProperty, ObjectProperty, ObjectProperty->ContainerPtrToValuePtr(ObjToWrite), PropertyPath, -1, PrefabItemToActorMap); } // Note: there cannot be more than array, structs, and straight up object deemed as cross ref // Nothing to do here diff --git a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h index beb3fe69..a3d86e11 100644 --- a/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h +++ b/Source/PrefabricatorRuntime/Public/Asset/PrefabricatorAsset.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" #include "Engine/EngineTypes.h" + #include "PrefabricatorAsset.generated.h" class APrefabActor; @@ -35,7 +36,7 @@ struct PREFABRICATORRUNTIME_API FPrefabricatorNestedPropertyData int32 ArrayLength = -1; UPROPERTY() - TMap CrossReferencePrefabActorIdMap; + FGuid CrossReferencePrefabActorId; }; UCLASS() From c588e6f078a46b5065be914eda74fd4f72ec8845 Mon Sep 17 00:00:00 2001 From: OliPerraul Date: Mon, 27 Nov 2023 20:42:55 -0500 Subject: [PATCH 8/8] restore build files --- .../ConstructionSystemEditor/ConstructionSystemEditor.Build.cs | 1 - .../ConstructionSystemRuntime.Build.cs | 3 +-- Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs | 3 +-- .../PrefabricatorEditorPostInit.Build.cs | 3 +-- Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs | 3 +-- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs index 15becb49..3b3dfed4 100644 --- a/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs +++ b/Source/ConstructionSystemEditor/ConstructionSystemEditor.Build.cs @@ -8,7 +8,6 @@ public ConstructionSystemEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - OptimizeCode = CodeOptimization.Never; PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... diff --git a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs index fdcec759..d4f8276c 100644 --- a/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs +++ b/Source/ConstructionSystemRuntime/ConstructionSystemRuntime.Build.cs @@ -8,8 +8,7 @@ public ConstructionSystemRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - OptimizeCode = CodeOptimization.Never; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs index 96ed7dcf..5226ae28 100644 --- a/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs +++ b/Source/PrefabricatorEditor/PrefabricatorEditor.Build.cs @@ -8,8 +8,7 @@ public PrefabricatorEditor(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - OptimizeCode = CodeOptimization.Never; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs index bacbe75d..c9e5ae05 100644 --- a/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs +++ b/Source/PrefabricatorEditorPostInit/PrefabricatorEditorPostInit.Build.cs @@ -8,8 +8,7 @@ public PrefabricatorEditorPostInit(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - OptimizeCode = CodeOptimization.Never; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } diff --git a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs index 8cc918a3..d686a32f 100644 --- a/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs +++ b/Source/PrefabricatorRuntime/PrefabricatorRuntime.Build.cs @@ -8,8 +8,7 @@ public PrefabricatorRuntime(ReadOnlyTargetRules Target) : base(Target) { bUseUnity = false; PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - OptimizeCode = CodeOptimization.Never; - PublicIncludePaths.AddRange( + PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... }