2024-01-11 04:24:45 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "StateTreePropertyRefHelpers.h"
# include "StateTreePropertyRef.h"
# include "UObject/TextProperty.h"
# include "UObject/EnumProperty.h"
# include "UObject/Class.h"
# include "StateTreePropertyBindings.h"
2024-02-14 09:04:52 -05:00
# if WITH_EDITOR
2024-01-11 04:24:45 -05:00
# include "EdGraphSchema_K2.h"
2024-02-14 09:04:52 -05:00
# include "IPropertyAccessEditor.h"
# include "EdGraph/EdGraphPin.h"
# endif
2024-01-11 04:24:45 -05:00
namespace UE : : StateTree : : PropertyRefHelpers
{
2024-02-14 09:04:52 -05:00
# if WITH_EDITOR
2024-01-11 04:24:45 -05:00
static const FName BoolName = TEXT ( " bool " ) ;
static const FName ByteName = TEXT ( " byte " ) ;
static const FName Int32Name = TEXT ( " int32 " ) ;
static const FName Int64Name = TEXT ( " int64 " ) ;
static const FName FloatName = TEXT ( " float " ) ;
static const FName DoubleName = TEXT ( " double " ) ;
static const FName NameName = TEXT ( " Name " ) ;
static const FName StringName = TEXT ( " String " ) ;
static const FName TextName = TEXT ( " Text " ) ;
2024-03-04 09:08:47 -05:00
const FName IsRefToArrayName = TEXT ( " IsRefToArray " ) ;
const FName CanRefToArrayName = TEXT ( " CanRefToArray " ) ;
const FName RefTypeName = TEXT ( " RefType " ) ;
2024-02-14 09:04:52 -05:00
static const FName IsOptionalName = TEXT ( " Optional " ) ;
2024-01-11 04:24:45 -05:00
2024-02-14 09:04:52 -05:00
bool ArePropertyRefsCompatible ( const FProperty & TargetRefProperty , const FProperty & SourceRefProperty , const void * TargetRefAddress , const void * SourceRefAddress )
2024-01-11 04:24:45 -05:00
{
2024-02-14 09:04:52 -05:00
check ( IsPropertyRef ( SourceRefProperty ) & & IsPropertyRef ( TargetRefProperty ) ) ;
check ( SourceRefAddress & & TargetRefAddress ) ;
FEdGraphPinType SourceRefPin = GetPropertyRefInternalTypeAsPin ( SourceRefProperty , SourceRefAddress ) ;
FEdGraphPinType TargetRefPin = GetPropertyRefInternalTypeAsPin ( TargetRefProperty , TargetRefAddress ) ;
return SourceRefPin . PinCategory = = TargetRefPin . PinCategory & & SourceRefPin . ContainerType = = TargetRefPin . ContainerType
& & SourceRefPin . PinSubCategoryObject = = TargetRefPin . PinSubCategoryObject ;
}
bool IsNativePropertyRefCompatibleWithProperty ( const FProperty & RefProperty , const FProperty & SourceProperty )
{
check ( IsPropertyRef ( RefProperty ) ) ;
2024-01-11 04:24:45 -05:00
const FProperty * TestProperty = & SourceProperty ;
2024-03-04 09:08:47 -05:00
const bool bCanTargetRefArray = RefProperty . HasMetaData ( CanRefToArrayName ) ;
2024-01-11 04:24:45 -05:00
const bool bIsTargetRefArray = RefProperty . HasMetaData ( IsRefToArrayName ) ;
2024-03-04 09:08:47 -05:00
if ( bIsTargetRefArray | | bCanTargetRefArray )
2024-01-11 04:24:45 -05:00
{
if ( const FArrayProperty * ArrayProperty = CastField < FArrayProperty > ( TestProperty ) )
{
TestProperty = ArrayProperty - > Inner ;
}
2024-03-04 09:08:47 -05:00
else if ( ! bCanTargetRefArray )
2024-01-11 04:24:45 -05:00
{
return false ;
}
}
2024-03-04 09:08:47 -05:00
FString TargetTypeNameFullStr = RefProperty . GetMetaData ( RefTypeName ) ;
if ( TargetTypeNameFullStr . IsEmpty ( ) )
2024-01-11 04:24:45 -05:00
{
return false ;
}
2024-03-04 09:08:47 -05:00
TargetTypeNameFullStr . RemoveSpacesInline ( ) ;
2024-01-11 04:24:45 -05:00
2024-03-04 09:08:47 -05:00
TArray < FString > TargetTypes ;
TargetTypeNameFullStr . ParseIntoArray ( TargetTypes , TEXT ( " , " ) , true ) ;
const FStructProperty * SourceStructProperty = CastField < FStructProperty > ( TestProperty ) ;
// Check inside loop are only allowed to return true to avoid shortcircuiting the loop.
for ( const FString & TargetTypeNameStr : TargetTypes )
2024-01-11 04:24:45 -05:00
{
2024-03-04 09:08:47 -05:00
const FName TargetTypeName = FName ( * TargetTypeNameStr ) ;
// Compare properties metadata directly if SourceProperty is PropertyRef as well
if ( SourceStructProperty & & SourceStructProperty - > Struct = = FStateTreePropertyRef : : StaticStruct ( ) )
2024-01-11 04:24:45 -05:00
{
2024-03-04 09:08:47 -05:00
const FName SourceTypeName ( SourceStructProperty - > GetMetaData ( RefTypeName ) ) ;
const bool bIsSourceRefArray = SourceStructProperty - > GetBoolMetaData ( IsRefToArrayName ) ;
if ( SourceTypeName = = TargetTypeName & & bIsSourceRefArray = = bIsTargetRefArray )
{
return true ;
}
2024-01-11 04:24:45 -05:00
}
2024-03-04 09:08:47 -05:00
if ( TargetTypeName = = BoolName )
2024-01-11 04:24:45 -05:00
{
2024-03-04 09:08:47 -05:00
if ( TestProperty - > IsA < FBoolProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = ByteName )
{
if ( TestProperty - > IsA < FByteProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = Int32Name )
{
if ( TestProperty - > IsA < FIntProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = Int64Name )
{
if ( TestProperty - > IsA < FInt64Property > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = FloatName )
{
if ( TestProperty - > IsA < FFloatProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = DoubleName )
{
if ( TestProperty - > IsA < FDoubleProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = NameName )
{
if ( TestProperty - > IsA < FNameProperty > ( ) )
{
return true ;
}
2024-01-11 04:24:45 -05:00
}
2024-03-04 09:08:47 -05:00
else if ( TargetTypeName = = StringName )
2024-01-11 04:24:45 -05:00
{
2024-03-04 09:08:47 -05:00
if ( TestProperty - > IsA < FStrProperty > ( ) )
{
return true ;
}
}
else if ( TargetTypeName = = TextName )
{
if ( TestProperty - > IsA < FTextProperty > ( ) )
{
return true ;
}
}
else
{
UField * TargetRefField = UClass : : TryFindTypeSlow < UField > ( TargetTypeNameStr ) ;
if ( ! TargetRefField )
{
TargetRefField = LoadObject < UField > ( nullptr , * TargetTypeNameStr ) ;
}
if ( SourceStructProperty )
{
if ( SourceStructProperty - > Struct - > IsChildOf ( Cast < UStruct > ( TargetRefField ) ) )
{
return true ;
}
}
if ( const FObjectProperty * ObjectProperty = CastField < FObjectProperty > ( TestProperty ) )
{
// Only referencing object of the same exact class should be allowed. Otherwise one could e.g assign UObject to AActor property through reference to UObject.
if ( ObjectProperty - > PropertyClass = = Cast < UStruct > ( TargetRefField ) )
{
return true ;
}
}
else if ( const FEnumProperty * EnumProperty = CastField < FEnumProperty > ( TestProperty ) )
{
if ( EnumProperty - > GetEnum ( ) = = TargetRefField )
{
return true ;
}
}
2024-01-11 04:24:45 -05:00
}
}
return false ;
}
2024-02-14 09:04:52 -05:00
bool IsPropertyRefCompatibleWithProperty ( const FProperty & RefProperty , const FProperty & SourceProperty , const void * PropertyRefAddress , const void * SourceAddress )
{
check ( PropertyRefAddress ) ;
check ( SourceAddress ) ;
check ( IsPropertyRef ( RefProperty ) ) ;
if ( IsPropertyRef ( SourceProperty ) )
{
return ArePropertyRefsCompatible ( RefProperty , SourceProperty , PropertyRefAddress , SourceAddress ) ;
}
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( & RefProperty ) )
{
if ( StructProperty - > Struct = = FStateTreePropertyRef : : StaticStruct ( ) )
{
return IsNativePropertyRefCompatibleWithProperty ( RefProperty , SourceProperty ) ;
}
else if ( StructProperty - > Struct = = FStateTreeBlueprintPropertyRef : : StaticStruct ( ) )
{
return IsBlueprintPropertyRefCompatibleWithProperty ( SourceProperty , PropertyRefAddress ) ;
}
}
checkNoEntry ( ) ;
return false ;
}
2024-01-11 04:24:45 -05:00
bool IsPropertyAccessibleForPropertyRef ( const FProperty & SourceProperty , FStateTreeBindableStructDesc SourceStruct , bool bIsOutput )
{
switch ( SourceStruct . DataSource )
{
case EStateTreeBindableStructSource : : Parameter :
2024-03-11 04:54:44 -04:00
case EStateTreeBindableStructSource : : StateParameter :
case EStateTreeBindableStructSource : : TransitionEvent :
case EStateTreeBindableStructSource : : StateEvent :
2024-01-11 04:24:45 -05:00
return true ;
case EStateTreeBindableStructSource : : Context :
case EStateTreeBindableStructSource : : Condition :
2024-05-15 14:50:35 -04:00
case EStateTreeBindableStructSource : : Consideration :
2024-06-04 03:56:38 -04:00
case EStateTreeBindableStructSource : : PropertyFunction :
2024-01-11 04:24:45 -05:00
return false ;
case EStateTreeBindableStructSource : : GlobalTask :
case EStateTreeBindableStructSource : : Evaluator :
case EStateTreeBindableStructSource : : Task :
return bIsOutput | | IsPropertyRef ( SourceProperty ) ;
2024-03-11 04:54:44 -04:00
2024-01-11 04:24:45 -05:00
default :
checkNoEntry ( ) ;
}
return false ;
}
bool IsPropertyAccessibleForPropertyRef ( TConstArrayView < FStateTreePropertyPathIndirection > SourcePropertyPathIndirections , FStateTreeBindableStructDesc SourceStruct )
{
bool bIsOutput = false ;
for ( const FStateTreePropertyPathIndirection & Indirection : SourcePropertyPathIndirections )
{
if ( UE : : StateTree : : GetUsageFromMetaData ( Indirection . GetProperty ( ) ) = = EStateTreePropertyUsage : : Output )
{
bIsOutput = true ;
break ;
}
}
return IsPropertyAccessibleForPropertyRef ( * SourcePropertyPathIndirections . Last ( ) . GetProperty ( ) , SourceStruct , bIsOutput ) ;
}
2024-02-13 08:30:26 -05:00
bool IsPropertyAccessibleForPropertyRef ( const FProperty & SourceProperty , TConstArrayView < FBindingChainElement > BindingChain , FStateTreeBindableStructDesc SourceStruct )
2024-01-11 04:24:45 -05:00
{
bool bIsOutput = UE : : StateTree : : GetUsageFromMetaData ( & SourceProperty ) = = EStateTreePropertyUsage : : Output ;
2024-02-13 08:30:26 -05:00
for ( const FBindingChainElement & ChainElement : BindingChain )
2024-01-11 04:24:45 -05:00
{
2024-02-13 08:30:26 -05:00
if ( const FProperty * Property = ChainElement . Field . Get < FProperty > ( ) )
2024-01-11 04:24:45 -05:00
{
if ( UE : : StateTree : : GetUsageFromMetaData ( Property ) = = EStateTreePropertyUsage : : Output )
{
bIsOutput = true ;
break ;
}
}
}
return IsPropertyAccessibleForPropertyRef ( SourceProperty , SourceStruct , bIsOutput ) ;
}
2024-02-14 09:04:52 -05:00
FEdGraphPinType GetBlueprintPropertyRefInternalTypeAsPin ( const FStateTreeBlueprintPropertyRef & PropertyRef )
{
FEdGraphPinType PinType ;
PinType . PinSubCategory = NAME_None ;
if ( PropertyRef . IsRefToArray ( ) )
{
PinType . ContainerType = EPinContainerType : : Array ;
}
switch ( PropertyRef . GetRefType ( ) )
{
case EStateTreePropertyRefType : : None :
break ;
case EStateTreePropertyRefType : : Bool :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Boolean ;
break ;
case EStateTreePropertyRefType : : Byte :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Byte ;
break ;
case EStateTreePropertyRefType : : Int32 :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Int ;
break ;
case EStateTreePropertyRefType : : Int64 :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Int64 ;
break ;
case EStateTreePropertyRefType : : Float :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Real ;
PinType . PinSubCategory = UEdGraphSchema_K2 : : PC_Float ;
break ;
case EStateTreePropertyRefType : : Double :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Real ;
PinType . PinSubCategory = UEdGraphSchema_K2 : : PC_Double ;
break ;
case EStateTreePropertyRefType : : Name :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Name ;
break ;
case EStateTreePropertyRefType : : String :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_String ;
break ;
case EStateTreePropertyRefType : : Text :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Text ;
break ;
case EStateTreePropertyRefType : : Enum :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Enum ;
PinType . PinSubCategoryObject = PropertyRef . GetTypeObject ( ) ;
break ;
case EStateTreePropertyRefType : : Struct :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Struct ;
PinType . PinSubCategoryObject = PropertyRef . GetTypeObject ( ) ;
break ;
case EStateTreePropertyRefType : : Object :
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Object ;
PinType . PinSubCategoryObject = PropertyRef . GetTypeObject ( ) ;
break ;
default :
ensureMsgf ( false , TEXT ( " Unhandled type %s " ) , * UEnum : : GetValueAsString ( PropertyRef . GetRefType ( ) ) ) ;
break ;
}
return PinType ;
}
FEdGraphPinType GetNativePropertyRefInternalTypeAsPin ( const FProperty & RefProperty )
2024-01-11 04:24:45 -05:00
{
2024-06-11 03:39:06 -04:00
TArray < FEdGraphPinType , TInlineAllocator < 1 > > PinTypes = GetPropertyRefInternalTypesAsPins ( RefProperty ) ;
if ( PinTypes . Num ( ) = = 1 )
2024-01-11 04:24:45 -05:00
{
2024-06-11 03:39:06 -04:00
return PinTypes [ 0 ] ;
2024-01-11 04:24:45 -05:00
}
2024-06-11 03:39:06 -04:00
return FEdGraphPinType ( ) ;
2024-01-11 04:24:45 -05:00
}
2024-02-14 09:04:52 -05:00
FEdGraphPinType GetPropertyRefInternalTypeAsPin ( const FProperty & RefProperty , const void * PropertyRefAddress )
2024-01-11 04:24:45 -05:00
{
2024-02-14 09:04:52 -05:00
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( & RefProperty ) )
2024-01-11 04:24:45 -05:00
{
2024-02-14 09:04:52 -05:00
if ( StructProperty - > Struct = = FStateTreePropertyRef : : StaticStruct ( ) )
{
return GetNativePropertyRefInternalTypeAsPin ( RefProperty ) ;
}
else if ( StructProperty - > Struct = = FStateTreeBlueprintPropertyRef : : StaticStruct ( ) )
{
check ( PropertyRefAddress ) ;
return GetBlueprintPropertyRefInternalTypeAsPin ( * reinterpret_cast < const FStateTreeBlueprintPropertyRef * > ( PropertyRefAddress ) ) ;
}
}
checkNoEntry ( ) ;
return FEdGraphPinType ( ) ;
}
void STATETREEMODULE_API GetBlueprintPropertyRefInternalTypeFromPin ( const FEdGraphPinType & PinType , EStateTreePropertyRefType & OutRefType , bool & bOutIsArray , UObject * & OutObjectType )
{
OutRefType = EStateTreePropertyRefType : : None ;
bOutIsArray = false ;
OutObjectType = nullptr ;
// Set container type
switch ( PinType . ContainerType )
{
case EPinContainerType : : Array :
bOutIsArray = true ;
break ;
case EPinContainerType : : Set :
ensureMsgf ( false , TEXT ( " Unsuported container type [Set] " ) ) ;
break ;
case EPinContainerType : : Map :
ensureMsgf ( false , TEXT ( " Unsuported container type [Map] " ) ) ;
break ;
default :
break ;
}
// Value type
if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Boolean )
{
OutRefType = EStateTreePropertyRefType : : Bool ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Byte )
{
if ( UEnum * Enum = Cast < UEnum > ( PinType . PinSubCategoryObject ) )
{
OutRefType = EStateTreePropertyRefType : : Enum ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else
{
OutRefType = EStateTreePropertyRefType : : Byte ;
}
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Int )
{
OutRefType = EStateTreePropertyRefType : : Int32 ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Int64 )
{
OutRefType = EStateTreePropertyRefType : : Int64 ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Real )
{
if ( PinType . PinSubCategory = = UEdGraphSchema_K2 : : PC_Float )
{
OutRefType = EStateTreePropertyRefType : : Float ;
}
else if ( PinType . PinSubCategory = = UEdGraphSchema_K2 : : PC_Double )
{
OutRefType = EStateTreePropertyRefType : : Double ;
}
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Name )
{
OutRefType = EStateTreePropertyRefType : : Name ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_String )
{
OutRefType = EStateTreePropertyRefType : : String ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Text )
{
OutRefType = EStateTreePropertyRefType : : Text ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Enum )
{
OutRefType = EStateTreePropertyRefType : : Enum ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Struct )
{
OutRefType = EStateTreePropertyRefType : : Struct ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Object )
{
OutRefType = EStateTreePropertyRefType : : Object ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_SoftObject )
{
OutRefType = EStateTreePropertyRefType : : SoftObject ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Class )
{
OutRefType = EStateTreePropertyRefType : : Class ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else if ( PinType . PinCategory = = UEdGraphSchema_K2 : : PC_SoftClass )
{
OutRefType = EStateTreePropertyRefType : : SoftClass ;
OutObjectType = PinType . PinSubCategoryObject . Get ( ) ;
}
else
{
ensureMsgf ( false , TEXT ( " Unhandled pin category %s " ) , * PinType . PinCategory . ToString ( ) ) ;
}
}
bool STATETREEMODULE_API IsPropertyRefMarkedAsOptional ( const FProperty & RefProperty , const void * PropertyRefAddress )
{
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( & RefProperty ) )
{
if ( StructProperty - > Struct = = FStateTreePropertyRef : : StaticStruct ( ) )
{
return RefProperty . HasMetaData ( IsOptionalName ) ;
}
else if ( StructProperty - > Struct = = FStateTreeBlueprintPropertyRef : : StaticStruct ( ) )
{
check ( PropertyRefAddress ) ;
return reinterpret_cast < const FStateTreeBlueprintPropertyRef * > ( PropertyRefAddress ) - > IsOptional ( ) ;
}
}
checkNoEntry ( ) ;
return false ;
}
2024-06-11 03:39:06 -04:00
TArray < FEdGraphPinType , TInlineAllocator < 1 > > GetPropertyRefInternalTypesAsPins ( const FProperty & RefProperty )
{
ensure ( IsPropertyRef ( RefProperty ) ) ;
const EPinContainerType ContainerType = RefProperty . HasMetaData ( IsRefToArrayName ) ? EPinContainerType : : Array : EPinContainerType : : None ;
TArray < FEdGraphPinType , TInlineAllocator < 1 > > PinTypes ;
FString TargetTypesString = RefProperty . GetMetaData ( RefTypeName ) ;
if ( TargetTypesString . IsEmpty ( ) )
{
return PinTypes ;
}
TArray < FString > TargetTypes ;
TargetTypesString . RemoveSpacesInline ( ) ;
TargetTypesString . ParseIntoArray ( TargetTypes , TEXT ( " , " ) , true ) ;
for ( const FString & TargetType : TargetTypes )
{
const FName TargetTypeName = * TargetType ;
FEdGraphPinType & PinType = PinTypes . AddDefaulted_GetRef ( ) ;
PinType . ContainerType = ContainerType ;
if ( TargetTypeName = = BoolName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Boolean ;
}
else if ( TargetTypeName = = ByteName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Byte ;
}
else if ( TargetTypeName = = Int32Name )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Int ;
}
else if ( TargetTypeName = = Int64Name )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Int64 ;
}
else if ( TargetTypeName = = FloatName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Real ;
PinType . PinSubCategory = UEdGraphSchema_K2 : : PC_Float ;
}
else if ( TargetTypeName = = DoubleName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Real ;
PinType . PinSubCategory = UEdGraphSchema_K2 : : PC_Double ;
}
else if ( TargetTypeName = = NameName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Name ;
}
else if ( TargetTypeName = = StringName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_String ;
}
else if ( TargetTypeName = = TextName )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Text ;
}
else
{
UField * TargetRefField = UClass : : TryFindTypeSlow < UField > ( TargetType ) ;
if ( ! TargetRefField )
{
TargetRefField = LoadObject < UField > ( nullptr , * TargetType ) ;
}
2024-06-11 04:15:08 -04:00
if ( UScriptStruct * Struct = Cast < UScriptStruct > ( TargetRefField ) )
2024-06-11 03:39:06 -04:00
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Struct ;
PinType . PinSubCategoryObject = Struct ;
}
2024-06-11 04:15:08 -04:00
else if ( UClass * ObjectClass = Cast < UClass > ( TargetRefField ) )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Object ;
PinType . PinSubCategoryObject = ObjectClass ;
}
2024-06-11 03:39:06 -04:00
else if ( UEnum * Enum = Cast < UEnum > ( TargetRefField ) )
{
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Enum ;
PinType . PinSubCategoryObject = Enum ;
}
else
{
checkf ( false , TEXT ( " Typename in meta-data (%s) is invalid " ) , * TargetType ) ;
}
}
}
return PinTypes ;
}
2024-02-14 09:04:52 -05:00
# endif
bool IsBlueprintPropertyRefCompatibleWithProperty ( const FProperty & SourceProperty , const void * PropertyRefAddress )
{
const FStateTreeBlueprintPropertyRef & PropertyRef = * reinterpret_cast < const FStateTreeBlueprintPropertyRef * > ( PropertyRefAddress ) ;
const FProperty * TestProperty = & SourceProperty ;
if ( PropertyRef . IsRefToArray ( ) )
{
if ( const FArrayProperty * ArrayProperty = CastField < FArrayProperty > ( TestProperty ) )
{
TestProperty = ArrayProperty - > Inner ;
}
else
{
return false ;
}
}
switch ( PropertyRef . GetRefType ( ) )
{
case EStateTreePropertyRefType : : None :
return false ;
case EStateTreePropertyRefType : : Bool :
return Validator < bool > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Byte :
return Validator < uint8 > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Int32 :
return Validator < int32 > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Int64 :
return Validator < int64 > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Float :
return Validator < float > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Double :
return Validator < double > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Name :
return Validator < FName > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : String :
return Validator < FString > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Text :
return Validator < FText > : : IsValid ( * TestProperty ) ;
case EStateTreePropertyRefType : : Enum :
if ( const UEnum * Enum = Cast < UEnum > ( PropertyRef . GetTypeObject ( ) ) )
{
return IsPropertyCompatibleWithEnum ( * TestProperty , * Enum ) ;
}
return false ;
case EStateTreePropertyRefType : : Struct :
if ( const UScriptStruct * Struct = Cast < UScriptStruct > ( PropertyRef . GetTypeObject ( ) ) )
{
return IsPropertyCompatibleWithStruct ( * TestProperty , * Struct ) ;
}
return false ;
case EStateTreePropertyRefType : : Object :
if ( const UClass * Class = Cast < UClass > ( PropertyRef . GetTypeObject ( ) ) )
{
return IsPropertyCompatibleWithClass ( * TestProperty , * Class ) ;
}
return false ;
default :
checkNoEntry ( ) ;
2024-01-11 04:24:45 -05:00
}
return false ;
}
2024-02-14 09:04:52 -05:00
bool IsPropertyRef ( const FProperty & Property )
{
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( & Property ) )
{
return StructProperty - > Struct - > IsChildOf ( FStateTreePropertyRef : : StaticStruct ( ) ) ;
}
return false ;
}
bool IsPropertyCompatibleWithEnum ( const FProperty & Property , const UEnum & Enum )
{
if ( const FEnumProperty * EnumProperty = CastField < FEnumProperty > ( & Property ) )
{
return EnumProperty - > GetEnum ( ) = = & Enum ;
}
return false ;
}
bool IsPropertyCompatibleWithClass ( const FProperty & Property , const UClass & Class )
{
if ( const FObjectProperty * ObjectProperty = CastField < FObjectProperty > ( & Property ) )
{
return ObjectProperty - > PropertyClass = = & Class ;
}
return false ;
}
bool IsPropertyCompatibleWithStruct ( const FProperty & Property , const UScriptStruct & Struct )
{
if ( const FStructProperty * StructProperty = CastField < FStructProperty > ( & Property ) )
{
return StructProperty - > Struct = = & Struct ;
}
return false ;
}
}