// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Engine/DataAsset.h" #include "GameplayTagContainer.h" #include "Math/Box.h" #include "WorldConditionQuery.h" #include "WorldConditions/SmartObjectWorldConditionSchema.h" #include "SmartObjectTypes.h" #include "StructUtils/PropertyBag.h" #include "PropertyBindingPath.h" #include "PropertyBindingBindingCollection.h" #include "PropertyBindingBindingCollectionOwner.h" #include "SmartObjectBindingCollection.h" #include "SmartObjectDefinition.generated.h" #define UE_API SMARTOBJECTSMODULE_API class UGameplayBehaviorConfig; class USmartObjectSlotValidationFilter; class USmartObjectDefinition; enum class ESmartObjectTagFilteringPolicy: uint8; enum class ESmartObjectTagMergingPolicy: uint8; namespace EMessageSeverity { enum Type : int; } namespace UE::SmartObject::Delegates { #if WITH_EDITOR /** Called in editor when parameters for a specific SmartObjectDefinition changes. */ DECLARE_MULTICAST_DELEGATE_OneParam(FOnParametersChanged, const USmartObjectDefinition& /*SmartObjectDefinition*/); extern SMARTOBJECTSMODULE_API FOnParametersChanged OnParametersChanged; /** Delegate to retrieve Registry Tags for SmartObjectDefinition */ DECLARE_DELEGATE_TwoParams(FOnGetAssetRegistryTags, const USmartObjectDefinition& /*SmartObjectDefinition*/, FAssetRegistryTagsContext /*Context*/); extern SMARTOBJECTSMODULE_API FOnGetAssetRegistryTags OnGetAssetRegistryTags; /** Called in editor when a new SmartObjectSlotDefinition is created (not called when duplicating an existing one). */ DECLARE_DELEGATE_TwoParams(FOnSlotDefinitionCreated, USmartObjectDefinition& /*SmartObjectDefinition*/, FSmartObjectSlotDefinition& /*SmartObjectSlotDefinition*/); extern SMARTOBJECTSMODULE_API FOnSlotDefinitionCreated OnSlotDefinitionCreated; /** Called in editor when a SmartObjectDefinition is about to be saved. */ DECLARE_MULTICAST_DELEGATE_OneParam(FOnSavingDefinition, const USmartObjectDefinition& /*SmartObjectDefinition*/); extern SMARTOBJECTSMODULE_API FOnSavingDefinition OnSavingDefinition; #endif // WITH_EDITOR }; // UE::SmartObject::Delegates /** Indicates how Tags from slots and parent object are combined to be evaluated by a TagQuery from a find request. */ UENUM() enum class ESmartObjectSlotShape : uint8 { Circle, Rectangle }; /** * Abstract class that can be extended to bind a new type of behavior framework * to the smart objects by defining the required definition. */ UCLASS(MinimalAPI, Abstract, NotBlueprintable, EditInlineNew, CollapseCategories, HideDropdown) class USmartObjectBehaviorDefinition : public UObject { GENERATED_BODY() }; /** Helper struct for definition data, which allows to identify items based on GUID in editor (even empty ones). */ USTRUCT() struct FSmartObjectDefinitionDataProxy { GENERATED_BODY() FSmartObjectDefinitionDataProxy() = default; template>>> static FSmartObjectDefinitionDataProxy Make(const T& Struct) { FSmartObjectDefinitionDataProxy NewProxy; NewProxy.Data.InitializeAsScriptStruct(TBaseStructure::Get(), reinterpret_cast(&Struct)); #if WITH_EDITORONLY_DATA NewProxy.ID = FGuid::NewGuid(); #endif return NewProxy; } UPROPERTY(EditDefaultsOnly, Category = "Slot", meta = (ExcludeBaseStruct)) TInstancedStruct Data; #if WITH_EDITORONLY_DATA UPROPERTY(EditDefaultsOnly, Category = "Slot", meta = (Hidden)) FGuid ID; #endif }; using FSmartObjectSlotDefinitionDataProxy UE_DEPRECATED(5.4, "Deprecated struct. Please use FSmartObjectDefinitionDataProxy instead.") = FSmartObjectDefinitionDataProxy; /** * Persistent and sharable definition of a smart object slot. */ USTRUCT(BlueprintType) struct FSmartObjectSlotDefinition { GENERATED_BODY() // Macro needed to avoid deprecation errors with "Data" being copied or created in the default methods PRAGMA_DISABLE_DEPRECATION_WARNINGS FSmartObjectSlotDefinition() = default; FSmartObjectSlotDefinition(const FSmartObjectSlotDefinition&) = default; FSmartObjectSlotDefinition(FSmartObjectSlotDefinition&&) = default; FSmartObjectSlotDefinition& operator=(const FSmartObjectSlotDefinition&) = default; FSmartObjectSlotDefinition& operator=(FSmartObjectSlotDefinition&&) = default; PRAGMA_ENABLE_DEPRECATION_WARNINGS /** * Returns a reference to the definition data of the specified type. * Method will fail a check if the slot definition doesn't contain the given type. */ template const T& GetDefinitionData() const { static_assert(TIsDerivedFrom::IsDerived, "Given struct doesn't represent a valid definition data type. Make sure to inherit from FSmartObjectDefinitionData or one of its child-types."); for (const FSmartObjectDefinitionDataProxy& DataProxy : DefinitionData) { if (DataProxy.Data.GetScriptStruct() && DataProxy.Data.GetScriptStruct()->IsChildOf(T::StaticStruct())) { return DataProxy.Data.Get(); } } checkf(false, TEXT("Failed to find slot definition data")); return nullptr; } /** * Returns a pointer to the definition data of the specified type. * Method will return null if the slot doesn't contain the given type. */ template const T* GetDefinitionDataPtr() const { static_assert(TIsDerivedFrom::IsDerived, "Given struct doesn't represent a valid definition data type. Make sure to inherit from FSmartObjectDefinitionData or one of its child-types."); for (const FSmartObjectDefinitionDataProxy& DataProxy : DefinitionData) { if (DataProxy.Data.GetScriptStruct() && DataProxy.Data.GetScriptStruct()->IsChildOf(T::StaticStruct())) { return DataProxy.Data.GetPtr(); } } return nullptr; } #if WITH_EDITORONLY_DATA UPROPERTY(EditDefaultsOnly, Category = "Slot") FName Name; UPROPERTY(EditAnywhere, Category = "Slot", meta = (DisplayName = "Color")) FColor DEBUG_DrawColor = FColor::Yellow; UPROPERTY(EditAnywhere, Category = "Slot", meta = (DisplayName = "Shape")) ESmartObjectSlotShape DEBUG_DrawShape = ESmartObjectSlotShape::Circle; UPROPERTY(EditAnywhere, Category = "Slot", meta = (DisplayName = "Size")) float DEBUG_DrawSize = 40.0f; UPROPERTY(EditAnywhere, Category = "Slot", meta = (Hidden)) FGuid ID; #endif // WITH_EDITORONLY_DATA /** Offset relative to the parent object where the slot is located. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") FVector3f Offset = FVector3f::ZeroVector; /** Rotation relative to the parent object. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") FRotator3f Rotation = FRotator3f::ZeroRotator; /** Whether the slot is enable initially. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") bool bEnabled = true; /** This slot is available only for users matching this query. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") FGameplayTagQuery UserTagFilter; /** * 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(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") FGameplayTagContainer ActivityTags; /** Initial runtime tags. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot") FGameplayTagContainer RuntimeTags; /** Preconditions that must pass for the slot to be selected. */ UPROPERTY(EditDefaultsOnly, Category = "Slot") FWorldConditionQueryDefinition SelectionPreconditions; /** * 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. */ UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Slot", Instanced) TArray> BehaviorDefinitions; /** Custom definition data items (struct inheriting from SmartObjecDefinitionData) that can be added to the slot definition and accessed through a FSmartObjectSlotView */ UPROPERTY(EditDefaultsOnly, Category = "Slot") TArray DefinitionData; #if WITH_EDITORONLY_DATA UE_DEPRECATED(5.4, "Use DefinitionData instead.") UPROPERTY() TArray Data_DEPRECATED; #endif }; /** * Data used for previewing in the Smart Object editor. */ USTRUCT(BlueprintType) struct FSmartObjectDefinitionPreviewData { GENERATED_BODY() /** Actor class used as the object for previewing the definition in the asset editor. */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Object Preview") TSoftClassPtr ObjectActorClass; /** Path of the static mesh used as the object for previewing the definition in the asset editor. */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Object Preview", meta = (AllowedClasses = "/Script/Engine.StaticMesh")) FSoftObjectPath ObjectMeshPath; /** Actor class used for previewing the smart object user actor in the asset editor. */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "User Preview") TSoftClassPtr UserActorClass; /** Validation filter used for previewing the smart object user in the asset editor. */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "User Preview") TSoftClassPtr UserValidationFilterClass; }; /** * SmartObject definition asset. Contains sharable information that can be used by multiple SmartObject instances at runtime. */ UCLASS(MinimalAPI, BlueprintType, Blueprintable, CollapseCategories) class USmartObjectDefinition : public UDataAsset, public IPropertyBindingBindingCollectionOwner { GENERATED_BODY() public: UE_API explicit USmartObjectDefinition(const FObjectInitializer& ObjectInitializer); /** * Retrieves a specific type of behavior definition for a given slot. * When the slot doesn't provide one or if the provided index is not valid * 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. */ UE_API const USmartObjectBehaviorDefinition* GetBehaviorDefinition(const int32 SlotIndex, const TSubclassOf& DefinitionClass) const; /** @return Preconditions that must pass for the object to be found/used. */ const FWorldConditionQueryDefinition& GetPreconditions() const { return Preconditions; } /** @return mutable Preconditions that must pass for the object to be found/used. */ FWorldConditionQueryDefinition& GetMutablePreconditions() { return Preconditions; } /** @return a view on all the slot definitions */ TConstArrayView GetSlots() const { return Slots; } /** @return slot definition stored at a given index */ const FSmartObjectSlotDefinition& GetSlot(const int32 Index) const { return Slots[Index]; } /** @return mutable slot definition stored at a given index */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") FSmartObjectSlotDefinition& GetMutableSlot(const int32 Index) { return Slots[Index]; } /** @return True if specified slot index is valid. */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") bool IsValidSlotIndex(const int32 SlotIndex) const { return Slots.IsValidIndex(SlotIndex); } UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject", meta=(DisplayName="Get Smart Object Slot Definitions")) const TArray& K2_GetSlots() const { return Slots; } #if WITH_EDITOR /** Returns a view on all the slot definitions */ TArrayView GetMutableSlots() { return Slots; } /** @return validation filter class for preview. */ UE_API TSubclassOf GetPreviewValidationFilterClass() const; /** @return Index of the slot that has the specified ID, or INDEX_NONE if not found. */ UE_API int32 FindSlotByID(const FGuid ID) const; /** * Returns slot and definition data indices the ID represents. * @param ID ID of the slots or definition data to find * @param OutSlotIndex Index of the slot the ID points to * @param OutDefinitionDataIndex Index of the definition data the ID points to, or INDEX_NONE, if ID points directly to a slot. * @return true if ID matches data in the definition. */ UE_API bool FindSlotAndDefinitionDataIndexByID(const FGuid ID, int32& OutSlotIndex, int32& OutDefinitionDataIndex) const; UE_API virtual void GetAssetRegistryTags(FAssetRegistryTagsContext Context) const override; #endif // WITH_EDITOR UE_API virtual void PostDuplicate(EDuplicateMode::Type DuplicateMode) override; /** Return bounds encapsulating all slots */ UFUNCTION(BlueprintCallable, Category="SmartObject") UE_API FBox GetBounds() const; /** Adds and returns a reference to a defaulted slot (used for testing purposes) */ FSmartObjectSlotDefinition& DebugAddSlot() { return Slots.AddDefaulted_GetRef(); } /** * 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, or OwnerTransform if index is invalid. * @note Method will ensure on invalid slot index. */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") UE_API FTransform GetSlotWorldTransform(const int32 SlotIndex, const FTransform& OwnerTransform) const; /** * 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 */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject", meta = (DisplayName="Get Slot Activity Tags (By Index)", ScriptName="GetSlotActivityTagsByIndex", AutoCreateRefTerm = "OutActivityTags")) UE_API void GetSlotActivityTags(const int32 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 */ UE_API void GetSlotActivityTags(const FSmartObjectSlotDefinition& SlotDefinition, FGameplayTagContainer& OutActivityTags) const; /** Returns the tag query to run on the user tags provided by a request to accept this definition */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") const FGameplayTagQuery& GetUserTagFilter() const { return UserTagFilter; } /** Sets the tag query to run on the user tags provided by a request to accept this definition */ UFUNCTION(BlueprintCallable, Category="SmartObject") void SetUserTagFilter(const FGameplayTagQuery& InUserTagFilter) { UserTagFilter = InUserTagFilter; } /** Returns the list of tags describing the activity associated to this definition */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") const FGameplayTagContainer& GetActivityTags() const { return ActivityTags; } /** Sets the list of tags describing the activity associated to this definition */ void SetActivityTags(const FGameplayTagContainer& InActivityTags) { ActivityTags = InActivityTags; } /** Returns the tag filtering policy that should be applied on User tags by this definition */ UFUNCTION(BlueprintCallable, BlueprintPure, Category="SmartObject") ESmartObjectTagFilteringPolicy GetUserTagsFilteringPolicy() const { return UserTagsFilteringPolicy; } /** 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; } /** * Performs validation for the current definition. The method will return on the first error encountered by default * but could go through all validations and report all errors (e.g. when saving the asset errors are reported to the user). * An object using an invalid definition will not be registered in the simulation. * The result of the validation is stored until next validation and can be retrieved using `IsValid`. * @param ErrorsToReport Optional list of error messages that could be provided to report them * @return true if the definition is valid */ UE_API bool Validate(TArray>* ErrorsToReport = nullptr) const; UE_DEPRECATED(5.6, "Use the version allowing to specify the verbosity.") UE_API bool Validate(TArray* ErrorsToReport) const; /** Provides a description of the definition */ friend FString LexToString(const USmartObjectDefinition& Definition) { return FString::Printf(TEXT("NumSlots=%d NumDefs=%d HasUserFilter=%s HasPreConditions=%s"), Definition.Slots.Num(), Definition.DefaultBehaviorDefinitions.Num(), *LexToString(!Definition.UserTagFilter.IsEmpty()), *LexToString(Definition.Preconditions.IsValid())); } /** * Indicates if 'Validate' was called. * Need to be called before calling 'IsDefinitionValid' to make the distinction between * an invalid asset and one that hasn't been validated yet. * @return true if 'Validate' was called, false otherwise * @see Validate * @see IsValidDefinition */ bool HasBeenValidated() const { return bValid.IsSet(); } /** * Indicates the result of the last validation if 'Validate' was called. * Need to call 'HasBeenValidated' before to make the distinction between an invalid * asset and one that hasn't been validated yet. * @returns result of the last validation if 'Validate' was called; false otherwise * @see Validate * @see HasBeenValidated */ bool IsDefinitionValid() const { return bValid.Get(false); } /** Returns result of the last validation if `Validate` was called; unset otherwise. */ UE_DEPRECATED(5.5, "Use IsDefinitionValid that returns a boolean instead.") TOptional IsValid() const { return bValid; } #if WITH_EDITORONLY_DATA /** Actor class used for previewing the definition in the asset editor. */ UE_DEPRECATED(5.3, "Use ObjectActorClass in PreviewData instead.") UPROPERTY() TSoftClassPtr PreviewClass_DEPRECATED; /** Path of the static mesh used for previewing the definition in the asset editor. */ UE_DEPRECATED(5.3, "Use ObjectMeshPath in PreviewData instead.") UPROPERTY() FSoftObjectPath PreviewMeshPath_DEPRECATED; /** Actor class used for previewing the user in the asset editor. */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "SmartObject") FSmartObjectDefinitionPreviewData PreviewData; #endif // WITH_EDITORONLY_DATA const USmartObjectWorldConditionSchema* GetWorldConditionSchema() const { return WorldConditionSchemaClass.GetDefaultObject(); } const TSubclassOf& GetWorldConditionSchemaClass() const { return WorldConditionSchemaClass; } /** * Returns a reference to the definition data of the specified type. * Method will fail a check if the slot definition doesn't contain the given type. */ template const T& GetDefinitionData() const { static_assert(TIsDerivedFrom::IsDerived, "Given struct doesn't represent a valid definition data type. Make sure to inherit from FSmartObjectDefinitionData or one of its child-types."); for (const FSmartObjectDefinitionDataProxy& DataProxy : DefinitionData) { if (DataProxy.Data.GetScriptStruct()->IsChildOf(T::StaticStruct())) { return DataProxy.Data.Get(); } } checkf(false, TEXT("Failed to find definition data")); return nullptr; } /** * Returns a pointer to the definition data of the specified type. * Method will return null if the slot doesn't contain the given type. */ template const T* GetDefinitionDataPtr() const { static_assert(TIsDerivedFrom::IsDerived, "Given struct doesn't represent a valid definition data type. Make sure to inherit from FSmartObjectDefinitionData or one of its child-types."); for (const FSmartObjectDefinitionDataProxy& DataProxy : DefinitionData) { if (DataProxy.Data.GetScriptStruct() && DataProxy.Data.GetScriptStruct()->IsChildOf(T::StaticStruct())) { return DataProxy.Data.GetPtr(); } } return nullptr; } /** @return reference to definition default parameters. */ const FInstancedPropertyBag& GetDefaultParameters() const { return Parameters; } /** * Returns a variation of this asset with specified parameters applied. * The variations are cached, and if a variation with same parameters is already in use, the existing asset is returned. * @return Pointer to an asset variation. */ USmartObjectDefinition* GetAssetVariation(const FInstancedPropertyBag& Parameters, UWorld* World); UE_DEPRECATED(5.6, "Use the overload taking a UWorld as parameter.") USmartObjectDefinition* GetAssetVariation(const FInstancedPropertyBag&) { return nullptr; } /** * Calculates hash of the parameters. * @return hash calculated for the provided bag of parameters. */ static UE_API uint64 GetVariationParametersHash(const FInstancedPropertyBag& Parameters); UE_DEPRECATED(5.6, "Use UE::PropertyBinding::GetPropertyCompatibility instead") static UE_API bool ArePropertiesCompatible(const FProperty* SourceProperty, const FProperty* TargetProperty); protected: //~ Begin IPropertyBindingBindingCollectionOwner interface UE_API virtual bool GetBindingDataView(const FPropertyBindingBinding& InBinding, EBindingSide InSide, FPropertyBindingDataView& OutDataView) override; #if WITH_EDITOR UE_API virtual bool GetBindingDataViewByID(const FGuid InStructID, FPropertyBindingDataView& OutDataView) const override; UE_API virtual bool GetBindableStructByID(const FGuid InStructID, TInstancedStruct& OutDesc) const override; UE_API virtual void GetBindableStructs(const FGuid InTargetStructID, TArray>& OutStructDescs) const override; UE_API virtual void CreateParametersForStruct(const FGuid InStructID, TArrayView InOutCreationDescs) override; UE_API virtual void OnPropertyBindingChanged(const FPropertyBindingPath& InSourcePath, const FPropertyBindingPath& InTargetPath) override; UE_API virtual FPropertyBindingBindingCollection* GetEditorPropertyBindings() override; UE_API virtual const FPropertyBindingBindingCollection* GetEditorPropertyBindings() const override; UE_API virtual FGuid GetFallbackStructID() const override; //~ End IPropertyBindingBindingCollectionOwner interface UE_API void UpdateSlotReferences(); /** Updates the path for all bindings from the associated value and remove invalid ones. */ UE_API void UpdateBindingPaths(); /** * Updates a single path and returns whether it is still valid. * @param Path The path to update and validate * @return Whether the path has been updated successfully and still valid */ UE_API bool UpdateAndValidatePath(FPropertyBindingPath& Path) const; UE_API FSmartObjectDefinitionDataHandle GetDataHandleByID(const FGuid StructID); UE_API virtual void GetPreloadDependencies(TArray& OutDeps) override; UE_API virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override; UE_API virtual void PreSave(FObjectPreSaveContext SaveContext) override; UE_API virtual void CollectSaveOverrides(FObjectCollectSaveOverridesContext SaveContext) override; UE_API virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override; #endif // WITH_EDITOR UE_API virtual void PostInitProperties() override; UE_API virtual void PostLoad() override; private: friend FSmartObjectBindingCollection; /** Finds first behavior definition of a given class in the provided list of definitions. */ static const USmartObjectBehaviorDefinition* GetBehaviorDefinitionByType(const TArray& BehaviorDefinitions, const TSubclassOf& DefinitionClass); void ApplyParameters(); bool GetDataView(const FSmartObjectDefinitionDataHandle DataHandle, FPropertyBindingDataView& OutDataView); #if WITH_EDITOR void EnsureValidGuids(); void UpdatePropertyBindings(); #endif // WITH_EDITOR /** Used internally by USmartObjectDefinition to store a variation of a definition asset. */ struct FSmartObjectDefinitionAssetVariation { FSmartObjectDefinitionAssetVariation() = default; FSmartObjectDefinitionAssetVariation(USmartObjectDefinition* InDefinitionAsset, uint64 InParametersHash) : DefinitionAsset(InDefinitionAsset) , ParametersHash(InParametersHash) { } /** Pointer to the asset variation which has the parameters applied to it. Stored as weak pointer, so that we can prune variations which are not used anymore. */ TWeakObjectPtr DefinitionAsset = nullptr; /** Hash of the variation properties. */ uint64 ParametersHash = 0; }; /** Variations of the asset based on provided parameters, created on demand via GetAssetVariation(). */ TArray Variations; /** Parameters for the SmartObject definition */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject", meta = (NoBinding)) FInstancedPropertyBag Parameters; /** Binding ID for the parameters. */ UPROPERTY() FGuid ParametersID; /** Binding ID for the whole asset. */ UPROPERTY() FGuid RootID; /** Property bindings. */ UPROPERTY(VisibleAnywhere, Category = "SmartObject", AdvancedDisplay) FSmartObjectBindingCollection BindingCollection; /** * 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. */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject") TArray Slots; /** List of behavior definitions of different types provided to SO's user if the slot does not provide one. */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject", Instanced) TArray> DefaultBehaviorDefinitions; /** This object is available if user tags match this query; always available if query is empty. */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject") FGameplayTagQuery UserTagFilter; #if WITH_EDITORONLY_DATA UE_DEPRECATED(5.6, "Use BindingCollection instead.") UPROPERTY(meta = (DeprecatedProperty, DeprecationMessage = "Use BindingCollection instead.")) TArray PropertyBindings_DEPRECATED; /** This object is available if instance tags match this query; always available if query is empty. */ UE_DEPRECATED(5.2, "FWorldCondition_SmartObjectActorTagQuery or FSmartObjectWorldConditionObjectTagQuery used in Preconditions instead.") UPROPERTY(meta = (DeprecatedProperty, DeprecationMessage = "Use FWorldCondition_SmartObjectActorTagQuery or FSmartObjectWorldConditionObjectTagQuery in Preconditions instead.")) FGameplayTagQuery ObjectTagFilter; #endif // WITH_EDITORONLY_DATA /** Preconditions that must pass for the object to be found/used. */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject", meta = (NoBinding)) FWorldConditionQueryDefinition Preconditions; private: /** Tags identifying this Smart Object's use case. Can be used while looking for objects supporting given activity */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject") FGameplayTagContainer ActivityTags; /** Custom definition data items (struct inheriting from SmartObjectDefinitionData) for the whole Smart Object. */ UPROPERTY(EditDefaultsOnly, Category = "SmartObject", meta=(DisallowedStructs="/Script/SmartObjectsModule.SmartObjectSlotAnnotation")) TArray DefinitionData; UPROPERTY(EditDefaultsOnly, Category = "SmartObject", AdvancedDisplay, meta = (NoBinding)) TSubclassOf WorldConditionSchemaClass; /** Indicates how Tags from slots and parent object are combined to be evaluated by a TagQuery from a find request. */ UPROPERTY(EditAnywhere, Category = "SmartObject", AdvancedDisplay, meta = (NoBinding)) 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, meta = (NoBinding)) ESmartObjectTagFilteringPolicy UserTagsFilteringPolicy; mutable TOptional bValid; friend class FSmartObjectSlotReferenceDetails; friend class FSmartObjectViewModel; friend class FSmartObjectAssetToolkit; friend class FSmartObjectDefinitionDetails; }; #undef UE_API