2021-09-28 13:33:00 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "GameplayTagContainer.h"
2022-01-19 14:16:16 -05:00
# include "InstancedStruct.h"
# include "MassEntityTypes.h"
2021-11-26 15:48:13 -05:00
# include "Engine/DataAsset.h"
# include "SmartObjectDefinition.generated.h"
2021-09-28 13:33:00 -04:00
class UGameplayBehaviorConfig ;
2022-03-02 13:25:37 -05:00
enum class ESmartObjectTagFilteringPolicy : uint8 ;
2022-03-02 22:33:53 -05:00
enum class ESmartObjectTagMergingPolicy : uint8 ;
2021-09-28 13:33:00 -04:00
/**
* Abstract class that can be extended to bind a new type of behavior framework
2021-11-26 15:48:13 -05:00
* to the smart objects by defining the required definition .
2021-09-28 13:33:00 -04:00
*/
2021-11-16 07:45:37 -05:00
UCLASS ( Abstract , NotBlueprintable , EditInlineNew , CollapseCategories , HideDropdown )
2021-11-26 15:48:13 -05:00
class SMARTOBJECTSMODULE_API USmartObjectBehaviorDefinition : public UObject
2021-09-28 13:33:00 -04:00
{
GENERATED_BODY ( )
} ;
/**
2021-11-26 15:48:13 -05:00
* Persistent and sharable definition of a smart object slot .
2021-09-28 13:33:00 -04:00
*/
USTRUCT ( )
2022-01-19 14:16:16 -05:00
struct SMARTOBJECTSMODULE_API FSmartObjectSlotDefinition
2021-09-28 13:33:00 -04:00
{
GENERATED_BODY ( )
2022-02-17 03:40:43 -05:00
# if WITH_EDITORONLY_DATA
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
FName Name ;
UPROPERTY ( EditAnywhere , Category = SmartObject , meta = ( DisplayName = " Color " ) )
FColor DEBUG_DrawColor = FColor : : Yellow ;
# endif // WITH_EDITORONLY_DATA
2021-09-28 13:33:00 -04:00
/** This slot is available only for users matching this query. */
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
FGameplayTagQuery UserTagFilter ;
2022-03-02 13:25:37 -05:00
/**
* Tags identifying this slot ' s use case . Can be used while looking for slots supporting given activity .
* Depending on the tag filtering policy these tags can override the parent object ' s tags
* or be combined with them while applying filters from requests .
*/
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
FGameplayTagContainer ActivityTags ;
2021-09-28 13:33:00 -04:00
/** Offset relative to the parent object where the slot is located. */
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
2022-01-07 14:28:06 -05:00
FVector Offset = FVector : : ZeroVector ;
2021-09-28 13:33:00 -04:00
2022-01-07 14:28:06 -05:00
/** Rotation relative to the parent object. */
2021-09-28 13:33:00 -04:00
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
2022-01-07 14:28:06 -05:00
FRotator Rotation = FRotator : : ZeroRotator ;
2021-09-28 13:33:00 -04:00
2022-03-17 11:17:04 -04:00
/** Custom data (struct inheriting from SmartObjectSlotDefinitionData) that can be added to the slot definition and accessed through a FSmartObjectSlotView */
2022-05-22 10:30:02 -04:00
UPROPERTY ( EditDefaultsOnly , Category = " SmartObject " , meta = ( BaseStruct = " /Script/SmartObjectsModule.SmartObjectSlotDefinitionData " , ExcludeBaseStruct ) )
2022-01-19 14:16:16 -05:00
TArray < FInstancedStruct > Data ;
2021-09-28 13:33:00 -04:00
/**
2021-11-26 15:48:13 -05:00
* All available definitions associated to this slot .
* This allows multiple frameworks to provide their specific behavior definition to the slot .
* Note that there should be only one definition of each type since the first one will be selected .
2021-09-28 13:33:00 -04:00
*/
UPROPERTY ( EditDefaultsOnly , Category = SmartObject , Instanced )
2021-11-26 15:48:13 -05:00
TArray < USmartObjectBehaviorDefinition * > BehaviorDefinitions ;
2021-09-28 13:33:00 -04:00
} ;
/**
2021-11-26 15:48:13 -05:00
* Helper struct to wrap basic functionalities to store the index of a slot in a SmartObject definition
2021-09-28 13:33:00 -04:00
*/
2021-11-26 15:48:13 -05:00
USTRUCT ( BlueprintType )
2021-09-28 13:33:00 -04:00
struct SMARTOBJECTSMODULE_API FSmartObjectSlotIndex
{
GENERATED_BODY ( )
explicit FSmartObjectSlotIndex ( const int32 InSlotIndex = INDEX_NONE ) : Index ( InSlotIndex ) { }
bool IsValid ( ) const { return Index ! = INDEX_NONE ; }
void Invalidate ( ) { Index = INDEX_NONE ; }
operator int32 ( ) const { return Index ; }
bool operator = = ( const FSmartObjectSlotIndex & Other ) const { return Index = = Other . Index ; }
2022-01-19 14:16:16 -05:00
friend FString LexToString ( const FSmartObjectSlotIndex & SlotIndex ) { return FString : : Printf ( TEXT ( " [Slot:%d] " ) , SlotIndex . Index ) ; }
2021-09-28 13:33:00 -04:00
private :
UPROPERTY ( Transient )
int32 Index = INDEX_NONE ;
} ;
/**
2022-01-19 14:16:16 -05:00
* SmartObject definition asset . Contains sharable information that can be used by multiple SmartObject instances at runtime .
2021-09-28 13:33:00 -04:00
*/
2021-11-26 15:48:13 -05:00
UCLASS ( BlueprintType , Blueprintable , CollapseCategories )
class SMARTOBJECTSMODULE_API USmartObjectDefinition : public UDataAsset
2021-09-28 13:33:00 -04:00
{
GENERATED_BODY ( )
2021-11-26 15:48:13 -05:00
2021-09-28 13:33:00 -04:00
public :
2022-03-02 13:25:37 -05:00
explicit USmartObjectDefinition ( const FObjectInitializer & ObjectInitializer ) ;
2021-09-28 13:33:00 -04:00
/**
2021-11-26 15:48:13 -05:00
* Retrieves a specific type of behavior definition for a given slot .
2021-09-28 13:33:00 -04:00
* When the slot doesn ' t provide one or if the provided index is not valid
2021-11-26 15:48:13 -05:00
* the search will look in the object default definitions .
*
* @ param SlotIndex Index of the slot for which the definition is requested
* @ param DefinitionClass Type of the requested behavior definition
* @ return The behavior definition found or null if none are available for the requested type .
2021-09-28 13:33:00 -04:00
*/
2021-11-26 15:48:13 -05:00
const USmartObjectBehaviorDefinition * GetBehaviorDefinition ( const FSmartObjectSlotIndex & SlotIndex , const TSubclassOf < USmartObjectBehaviorDefinition > & DefinitionClass ) const ;
2021-09-28 13:33:00 -04:00
2021-11-26 15:48:13 -05:00
/** Returns a view on all the slot definitions */
2022-01-19 14:16:16 -05:00
TConstArrayView < FSmartObjectSlotDefinition > GetSlots ( ) const { return Slots ; }
# if WITH_EDITOR
/** Returns a view on all the slot definitions */
TArrayView < FSmartObjectSlotDefinition > GetMutableSlots ( ) { return Slots ; }
# endif
2021-09-28 13:33:00 -04:00
2022-01-07 14:28:06 -05:00
/** Return bounds encapsulating all slots */
FBox GetBounds ( ) const ;
2021-09-28 13:33:00 -04:00
/** Adds and returns a reference to a defaulted slot (used for testing purposes) */
2022-01-19 14:16:16 -05:00
FSmartObjectSlotDefinition & DebugAddSlot ( ) { return Slots . AddDefaulted_GetRef ( ) ; }
2021-09-28 13:33:00 -04:00
/**
* Returns the transform ( in world space ) of the given slot index .
* @ param OwnerTransform Transform ( in world space ) of the slot owner .
* @ param SlotIndex Index within the list of slots .
* @ return Transform ( in world space ) of the slot associated to SlotIndex .
* @ note Method will ensure on invalid invalid index .
*/
TOptional < FTransform > GetSlotTransform ( const FTransform & OwnerTransform , const FSmartObjectSlotIndex SlotIndex ) const ;
2022-03-02 22:33:53 -05:00
/**
* Fills the provided GameplayTagContainer with the activity tags associated to the slot according to the tag merging policy .
* @ param SlotIndex Index of the slot for which the tags are requested
* @ param OutActivityTags Tag container to fill with the activity tags associated to the slot
*/
void GetSlotActivityTags ( const FSmartObjectSlotIndex & SlotIndex , FGameplayTagContainer & OutActivityTags ) const ;
/**
* Fills the provided GameplayTagContainer with the activity tags associated to the slot according to the tag merging policy .
* @ param SlotDefinition Definition of the slot for which the tags are requested
* @ param OutActivityTags Tag container to fill with the activity tags associated to the slot
*/
void GetSlotActivityTags ( const FSmartObjectSlotDefinition & SlotDefinition , FGameplayTagContainer & OutActivityTags ) const ;
2022-03-02 13:25:37 -05:00
/** Returns the tag query to run on the user tags provided by a request to accept this definition */
2021-09-28 13:33:00 -04:00
const FGameplayTagQuery & GetUserTagFilter ( ) const { return UserTagFilter ; }
2022-03-02 13:25:37 -05:00
/** Sets the tag query to run on the user tags provided by a request to accept this definition */
void SetUserTagFilter ( const FGameplayTagQuery & InUserTagFilter ) { UserTagFilter = InUserTagFilter ; }
/** Returns the tag query to run on the runtime tags of a smart object instance to accept it */
2021-09-28 13:33:00 -04:00
const FGameplayTagQuery & GetObjectTagFilter ( ) const { return ObjectTagFilter ; }
2022-03-02 13:25:37 -05:00
/** Sets the tag query to run on the runtime tags of a smart object instance to accept it */
void SetObjectTagFilter ( const FGameplayTagQuery & InObjectTagFilter ) { ObjectTagFilter = InObjectTagFilter ; }
2021-11-26 15:48:13 -05:00
/** Returns the list of tags describing the activity associated to this definition */
2021-09-28 13:33:00 -04:00
const FGameplayTagContainer & GetActivityTags ( ) const { return ActivityTags ; }
2022-03-02 13:25:37 -05:00
/** Sets the list of tags describing the activity associated to this definition */
void SetActivityTags ( const FGameplayTagContainer & InActivityTags ) { ActivityTags = InActivityTags ; }
2022-03-02 22:33:53 -05:00
/** Returns the tag filtering policy that should be applied on User tags by this definition */
ESmartObjectTagFilteringPolicy GetUserTagsFilteringPolicy ( ) const { return UserTagsFilteringPolicy ; }
2022-03-02 13:25:37 -05:00
2022-03-02 22:33:53 -05:00
/** Sets the tag filtering policy to apply on User tags by this definition */
void SetUserTagsFilteringPolicy ( const ESmartObjectTagFilteringPolicy InUserTagsFilteringPolicy ) { UserTagsFilteringPolicy = InUserTagsFilteringPolicy ; }
/** Returns the tag merging policy to apply on Activity tags from this definition */
ESmartObjectTagMergingPolicy GetActivityTagsMergingPolicy ( ) const { return ActivityTagsMergingPolicy ; }
/** Sets the tag merging policy to apply on Activity tags from this definition */
void SetActivityTagsMergingPolicy ( const ESmartObjectTagMergingPolicy InActivityTagsMergingPolicy ) { ActivityTagsMergingPolicy = InActivityTagsMergingPolicy ; }
2022-03-02 13:25:37 -05:00
2021-09-28 13:33:00 -04:00
/**
2021-11-26 15:48:13 -05:00
* Performs validation and logs errors if any . An object using an invalid definition
2021-09-28 13:33:00 -04:00
* will not be registered in the simulation .
2021-11-02 11:12:43 -04:00
* The result of the validation is stored until next validation and can be retrieved using ` IsValid ` .
2021-11-26 15:48:13 -05:00
* @ return true if the definition is valid
2021-09-28 13:33:00 -04:00
*/
bool Validate ( ) const ;
2021-11-26 15:48:13 -05:00
/** Provides a description of the definition */
2022-01-19 14:16:16 -05:00
friend FString LexToString ( const USmartObjectDefinition & Definition )
{
return FString : : Printf ( TEXT ( " NumSlots=%d NumDefs=%d HasUserFilter=%s HasObjectFilter=%s " ) ,
Definition . Slots . Num ( ) ,
Definition . DefaultBehaviorDefinitions . Num ( ) ,
* LexToString ( ! Definition . UserTagFilter . IsEmpty ( ) ) ,
* LexToString ( ! Definition . ObjectTagFilter . IsEmpty ( ) ) ) ;
}
2021-09-28 13:33:00 -04:00
2021-11-02 11:12:43 -04:00
/** Returns result of the last validation if `Validate` was called; unset otherwise. */
TOptional < bool > IsValid ( ) const { return bValid ; }
2022-01-26 07:44:21 -05:00
# if WITH_EDITORONLY_DATA
/** Actor class used for previewing the definition in the asset editor. */
2022-03-02 13:25:37 -05:00
UPROPERTY ( )
2022-01-26 07:44:21 -05:00
TSoftClassPtr < AActor > PreviewClass ;
/** Path of the static mesh used for previewing the definition in the asset editor. */
2022-03-02 13:25:37 -05:00
UPROPERTY ( )
2022-01-26 07:44:21 -05:00
FSoftObjectPath PreviewMeshPath ;
# endif
2021-09-28 13:33:00 -04:00
private :
2021-11-26 15:48:13 -05:00
/** Finds first behavior definition of a given class in the provided list of definitions. */
static const USmartObjectBehaviorDefinition * GetBehaviorDefinitionByType ( const TArray < USmartObjectBehaviorDefinition * > & BehaviorDefinitions , const TSubclassOf < USmartObjectBehaviorDefinition > & DefinitionClass ) ;
2021-09-28 13:33:00 -04:00
/**
* Where SmartObject ' s user needs to stay to be able to activate it . These
* will be used by AI to approach the object . Locations are relative to object ' s location .
*/
2021-11-02 11:12:43 -04:00
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
2022-01-19 14:16:16 -05:00
TArray < FSmartObjectSlotDefinition > Slots ;
2021-09-28 13:33:00 -04:00
2021-11-26 15:48:13 -05:00
/** List of behavior definitions of different types provided to SO's user if the slot does not provide one. */
2021-11-02 11:12:43 -04:00
UPROPERTY ( EditDefaultsOnly , Category = SmartObject , Instanced )
2021-11-26 15:48:13 -05:00
TArray < USmartObjectBehaviorDefinition * > DefaultBehaviorDefinitions ;
2021-09-28 13:33:00 -04:00
2022-03-17 11:17:04 -04:00
/** This object is available if user tags match this query; always available if query is empty. */
2021-11-02 11:12:43 -04:00
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
2021-09-28 13:33:00 -04:00
FGameplayTagQuery UserTagFilter ;
2022-03-17 11:17:04 -04:00
/** This object is available if instance tags match this query; always available if query is empty. */
UPROPERTY ( EditDefaultsOnly , Category = SmartObject , meta = ( DisplayName = " Object Activation Tag Filter " ) )
2021-09-28 13:33:00 -04:00
FGameplayTagQuery ObjectTagFilter ;
/** Tags identifying this Smart Object's use case. Can be used while looking for objects supporting given activity */
2021-11-02 11:12:43 -04:00
UPROPERTY ( EditDefaultsOnly , Category = SmartObject )
2021-09-28 13:33:00 -04:00
FGameplayTagContainer ActivityTags ;
2021-11-02 11:12:43 -04:00
2022-03-02 22:33:53 -05:00
/** Indicates how Tags from slots and parent object are combined to be evaluated by a TagQuery from a find request. */
2022-03-02 13:25:37 -05:00
UPROPERTY ( EditAnywhere , Category = SmartObject , AdvancedDisplay )
2022-03-02 22:33:53 -05:00
ESmartObjectTagMergingPolicy ActivityTagsMergingPolicy ;
/** Indicates how TagQueries from slots and parent object will be processed against User Tags from a find request. */
UPROPERTY ( EditAnywhere , Category = SmartObject , AdvancedDisplay )
ESmartObjectTagFilteringPolicy UserTagsFilteringPolicy ;
2022-03-02 13:25:37 -05:00
2021-11-02 11:12:43 -04:00
mutable TOptional < bool > bValid ;
2021-09-28 13:33:00 -04:00
} ;
2022-01-19 14:16:16 -05:00
/**
2022-02-17 03:40:43 -05:00
* Mass Fragment used to share slot definition between slot instances .
2022-01-19 14:16:16 -05:00
*/
USTRUCT ( )
struct SMARTOBJECTSMODULE_API FSmartObjectSlotDefinitionFragment : public FMassSharedFragment
{
GENERATED_BODY ( )
FSmartObjectSlotDefinitionFragment ( ) = default ;
explicit FSmartObjectSlotDefinitionFragment ( const USmartObjectDefinition & InObjectDefinition , const FSmartObjectSlotDefinition & InSlotDefinition )
: SmartObjectDefinition ( & InObjectDefinition ) , SlotDefinition ( & InSlotDefinition ) { }
/** Pointer to the parent object definition to preserve slot definition pointer validity. */
UPROPERTY ( Transient )
const USmartObjectDefinition * SmartObjectDefinition = nullptr ;
/** Pointer to the slot definition contained by the SmartObject definition. */
const FSmartObjectSlotDefinition * SlotDefinition = nullptr ;
} ;