// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "DetailFilter.h" #include "UObject/WeakObjectPtr.h" #include "PropertyPath.h" #include "TickableEditorObject.h" #include "IPropertyUtilities.h" #include "PropertyEditorModule.h" #include "IPropertyRowGenerator.h" class FDetailCategoryImpl; class FDetailLayoutBuilderImpl; class FPropertyNode; class IDetailCustomization; class IDetailNodeTree; class FComplexPropertyNode; class FDetailTreeNode; class IPropertyGenerationUtilities; class FStructOnScope; class IStructureDataProvider; struct FPropertyNodeMap { FPropertyNodeMap() : ParentProperty(NULL) {} /** Object property node which contains the properties in the node map */ FPropertyNode* ParentProperty; /** Property name to property node map */ TMap > PropertyNameToNode; bool Contains(FName PropertyName) const { return PropertyNameToNode.Contains(PropertyName); } void Add(FName PropertyName, TSharedPtr& PropertyNode) { PropertyNameToNode.Add(PropertyName, PropertyNode); } }; /** Mapping of categories to all top level item property nodes in that category */ typedef TMap > FCategoryMap; /** Class to properties in that class */ typedef TMap FClassInstanceToPropertyMap; /** Class to properties in that class */ typedef TMap FClassToPropertyMap; struct FDetailLayoutData { TSharedPtr DetailLayout; FClassToPropertyMap ClassToPropertyMap; /** A unique classes being viewed */ TSet> ClassesWithProperties; /** Customization class instances currently active in this view */ TArray> CustomizationClassInstances; }; class FPropertyRowGenerator : public IPropertyRowGenerator, public FTickableEditorObject, public TSharedFromThis { public: FPropertyRowGenerator(const FPropertyRowGeneratorArgs& InArgs); UE_DEPRECATED(5.0, "FPropertyRowGenerator which takes in a thumbnail pool parameter is no longer necessary.") FPropertyRowGenerator(const FPropertyRowGeneratorArgs& InArgs, TSharedPtr InThumbnailPool); ~FPropertyRowGenerator(); DECLARE_DERIVED_EVENT(FPropertyRowGenerator, IPropertyRowGenerator::FOnRowsRefreshed, FOnRowsRefreshed); /** IPropertyRowGenerator interface */ virtual void SetObjects(const TArray& InObjects) override; virtual void SetStructure(const TSharedPtr& InStruct) override; virtual void SetStructure(const TSharedPtr& InStructProvider) override; virtual const TArray>& GetSelectedObjects() const override { return SelectedObjects; } virtual const TArray>& GetRootTreeNodes() const override; virtual TSharedPtr FindTreeNode(TSharedPtr PropertyHandle) const override; virtual TArray> FindTreeNodes(const TArray>& PropertyHandles) const override; virtual FOnRowsRefreshed& OnRowsRefreshed() override { return RowsRefreshedDelegate; } virtual void RegisterInstancedCustomPropertyLayout(UStruct* Class, FOnGetDetailCustomizationInstance DetailLayoutDelegate) override; virtual void RegisterInstancedCustomPropertyTypeLayout(FName PropertyTypeName, FOnGetPropertyTypeCustomizationInstance PropertyTypeLayoutDelegate, TSharedPtr Identifier = nullptr) override; virtual void UnregisterInstancedCustomPropertyLayout(UStruct* Class) override; virtual void UnregisterInstancedCustomPropertyTypeLayout(FName PropertyTypeName, TSharedPtr Identifier = nullptr) override; virtual void SetCustomValidatePropertyNodesFunction(FOnValidatePropertyRowGeneratorNodes InCustomValidatePropertyNodesFunction) override { CustomValidatePropertyNodesFunction = MoveTemp(InCustomValidatePropertyNodesFunction); } /** This function sets property paths to generate PropertyNodes.This improves the performance for cases where PropertyView is only showing a few properties of the object by not generating all other PropertyNodes */ virtual void SetPropertyGenerationAllowListPaths(const TSet& InPropertyGenerationAllowListPaths) override; virtual void InvalidateCachedState() override; virtual void FilterNodes(const TArray& InFilterStrings) override; /** FTickableEditorObject interface */ virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; } virtual void Tick(float DeltaTime) override; virtual TStatId GetStatId() const override; /** IPropertyUtilities interface */ virtual class FNotifyHook* GetNotifyHook() const { return Args.NotifyHook; } virtual void EnqueueDeferredAction(FSimpleDelegate DeferredAction); virtual bool IsPropertyEditingEnabled() const; virtual void ForceRefresh(); virtual void RequestRefresh() { bRefreshPending = true; } virtual TSharedPtr GetThumbnailPool() const; virtual bool HasClassDefaultObject() const { return bViewingClassDefaultObject; } virtual const TArray>& GetClassViewerFilters() const; const FCustomPropertyTypeLayoutMap& GetInstancedPropertyTypeLayoutMap() const; void UpdateDetailRows(); virtual FOnNotifyStartedChangingProperties& OnNotifyStartedChangingProperties() override { return OnNotifyStartedChangingPropertiesDelegate; } virtual FOnFinishedChangingProperties& OnFinishedChangingProperties() override { return OnFinishedChangingPropertiesDelegate; } private: void PreSetObject(int32 NumNewObjects, bool bHasStructRoots); void PostSetObject(); void UpdatePropertyMaps(); void UpdateSinglePropertyMap(TSharedPtr InRootPropertyNode, FDetailLayoutData& LayoutData); bool ValidatePropertyNodes(const FRootPropertyNodeList& PropertyNodeList); TSharedPtr FindTreeNodeRecursive(const TSharedPtr& StartNode, TSharedPtr PropertyHandle) const; void LayoutNodeVisibilityChanged(); private: const FPropertyRowGeneratorArgs Args; /** The root property nodes of the property tree for a specific set of UObjects */ FRootPropertyNodeList RootPropertyNodes; /** Root tree nodes that needs to be destroyed when safe */ FRootPropertyNodeList RootNodesPendingKill; /** Root tree nodes visible in the tree */ TArray> RootTreeNodes; /** The current detail layout based on objects in this details panel. There is one layout for each top level object node.*/ TArray DetailLayouts; /** Customization instances that need to be destroyed when safe to do so */ TArray> CustomizationClassInstancesPendingDelete; /** Actions that should be executed next tick */ TArray DeferredActions; /** Currently viewed objects */ TArray> SelectedObjects; /** Delegate to call when the user of this generator needs to know the rows are invalid */ FOnRowsRefreshed RowsRefreshedDelegate; /** A mapping of type names to detail layout delegates, called when querying for custom detail layouts in this instance of the details view only */ FCustomPropertyTypeLayoutMap InstancedTypeToLayoutMap; /** A mapping of classes to detail layout delegates, called when querying for custom detail layouts in this instance of the details view only*/ FCustomDetailLayoutMap InstancedClassToDetailLayoutMap; /** Utility class for accessing commonly used helper methods from customizations */ TSharedRef PropertyUtilities; /** Utility class for accessing internal helper methods */ TSharedRef PropertyGenerationUtilities; /** Delegate called when the details panel finishes editing a property (after post edit change is called) */ FOnFinishedChangingProperties OnFinishedChangingPropertiesDelegate; /** Delegate called before the details panel finishes editing a property (after pre edit change is called) */ FOnNotifyStartedChangingProperties OnNotifyStartedChangingPropertiesDelegate; /** The ValidatePropertyNodes function can be overridden with this member, if set. Useful if your implementation doesn't require this kind of validation each Tick. */ FOnValidatePropertyRowGeneratorNodes CustomValidatePropertyNodesFunction; /** If specified only nodes for these properties will be generated */ TSet PropertyGenerationAllowListPaths; /** Filter to apply on generated rows nodes */ FDetailFilter CurrentFilter; bool bViewingClassDefaultObject = false; bool bRefreshPending = false; };