2022-09-28 01:06:15 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-08-10 16:03:37 +00:00
# include "StateTreeInstanceData.h"
2022-12-05 03:19:45 -05:00
# include "StateTreeTypes.h"
2022-12-05 05:01:48 -05:00
# include "Serialization/MemoryReader.h"
# include "Serialization/MemoryWriter.h"
2023-01-23 12:48:04 -05:00
# include "VisualLogger/VisualLogger.h"
2022-08-10 16:03:37 +00:00
2022-09-28 01:06:15 -04:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(StateTreeInstanceData)
2022-12-05 03:19:45 -05:00
namespace UE : : StateTree
{
/**
* Duplicates object , and tries to covert old BP classes ( REINST_ * ) to their newer version .
*/
UObject * DuplicateNodeInstance ( const UObject & Instance , UObject & InOwner )
{
const UClass * InstanceClass = Instance . GetClass ( ) ;
if ( InstanceClass - > HasAnyClassFlags ( CLASS_NewerVersionExists ) )
{
const UClass * AuthoritativeClass = InstanceClass - > GetAuthoritativeClass ( ) ;
UObject * NewInstance = NewObject < UObject > ( & InOwner , AuthoritativeClass ) ;
// Try to copy the values over using serialization
TArray < uint8 > Data ;
FMemoryWriter Writer ( Data ) ;
UObject & NonConstInstance = const_cast < UObject & > ( Instance ) ;
NonConstInstance . Serialize ( Writer ) ;
FMemoryReader Reader ( Data ) ;
NewInstance - > Serialize ( Reader ) ;
2023-01-24 00:27:06 -05:00
UE_LOG ( LogStateTree , Display , TEXT ( " FStateTreeInstanceData: Duplicating '%s' with old class '%s' as '%s', potential data loss. " ) ,
2022-12-05 03:19:45 -05:00
* GetFullNameSafe ( & Instance ) , * GetNameSafe ( InstanceClass ) , * GetNameSafe ( AuthoritativeClass ) ) ;
return NewInstance ;
}
return DuplicateObject ( & Instance , & InOwner ) ;
}
} // UE::StateTree
2023-01-23 12:48:04 -05:00
2022-08-10 16:03:37 +00:00
//----------------------------------------------------------------//
2023-01-23 12:48:04 -05:00
// FStateTreeInstanceStorage
//----------------------------------------------------------------//
void FStateTreeInstanceStorage : : AddTransitionRequest ( const UObject * Owner , const FStateTreeTransitionRequest & Request )
{
constexpr int32 MaxPendingTransitionRequests = 32 ;
if ( TransitionRequests . Num ( ) > = MaxPendingTransitionRequests )
{
UE_VLOG_UELOG ( Owner , LogStateTree , Error , TEXT ( " %s: Too many transition requests sent to '%s' (%d pending). Dropping request. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) , * GetNameSafe ( Owner ) , TransitionRequests . Num ( ) ) ;
return ;
}
TransitionRequests . Add ( Request ) ;
}
2023-01-24 15:07:59 -05:00
void FStateTreeInstanceStorage : : ResetTransitionRequests ( )
{
TransitionRequests . Reset ( ) ;
}
2023-01-23 12:48:04 -05:00
//----------------------------------------------------------------//
// FStateTreeInstanceData
2022-08-10 16:03:37 +00:00
//----------------------------------------------------------------//
2022-11-30 07:17:26 -05:00
FStateTreeInstanceData : : FStateTreeInstanceData ( )
2022-11-01 15:11:19 -04:00
{
2022-11-30 07:17:26 -05:00
InstanceStorage . InitializeAs < FStateTreeInstanceStorage > ( ) ;
}
FStateTreeInstanceData : : ~ FStateTreeInstanceData ( )
{
Reset ( ) ;
}
bool FStateTreeInstanceStorage : : IsValid ( ) const
{
return InstanceStructs . Num ( ) > 0 | | InstanceObjects . Num ( ) > 0 ;
}
const FStateTreeInstanceStorage & FStateTreeInstanceData : : GetStorage ( ) const
{
check ( InstanceStorage . GetMemory ( ) ! = nullptr & & InstanceStorage . GetScriptStruct ( ) = = TBaseStructure < FStateTreeInstanceStorage > : : Get ( ) ) ;
return * reinterpret_cast < const FStateTreeInstanceStorage * > ( InstanceStorage . GetMemory ( ) ) ;
}
FStateTreeInstanceStorage & FStateTreeInstanceData : : GetMutableStorage ( )
{
check ( InstanceStorage . GetMemory ( ) ! = nullptr & & InstanceStorage . GetScriptStruct ( ) = = TBaseStructure < FStateTreeInstanceStorage > : : Get ( ) ) ;
return * reinterpret_cast < FStateTreeInstanceStorage * > ( InstanceStorage . GetMutableMemory ( ) ) ;
}
2023-01-12 09:00:45 -05:00
const FStateTreeExecutionState * FStateTreeInstanceData : : GetExecutionState ( ) const
{
if ( ! IsValid ( ) )
{
return nullptr ;
}
const FConstStructView ExecView = GetStruct ( 0 ) ; // Execution state is fixed at index 0.
return ExecView . GetPtr < FStateTreeExecutionState > ( ) ;
}
2022-11-30 07:17:26 -05:00
TArray < FStateTreeEvent > & FStateTreeInstanceData : : GetEvents ( ) const
{
return const_cast < FStateTreeInstanceData * > ( this ) - > GetMutableStorage ( ) . EventQueue . GetEventsArray ( ) ;
}
FStateTreeEventQueue & FStateTreeInstanceData : : GetMutableEventQueue ( )
{
return GetMutableStorage ( ) . EventQueue ;
}
const FStateTreeEventQueue & FStateTreeInstanceData : : GetEventQueue ( ) const
{
return GetStorage ( ) . EventQueue ;
2022-11-01 15:11:19 -04:00
}
2023-01-23 12:48:04 -05:00
void FStateTreeInstanceData : : AddTransitionRequest ( const UObject * Owner , const FStateTreeTransitionRequest & Request )
{
GetMutableStorage ( ) . AddTransitionRequest ( Owner , Request ) ;
}
TConstArrayView < FStateTreeTransitionRequest > FStateTreeInstanceData : : GetTransitionRequests ( ) const
{
return GetStorage ( ) . GetTransitionRequests ( ) ;
}
void FStateTreeInstanceData : : ResetTransitionRequests ( )
{
GetMutableStorage ( ) . ResetTransitionRequests ( ) ;
}
2022-08-10 16:03:37 +00:00
int32 FStateTreeInstanceData : : GetEstimatedMemoryUsage ( ) const
{
2022-11-30 07:17:26 -05:00
const FStateTreeInstanceStorage & Storage = GetStorage ( ) ;
2022-08-10 16:03:37 +00:00
int32 Size = sizeof ( FStateTreeInstanceData ) ;
2022-11-30 07:17:26 -05:00
Size + = Storage . InstanceStructs . GetAllocatedMemory ( ) ;
2022-08-10 16:03:37 +00:00
2022-11-30 07:17:26 -05:00
for ( const UObject * InstanceObject : Storage . InstanceObjects )
2022-08-10 16:03:37 +00:00
{
if ( InstanceObject )
{
Size + = InstanceObject - > GetClass ( ) - > GetStructureSize ( ) ;
}
}
return Size ;
}
int32 FStateTreeInstanceData : : GetNumItems ( ) const
{
2022-11-30 07:17:26 -05:00
const FStateTreeInstanceStorage & Storage = GetStorage ( ) ;
return Storage . InstanceStructs . Num ( ) + Storage . InstanceObjects . Num ( ) ;
2022-08-10 16:03:37 +00:00
}
bool FStateTreeInstanceData : : Identical ( const FStateTreeInstanceData * Other , uint32 PortFlags ) const
{
if ( Other = = nullptr )
{
return false ;
}
// Identical if both are uninitialized.
if ( ! IsValid ( ) & & ! Other - > IsValid ( ) )
{
return true ;
}
// Not identical if one is valid and other is not.
if ( IsValid ( ) ! = Other - > IsValid ( ) )
{
return false ;
}
2022-11-30 07:17:26 -05:00
const FStateTreeInstanceStorage & Storage = GetStorage ( ) ;
const FStateTreeInstanceStorage & OtherStorage = Other - > GetStorage ( ) ;
2022-08-10 16:03:37 +00:00
// Not identical if different amount of instanced objects.
2022-11-30 07:17:26 -05:00
if ( Storage . InstanceObjects . Num ( ) ! = OtherStorage . InstanceObjects . Num ( ) )
2022-08-10 16:03:37 +00:00
{
return false ;
}
// Not identical if structs are different.
2022-11-30 07:17:26 -05:00
if ( Storage . InstanceStructs . Identical ( & OtherStorage . InstanceStructs , PortFlags ) = = false )
2022-08-10 16:03:37 +00:00
{
return false ;
}
// Check that the instance object contents are identical.
// Copied from object property.
2022-11-30 07:17:26 -05:00
auto AreObjectsIdentical = [ ] ( UObject * A , UObject * B , uint32 PortFlags ) - > bool
2022-08-10 16:03:37 +00:00
{
if ( ( PortFlags & PPF_DuplicateForPIE ) ! = 0 )
{
return false ;
}
if ( A = = B )
{
return true ;
}
// Resolve the object handles and run the deep comparison logic
if ( ( PortFlags & ( PPF_DeepCompareInstances | PPF_DeepComparison ) ) ! = 0 )
{
return FObjectPropertyBase : : StaticIdentical ( A , B , PortFlags ) ;
}
return true ;
} ;
bool bResult = true ;
2022-11-30 07:17:26 -05:00
for ( int32 Index = 0 ; Index < Storage . InstanceObjects . Num ( ) ; Index + + )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
if ( Storage . InstanceObjects [ Index ] ! = nullptr & & OtherStorage . InstanceObjects [ Index ] ! = nullptr )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
if ( ! AreObjectsIdentical ( Storage . InstanceObjects [ Index ] , OtherStorage . InstanceObjects [ Index ] , PortFlags ) )
2022-08-10 16:03:37 +00:00
{
bResult = false ;
break ;
}
}
else
{
bResult = false ;
break ;
}
}
return bResult ;
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : PostSerialize ( const FArchive & Ar )
{
# if WITH_EDITORONLY_DATA
if ( Ar . IsLoading ( ) )
{
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if ( InstanceStructs_DEPRECATED . Num ( ) > 0 | | InstanceObjects_DEPRECATED . Num ( ) > 0 )
{
if ( ! Storage . IsValid ( ) )
{
Storage . InstanceStructs . Reset ( ) ;
Storage . InstanceStructs . Append ( InstanceStructs_DEPRECATED ) ;
Storage . InstanceObjects = InstanceObjects_DEPRECATED ;
}
InstanceStructs_DEPRECATED . Reset ( ) ;
InstanceObjects_DEPRECATED . Reset ( ) ;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
# endif
}
2022-08-10 16:03:37 +00:00
void FStateTreeInstanceData : : CopyFrom ( UObject & InOwner , const FStateTreeInstanceData & InOther )
{
if ( & InOther = = this )
{
return ;
}
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
const FStateTreeInstanceStorage & OtherStorage = InOther . GetStorage ( ) ;
2022-08-10 16:03:37 +00:00
// Copy structs
2022-11-30 07:17:26 -05:00
Storage . InstanceStructs = OtherStorage . InstanceStructs ;
2022-08-10 16:03:37 +00:00
// Copy instance objects.
2022-11-30 07:17:26 -05:00
Storage . InstanceObjects . Reset ( ) ;
for ( const UObject * Instance : OtherStorage . InstanceObjects )
2022-08-10 16:03:37 +00:00
{
if ( ensure ( Instance ! = nullptr ) )
{
2022-12-05 03:19:45 -05:00
Storage . InstanceObjects . Add ( UE : : StateTree : : DuplicateNodeInstance ( * Instance , InOwner ) ) ;
2022-08-10 16:03:37 +00:00
}
}
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : Init ( UObject & InOwner , TConstArrayView < FInstancedStruct > InStructs , TConstArrayView < const UObject * > InObjects )
2022-08-10 16:03:37 +00:00
{
Reset ( ) ;
Append ( InOwner , InStructs , InObjects ) ;
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : Init ( UObject & InOwner , TConstArrayView < FConstStructView > InStructs , TConstArrayView < const UObject * > InObjects )
2022-08-10 16:03:37 +00:00
{
Reset ( ) ;
Append ( InOwner , InStructs , InObjects ) ;
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : Append ( UObject & InOwner , TConstArrayView < FInstancedStruct > InStructs , TConstArrayView < const UObject * > InObjects )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
Storage . InstanceStructs . Append ( InStructs ) ;
2022-08-10 16:03:37 +00:00
2022-11-30 07:17:26 -05:00
Storage . InstanceObjects . Reserve ( Storage . InstanceObjects . Num ( ) + InObjects . Num ( ) ) ;
2022-08-10 16:03:37 +00:00
for ( const UObject * Instance : InObjects )
{
if ( ensure ( Instance ! = nullptr ) )
{
2022-12-05 03:19:45 -05:00
Storage . InstanceObjects . Add ( UE : : StateTree : : DuplicateNodeInstance ( * Instance , InOwner ) ) ;
2022-08-10 16:03:37 +00:00
}
}
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : Append ( UObject & InOwner , TConstArrayView < FConstStructView > InStructs , TConstArrayView < const UObject * > InObjects )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
Storage . InstanceStructs . Append ( InStructs ) ;
2022-08-10 16:03:37 +00:00
2022-11-30 07:17:26 -05:00
Storage . InstanceObjects . Reserve ( Storage . InstanceObjects . Num ( ) + InObjects . Num ( ) ) ;
2022-08-10 16:03:37 +00:00
for ( const UObject * Instance : InObjects )
{
if ( ensure ( Instance ! = nullptr ) )
{
2022-12-05 03:19:45 -05:00
Storage . InstanceObjects . Add ( UE : : StateTree : : DuplicateNodeInstance ( * Instance , InOwner ) ) ;
2022-08-10 16:03:37 +00:00
}
}
}
2022-11-30 07:17:26 -05:00
void FStateTreeInstanceData : : ShrinkTo ( const int32 NumStructs , const int32 NumObjects )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
check ( NumStructs < = Storage . InstanceStructs . Num ( ) & & NumObjects < = Storage . InstanceObjects . Num ( ) ) ;
Storage . InstanceStructs . SetNum ( NumStructs ) ;
Storage . InstanceObjects . SetNum ( NumObjects ) ;
}
bool FStateTreeInstanceData : : IsValid ( ) const
{
if ( ! InstanceStorage . IsValid ( ) )
{
return false ;
}
return GetStorage ( ) . IsValid ( ) ;
2022-08-10 16:03:37 +00:00
}
void FStateTreeInstanceData : : Reset ( )
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
Storage . InstanceStructs . Reset ( ) ;
Storage . InstanceObjects . Reset ( ) ;
Storage . EventQueue . Reset ( ) ;
2022-08-10 16:03:37 +00:00
}