2021-11-26 15:48:13 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "SmartObjectDefinition.h"
2022-03-02 13:25:37 -05:00
# include "SmartObjectSettings.h"
2023-08-29 07:48:32 -04:00
# include "Misc/EnumerateRange.h"
2022-11-01 15:11:25 -04:00
# if WITH_EDITOR
# include "UObject/ObjectSaveContext.h"
2023-01-18 10:52:51 -05:00
# include "WorldConditions/WorldCondition_SmartObjectActorTagQuery.h"
# include "WorldConditions/SmartObjectWorldConditionObjectTagQuery.h"
2023-03-27 08:22:19 -04:00
# include "SmartObjectUserComponent.h"
# include "Engine/SCS_Node.h"
2023-04-27 17:53:18 -04:00
# include "Misc/DataValidation.h"
2023-08-29 07:48:32 -04:00
# include "SmartObjectPropertyHelpers.h"
2023-12-20 08:17:55 -05:00
# include "Interfaces/ITargetPlatform.h"
2022-11-01 15:11:25 -04:00
# endif
2022-09-28 01:06:15 -04:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(SmartObjectDefinition)
2023-01-23 18:48:38 -05:00
# define LOCTEXT_NAMESPACE "SmartObjectDefinition"
2022-01-07 14:28:06 -05:00
namespace UE : : SmartObject
{
const FVector DefaultSlotSize ( 40 , 40 , 90 ) ;
}
2022-03-02 13:25:37 -05:00
USmartObjectDefinition : : USmartObjectDefinition ( const FObjectInitializer & ObjectInitializer ) : UDataAsset ( ObjectInitializer )
{
2022-03-02 22:33:53 -05:00
UserTagsFilteringPolicy = GetDefault < USmartObjectSettings > ( ) - > DefaultUserTagsFilteringPolicy ;
ActivityTagsMergingPolicy = GetDefault < USmartObjectSettings > ( ) - > DefaultActivityTagsMergingPolicy ;
2022-11-17 07:44:24 -05:00
WorldConditionSchemaClass = GetDefault < USmartObjectSettings > ( ) - > DefaultWorldConditionSchemaClass ;
2022-03-02 13:25:37 -05:00
}
2023-01-23 18:48:38 -05:00
# if WITH_EDITOR
2023-04-27 17:53:18 -04:00
EDataValidationResult USmartObjectDefinition : : IsDataValid ( FDataValidationContext & Context ) const
2023-01-23 18:48:38 -05:00
{
2023-04-27 17:53:18 -04:00
const EDataValidationResult Result = Super : : IsDataValid ( Context ) ;
2023-01-23 18:48:38 -05:00
2023-04-27 17:53:18 -04:00
TArray < FText > ValidationErrors ;
2023-01-23 18:48:38 -05:00
Validate ( & ValidationErrors ) ;
2023-04-27 17:53:18 -04:00
for ( const FText & Error : ValidationErrors )
{
Context . AddError ( Error ) ;
}
2023-01-23 18:48:38 -05:00
2023-08-16 14:15:36 -04:00
return CombineDataValidationResults ( Result , bValid . GetValue ( ) ? EDataValidationResult : : Valid : EDataValidationResult : : Invalid ) ;
2023-01-23 18:48:38 -05:00
}
2023-03-27 08:22:19 -04:00
TSubclassOf < USmartObjectSlotValidationFilter > USmartObjectDefinition : : GetPreviewValidationFilterClass ( ) const
{
if ( PreviewData . UserActorClass . IsValid ( ) )
{
if ( const UClass * UserActorClass = PreviewData . UserActorClass . Get ( ) )
{
// Try to get smart object user component added in the BP.
if ( const UBlueprintGeneratedClass * UserBlueprintClass = Cast < UBlueprintGeneratedClass > ( UserActorClass ) )
{
const TArray < USCS_Node * > & Nodes = UserBlueprintClass - > SimpleConstructionScript - > GetAllNodes ( ) ;
for ( USCS_Node * Node : Nodes )
{
UActorComponent * Component = Node - > GetActualComponentTemplate ( const_cast < UBlueprintGeneratedClass * > ( UserBlueprintClass ) ) ;
if ( const USmartObjectUserComponent * UserComponent = Cast < USmartObjectUserComponent > ( Component ) )
{
return UserComponent - > GetValidationFilter ( ) ;
}
}
}
// Try to get the component from the CDO (e.g. added as default object in C++).
if ( const AActor * UserActor = Cast < AActor > ( UserActorClass - > GetDefaultObject ( ) ) )
{
if ( const USmartObjectUserComponent * UserComponent = UserActor - > GetComponentByClass < USmartObjectUserComponent > ( ) )
{
return UserComponent - > GetValidationFilter ( ) ;
}
}
}
return nullptr ;
}
if ( PreviewData . UserValidationFilterClass . IsValid ( ) )
{
return PreviewData . UserValidationFilterClass . Get ( ) ;
}
return nullptr ;
}
2023-01-23 18:48:38 -05:00
# endif // WITH_EDITOR
bool USmartObjectDefinition : : Validate ( TArray < FText > * ErrorsToReport ) const
2021-11-26 15:48:13 -05:00
{
bValid = false ;
// Detect null entries in default definitions
int32 NullEntryIndex ;
if ( DefaultBehaviorDefinitions . Find ( nullptr , NullEntryIndex ) )
{
2023-01-23 18:48:38 -05:00
if ( ErrorsToReport )
{
ErrorsToReport - > Emplace ( FText : : Format ( LOCTEXT ( " NullDefaultBehaviorEntryError " , " Null entry found at index {0} in default behavior definition list " ) , NullEntryIndex ) ) ;
}
else
{
return false ;
}
2021-11-26 15:48:13 -05:00
}
// Detect null entries in slot definitions
for ( int i = 0 ; i < Slots . Num ( ) ; + + i )
{
2022-01-19 14:16:16 -05:00
const FSmartObjectSlotDefinition & Slot = Slots [ i ] ;
2021-11-26 15:48:13 -05:00
if ( Slot . BehaviorDefinitions . Find ( nullptr , NullEntryIndex ) )
{
2023-01-23 18:48:38 -05:00
if ( ErrorsToReport )
{
ErrorsToReport - > Emplace ( FText : : Format ( LOCTEXT ( " NullSlotBehaviorEntryError " , " Null entry found at index {0} in default behavior definition list " ) , NullEntryIndex ) ) ;
}
else
{
return false ;
}
2021-11-26 15:48:13 -05:00
}
}
// Detect missing definitions in slots if no default one are provided
if ( DefaultBehaviorDefinitions . Num ( ) = = 0 )
{
for ( int i = 0 ; i < Slots . Num ( ) ; + + i )
{
2022-01-19 14:16:16 -05:00
const FSmartObjectSlotDefinition & Slot = Slots [ i ] ;
2021-11-26 15:48:13 -05:00
if ( Slot . BehaviorDefinitions . Num ( ) = = 0 )
{
2023-01-23 18:48:38 -05:00
if ( ErrorsToReport )
{
ErrorsToReport - > Emplace ( FText : : Format ( LOCTEXT ( " MissingSlotBehaviorError " , " Slot at index {0} needs to provide a behavior definition since there is no default one in the SmartObject definition " ) , i ) ) ;
}
else
{
return false ;
}
2021-11-26 15:48:13 -05:00
}
}
}
2023-08-16 14:15:36 -04:00
bValid = ErrorsToReport = = nullptr | | ErrorsToReport - > IsEmpty ( ) ;
return bValid . GetValue ( ) ;
2021-11-26 15:48:13 -05:00
}
2022-03-02 22:33:53 -05:00
FBox USmartObjectDefinition : : GetBounds ( ) const
{
FBox BoundingBox ( ForceInitToZero ) ;
for ( const FSmartObjectSlotDefinition & Slot : GetSlots ( ) )
{
2023-07-18 08:42:51 -04:00
BoundingBox + = FVector ( Slot . Offset ) + UE : : SmartObject : : DefaultSlotSize ;
BoundingBox + = FVector ( Slot . Offset ) - UE : : SmartObject : : DefaultSlotSize ;
2022-03-02 22:33:53 -05:00
}
return BoundingBox ;
}
2023-07-18 08:42:51 -04:00
void USmartObjectDefinition : : GetSlotActivityTags ( const int32 SlotIndex , FGameplayTagContainer & OutActivityTags ) const
2022-03-02 22:33:53 -05:00
{
if ( ensureMsgf ( Slots . IsValidIndex ( SlotIndex ) , TEXT ( " Requesting activity tags for an out of range slot index: %s " ) , * LexToString ( SlotIndex ) ) )
{
GetSlotActivityTags ( Slots [ SlotIndex ] , OutActivityTags ) ;
}
}
void USmartObjectDefinition : : GetSlotActivityTags ( const FSmartObjectSlotDefinition & SlotDefinition , FGameplayTagContainer & OutActivityTags ) const
{
OutActivityTags = ActivityTags ;
if ( ActivityTagsMergingPolicy = = ESmartObjectTagMergingPolicy : : Combine )
{
OutActivityTags . AppendTags ( SlotDefinition . ActivityTags ) ;
}
else if ( ActivityTagsMergingPolicy = = ESmartObjectTagMergingPolicy : : Override & & ! SlotDefinition . ActivityTags . IsEmpty ( ) )
{
OutActivityTags = SlotDefinition . ActivityTags ;
}
}
2023-07-18 08:42:51 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2022-03-02 22:33:53 -05:00
TOptional < FTransform > USmartObjectDefinition : : GetSlotTransform ( const FTransform & OwnerTransform , const FSmartObjectSlotIndex SlotIndex ) const
{
TOptional < FTransform > Transform ;
if ( ensureMsgf ( Slots . IsValidIndex ( SlotIndex ) , TEXT ( " Requesting slot transform for an out of range index: %s " ) , * LexToString ( SlotIndex ) ) )
{
const FSmartObjectSlotDefinition & Slot = Slots [ SlotIndex ] ;
2023-07-18 08:42:51 -04:00
Transform = FTransform ( FRotator ( Slot . Rotation ) , FVector ( Slot . Offset ) ) * OwnerTransform ;
2022-03-02 22:33:53 -05:00
}
return Transform ;
}
2023-07-18 08:42:51 -04:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2022-03-02 22:33:53 -05:00
2023-07-18 08:42:51 -04:00
FTransform USmartObjectDefinition : : GetSlotWorldTransform ( const int32 SlotIndex , const FTransform & OwnerTransform ) const
{
if ( ensureMsgf ( Slots . IsValidIndex ( SlotIndex ) , TEXT ( " Requesting slot transform for an out of range index: %s " ) , * LexToString ( SlotIndex ) ) )
{
const FSmartObjectSlotDefinition & Slot = Slots [ SlotIndex ] ;
return FTransform ( FRotator ( Slot . Rotation ) , FVector ( Slot . Offset ) ) * OwnerTransform ;
}
return OwnerTransform ;
}
2022-03-02 22:33:53 -05:00
2023-07-18 08:42:51 -04:00
const USmartObjectBehaviorDefinition * USmartObjectDefinition : : GetBehaviorDefinition ( const int32 SlotIndex ,
2022-03-02 13:25:37 -05:00
const TSubclassOf < USmartObjectBehaviorDefinition > & DefinitionClass ) const
2021-11-26 15:48:13 -05:00
{
const USmartObjectBehaviorDefinition * Definition = nullptr ;
if ( Slots . IsValidIndex ( SlotIndex ) )
{
Definition = GetBehaviorDefinitionByType ( Slots [ SlotIndex ] . BehaviorDefinitions , DefinitionClass ) ;
}
if ( Definition = = nullptr )
{
Definition = GetBehaviorDefinitionByType ( DefaultBehaviorDefinitions , DefinitionClass ) ;
}
return Definition ;
}
const USmartObjectBehaviorDefinition * USmartObjectDefinition : : GetBehaviorDefinitionByType ( const TArray < USmartObjectBehaviorDefinition * > & BehaviorDefinitions ,
const TSubclassOf < USmartObjectBehaviorDefinition > & DefinitionClass )
{
2023-01-18 10:52:51 -05:00
USmartObjectBehaviorDefinition * const * BehaviorDefinition = BehaviorDefinitions . FindByPredicate ( [ & DefinitionClass ] ( const USmartObjectBehaviorDefinition * SlotBehaviorDefinition )
2021-11-26 15:48:13 -05:00
{
return SlotBehaviorDefinition ! = nullptr & & SlotBehaviorDefinition - > GetClass ( ) - > IsChildOf ( * DefinitionClass ) ;
} ) ;
return BehaviorDefinition ! = nullptr ? * BehaviorDefinition : nullptr ;
}
2022-11-01 15:11:25 -04:00
# if WITH_EDITOR
int32 USmartObjectDefinition : : FindSlotByID ( const FGuid ID ) const
{
const int32 Slot = Slots . IndexOfByPredicate ( [ & ID ] ( const FSmartObjectSlotDefinition & Slot ) { return Slot . ID = = ID ; } ) ;
return Slot ;
}
2022-09-28 01:06:15 -04:00
2023-08-29 07:48:32 -04:00
bool USmartObjectDefinition : : FindSlotAndDefinitionDataIndexByID ( const FGuid ID , int32 & OutSlotIndex , int32 & OutDefinitionDataIndex ) const
{
OutSlotIndex = INDEX_NONE ;
OutDefinitionDataIndex = INDEX_NONE ;
// First try to find direct match on a slot.
for ( TConstEnumerateRef < const FSmartObjectSlotDefinition > SlotDefinition : EnumerateRange ( Slots ) )
{
if ( SlotDefinition - > ID = = ID )
{
OutSlotIndex = SlotDefinition . GetIndex ( ) ;
return true ;
}
// Next try to find slot index based on definition data.
2023-12-04 07:36:52 -05:00
const int32 DefinitionDataIndex = SlotDefinition - > DefinitionData . IndexOfByPredicate ( [ & ID ] ( const FSmartObjectDefinitionDataProxy & DataProxy )
2023-08-29 07:48:32 -04:00
{
return DataProxy . ID = = ID ;
} ) ;
if ( DefinitionDataIndex ! = INDEX_NONE )
{
OutSlotIndex = SlotDefinition . GetIndex ( ) ;
OutDefinitionDataIndex = DefinitionDataIndex ;
return true ;
}
}
return false ;
}
2022-11-01 15:11:25 -04:00
void USmartObjectDefinition : : PostEditChangeChainProperty ( FPropertyChangedChainEvent & PropertyChangedEvent )
{
Super : : PostEditChangeChainProperty ( PropertyChangedEvent ) ;
2023-08-29 07:48:32 -04:00
const FSmartObjectEditPropertyPath ChangePropertyPath ( PropertyChangedEvent ) ;
static const FSmartObjectEditPropertyPath SlotsPath ( USmartObjectDefinition : : StaticClass ( ) , TEXT ( " Slots " ) ) ;
static const FSmartObjectEditPropertyPath WorldConditionSchemaClassPath ( USmartObjectDefinition : : StaticClass ( ) , TEXT ( " WorldConditionSchemaClass " ) ) ;
static const FSmartObjectEditPropertyPath SlotsDefinitionDataPath ( USmartObjectDefinition : : StaticClass ( ) , TEXT ( " Slots.DefinitionData " ) ) ;
2022-11-01 15:11:25 -04:00
// Ensure unique Slot ID on added or duplicated items.
if ( PropertyChangedEvent . ChangeType = = EPropertyChangeType : : ArrayAdd
| | PropertyChangedEvent . ChangeType = = EPropertyChangeType : : Duplicate )
{
2023-08-29 07:48:32 -04:00
if ( ChangePropertyPath . IsPathExact ( SlotsPath ) )
2022-11-01 15:11:25 -04:00
{
2023-08-29 07:48:32 -04:00
const int32 SlotIndex = ChangePropertyPath . GetPropertyArrayIndex ( SlotsPath ) ;
if ( Slots . IsValidIndex ( SlotIndex ) )
2022-11-01 15:11:25 -04:00
{
2023-08-29 07:48:32 -04:00
FSmartObjectSlotDefinition & SlotDefinition = Slots [ SlotIndex ] ;
SlotDefinition . ID = FGuid : : NewGuid ( ) ;
SlotDefinition . SelectionPreconditions . SetSchemaClass ( WorldConditionSchemaClass ) ;
// Set new IDs to all duplicated data too
2023-12-04 07:36:52 -05:00
for ( FSmartObjectDefinitionDataProxy & DataProxy : SlotDefinition . DefinitionData )
2023-08-29 07:48:32 -04:00
{
DataProxy . ID = FGuid : : NewGuid ( ) ;
}
}
}
if ( ChangePropertyPath . IsPathExact ( SlotsDefinitionDataPath ) )
{
const int32 SlotIndex = ChangePropertyPath . GetPropertyArrayIndex ( SlotsPath ) ;
if ( Slots . IsValidIndex ( SlotIndex ) )
{
FSmartObjectSlotDefinition & SlotDefinition = Slots [ SlotIndex ] ;
const int32 DataIndex = ChangePropertyPath . GetPropertyArrayIndex ( SlotsDefinitionDataPath ) ;
if ( SlotDefinition . DefinitionData . IsValidIndex ( DataIndex ) )
{
2023-12-04 07:36:52 -05:00
FSmartObjectDefinitionDataProxy & DataProxy = SlotDefinition . DefinitionData [ DataIndex ] ;
2023-08-29 07:48:32 -04:00
DataProxy . ID = FGuid : : NewGuid ( ) ;
}
2022-11-01 15:11:25 -04:00
}
}
}
// Anything in the slots changed, update references.
2023-08-29 07:48:32 -04:00
if ( ChangePropertyPath . ContainsPath ( SlotsPath ) )
2022-11-01 15:11:25 -04:00
{
UpdateSlotReferences ( ) ;
}
2022-11-04 06:56:50 -04:00
2022-11-17 07:44:24 -05:00
// If schema changes, update preconditions too.
2023-08-29 07:48:32 -04:00
if ( ChangePropertyPath . IsPathExact ( WorldConditionSchemaClassPath ) )
2022-11-01 15:11:25 -04:00
{
2022-11-17 07:44:24 -05:00
for ( FSmartObjectSlotDefinition & Slot : Slots )
2022-11-01 15:11:25 -04:00
{
2023-01-26 06:15:02 -05:00
Slot . SelectionPreconditions . SetSchemaClass ( WorldConditionSchemaClass ) ;
2023-03-02 12:12:47 -05:00
Slot . SelectionPreconditions . Initialize ( this ) ;
2022-11-01 15:11:25 -04:00
}
}
2022-11-04 06:56:50 -04:00
Validate ( ) ;
2022-11-01 15:11:25 -04:00
}
void USmartObjectDefinition : : PreSave ( FObjectPreSaveContext SaveContext )
{
2022-11-17 07:44:24 -05:00
for ( FSmartObjectSlotDefinition & Slot : Slots )
{
2023-03-02 12:12:47 -05:00
Slot . SelectionPreconditions . Initialize ( this ) ;
2022-11-17 07:44:24 -05:00
}
2022-11-01 15:11:25 -04:00
UpdateSlotReferences ( ) ;
Super : : PreSave ( SaveContext ) ;
2023-12-20 08:17:55 -05:00
# if WITH_EDITOR
if ( SaveContext . IsCooking ( )
& & SaveContext . GetTargetPlatform ( ) - > IsClientOnly ( )
& & GetDefault < USmartObjectSettings > ( ) - > bShouldExcludePreConditionsOnDedicatedClient
& & ! HasAnyFlags ( RF_ArchetypeObject | RF_ClassDefaultObject ) )
{
FObjectSaveOverride ObjSaveOverride ;
// Add path to the conditions within the main definition
FProperty * OverrideProperty = FindFProperty < FProperty > ( GetClass ( ) , GET_MEMBER_NAME_CHECKED ( USmartObjectDefinition , Preconditions ) ) ;
check ( OverrideProperty ) ;
FPropertySaveOverride PropOverride ;
PropOverride . PropertyPath = FFieldPath ( OverrideProperty ) ;
PropOverride . bMarkTransient = true ;
ObjSaveOverride . PropOverrides . Add ( PropOverride ) ;
// Add path to the conditions within the slot definition struct
OverrideProperty = FindFProperty < FProperty > ( FSmartObjectSlotDefinition : : StaticStruct ( ) , GET_MEMBER_NAME_CHECKED ( FSmartObjectSlotDefinition , SelectionPreconditions ) ) ;
check ( OverrideProperty ) ;
PropOverride . PropertyPath = FFieldPath ( OverrideProperty ) ;
ObjSaveOverride . PropOverrides . Add ( PropOverride ) ;
SaveContext . AddSaveOverride ( this , ObjSaveOverride ) ;
}
# endif // WITH_EDITOR
2022-11-01 15:11:25 -04:00
}
void USmartObjectDefinition : : UpdateSlotReferences ( )
{
for ( FSmartObjectSlotDefinition & Slot : Slots )
{
2023-12-04 07:36:52 -05:00
for ( FSmartObjectDefinitionDataProxy & DataProxy : Slot . DefinitionData )
2022-11-01 15:11:25 -04:00
{
2023-08-29 07:48:32 -04:00
if ( ! DataProxy . Data . IsValid ( ) )
2022-11-01 15:11:25 -04:00
{
continue ;
}
2023-08-29 07:48:32 -04:00
const UScriptStruct * ScriptStruct = DataProxy . Data . GetScriptStruct ( ) ;
uint8 * Memory = DataProxy . Data . GetMutableMemory ( ) ;
2022-11-01 15:11:25 -04:00
for ( TFieldIterator < FProperty > It ( ScriptStruct ) ; It ; + + It )
{
2023-01-18 10:52:51 -05:00
if ( const FStructProperty * StructProp = CastField < FStructProperty > ( * It ) )
2022-11-01 15:11:25 -04:00
{
if ( StructProp - > Struct = = TBaseStructure < FSmartObjectSlotReference > : : Get ( ) )
{
FSmartObjectSlotReference & Ref = * StructProp - > ContainerPtrToValuePtr < FSmartObjectSlotReference > ( Memory ) ;
const int32 Index = FindSlotByID ( Ref . GetSlotID ( ) ) ;
Ref . SetIndex ( Index ) ;
}
}
}
}
}
}
2022-11-17 07:44:24 -05:00
# endif // WITH_EDITOR
void USmartObjectDefinition : : PostLoad ( )
{
Super : : PostLoad ( ) ;
// Fill in missing world condition schema for old data.
if ( ! WorldConditionSchemaClass )
{
WorldConditionSchemaClass = GetDefault < USmartObjectSettings > ( ) - > DefaultWorldConditionSchemaClass ;
}
2023-01-18 10:52:51 -05:00
2023-01-26 06:15:02 -05:00
if ( Preconditions . GetSchemaClass ( ) . Get ( ) = = nullptr )
2023-01-18 10:52:51 -05:00
{
2023-01-26 06:15:02 -05:00
Preconditions . SetSchemaClass ( WorldConditionSchemaClass ) ;
2023-01-18 10:52:51 -05:00
}
# if WITH_EDITOR
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if ( ! ObjectTagFilter . IsEmpty ( ) )
{
FWorldCondition_SmartObjectActorTagQuery NewActorTagQueryCondition ;
NewActorTagQueryCondition . TagQuery = ObjectTagFilter ;
2023-01-26 06:15:02 -05:00
Preconditions . AddCondition ( FWorldConditionEditable ( 0 , EWorldConditionOperator : : And , FConstStructView : : Make ( NewActorTagQueryCondition ) ) ) ;
2023-01-18 10:52:51 -05:00
ObjectTagFilter . Clear ( ) ;
UE_ASSET_LOG ( LogSmartObject , Log , this , TEXT ( " Deprecated object tag filter has been replaced by a %s precondition to validate tags on the smart object actor. "
" If the intent was to validate against instance runtime tags then the condition should be replaced by %s. " ) ,
* FWorldCondition_SmartObjectActorTagQuery : : StaticStruct ( ) - > GetName ( ) ,
* FSmartObjectWorldConditionObjectTagQuery : : StaticStruct ( ) - > GetName ( ) ) ;
}
2023-03-27 08:22:19 -04:00
if ( PreviewClass_DEPRECATED . IsValid ( ) )
{
PreviewData . ObjectActorClass = PreviewClass_DEPRECATED ;
PreviewClass_DEPRECATED . Reset ( ) ;
}
if ( PreviewMeshPath_DEPRECATED . IsValid ( ) )
{
PreviewData . ObjectMeshPath = PreviewMeshPath_DEPRECATED ;
PreviewMeshPath_DEPRECATED . Reset ( ) ;
}
2023-08-29 07:48:32 -04:00
for ( FSmartObjectSlotDefinition & Slot : Slots )
{
if ( Slot . Data_DEPRECATED . Num ( ) > 0 )
{
Slot . DefinitionData . Reserve ( Slot . Data_DEPRECATED . Num ( ) ) ;
for ( const FInstancedStruct & Data : Slot . Data_DEPRECATED )
{
2023-12-04 07:36:52 -05:00
FSmartObjectDefinitionDataProxy & DataProxy = Slot . DefinitionData . AddDefaulted_GetRef ( ) ;
2023-08-29 07:48:32 -04:00
DataProxy . Data . InitializeAsScriptStruct ( Data . GetScriptStruct ( ) , Data . GetMemory ( ) ) ;
DataProxy . ID = FGuid : : NewGuid ( ) ;
}
Slot . Data_DEPRECATED . Reset ( ) ;
}
}
2023-01-18 10:52:51 -05:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
# endif
2023-03-02 12:12:47 -05:00
Preconditions . Initialize ( this ) ;
2022-11-17 07:44:24 -05:00
for ( FSmartObjectSlotDefinition & Slot : Slots )
{
# if WITH_EDITOR
// Fill in missing slot ID for old data.
if ( ! Slot . ID . IsValid ( ) )
{
Slot . ID = FGuid : : NewGuid ( ) ;
}
# endif
// Fill in missing world condition schema for old data.
2023-01-26 06:15:02 -05:00
if ( Slot . SelectionPreconditions . GetSchemaClass ( ) . Get ( ) = = nullptr )
2022-11-17 07:44:24 -05:00
{
2023-01-26 06:15:02 -05:00
Slot . SelectionPreconditions . SetSchemaClass ( WorldConditionSchemaClass ) ;
2022-11-17 07:44:24 -05:00
}
2023-03-02 12:12:47 -05:00
Slot . SelectionPreconditions . Initialize ( this ) ;
2022-11-17 07:44:24 -05:00
}
# if WITH_EDITOR
UpdateSlotReferences ( ) ;
Validate ( ) ;
# endif
}
2023-01-23 18:48:38 -05:00
# undef LOCTEXT_NAMESPACE