1083 lines
37 KiB
C++
1083 lines
37 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
#pragma once
|
|
|
|
#include "EditorUndoClient.h"
|
|
#include "Framework/Commands/UICommandList.h"
|
|
#include "Framework/Views/ITypedTableView.h"
|
|
#include "Input/Reply.h"
|
|
#include "Layout/Visibility.h"
|
|
#include "Misc/Attribute.h"
|
|
#include "Misc/TextFilter.h"
|
|
#include "SlateFwd.h"
|
|
#include "Styling/SlateColor.h"
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "Widgets/SWidget.h"
|
|
#include "Widgets/Views/STableRow.h"
|
|
#include "Widgets/Views/STableViewBase.h"
|
|
#include "Delegates/DelegateCombinations.h"
|
|
#include "Framework/Views/ITypedTableView.h"
|
|
#include "Types/SlateEnums.h"
|
|
#include "Folder.h"
|
|
|
|
#include "ISceneOutliner.h"
|
|
#include "SceneOutlinerFwd.h"
|
|
|
|
#include "SOutlinerTreeView.h"
|
|
#include "SceneOutlinerPublicTypes.h"
|
|
#include "SceneOutlinerStandaloneTypes.h"
|
|
|
|
#include "ISceneOutlinerHierarchy.h"
|
|
#include "SceneOutlinerDragDrop.h"
|
|
|
|
#include "SceneOutlinerSCCHandler.h"
|
|
#include "SceneOutlinerTreeItemSCC.h"
|
|
|
|
class FMenuBuilder;
|
|
class UToolMenu;
|
|
class ISceneOutlinerColumn;
|
|
class SComboButton;
|
|
class ULevel;
|
|
struct FToolMenuSection;
|
|
template<typename FilterType> class SFilterBar;
|
|
template<typename ItemType> class STreeView;
|
|
class SFilterSearchBox;
|
|
struct FCustomTextFilterData;
|
|
template<typename FilterType> class ICustomTextFilter;
|
|
|
|
SCENEOUTLINER_API DECLARE_LOG_CATEGORY_EXTERN(LogSceneOutliner, Log, All);
|
|
|
|
/**
|
|
* Scene Outliner definition
|
|
* Note the Scene Outliner is also called the World Outliner
|
|
*/
|
|
namespace SceneOutliner
|
|
{
|
|
DECLARE_EVENT_OneParam(SSceneOutliner, FTreeItemPtrEvent, FSceneOutlinerTreeItemPtr);
|
|
|
|
DECLARE_EVENT_TwoParams(SSceneOutliner, FOnItemSelectionChanged, FSceneOutlinerTreeItemPtr, ESelectInfo::Type);
|
|
|
|
typedef TTextFilter< const ISceneOutlinerTreeItem& > TreeItemTextFilter;
|
|
|
|
/** Structure that defines an operation that should be applied to the tree */
|
|
struct FPendingTreeOperation
|
|
{
|
|
enum EType { Added, Removed, Moved };
|
|
FPendingTreeOperation(EType InType, TSharedRef<ISceneOutlinerTreeItem> InItem) : Type(InType), Item(InItem) { }
|
|
|
|
/** The type of operation that is to be applied */
|
|
EType Type;
|
|
|
|
/** The tree item to which this operation relates */
|
|
FSceneOutlinerTreeItemRef Item;
|
|
};
|
|
|
|
/** Set of actions to apply to new tree items */
|
|
namespace ENewItemAction
|
|
{
|
|
enum Type : uint8
|
|
{
|
|
/** Do nothing when it is created */
|
|
None = 0,
|
|
/** Select the item when it is created */
|
|
Select = 1 << 0,
|
|
/** Scroll the item into view when it is created */
|
|
ScrollIntoView = 1 << 1,
|
|
/** Interactively rename the item when it is created (implies the above) */
|
|
Rename = 1 << 2,
|
|
};
|
|
}
|
|
|
|
namespace ExtensionHooks
|
|
{
|
|
static FName Hierarchy(TEXT("Hierarchy"));
|
|
static FName Show(TEXT("Show"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stores a set of selected items with parsing functions for the scene outliner
|
|
*/
|
|
struct FSceneOutlinerItemSelection
|
|
{
|
|
/** Set of selected items */
|
|
mutable TArray<TWeakPtr<ISceneOutlinerTreeItem>> SelectedItems;
|
|
|
|
FSceneOutlinerItemSelection() {}
|
|
|
|
FSceneOutlinerItemSelection(const TArray<FSceneOutlinerTreeItemPtr>& InSelectedItems)
|
|
: SelectedItems(InSelectedItems) {}
|
|
|
|
FSceneOutlinerItemSelection(SSceneOutlinerTreeView& Tree)
|
|
: FSceneOutlinerItemSelection(Tree.GetSelectedItems()) {}
|
|
|
|
/** Returns true if the selection has an item of a specified type */
|
|
template <typename TreeType>
|
|
bool Has() const
|
|
{
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (const auto ItemPtr = Item.Pin())
|
|
{
|
|
if (ItemPtr->IsA<TreeType>())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Returns the total number of items in the selection */
|
|
uint32 Num() const
|
|
{
|
|
return SelectedItems.Num();
|
|
}
|
|
|
|
/** Returns the number of items of the specified types in the selection */
|
|
template <typename ...TreeTypes>
|
|
uint32 Num() const
|
|
{
|
|
uint32 Result = 0;
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (const auto ItemPtr = Item.Pin())
|
|
{
|
|
if ((ItemPtr->IsA<TreeTypes>() || ...))
|
|
{
|
|
++Result;
|
|
}
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/** Add a new item to the selection */
|
|
void Add(FSceneOutlinerTreeItemPtr NewItem)
|
|
{
|
|
SelectedItems.Add(NewItem);
|
|
}
|
|
|
|
/** Get all items of a specified type */
|
|
template <typename TreeType>
|
|
void Get(TArray<TreeType*>& OutArray) const
|
|
{
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (const auto ItemPtr = Item.Pin())
|
|
{
|
|
if (TreeType* CastedItem = ItemPtr->CastTo<TreeType>())
|
|
{
|
|
OutArray.Add(CastedItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Get(TArray<FSceneOutlinerTreeItemPtr>& OutArray) const
|
|
{
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (const auto ItemPtr = Item.Pin())
|
|
{
|
|
OutArray.Add(ItemPtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Apply a function to each item of a specified type */
|
|
template <typename TreeType>
|
|
void ForEachItem(TFunctionRef<void(TreeType&)> Func) const
|
|
{
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (const auto ItemPtr = Item.Pin())
|
|
{
|
|
if (TreeType* CastedItem = ItemPtr->CastTo<TreeType>())
|
|
{
|
|
Func(*CastedItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Apply a function to every item in the selection regardless of type. */
|
|
void ForEachItem(TFunctionRef<void(FSceneOutlinerTreeItemPtr&)> Func) const
|
|
{
|
|
for (const TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
if (auto ItemPtr = Item.Pin())
|
|
{
|
|
Func(ItemPtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Use a selector to retrieve a specific data type from items in the selection. Will only add an item's data if the selector returns true for that item. */
|
|
template <typename DataType>
|
|
TArray<DataType> GetData(TFunctionRef<bool(const TWeakPtr<ISceneOutlinerTreeItem>&, DataType&)> Selector) const
|
|
{
|
|
TArray<DataType> Result;
|
|
for (TWeakPtr<ISceneOutlinerTreeItem>& Item : SelectedItems)
|
|
{
|
|
DataType Data;
|
|
if (Selector(Item, Data))
|
|
{
|
|
Result.Add(Data);
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Scene Outliner widget
|
|
*/
|
|
class SCENEOUTLINER_API SSceneOutliner : public ISceneOutliner, public FEditorUndoClient, public FGCObject
|
|
{
|
|
|
|
public:
|
|
|
|
SLATE_BEGIN_ARGS(SSceneOutliner)
|
|
{}
|
|
SLATE_END_ARGS()
|
|
|
|
/**
|
|
* Construct this widget. Called by the SNew() Slate macro.
|
|
*
|
|
* @param InArgs Declaration used by the SNew() macro to construct this widget
|
|
* @param InitOptions Programmer-driven initialization options for this widget
|
|
*/
|
|
void Construct(const FArguments& InArgs, const FSceneOutlinerInitializationOptions& InitOptions);
|
|
|
|
/** Default constructor - initializes data that is shared between all tree items */
|
|
SSceneOutliner()
|
|
: SharedData(MakeShareable(new FSharedSceneOutlinerData))
|
|
, Filters(MakeShareable(new FSceneOutlinerFilters))
|
|
, InteractiveFilters(MakeShareable(new FSceneOutlinerFilters))
|
|
{}
|
|
|
|
/** SSceneOutliner destructor */
|
|
virtual ~SSceneOutliner();
|
|
|
|
/** SWidget interface */
|
|
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
|
virtual bool SupportsKeyboardFocus() const override;
|
|
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
|
|
|
|
/** Sends a requests to the Scene Outliner to refresh itself the next chance it gets */
|
|
virtual void Refresh() override;
|
|
|
|
void RefreshSelection();
|
|
|
|
//~ Begin FEditorUndoClient Interface
|
|
virtual void PostUndo(bool bSuccess) override;
|
|
virtual void PostRedo(bool bSuccess) override { PostUndo(bSuccess); }
|
|
// End of FEditorUndoClient
|
|
|
|
/** @return Returns the common data for this outliner */
|
|
virtual const FSharedSceneOutlinerData& GetSharedData() const override
|
|
{
|
|
return *SharedData;
|
|
}
|
|
|
|
/** Get a const reference to the actual tree hierarchy */
|
|
virtual const STreeView<FSceneOutlinerTreeItemPtr>& GetTree() const override
|
|
{
|
|
return *OutlinerTreeView;
|
|
}
|
|
|
|
virtual const TSharedPtr< SSceneOutlinerTreeView>& GetTreeView() const
|
|
{
|
|
return OutlinerTreeView;
|
|
}
|
|
|
|
/** @return Returns a string to use for highlighting results in the outliner list */
|
|
virtual TAttribute<FText> GetFilterHighlightText() const override;
|
|
|
|
/** Set the keyboard focus to the outliner */
|
|
virtual void SetKeyboardFocus() override;
|
|
|
|
/** Gets the cached icon for this class name */
|
|
virtual const FSlateBrush* GetCachedIconForClass(FName InClassName) const override;
|
|
|
|
/** Sets the cached icon for this class name */
|
|
virtual void CacheIconForClass(FName InClassName, const FSlateBrush* InSlateBrush) override;
|
|
|
|
/** Should the scene outliner accept a request to rename a object */
|
|
virtual bool CanExecuteRenameRequest(const ISceneOutlinerTreeItem& ItemPtr) const override;
|
|
|
|
/**
|
|
* Add a filter to the scene outliner
|
|
* @param Filter The filter to apply to the scene outliner
|
|
* @return The index of the filter.
|
|
*/
|
|
virtual int32 AddFilter(const TSharedRef<FSceneOutlinerFilter>& Filter) override;
|
|
|
|
/**
|
|
* Add a filter to the scene outliner's filter bar
|
|
* @param Filter The filter to add
|
|
*/
|
|
virtual void AddFilterToFilterBar(const TSharedRef<FFilterBase<SceneOutliner::FilterBarType>>& InFilter) override;
|
|
|
|
/**
|
|
* Disable all filters currently active in the filter bar
|
|
* @param bRemove if true, the filter will also be unpinned and removed from the filter bar
|
|
*/
|
|
virtual void DisableAllFilterBarFilters(bool bRemove) override;
|
|
|
|
|
|
/**
|
|
* Remove a filter from the scene outliner
|
|
* @param Filter The Filter to remove
|
|
* @return True if the filter was removed.
|
|
*/
|
|
virtual bool RemoveFilter(const TSharedRef<FSceneOutlinerFilter>& Filter) override;
|
|
|
|
/**
|
|
* Add an interactive filter to the scene outliner
|
|
* @param Filter The filter used to determine if scene outliner items are interactive.
|
|
* @return The index of the filter.
|
|
*/
|
|
virtual int32 AddInteractiveFilter(const TSharedRef<FSceneOutlinerFilter>& Filter) override;
|
|
|
|
/**
|
|
* Remove an interactive filter from the scene outliner
|
|
* @param Filter The Filter to remove
|
|
* @return True if the filter was removed.
|
|
*/
|
|
virtual bool RemoveInteractiveFilter(const TSharedRef<FSceneOutlinerFilter>& Filter) override;
|
|
|
|
/**
|
|
* Retrieve the filter at the specified index
|
|
* @param Index The index of the filter to retrive
|
|
* @return A valid poiter to a filter if the index was valid
|
|
*/
|
|
virtual TSharedPtr<FSceneOutlinerFilter> GetFilterAtIndex(int32 Index) override;
|
|
|
|
/** Get number of filters applied to the scene outliner */
|
|
virtual int32 GetFilterCount() const override;
|
|
|
|
/**
|
|
* Add or replace a column of the scene outliner
|
|
* Note: The column id must match the id of the column returned by the factory
|
|
* @param ColumnId The id of the column to add
|
|
* @param ColumnInfo The struct that contains the information on how to present and retrieve the column
|
|
*/
|
|
virtual void AddColumn(FName ColumnId, const FSceneOutlinerColumnInfo& ColumnInfo) override;
|
|
|
|
/**
|
|
* Remove a column of the scene outliner
|
|
* @param ColumnId The name of the column to remove
|
|
*/
|
|
virtual void RemoveColumn(FName ColumnId) override;
|
|
|
|
void SetColumnVisibility(FName ColumnId, bool bIsVisible);
|
|
|
|
/** Return the name/Id of the columns of the scene outliner */
|
|
virtual TArray<FName> GetColumnIds() const override;
|
|
|
|
/** @return Returns the current sort mode of the specified column */
|
|
virtual EColumnSortMode::Type GetColumnSortMode(const FName ColumnId) const;
|
|
|
|
/** Request that the tree be sorted at a convenient time */
|
|
virtual void RequestSort();
|
|
|
|
/** Returns true if edit delete can be executed */
|
|
virtual bool Delete_CanExecute();
|
|
|
|
/** Returns true if edit rename can be executed */
|
|
virtual bool Rename_CanExecute();
|
|
|
|
/** Executes rename. */
|
|
virtual void Rename_Execute();
|
|
|
|
/** Returns true if edit cut can be executed */
|
|
virtual bool Cut_CanExecute();
|
|
|
|
/** Returns true if edit copy can be executed */
|
|
virtual bool Copy_CanExecute();
|
|
|
|
/** Returns true if edit paste can be executed */
|
|
virtual bool Paste_CanExecute();
|
|
|
|
/** Can the scene outliner rows generated on drag event */
|
|
virtual bool CanSupportDragAndDrop() const override;
|
|
|
|
/** Tells the scene outliner that it should do a full refresh, which will clear the entire tree and rebuild it from scratch. */
|
|
virtual void FullRefresh() override;
|
|
|
|
/** Hook to add custom options to toolbar in a derived class */
|
|
virtual void CustomAddToToolbar(TSharedPtr<class SHorizontalBox> Toolbar) {}
|
|
|
|
/** Check if a filter with the given name exists and is active in the filter bar for this Outliner (if this Outliner has a filter bar). */
|
|
virtual bool IsFilterActive(const FString& FilterName) const override;
|
|
|
|
/** Retrieve an ISceneOutlinerTreeItem by its ID if it exists in the tree */
|
|
virtual FSceneOutlinerTreeItemPtr GetTreeItem(FSceneOutlinerTreeItemID, bool bIncludePending = false) override;
|
|
|
|
/** Set a delay (in seconds) before the the next requested UI refresh executes. Note: This only applies until the next refresh that executes
|
|
* and any subsequent ones will be immediate. */
|
|
virtual void SetNextUIRefreshDelay(float InDelay) override;
|
|
|
|
public:
|
|
/** Event to react to a user double click on a item */
|
|
SceneOutliner::FTreeItemPtrEvent& GetDoubleClickEvent() { return OnDoubleClickOnTreeEvent; }
|
|
|
|
/**
|
|
* Allow the system that use the scene outliner to react when it's selection is changed
|
|
* Note: This event will only be broadcast on a user input.
|
|
*/
|
|
SceneOutliner::FOnItemSelectionChanged& GetOnItemSelectionChanged() { return OnItemSelectionChanged; }
|
|
|
|
/** Set the item selection of the outliner based on a selector function. Any items which return true will be added */
|
|
virtual void SetSelection(const TFunctionRef<bool(ISceneOutlinerTreeItem&)> Selector) override;
|
|
|
|
/** Set the selection status of a set of items in the scene outliner */
|
|
void SetItemSelection(const TArray<FSceneOutlinerTreeItemPtr>& InItems, bool bSelected, ESelectInfo::Type SelectInfo = ESelectInfo::Direct);
|
|
|
|
/** Set the selection status of a single item in the scene outliner */
|
|
void SetItemSelection(const FSceneOutlinerTreeItemPtr& InItem, bool bSelected, ESelectInfo::Type SelectInfo = ESelectInfo::Direct);
|
|
|
|
/** Adds a set of items to the current selection */
|
|
void AddToSelection(const TArray<FSceneOutlinerTreeItemPtr>& InItems, ESelectInfo::Type SelectInfo = ESelectInfo::Direct);
|
|
|
|
/** Remove a set of items from the current selection */
|
|
void RemoveFromSelection(const TArray<FSceneOutlinerTreeItemPtr>& InItems, ESelectInfo::Type SelectInfo = ESelectInfo::Direct);\
|
|
|
|
/** Adds a single item to the current selection */
|
|
void AddToSelection(const FSceneOutlinerTreeItemPtr& InItem, ESelectInfo::Type SelectInfo = ESelectInfo::Direct);
|
|
|
|
/**
|
|
* Returns the list of currently selected tree items
|
|
*/
|
|
virtual TArray<FSceneOutlinerTreeItemPtr> GetSelectedItems() const { return OutlinerTreeView->GetSelectedItems(); }
|
|
|
|
/**
|
|
* Returns the currently selected items.
|
|
*/
|
|
virtual FSceneOutlinerItemSelection GetSelection() const { return FSceneOutlinerItemSelection(*OutlinerTreeView); }
|
|
|
|
/**
|
|
* Pins an item list in the outliner.
|
|
*/
|
|
virtual void PinItems(const TArray<FSceneOutlinerTreeItemPtr>& InItems) override;
|
|
|
|
/**
|
|
* Unpins an item list in the outliner.
|
|
*/
|
|
virtual void UnpinItems(const TArray<FSceneOutlinerTreeItemPtr>& InItems) override;
|
|
|
|
/**
|
|
* Returns true if any of the items can be pinned.
|
|
*/
|
|
virtual bool CanPinItems(const TArray<FSceneOutlinerTreeItemPtr>& InItems) const override;
|
|
|
|
/**
|
|
* Returns true if any of the items can be unpinned.
|
|
*/
|
|
virtual bool CanUnpinItems(const TArray<FSceneOutlinerTreeItemPtr>& InItems) const override;
|
|
|
|
/**
|
|
* Pin selected items
|
|
*/
|
|
virtual void PinSelectedItems() override;
|
|
|
|
/**
|
|
* Unpins selected items
|
|
*/
|
|
virtual void UnpinSelectedItems() override;
|
|
|
|
/**
|
|
* Returns true if any of the selected items can be pinned
|
|
*/
|
|
virtual bool CanPinSelectedItems() const override;
|
|
|
|
/**
|
|
* Returns true if any of the selected items can be unpinned
|
|
*/
|
|
virtual bool CanUnpinSelectedItems() const override;
|
|
|
|
/**
|
|
* Scrolls the outliner to the selected item(s).
|
|
* If more are selected, the chosen item is undeterministic.
|
|
*/
|
|
virtual void FrameSelectedItems() override;
|
|
|
|
/**
|
|
* Scrolls the outliner to the specified item if it's found.
|
|
* No action is done otherwise.
|
|
*/
|
|
virtual void FrameItem(const FSceneOutlinerTreeItemID& Item) override;
|
|
|
|
/**
|
|
* Returns the parent tree item for a given item if it exists, nullptr otherwise.
|
|
*/
|
|
FSceneOutlinerTreeItemPtr FindParent(const ISceneOutlinerTreeItem& InItem) const;
|
|
|
|
/**
|
|
* Add a folder to the selection of the scene outliner
|
|
* @param FolderName The name of the folder to add to selection
|
|
*/
|
|
void AddFolderToSelection(const FName& FolderName);
|
|
|
|
/**
|
|
* Remove a folder from the selection of the scene outliner
|
|
* @param FolderName The name of the folder to remove from the selection
|
|
*/
|
|
void RemoveFolderFromSelection(const FName& FolderName);
|
|
|
|
/** Deselect all selected items */
|
|
void ClearSelection();
|
|
|
|
/** Sets the next item to rename */
|
|
void SetPendingRenameItem(const FSceneOutlinerTreeItemPtr& InItem) { PendingRenameItem = InItem; Refresh(); }
|
|
|
|
/** Get the outliner filter collection */
|
|
TSharedPtr<FSceneOutlinerFilters>& GetFilters() { return Filters; }
|
|
|
|
/** Create a drag drop operation */
|
|
TSharedPtr<FDragDropOperation> CreateDragDropOperation(const FPointerEvent& MouseEvent, const TArray<FSceneOutlinerTreeItemPtr>& InTreeItems) const;
|
|
|
|
/** Parse a drag drop operation into a payload */
|
|
bool ParseDragDrop(FSceneOutlinerDragDropPayload& OutPayload, const FDragDropOperation& Operation) const;
|
|
|
|
/** Validate a drag drop operation on a drop target */
|
|
FSceneOutlinerDragValidationInfo ValidateDrop(const ISceneOutlinerTreeItem& DropTarget, const FSceneOutlinerDragDropPayload& Payload) const;
|
|
|
|
/** Called when a payload is dropped onto a target */
|
|
void OnDropPayload(ISceneOutlinerTreeItem& DropTarget, const FSceneOutlinerDragDropPayload& Payload, const FSceneOutlinerDragValidationInfo& ValidationInfo) const;
|
|
|
|
/** Called when a payload is dragged over an item */
|
|
FReply OnDragOverItem(const FDragDropEvent& Event, const ISceneOutlinerTreeItem& Item) const;
|
|
|
|
/** Used to test if Outliner related selection changes have already been handled */
|
|
bool GetIsReentrant() const { return bIsReentrant; }
|
|
|
|
/** Get the unique identifier associated with this outliner */
|
|
FName GetOutlinerIdentifier() const { return OutlinerIdentifier; }
|
|
|
|
/** Toggle if SceneOutliner should show Transient objects */
|
|
void SetShowTransient(bool bInShowTransient) { SharedData.Get()->bShowTransient = bInShowTransient; }
|
|
|
|
private:
|
|
/** Methods that implement structural modification logic for the tree */
|
|
|
|
/** Empty all the tree item containers maintained by this outliner */
|
|
void EmptyTreeItems();
|
|
|
|
/** Apply incremental changes to, or a complete repopulation of the tree */
|
|
void Populate();
|
|
|
|
/** Repopulates the entire tree */
|
|
void RepopulateEntireTree();
|
|
|
|
/** Adds a single new item to the pending map and creates an add operation for it */
|
|
void AddPendingItem(FSceneOutlinerTreeItemPtr Item);
|
|
|
|
/** Adds a new item and all of its children to the pending items. */
|
|
void AddPendingItemAndChildren(FSceneOutlinerTreeItemPtr Item);
|
|
|
|
/** Attempts to add a pending item to the current tree. Will add any parents if required. */
|
|
bool AddItemToTree(FSceneOutlinerTreeItemRef InItem);
|
|
|
|
/** Add an item to the tree, even if it doesn't match the filter terms. Used to add parent's that would otherwise be filtered out */
|
|
void AddUnfilteredItemToTree(FSceneOutlinerTreeItemRef Item);
|
|
|
|
/** Ensure that the specified item's parent is added to the tree, if applicable */
|
|
FSceneOutlinerTreeItemPtr EnsureParentForItem(FSceneOutlinerTreeItemRef Item);
|
|
|
|
/** Remove the specified item from the tree */
|
|
void RemoveItemFromTree(FSceneOutlinerTreeItemRef InItem);
|
|
|
|
/** Called when a child has been removed from the specified parent. Will potentially remove the parent from the tree */
|
|
void OnChildRemovedFromParent(ISceneOutlinerTreeItem& Parent);
|
|
|
|
/** Called when a child has been moved in the tree hierarchy */
|
|
void OnItemMoved(const FSceneOutlinerTreeItemRef& Item);
|
|
|
|
public:
|
|
// Test the filters using stack-allocated data to prevent unnecessary heap allocations
|
|
template <typename TreeItemType, typename TreeItemData>
|
|
FSceneOutlinerTreeItemPtr CreateItemFor(const TreeItemData& Data, TFunctionRef<void(const TreeItemType&)> OnItemPassesFilters, bool bForce = false)
|
|
{
|
|
const TreeItemType Temporary(Data);
|
|
bool bPassesFilters = Filters->PassesAllFilters(Temporary);
|
|
|
|
if(FilterCollection)
|
|
{
|
|
bPassesFilters &= FilterCollection->PassesAllFilters(Temporary);
|
|
}
|
|
|
|
if (bPassesFilters)
|
|
{
|
|
OnItemPassesFilters(Temporary);
|
|
}
|
|
|
|
if (SearchBoxFilter)
|
|
{
|
|
bPassesFilters &= SearchBoxFilter->PassesFilter(Temporary);
|
|
}
|
|
|
|
if (bForce || bPassesFilters)
|
|
{
|
|
FSceneOutlinerTreeItemPtr Result = MakeShareable(new TreeItemType(Data));
|
|
Result->WeakSceneOutliner = StaticCastSharedRef<ISceneOutliner>(AsShared());
|
|
Result->Flags.bIsFilteredOut = !bPassesFilters;
|
|
Result->Flags.bInteractive = Filters->GetInteractiveState(*Result) && InteractiveFilters->GetInteractiveState(*Result);
|
|
return Result;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/** Instruct the outliner to perform an action on the specified item when it is created */
|
|
void OnItemAdded(const FSceneOutlinerTreeItemID& ItemID, uint8 ActionMask);
|
|
|
|
/** Get the columns to be displayed in this outliner */
|
|
const TMap<FName, TSharedPtr<ISceneOutlinerColumn>>& GetColumns() const
|
|
{
|
|
return Columns;
|
|
}
|
|
|
|
void GetSortedColumnIDs(TArray<FName>& OutColumnIDs) const;
|
|
|
|
bool PassesFilters(const ISceneOutlinerTreeItem& Item) const
|
|
{
|
|
return Filters->PassesAllFilters(Item);
|
|
}
|
|
|
|
/** @return Returns true if the text filter is currently active */
|
|
bool IsTextFilterActive() const;
|
|
|
|
bool PassesTextFilter(const FSceneOutlinerTreeItemPtr& Item) const
|
|
{
|
|
return PassesAllFilters(Item);
|
|
}
|
|
|
|
bool PassesAllFilters(const FSceneOutlinerTreeItemPtr& Item) const
|
|
{
|
|
bool bPassesFilters = false;
|
|
|
|
if (SearchBoxFilter)
|
|
{
|
|
bPassesFilters = SearchBoxFilter->PassesFilter(*Item);
|
|
}
|
|
|
|
if(FilterCollection)
|
|
{
|
|
bPassesFilters &= FilterCollection->PassesAllFilters(*Item);
|
|
}
|
|
|
|
return bPassesFilters;
|
|
|
|
}
|
|
|
|
bool HasSelectorFocus(FSceneOutlinerTreeItemPtr Item) const
|
|
{
|
|
return OutlinerTreeView->Private_HasSelectorFocus(Item);
|
|
}
|
|
|
|
/** Handler for when a property changes on any item. Called by the mode */
|
|
void OnItemLabelChanged(FSceneOutlinerTreeItemPtr ChangedItem, bool bFlashHighlight = true);
|
|
private:
|
|
|
|
/** BindCommands for this Outliner */
|
|
void BindCommands();
|
|
|
|
/** Map of columns that are shown on this outliner. */
|
|
TMap<FName, TSharedPtr<ISceneOutlinerColumn>> Columns;
|
|
|
|
/** Set up the columns required for this outliner */
|
|
void SetupColumns();
|
|
|
|
void HandleHiddenColumnsChanged();
|
|
|
|
/** Refresh the scene outliner columns */
|
|
void RefreshColumns();
|
|
|
|
void AddColumn_Internal(const FName& ColumnId, const FSceneOutlinerColumnInfo& ColumnInfo, const TMap<FName, bool>& ColumnVisibilities, int32 InsertPosition = INDEX_NONE);
|
|
void RemoveColumn_Internal(const FName& ColumnId);
|
|
|
|
/** Populates OutSearchStrings with the strings associated with TreeItem that should be used in searching */
|
|
void PopulateSearchStrings( const ISceneOutlinerTreeItem& TreeItem, OUT TArray< FString >& OutSearchStrings ) const;
|
|
|
|
/** Filter Bar related private functionality */
|
|
|
|
/** Creates a TextFilter for ISceneOutlinerTreeItem used to save searches as Text Filters */
|
|
TSharedPtr< SceneOutliner::TreeItemTextFilter > CreateTextFilter() const;
|
|
|
|
bool CompareItemWithClassName(SceneOutliner::FilterBarType InItem, const TSet<FTopLevelAssetPath>&) const;
|
|
|
|
/** Delegate for when a filter in the filter bar is changed */
|
|
void OnFilterBarFilterChanged();
|
|
|
|
/** Create the filter bar for this outliner using the specified init options */
|
|
void CreateFilterBar(const FSceneOutlinerFilterBarOptions& FilterBarOptions);
|
|
|
|
public:
|
|
/** Miscellaneous helper functions */
|
|
|
|
/** Scroll the specified item into view */
|
|
void ScrollItemIntoView(const FSceneOutlinerTreeItemPtr& Item);
|
|
|
|
void SetItemExpansion(const FSceneOutlinerTreeItemPtr& Item, bool bIsExpanded);
|
|
|
|
bool IsItemExpanded(const FSceneOutlinerTreeItemPtr& Item) const;
|
|
|
|
void ExpandAll();
|
|
void CollapseAll();
|
|
|
|
private:
|
|
|
|
/** Check whether we should be showing folders or not in this scene outliner */
|
|
bool ShouldShowFolders() const;
|
|
|
|
/** Get an array of selected folders */
|
|
void GetSelectedFolders(TArray<FFolderTreeItem*>& OutFolders) const;
|
|
|
|
private:
|
|
/** Tree view event bindings */
|
|
|
|
/** Called by STreeView to generate a table row for the specified item */
|
|
TSharedRef< ITableRow > OnGenerateRowForOutlinerTree( FSceneOutlinerTreeItemPtr Item, const TSharedRef< STableViewBase >& OwnerTable );
|
|
|
|
/** Called by STreeView to generate a table row for the specified item is pinned*/
|
|
TSharedRef< ITableRow > OnGeneratePinnedRowForOutlinerTree(FSceneOutlinerTreeItemPtr Item, const TSharedRef< STableViewBase >& OwnerTable);
|
|
|
|
/** Called by STreeView to get child items for the specified parent item */
|
|
void OnGetChildrenForOutlinerTree( FSceneOutlinerTreeItemPtr InParent, TArray< FSceneOutlinerTreeItemPtr >& OutChildren );
|
|
|
|
/** Called by STreeView when the tree's selection has changed */
|
|
void OnOutlinerTreeSelectionChanged( FSceneOutlinerTreeItemPtr TreeItem, ESelectInfo::Type SelectInfo );
|
|
|
|
/** Called by STreeView when the user double-clicks on an item in the tree */
|
|
void OnOutlinerTreeDoubleClick( FSceneOutlinerTreeItemPtr TreeItem );
|
|
|
|
/** Called by STreeView when the user single-clicks on an item in the tree */
|
|
void OnOutlinerTreeSingleClick( FSceneOutlinerTreeItemPtr TreeItem ) const;
|
|
|
|
/** Called by STreeView when an item is scrolled into view */
|
|
void OnOutlinerTreeItemScrolledIntoView( FSceneOutlinerTreeItemPtr TreeItem, const TSharedPtr<ITableRow>& Widget );
|
|
|
|
/** Called when an item in the tree has been collapsed or expanded */
|
|
void OnItemExpansionChanged(FSceneOutlinerTreeItemPtr TreeItem, bool bIsExpanded) const;
|
|
|
|
private:
|
|
/** Level, editor and other global event hooks required to keep the outliner up to date */
|
|
|
|
void OnHierarchyChangedEvent(FSceneOutlinerHierarchyChangedData Event);
|
|
|
|
/** Handler for when an asset is reloaded */
|
|
void OnAssetReloaded(const EPackageReloadPhase InPackageReloadPhase, FPackageReloadedEvent* InPackageReloadedEvent);
|
|
|
|
public:
|
|
/** Copy specified folders to clipboard, keeping current clipboard contents if they differ from previous clipboard contents (meaning items were copied) */
|
|
void CopyFoldersToClipboard(const TArray<FName>& InFolders, const FString& InPrevClipboardContents);
|
|
|
|
/** Called by copy and duplicate */
|
|
void CopyFoldersBegin();
|
|
|
|
/** Called by copy and duplicate */
|
|
void CopyFoldersEnd();
|
|
|
|
/** Called by paste and duplicate */
|
|
void PasteFoldersBegin(TArray<FName> InFolders);
|
|
|
|
/** Paste folders end logic */
|
|
void PasteFoldersEnd();
|
|
|
|
/** Called by cut and delete */
|
|
void DeleteFoldersBegin();
|
|
|
|
/** Called by cut and delete */
|
|
void DeleteFoldersEnd();
|
|
|
|
/** Get an array of folders to paste */
|
|
TArray<FName> GetClipboardPasteFolders() const;
|
|
|
|
/** Construct folders export string to be used in clipboard */
|
|
FString ExportFolderList(TArray<FName> InFolders) const;
|
|
|
|
/** Construct array of folders to be created based on input clipboard string */
|
|
TArray<FName> ImportFolderList(const FString& InStrBuffer) const;
|
|
|
|
public:
|
|
/** Duplicates current folder and all descendants */
|
|
void DuplicateFoldersHierarchy();
|
|
|
|
private:
|
|
/** Cache selected folders during edit delete */
|
|
TArray<FFolderTreeItem*> CacheFoldersDelete;
|
|
|
|
/** Cache folders for cut/copy/paste/duplicate */
|
|
TArray<FName> CacheFoldersEdit;
|
|
|
|
/** CacheFoldersEdit target root object */
|
|
FFolder::FRootObject CacheFoldersEditRootObject;
|
|
|
|
/** Cache folders mapping (old to new) for cut/copy/paste/duplicate */
|
|
TMap<FName, FName> CacheFolderMap;
|
|
|
|
/** Cache clipboard contents for cut/copy */
|
|
FString CacheClipboardContents;
|
|
|
|
/** Maps pre-existing children during paste or duplicate */
|
|
TMap<FFolder, TArray<FSceneOutlinerTreeItemID>> CachePasteFolderExistingChildrenMap;
|
|
|
|
/** Cache which columns are hidden to know what changed */
|
|
TSet<FName> CacheHiddenColumns;
|
|
|
|
private:
|
|
bool GetCommonRootObjectFromSelection(FFolder::FRootObject& OutCommonRootObject) const;
|
|
|
|
/** Miscellaneous bindings required by the UI */
|
|
|
|
/** Called by the editable text control when the filter text is changed by the user */
|
|
void OnFilterTextChanged( const FText& InFilterText );
|
|
|
|
/** Called by the editable text control when a user presses enter or commits their text change */
|
|
void OnFilterTextCommitted( const FText& InFilterText, ETextCommit::Type CommitInfo );
|
|
|
|
/** Called by the filter button to get the image to display in the button */
|
|
const FSlateBrush* GetFilterButtonGlyph() const;
|
|
|
|
/** @return The filter button tool-tip text */
|
|
FString GetFilterButtonToolTip() const;
|
|
|
|
/** @return Returns whether the filter status line should be drawn */
|
|
EVisibility GetFilterStatusVisibility() const;
|
|
|
|
/** @return Returns the filter status text */
|
|
FText GetFilterStatusText() const;
|
|
|
|
/** @return Returns color for the filter status text message, based on success of search filter */
|
|
FSlateColor GetFilterStatusTextColor() const;
|
|
|
|
/** Returns the current visibility of the Empty label */
|
|
EVisibility GetEmptyLabelVisibility() const;
|
|
|
|
/** @return the selection mode; disabled entirely if in PIE/SIE mode */
|
|
ESelectionMode::Type GetSelectionMode() const;
|
|
|
|
/** @return the content for the view button */
|
|
TSharedRef<SWidget> GetViewButtonContent(bool bShowFilters);
|
|
|
|
/** @return the foreground color for the view button */
|
|
FSlateColor GetViewButtonForegroundColor() const;
|
|
|
|
public:
|
|
|
|
/** Open a context menu for this scene outliner */
|
|
TSharedPtr<SWidget> OnOpenContextMenu();
|
|
|
|
void FillFoldersSubMenu(UToolMenu* Menu) const;
|
|
void AddMoveToFolderOutliner(UToolMenu* Menu) const;
|
|
void FillSelectionSubMenu(UToolMenu* Menun) const;
|
|
TSharedRef<TSet<FFolder>> GatherInvalidMoveToDestinations() const;
|
|
|
|
/** Called to select descendants of the currently selected folders */
|
|
void SelectFoldersDescendants(bool bSelectImmediateChildrenOnly = false);
|
|
|
|
/** Moves the current selection to the specified folder path */
|
|
void MoveSelectionTo(const FFolder& NewParent);
|
|
|
|
/** Create a new folder under the specified parent name (NAME_None for root) */
|
|
void CreateFolder();
|
|
|
|
private:
|
|
/** Called when the user has clicked the button to add a new folder */
|
|
FReply OnCreateFolderClicked();
|
|
|
|
private:
|
|
|
|
/** Context menu opening delegate provided by the client */
|
|
FOnContextMenuOpening OnContextMenuOpening;
|
|
|
|
TSharedPtr<FSharedSceneOutlinerData> SharedData;
|
|
|
|
/** List of pending operations to be applied to the tree */
|
|
TArray<SceneOutliner::FPendingTreeOperation> PendingOperations;
|
|
|
|
/** Map of actions to apply to new tree items */
|
|
TMap<FSceneOutlinerTreeItemID, uint8> NewItemActions;
|
|
|
|
/** Our tree view */
|
|
TSharedPtr< SSceneOutlinerTreeView > OutlinerTreeView;
|
|
|
|
/** A map of all items we have in the tree */
|
|
FSceneOutlinerTreeItemMap TreeItemMap;
|
|
|
|
/** Pending tree items that are yet to be added the tree */
|
|
FSceneOutlinerTreeItemMap PendingTreeItemMap;
|
|
|
|
/** Pending tree items that are yet to be removed from the tree */
|
|
FSceneOutlinerTreeItemMap PendingTreeItemMap_Removal;
|
|
|
|
/** Folders pending selection */
|
|
TArray<FFolder> PendingFoldersSelect;
|
|
|
|
/** Root level tree items */
|
|
TArray<FSceneOutlinerTreeItemPtr> RootTreeItems;
|
|
|
|
/** The button that displays view options */
|
|
TSharedPtr<SComboButton> ViewOptionsComboButton;
|
|
|
|
/** Command list to be processed during the OnKeyDown, extended by derived Mode through BindCommands */
|
|
TSharedPtr<FUICommandList> CommandList;
|
|
|
|
private:
|
|
|
|
/** Called when SceneOutlinerModule column permission list changes. */
|
|
void OnColumnPermissionListChanged();
|
|
|
|
/** Structure containing information relating to the expansion state of parent items in the tree */
|
|
typedef TMap<FSceneOutlinerTreeItemID, bool> FParentsExpansionState;
|
|
|
|
/** Cached expansion state info */
|
|
mutable FParentsExpansionState CachedExpansionStateInfo;
|
|
|
|
private:
|
|
|
|
/** True if the outliner needs to be repopulated at the next appropriate opportunity, usually because our
|
|
item set has changed in some way. */
|
|
uint8 bNeedsRefresh : 1;
|
|
|
|
/** Processing a full refresh until pending items are processed */
|
|
uint8 bProcessingFullRefresh : 1;
|
|
|
|
/** true if the Scene Outliner should do a full refresh. */
|
|
uint8 bFullRefresh : 1;
|
|
|
|
/** true if the Scene Outliner should refresh selection */
|
|
uint8 bSelectionDirty : 1;
|
|
|
|
/** True if the Scene Outliner is currently responding to a level visibility change */
|
|
uint8 bDisableIntermediateSorting : 1;
|
|
|
|
uint8 bNeedsColumRefresh : 1;
|
|
|
|
/** True if the outliner should cache changes to column visibility into the config */
|
|
uint8 bShouldCacheColumnVisibility : 1;
|
|
|
|
/** True if we are forcing the underlying tree view to automatically expand all parents when searching */
|
|
mutable uint8 bForceParentItemsExpanded : 1;
|
|
|
|
/** Reentrancy guard */
|
|
bool bIsReentrant;
|
|
|
|
/** The delay (in seconds) before a UI sort and refresh is executed after being requested. 0 means the next refresh will be immediate */
|
|
float UIRefreshDelay = 0.0f;
|
|
|
|
/* Widget containing the filtering text box */
|
|
TSharedPtr< SFilterSearchBox > FilterTextBoxWidget;
|
|
|
|
/** The header row of the scene outliner */
|
|
TSharedPtr< SHeaderRow > HeaderRowWidget;
|
|
|
|
/** A collection of filters used to filter the displayed items and folders in the scene outliner */
|
|
TSharedPtr< FSceneOutlinerFilters > Filters;
|
|
|
|
/** A collection of extra filters applied on top of existing Filters to determine if items are interactive or not in the scene outliner */
|
|
TSharedPtr< FSceneOutlinerFilters > InteractiveFilters;
|
|
|
|
/** The TextFilter attached to the SearchBox widget of the Scene Outliner */
|
|
TSharedPtr< SceneOutliner::TreeItemTextFilter > SearchBoxFilter;
|
|
|
|
/** The FilterBar attached to this outliner to filter down assets further */
|
|
TSharedPtr< SFilterBar< SceneOutliner::FilterBarType > > FilterBar;
|
|
|
|
/** The FilterCollection belonging to the Filter Bar */
|
|
TSharedPtr< TFilterCollection< SceneOutliner::FilterBarType > > FilterCollection;
|
|
|
|
/** True if the search box will take keyboard focus next frame */
|
|
bool bPendingFocusNextFrame;
|
|
|
|
/** The tree item that is currently pending a rename */
|
|
TWeakPtr<ISceneOutlinerTreeItem> PendingRenameItem;
|
|
|
|
TMap<FName, const FSlateBrush*> CachedIcons;
|
|
|
|
SceneOutliner::FTreeItemPtrEvent OnDoubleClickOnTreeEvent;
|
|
|
|
SceneOutliner::FOnItemSelectionChanged OnItemSelectionChanged;
|
|
private:
|
|
|
|
virtual void AddReferencedObjects(FReferenceCollector& Collector) override {};
|
|
virtual FString GetReferencerName() const override
|
|
{
|
|
return TEXT("SceneOutliner::SSceneOutliner");
|
|
}
|
|
|
|
/** Functions relating to sorting */
|
|
|
|
/** Timer for PIE/SIE mode to sort the outliner. */
|
|
float SortOutlinerTimer;
|
|
|
|
/** true if the outliner currently needs to be sorted */
|
|
bool bSortDirty;
|
|
|
|
/** Specify which column to sort with */
|
|
FName SortByColumn;
|
|
|
|
/** Currently selected sorting mode */
|
|
EColumnSortMode::Type SortMode;
|
|
|
|
/** Identifier for this outliner (Set through FSceneOutlinerInitializationOptions) */
|
|
FName OutlinerIdentifier;
|
|
|
|
/** true if the hierarchy of items is pinned at the top of the outliner */
|
|
bool bShouldStackHierarchyHeaders = true;
|
|
|
|
void ToggleStackHierarchyHeaders();
|
|
|
|
bool ShouldStackHierarchyHeaders() const;
|
|
|
|
/** Handles column sorting mode change */
|
|
void OnColumnSortModeChanged( const EColumnSortPriority::Type SortPriority, const FName& ColumnId, const EColumnSortMode::Type InSortMode );
|
|
|
|
/** Sort the specified array of items based on the current sort column */
|
|
void SortItems(TArray<FSceneOutlinerTreeItemPtr>& Items) const;
|
|
|
|
virtual uint32 GetTypeSortPriority(const ISceneOutlinerTreeItem& Item) const override;
|
|
|
|
/** Handler for recursively expanding/collapsing items */
|
|
void SetItemExpansionRecursive(FSceneOutlinerTreeItemPtr Model, bool bInExpansionState);
|
|
|
|
/**
|
|
* Get a mutable version of the outliner config for setting values.
|
|
* @returns The outliner config for this outliner.
|
|
* @note If FSceneOutlinerInitializationOptions.OutlinerIdentifier is not set, it is not possible to store settings for this outliner.
|
|
*/
|
|
struct FSceneOutlinerConfig* GetMutableConfig();
|
|
|
|
/**
|
|
* Get a const version of the outliner config for getting values.
|
|
* @returns The outliner config for this outliner.
|
|
* @note If FSceneOutlinerInitializationOptions.OutlinerIdentifier is not set, it is not possible to retrieve settings for this outliner.
|
|
*/
|
|
const FSceneOutlinerConfig* GetConstConfig() const;
|
|
|
|
void SaveConfig();
|
|
|
|
TSharedPtr<FSceneOutlinerSCCHandler> SourceControlHandler;
|
|
|
|
public:
|
|
virtual TSharedPtr<FSceneOutlinerTreeItemSCC> GetItemSourceControl(const FSceneOutlinerTreeItemPtr& InItem) override;
|
|
|
|
void AddSourceControlMenuOptions(UToolMenu* Menu);
|
|
|
|
void FilterByType(TSharedPtr<FCustomClassFilterData> CustomClassFilterData);
|
|
void FilterByTypeCategory(TSharedPtr<FFilterCategory> TypeCategory, TArray<TSharedPtr<FCustomClassFilterData>> Classes);
|
|
bool NeedsRefresh() const;
|
|
|
|
void CreateCustomTextFilter(const FCustomTextFilterData& InFilterData, bool bApplyFilter);
|
|
void ModifyCustomTextFilter(const FCustomTextFilterData& InFilterData, const TSharedPtr<ICustomTextFilter<SceneOutliner::FilterBarType>>& InFilter);
|
|
void DeleteCustomTextFilter(const TSharedPtr<ICustomTextFilter<SceneOutliner::FilterBarType>>& InFilter);
|
|
};
|
|
|
|
struct SCENEOUTLINER_API FSceneOutlinerMenuHelper
|
|
{
|
|
static void AddMenuEntryCreateFolder(FToolMenuSection& InSection, SSceneOutliner& InOutliner);
|
|
static void AddMenuEntryCleanupFolders(FToolMenuSection& InSection, ULevel* InLevel);
|
|
};
|