// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Misc/Attribute.h" #include "Layout/Visibility.h" #include "AssetThumbnail.h" #include "IPropertyUtilities.h" #include "PropertyNode.h" #include "IPropertyTypeCustomization.h" #include "DetailWidgetRow.h" #include "DetailCategoryBuilderImpl.h" #include "Presentation/PropertyEditor/PropertyEditor.h" #include "IDetailPropertyRow.h" #include "PropertyEditorHelpers.h" struct FAddPropertyParams; class FCustomChildrenBuilder; class IDetailGroup; class FDetailPropertyRow : public IDetailPropertyRow, public IPropertyTypeCustomizationUtils, public IDetailLayoutRow, public TSharedFromThis { public: FDetailPropertyRow(TSharedPtr InPropertyNode, TSharedRef InParentCategory, TSharedPtr InExternalRootNode = nullptr); /** IDetailPropertyRow interface */ virtual TSharedPtr GetPropertyHandle() const override { return PropertyHandle; } virtual IDetailPropertyRow& DisplayName( const FText& InDisplayName ) override; virtual IDetailPropertyRow& ToolTip( const FText& InToolTip ) override; virtual IDetailPropertyRow& ShowPropertyButtons( bool bInShowPropertyButtons ) override; virtual IDetailPropertyRow& EditCondition( TAttribute EditConditionValue, FOnBooleanValueChanged OnEditConditionValueChanged, ECustomEditConditionMode EditConditionMode = ECustomEditConditionMode::Override ) override; virtual IDetailPropertyRow& EditConditionHides(bool bEditConditionHideValue) override; virtual IDetailPropertyRow& IsEnabled(TAttribute InIsEnabled) override; virtual IDetailPropertyRow& ShouldAutoExpand(bool bForceExpansion) override; virtual IDetailPropertyRow& Visibility( TAttribute Visibility ) override; virtual IDetailPropertyRow& OverrideResetToDefault(const FResetToDefaultOverride& ResetToDefault) override; virtual IDetailPropertyRow& DragDropHandler(TSharedPtr InDragDropHandler) override; virtual bool IsExpanded() const override; virtual FDetailWidgetRow& CustomWidget( bool bShowChildren = false ) override; virtual FDetailWidgetDecl* CustomNameWidget() override; virtual FDetailWidgetDecl* CustomValueWidget() override; virtual FDetailWidgetDecl* CustomResetToDefaultWidget() override; virtual void GetDefaultWidgets( TSharedPtr& OutNameWidget, TSharedPtr& OutValueWidget, bool bAddWidgetDecoration = false) override; virtual void GetDefaultWidgets( TSharedPtr& OutNameWidget, TSharedPtr& OutValueWidget, FDetailWidgetRow& Row, bool bAddWidgetDecoration = false) override; /** IPropertyTypeCustomizationUtils interface */ virtual TSharedPtr GetThumbnailPool() const override; virtual TSharedPtr GetPropertyUtilities() const override; /** IDetailLayoutRow interface */ virtual FName GetRowName() const override; virtual TOptional GetCustomResetToDefault() const override { return CustomResetToDefault; } /** @return true if this row has widgets with columns */ bool HasColumns() const; /** @return true if this row shows only children and is not visible itself */ bool ShowOnlyChildren() const; /** @return true if this row should be ticked */ bool RequiresTick() const; /** @return true if this row has an external property */ bool HasExternalProperty() const { return ExternalRootNode.IsValid(); } /** Sets the custom name that should be used to save and restore this nodes expansion state */ void SetCustomExpansionId(const FName ExpansionIdName) { CustomExpansionIdName = ExpansionIdName; } /** @return Gets the custom name that should be used to save and restore this nodes expansion state */ FName GetCustomExpansionId() const { return CustomExpansionIdName; } /** * Sets whether or not we force only children to be shown regardless of what the customization wants. * Typically used when this row is only for organizational purposes and doesnt have anything valid to show (like external object nodes) */ void SetForceShowOnlyChildren(bool bInForceShowOnlyChildren) { bForceShowOnlyChildren = bInForceShowOnlyChildren; } /** * Called when the owner node is initialized * * @param InParentCategory The category that this property is in * @param InIsParentEnabled Whether or not our parent is enabled */ void OnItemNodeInitialized( TSharedRef InParentCategory, const TAttribute& InIsParentEnabled, TSharedPtr InParentGroup); /** @return The widget row that should be displayed for this property row */ FDetailWidgetRow GetWidgetRow(); /** @return properties being customized */ TArrayView> GetPropertyHandles() const; /** @return the filter text associated with this row, if any */ FText GetFilterTextString() const; /** * @return The property node for this row */ TSharedPtr GetPropertyNode() const { return PropertyNode; } /** * @return The external root node for this row if it has one. */ TSharedPtr GetExternalRootNode() const { return ExternalRootNode; } /** * @return The property editor for this row */ TSharedPtr GetPropertyEditor() { return PropertyEditor; } /** * Called when children of this row should be generated * * @param OutChildren The list of children created */ void OnGenerateChildren( FDetailNodeList& OutChildren ); /** * @return Whether or not this row wants to force expansion */ bool GetForceAutoExpansion() const; /** * @return The visibility of this property */ EVisibility GetPropertyVisibility() const; static void MakeExternalPropertyRowCustomization(TSharedPtr StructData, FName PropertyName, TSharedRef ParentCategory, struct FDetailLayoutCustomization& OutCustomization, const FAddPropertyParams& Parameters); static void MakeExternalPropertyRowCustomization(TSharedPtr StructDataProvider, FName PropertyName, TSharedRef ParentCategory, struct FDetailLayoutCustomization& OutCustomization, const FAddPropertyParams& Parameters); static void MakeExternalPropertyRowCustomization(const TArray& InObjects, FName PropertyName, TSharedRef ParentCategory, struct FDetailLayoutCustomization& OutCustomization, const FAddPropertyParams& Parameters); static void MakeChildPropertyRowCustomization(TSharedRef PropertyHandle, TSharedPtr StructDataProvider, FName PropertyName, TSharedRef ParentCategory, struct FDetailLayoutCustomization& OutCustomization, const FAddPropertyParams& Parameters, const FText& DisplayNameOverride = FText()); private: /** * Makes a name widget or key widget for the tree */ void MakeNameOrKeyWidget( FDetailWidgetRow& Row, const TSharedPtr InCustomRow ) const; /** * Makes the value widget for the tree */ void MakeValueWidget( FDetailWidgetRow& Row, const TSharedPtr InCustomRow, bool bAddWidgetDecoration = true ) const; /** * Set the given widget row's custom properties. Note: Should be called before MakeNameOrKeyWidget and MakeValueWidget. */ void SetWidgetRowProperties( FDetailWidgetRow& Row ) const; /** * @return true if this row has an edit condition */ bool HasEditCondition() const; /** * @return Whether or not this row is enabled */ bool GetEnabledState() const; /** * @return true if this row's edit condition has been met */ bool IsEditConditionMet() const; /** * @return true if this row should be shown/hidden based on the edit condition state */ bool IsOnlyVisibleWhenEditConditionMet() const; /** * Looks up and caches (if not already) the associated type interface, and then returns it. * Could be null/invalid if no customization was specified for this row. * * Creating the CustomTypeInterface on demand, instead of at construction, allows for * IDetailCustomization's to override custom property type layouts via a IDetailLayoutBuilder. * */ TSharedPtr& GetTypeInterface(); /** * Generates children for the property node * * @param RootPropertyNode The property node to generate children for (May be a child of the property node being stored) * @param OutChildren The list of children created */ void GenerateChildrenForPropertyNode( TSharedPtr& RootPropertyNode, FDetailNodeList& OutChildren ); /** * Makes a property editor from the property node on this row * * @param InPropertyNode The node to create the editor for * @param PropertyUtilities Utilities for the property editor * @param InEditor The editor we wish to create if it does not yet exist. */ static TSharedRef MakePropertyEditor( const TSharedRef& InPropertyNode, const TSharedRef& PropertyUtilities, TSharedPtr& InEditor ); /** * Gets the property customization for the specified node * * @param InPropertyNode The node to check for customizations * @param InParentCategory The node's parent category * @return The property customization for the node, or null if one does not exist */ static TSharedPtr GetPropertyCustomization( const TSharedRef& InPropertyNode, const TSharedRef& InParentCategory ); /** Does the given property node require a key node to be created, or is a key property editor sufficient? */ static bool NeedsKeyNode(TSharedRef InPropertyNode, TSharedRef InParentCategory); private: /** User driven enabled state */ TAttribute CustomIsEnabledAttrib; /** Whether or not our parent is enabled */ TAttribute IsParentEnabled; /** Visibility of the property */ TAttribute PropertyVisibility; /** If the property on this row is a customized property type, this is the interface to that customization */ TSharedPtr CachedCustomTypeInterface; /** Builder for children of a customized property type */ TSharedPtr PropertyTypeLayoutBuilder; /** The property handle for this row */ TSharedPtr PropertyHandle; /** The property node for this row */ TSharedPtr PropertyNode; /** The property editor for this row */ TSharedPtr PropertyEditor; /** The property editor for this row's key */ TSharedPtr PropertyKeyEditor; /** The property Type customization for this row's key */ TSharedPtr CachedKeyCustomTypeInterface; /** Custom widgets to use for this row instead of the default ones */ TSharedPtr CustomPropertyWidget; /** User customized edit condition */ TAttribute CustomEditConditionValue; /** User customized edit condition change handler. */ FOnBooleanValueChanged CustomEditConditionValueChanged; /** Should this custom edit condition override or merge with the existing edit condition of the property (if any)? */ ECustomEditConditionMode CustomEditConditionMode = ECustomEditConditionMode::Override; /** User customized edit condition hides specifier */ bool bCustomEditConditionHides = false; /** User customized reset to default */ TOptional CustomResetToDefault; /** User customized drag/drop handler */ TSharedPtr CustomDragDropHandler; /** The category this row resides in */ TWeakPtr ParentCategory; /** Root of the property node if this node comes from an external tree */ TSharedPtr ExternalRootNode; TSharedPtr ExternalObjectLayout; /** The custom expansion ID name used to save and restore expansion state on this node */ FName CustomExpansionIdName; /** Whether or not to show standard property buttons */ bool bShowPropertyButtons; /** True to show custom property children */ bool bShowCustomPropertyChildren; /** True to force auto-expansion */ bool bForceAutoExpansion; /** True if we've already attempted to fill out our CustomTypeInterface (no need to rerun the query) */ bool bCachedCustomTypeInterface; /** True if this row is only for organizational purposes and doesnt have anything valid to show itself*/ bool bForceShowOnlyChildren = false; };