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"
2023-06-27 09:07:17 -04:00
# include "StateTreeExecutionTypes.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"
2023-02-09 04:20:54 -05:00
# include "StateTree.h"
# include "Serialization/ObjectAndNameAsStringProxyArchive.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
2023-02-09 04:20:54 -05:00
// FObjectAndNameAsStringProxyArchive is used to store and restore names and objects as memory writer does not support UObject references at all.
2022-12-05 03:19:45 -05:00
TArray < uint8 > Data ;
FMemoryWriter Writer ( Data ) ;
2023-02-09 04:20:54 -05:00
FObjectAndNameAsStringProxyArchive WriterProxy ( Writer , /*bInLoadIfFindFails*/ true ) ;
2022-12-05 03:19:45 -05:00
UObject & NonConstInstance = const_cast < UObject & > ( Instance ) ;
2023-02-09 04:20:54 -05:00
NonConstInstance . Serialize ( WriterProxy ) ;
2022-12-05 03:19:45 -05:00
FMemoryReader Reader ( Data ) ;
2023-02-09 04:20:54 -05:00
FObjectAndNameAsStringProxyArchive ReaderProxy ( Reader , /*bInLoadIfFindFails*/ true ) ;
NewInstance - > Serialize ( ReaderProxy ) ;
const UStateTree * OuterStateTree = Instance . GetTypedOuter < UStateTree > ( ) ;
UE_LOG ( LogStateTree , Display , TEXT ( " FStateTreeInstanceData: Duplicating '%s' with old class '%s' as '%s', potential data loss. Please resave State Tree asset %s. " ) ,
* GetFullNameSafe ( & Instance ) , * GetNameSafe ( InstanceClass ) , * GetNameSafe ( AuthoritativeClass ) , * GetFullNameSafe ( OuterStateTree ) ) ;
2022-12-05 03:19:45 -05:00
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-03-09 06:35:16 -05:00
bool FStateTreeInstanceStorage : : AreAllInstancesValid ( ) const
{
for ( FConstStructView Instance : InstanceStructs )
{
if ( ! Instance . IsValid ( ) )
{
return false ;
}
2023-11-17 07:41:08 -05:00
if ( const FStateTreeInstanceObjectWrapper * Wrapper = Instance . GetPtr < const FStateTreeInstanceObjectWrapper > ( ) )
2023-03-09 06:35:16 -05:00
{
2023-11-17 07:41:08 -05:00
if ( ! Wrapper - > InstanceObject )
{
return false ;
}
2023-03-09 06:35:16 -05:00
}
}
return true ;
}
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 ( ) ;
}
const FStateTreeInstanceStorage & FStateTreeInstanceData : : GetStorage ( ) const
{
2023-11-17 07:41:08 -05:00
check ( InstanceStorage . GetMemory ( ) ! = nullptr ) ;
2022-11-30 07:17:26 -05:00
return * reinterpret_cast < const FStateTreeInstanceStorage * > ( InstanceStorage . GetMemory ( ) ) ;
}
FStateTreeInstanceStorage & FStateTreeInstanceData : : GetMutableStorage ( )
{
2023-11-17 07:41:08 -05:00
check ( InstanceStorage . GetMemory ( ) ! = nullptr ) ;
2022-11-30 07:17:26 -05:00
return * reinterpret_cast < FStateTreeInstanceStorage * > ( InstanceStorage . GetMutableMemory ( ) ) ;
}
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 ( ) ;
}
2023-03-09 06:35:16 -05:00
bool FStateTreeInstanceData : : AreAllInstancesValid ( ) const
{
return GetStorage ( ) . AreAllInstancesValid ( ) ;
}
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
2023-11-17 07:41:08 -05:00
for ( FConstStructView Instance : Storage . InstanceStructs )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( const FStateTreeInstanceObjectWrapper * Wrapper = Instance . GetPtr < const FStateTreeInstanceObjectWrapper > ( ) )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( Wrapper - > InstanceObject )
{
Size + = Wrapper - > InstanceObject - > GetClass ( ) - > GetStructureSize ( ) ;
}
2022-08-10 16:03:37 +00:00
}
}
return Size ;
}
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 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 ;
2023-11-17 07:41:08 -05:00
for ( int32 Index = 0 ; Index < Storage . InstanceStructs . Num ( ) ; Index + + )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
const FStateTreeInstanceObjectWrapper * Wrapper = Storage . InstanceStructs [ Index ] . GetPtr < const FStateTreeInstanceObjectWrapper > ( ) ;
const FStateTreeInstanceObjectWrapper * OtherWrapper = OtherStorage . InstanceStructs [ Index ] . GetPtr < const FStateTreeInstanceObjectWrapper > ( ) ;
if ( Wrapper )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( ! OtherWrapper )
2022-08-10 16:03:37 +00:00
{
bResult = false ;
break ;
}
2023-11-17 07:41:08 -05:00
if ( Wrapper - > InstanceObject & & OtherWrapper - > InstanceObject )
{
if ( ! AreObjectsIdentical ( Wrapper - > InstanceObject , OtherWrapper - > InstanceObject , PortFlags ) )
{
bResult = false ;
break ;
}
}
2022-08-10 16:03:37 +00:00
}
}
return bResult ;
}
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.
2023-11-17 07:41:08 -05:00
for ( FStructView Instance : Storage . InstanceStructs )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( FStateTreeInstanceObjectWrapper * Wrapper = Instance . GetPtr < FStateTreeInstanceObjectWrapper > ( ) )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( Wrapper - > InstanceObject )
{
Wrapper - > InstanceObject = UE : : StateTree : : DuplicateNodeInstance ( * Wrapper - > InstanceObject , InOwner ) ;
}
2022-08-10 16:03:37 +00:00
}
}
}
2023-11-17 07:41:08 -05:00
void FStateTreeInstanceData : : Init ( UObject & InOwner , TConstArrayView < FInstancedStruct > InStructs )
2022-08-10 16:03:37 +00:00
{
Reset ( ) ;
2023-11-17 07:41:08 -05:00
Append ( InOwner , InStructs ) ;
2022-08-10 16:03:37 +00:00
}
2023-11-17 07:41:08 -05:00
void FStateTreeInstanceData : : Init ( UObject & InOwner , TConstArrayView < FConstStructView > InStructs )
2022-08-10 16:03:37 +00:00
{
Reset ( ) ;
2023-11-17 07:41:08 -05:00
Append ( InOwner , InStructs ) ;
2022-08-10 16:03:37 +00:00
}
2023-11-17 07:41:08 -05:00
void FStateTreeInstanceData : : Append ( UObject & InOwner , TConstArrayView < FInstancedStruct > InStructs )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
2023-11-17 07:41:08 -05:00
const int32 StartIndex = Storage . InstanceStructs . Num ( ) ;
2022-11-30 07:17:26 -05:00
Storage . InstanceStructs . Append ( InStructs ) ;
2023-11-17 07:41:08 -05:00
for ( int32 Index = StartIndex ; Index < Storage . InstanceStructs . Num ( ) ; Index + + )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( FStateTreeInstanceObjectWrapper * Wrapper = Storage . InstanceStructs [ Index ] . GetPtr < FStateTreeInstanceObjectWrapper > ( ) )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( Wrapper - > InstanceObject )
{
Wrapper - > InstanceObject = UE : : StateTree : : DuplicateNodeInstance ( * Wrapper - > InstanceObject , InOwner ) ;
}
2022-08-10 16:03:37 +00:00
}
}
}
2023-11-17 07:41:08 -05:00
void FStateTreeInstanceData : : Append ( UObject & InOwner , TConstArrayView < FConstStructView > InStructs )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
2023-11-17 07:41:08 -05:00
const int32 StartIndex = Storage . InstanceStructs . Num ( ) ;
2022-11-30 07:17:26 -05:00
Storage . InstanceStructs . Append ( InStructs ) ;
2022-08-10 16:03:37 +00:00
2023-11-17 07:41:08 -05:00
for ( int32 Index = StartIndex ; Index < Storage . InstanceStructs . Num ( ) ; Index + + )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( FStateTreeInstanceObjectWrapper * Wrapper = Storage . InstanceStructs [ Index ] . GetPtr < FStateTreeInstanceObjectWrapper > ( ) )
2022-08-10 16:03:37 +00:00
{
2023-11-17 07:41:08 -05:00
if ( Wrapper - > InstanceObject )
{
Wrapper - > InstanceObject = UE : : StateTree : : DuplicateNodeInstance ( * Wrapper - > InstanceObject , InOwner ) ;
}
2022-08-10 16:03:37 +00:00
}
}
}
2023-11-17 07:41:08 -05:00
void FStateTreeInstanceData : : ShrinkTo ( const int32 NumStructs )
2022-08-10 16:03:37 +00:00
{
2022-11-30 07:17:26 -05:00
FStateTreeInstanceStorage & Storage = GetMutableStorage ( ) ;
2023-11-17 07:41:08 -05:00
check ( NumStructs < = Storage . InstanceStructs . Num ( ) ) ;
2022-11-30 07:17:26 -05:00
Storage . InstanceStructs . SetNum ( NumStructs ) ;
}
bool FStateTreeInstanceData : : IsValid ( ) const
{
2023-11-17 07:41:08 -05:00
return InstanceStorage . 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 . EventQueue . Reset ( ) ;
2023-11-17 07:41:08 -05:00
ExecutionState . Reset ( ) ;
2022-08-10 16:03:37 +00:00
}