// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "SlateFwd.h" #include "Layout/Visibility.h" #include "Input/Reply.h" #include "PropertyPath.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SCompoundWidget.h" #include "IPropertyUtilities.h" #include "Widgets/Views/STableViewBase.h" #include "Widgets/Views/STableRow.h" #include "Widgets/Views/STreeView.h" #include "PropertyEditorDelegates.h" class AActor; class FNotifyHook; class FObjectPropertyNode; class FPropertyNode; typedef STreeView< TSharedPtr > SPropertyTree; class SPropertyTreeViewImpl : public SCompoundWidget { public: SLATE_BEGIN_ARGS( SPropertyTreeViewImpl ) : _IsLockable(true) , _HiddenPropertyVis( false ) , _AllowFavorites(true) , _AllowSearch( true ) , _ShowTopLevelNodes( true ) , _NotifyHook( NULL ) , _NameColumnWidth( 0.20f ) , _OnPropertySelectionChanged() , _OnPropertyMiddleClicked() , _ConstructExternalColumnHeaders() , _ConstructExternalColumnCell() {} SLATE_ARGUMENT( bool, IsLockable ) SLATE_ARGUMENT( bool, HiddenPropertyVis ); SLATE_ARGUMENT( bool, AllowFavorites ) SLATE_ARGUMENT( bool, AllowSearch ) SLATE_ARGUMENT( bool, ShowTopLevelNodes ) SLATE_ARGUMENT( FNotifyHook*, NotifyHook ) SLATE_ARGUMENT( float, NameColumnWidth ) SLATE_EVENT( FOnPropertySelectionChanged, OnPropertySelectionChanged ) SLATE_EVENT( FOnPropertyClicked, OnPropertyMiddleClicked ) SLATE_EVENT( FConstructExternalColumnHeaders, ConstructExternalColumnHeaders ) SLATE_EVENT( FConstructExternalColumnCell, ConstructExternalColumnCell ) SLATE_END_ARGS() SPropertyTreeViewImpl(); /** * Constructs the property view widgets */ void Construct(const FArguments& InArgs); /** Tells the property treeview to refresh its elements during the next tick */ virtual void RequestRefresh(); /** * Sets the objects that this property view will observe * * @param InObjects The list of objects to observe */ virtual void SetObjectArray( const TArray& InObjects ); virtual TSharedRef< FPropertyPath > GetRootPath() const; virtual void SetRootPath( const TSharedPtr< FPropertyPath >& Path ); /** * Replaces objects being observed by the view with new objects * * @param OldToNewObjectMap Mapping from objects to replace to their replacement */ virtual void ReplaceObjects( const TMap& OldToNewObjectMap ); /** * Removes objects from the view because they are about to be deleted * * @param DeletedObjects The objects to delete */ virtual void RemoveDeletedObjects( const TArray& DeletedObjects ); /** * Removes actors from the property nodes object array which are no longer available * * @param ValidActors The list of actors which are still valid */ virtual void RemoveInvalidActors( const TSet& ValidActors ); /** * Marks or unmarks a property node as a favorite. * * @param InPropertyNode The node to toggle favorite on */ virtual void ToggleFavorite( const TSharedRef< class FPropertyEditor >& PropertyEditor ); /** * Returns true if favorites are enabled for this property view */ virtual bool AreFavoritesEnabled() const { return bFavoritesEnabled; } /** * Creates the color picker window for this property view. * * @param Node The slate property node to edit. * @param bUseAlpha Whether or not alpha is supported */ virtual void CreateColorPickerWindow( const TSharedRef< class FPropertyEditor >& PropertyEditor, bool bUseAlpha ); /** * Returns true if the property window is locked and cant have its observed objects changed */ virtual bool IsLocked() const { return bIsLocked; } /** Returns the notify hook to use when properties change */ virtual FNotifyHook* GetNotifyHook() const { return NotifyHook; } /** Allows setting a custom delegate for deciding property visibility */ virtual void SetIsPropertyVisible( FIsPropertyVisible IsPropertyVisibleDelegate ); /** Sets the callback for when the property view changes */ virtual void SetOnObjectArrayChanged(FOnObjectArrayChanged OnObjectArrayChangedDelegate); /** Saves the expansion state of the property tree */ virtual void SaveExpandedItems(); /** Saves the widths of the columns in the property view */ virtual void SaveColumnWidths(); /** Gets the title for this property view based on objects being observed */ virtual FString GetTitle() const { return Title; } /** Expands all top level nodes */ virtual void ExpandAllNodes(); /** Enqueues an action to be executed next tick */ void EnqueueDeferredAction( FSimpleDelegate& DeferredAction ); /** * Sets the property tree to display from a node tree that always exists. * This puts the view into a mode where it does not refresh or rebuild the tree because it is managed externally * * @param RootNode The root of the existing property tree * @param PropertyToView The root of the displayed tree */ void SetFromExistingTree( TSharedPtr RootNode, TSharedPtr PropertyToView ); /** * Sets the filter text to the given value. */ virtual void SetFilterText( const FText& InFilterText ); /** Called when the filter text changes. This filters specific property nodes out of view */ void OnFilterTextChanged( const FText& InFilterText ); /** * Checks if the property or a child property is selected. * * @param InName The name of the property. * @param InArrayIndex The array index of the property. * * @return true if the Property is selected. */ virtual bool IsPropertySelected( const FString& InName, const int32 InArrayIndex = INDEX_NONE); /** * Checks if the property or a child property is selected. * * @param InName The name of the property. * @param InArrayIndex The array index of the property. * @param CheckChildren true if children should be checked. * * @return true if the Property or a child is selected. */ virtual bool IsPropertyOrChildrenSelected( const FString& InName, const int32 InArrayIndex = INDEX_NONE, const bool CheckChildren = true ); private: /** Delegate called when the property editor permission list is updated */ void OnPermissionListUpdated(TSoftObjectPtr, FName); /** Restores the expansion state in the tree for a specific object set */ void RestoreExpandedItems(); /** Restores the widths of the columns in the property view */ void RestoreColumnWidths(); /** Updates the top level property nodes. The root nodes for the treeview. */ void UpdateTopLevelPropertyNodes( TSharedPtr FirstVisibleNode ); /** Called before during SetObjectArray before we change the objects being observed */ void PreSetObject(); /** Called at the end of SetObjectArray after we change the objects being observed */ void PostSetObject(); // SWidget interface virtual void Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime ) override; // End of SWidget interface /** * Function called through a delegate on the property TreeView to request children of a property node * * @param InPropertyNode The property node to get children from * @param OutChildren The list of children of InPropertyNode that should be visible */ void OnGetChildrenForPropertyNode( TSharedPtr InPropertyNode, TArray< TSharedPtr >& OutChildren ); /** Check if a Property Node should be shown in the property tree if we have any external IsPropertyVisible delegates or permission lists */ bool IsPropertyNodeVisible(TSharedPtr InPropertyNode); /** * Function called through a delegate on the favorites TreeView to request children of a property node * * @param InPropertyNode The property node to get children from * @param OutChildren The list of children of InPropertyNode that should be visible */ void OnGetChildFavoritesForPropertyNode( TSharedPtr InPropertyNode, TArray< TSharedPtr >& OutChildren ); /** Called when the toggle favorites button is clicked */ FReply OnToggleFavoritesClicked(); /** Called when the locked button is clicked */ FReply OnLockButtonClicked(); /** * Hides or shows properties based on the passed in filter text * * @param InFilterText The filter text */ void FilterView( const FString& InFilterText ); /** Called when the favorites tree requests its visibility state */ EVisibility OnGetFavoritesVisibility() const; /** Returns the name of the image used for the icon on the filter button */ const FSlateBrush* OnGetFilterButtonImageResource() const; /** Returns the name of the image used for the icon on the favorites button */ const FSlateBrush* OnGetFavoriteButtonImageResource() const; /** Returns the name of the image used for the icon on the locked button */ const FSlateBrush* OnGetLockButtonImageResource() const; /** Reconstructs the entire property tree widgets */ void ConstructPropertyTree(); /** * Recursively marks nodes which should be favorite starting from the root */ void MarkFavorites(); /** * Recursively marks nodes which should be favorite * * @param InPropertyNode The property node to start marking favorites from * @param bAnyParentIsFavorite true of any parent of InPropertyNode is already marked as a favorite */ void MarkFavoritesInternal( TSharedPtr InPropertyNode, bool bAnyParentIsFavorite ); /** * Creates a property editor (the visual portion of a PropertyNode), for a specific property node * * @param InPropertyNode The property node to create the visual for */ TSharedRef CreatePropertyEditor( TSharedPtr InPropertyNode, const TSharedPtr& OwnerTable ); /** * Returns an SWidget used as the visual representation of a node in the property treeview. */ TSharedRef OnGenerateRowForPropertyTree( TSharedPtr InPropertyNode, const TSharedRef& OwnerTable ); /** Callback when property selection changes. */ void OnSelectionChanged( TSharedPtr InPropertyNode, ESelectInfo::Type SelectInfo ); /** * Loads favorites from INI */ void LoadFavorites(); /** * Saves favorites to INI */ void SaveFavorites(); /** * Requests that a property node's expansion state be changed due to being filtered * * @param PropertyNode The property node to change expansion state on * @param bExpand true to expand the node, false to collapse it */ void RequestItemExpanded( TSharedPtr PropertyNode, bool bExpand, bool bRecursiveExpansion = false ); private: /** List of properties which are favorites */ TSet FavoritesList; /** Stored set of expanded nodes before a filter was set */ TSet< TSharedPtr > PreFilterExpansionSet; /** Map of nodes that are requesting an automatic expansion/collapse due to being filtered */ TMap< TSharedPtr, bool > FilteredNodesRequestingExpansionState; /** Top level property nodes which are visible in the TreeView. These are always category nodes belonging to the RootPropertyNode */ TArray< TSharedPtr > TopLevelPropertyNodes; /** Top level favorite property nodes. These are root nodes of the favorite tree view */ TArray< TSharedPtr > TopLevelFavorites; /** Actions that should be executed next tick */ TArray DeferredActions; /** The root property node of the property tree for a specific set of UObjects */ TSharedPtr RootPropertyNode; /** Our property treeview */ TSharedPtr PropertyTree; /** Our property favorites treeview */ TSharedPtr FavoritesTree; /** The filter text box */ TSharedPtr FilterTextBox; /** The header row for the primary trees columns */ TSharedPtr< SHeaderRow > ColumnHeaderRow; /** Settings for this property view */ TSharedPtr PropertySettings; /** The current filter text */ FString CurrentFilterText; /** The title of the property view (for a window title) */ FString Title; /** Notify hook to call when properties are changed */ FNotifyHook* NotifyHook; /** True if there is an active filter (text in the filter box) */ bool bHasActiveFilter; /** True if this property view can be locked */ bool bLockable; /** True if this property view is currently locked (I.E The objects being observed are not changed automatically due to user selection)*/ bool bIsLocked; /** True if this property view allows favorites to visible and modified */ bool bFavoritesAllowed; /** True if favorites are currently enabled */ bool bFavoritesEnabled; /** True if we allow searching */ bool bAllowSearch; /** True if the property view shows all properties regardless of their flags */ bool bForceHiddenPropertyVisibility; /** Whether or not this tree view manages and creates property nodes or whether the nodes are externally managed */ bool bNodeTreeExternallyManaged; /** Whether or not this tree should ever display top level property nodes as categories */ bool bShowTopLevelPropertyNodes; /** Callback to send when the property view changes */ FOnObjectArrayChanged OnObjectArrayChanged; /** Callback when property selection changes. */ FOnPropertySelectionChanged OnPropertySelectionChanged; /** Callback when a property is clicked with the middle mouse button by the user */ FOnPropertyClicked OnPropertyMiddleClicked; /** Callback to see if a property is visible */ FIsPropertyVisible IsPropertyVisible; /** The initial width of the name column */ float InitialNameColumnWidth; /** The path to the property node that should be treated as the root */ TSharedRef< class FPropertyPath > RootPath; /** Called to construct any extra column headers external code wants to expose */ FConstructExternalColumnHeaders ConstructExternalColumnHeaders; /** Called to construct any the cell contents for columns created by external code*/ FConstructExternalColumnCell ConstructExternalColumnCell; };