EM_Task/UnrealEd/Public/Dialogs/DlgReferenceTree.h
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

227 lines
7.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Serialization/ArchiveUObject.h"
#include "Components/ActorComponent.h"
#include "GameFramework/Actor.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Input/Reply.h"
#include "Widgets/SCompoundWidget.h"
#include "Engine/Brush.h"
#include "Model.h"
#include "Widgets/Views/STableViewBase.h"
#include "Widgets/Views/STableRow.h"
#include "Widgets/Views/STreeView.h"
#include "Engine/Polys.h"
class FMenuBuilder;
class SWindow;
struct FReferenceTreeDataContainer;
/**
* A struct representing a node in the reference graph
*/
struct FReferenceGraphNode
{
/** The object this node represents */
UObject* Object;
/** Links from this nodes object. Each link represents a reference to the object. */
TSet<FReferenceGraphNode*> Links;
/** If the node has been visited while populating the reference tree. This prevents circular references. */
bool bVisited;
FReferenceGraphNode(UObject* InObject)
: Object(InObject),
bVisited(false)
{
}
/**
* Returns the object that should be displayed on the graph
*
* @param bShowScriptReferences If true we should return script objects.
*/
UObject* GetObjectToDisplay(bool bShowScriptReferences)
{
UObject* ObjectToDisplay = NULL;
// Check to see if the object in this node is a component. If it is try to display the actor that uses it.
UActorComponent* Comp = Cast<UActorComponent>(Object);
if (Comp)
{
if (Comp->GetOwner())
{
// Use the components owner if it has one.
ObjectToDisplay = Comp->GetOwner();
}
else if (Comp->GetOuter() && Comp->GetOuter()->IsA(AActor::StaticClass()))
{
// Use the components outer if it is an actor
ObjectToDisplay = Comp->GetOuter();
}
}
else if (Object->IsA(UPolys::StaticClass()))
{
// Special case handling for bsp.
// Outer chain: Polys->UModel->ABrush
UObject* PossibleModel = Object->GetOuter();
if (PossibleModel && PossibleModel->IsA(UModel::StaticClass()))
{
UObject* PossibleBrush = PossibleModel->GetOuter();
if (PossibleBrush && PossibleBrush->IsA(ABrush::StaticClass()))
{
ObjectToDisplay = PossibleBrush;
}
}
}
else
{
ObjectToDisplay = Object;
}
if (ObjectToDisplay && ObjectToDisplay->HasAnyFlags(RF_ClassDefaultObject) && !bShowScriptReferences)
{
// Don't return class default objects if we aren't showing script references
ObjectToDisplay = NULL;
}
return ObjectToDisplay;
}
};
typedef TMap<UObject*, FReferenceGraphNode*> FReferenceGraph;
/**
* An archive for creating a reference graph of all UObjects
*/
class FArchiveGenerateReferenceGraph: public FArchiveUObject
{
public:
FArchiveGenerateReferenceGraph(FReferenceGraph& OutGraph);
FArchive& operator<<(UObject*& Object);
private:
/** The object currently being serialized. */
UObject* CurrentObject;
/** The set of visited objects so we dont serialize something twice. */
TSet<UObject*> VisitedObjects;
/** Reference to the graph we are creating. */
FReferenceGraph& ObjectGraph;
};
typedef TSharedPtr<struct FReferenceTreeDataContainer> FReferenceTreeItemPtr;
typedef STreeView<FReferenceTreeItemPtr> SReferenceTreeView;
class UNREALED_API SReferenceTree: public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SReferenceTree)
: _Object(NULL)
{}
SLATE_ARGUMENT(UObject*, Object)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
~SReferenceTree();
static TWeakPtr<SWindow> SingletonInstance;
static void OpenDialog(UObject* InObject);
private:
/** Generates a row for the tree. */
TSharedRef<ITableRow> OnGenerateRowForReferenceTree(FReferenceTreeItemPtr Item, const TSharedRef<STableViewBase>& OwnerTable);
/**
* Populates the tree, for a specific root object
*
* @param InRootObject The root object to find the references of.
*
*/
void PopulateTree(UObject* RootObject);
/**
* Helper function for recursively generating the reference tree
*
* @param InNode The node to find all references of.
* @param InParentNode The generated tree node to parent all references to.
*
* @return true if any references were found.
*/
bool PopulateTreeRecursive(FReferenceGraphNode& InNode, FReferenceTreeItemPtr InParentNode);
/** Retrieves the children for a node in the tree. */
void OnGetChildrenForReferenceTree(FReferenceTreeItemPtr InParent, TArray<FReferenceTreeItemPtr>& OutChildren);
/** Builds the context menu widget. */
TSharedPtr<SWidget> BuildMenuWidget();
/** Fills the top menu for the window. */
void FillViewEntries(FMenuBuilder& MenuBuilder);
void FillOptionsEntries(FMenuBuilder& MenuBuilder);
/**
* Sets expansions states for every item in the tree.
*
* @param bInExpandItems true if items should be expanded, false if they should be collapsed.
*/
void SetAllExpansionStates(bool bInExpansionState);
/**
* Helper function for recursion to set expansions states for every item in the tree.
*
* @param InNode The node to recurse into.
* @param bInExpandItems true if items should be expanded, false if they should be collapsed.
*/
void SetAllExpansionStates_Helper(FReferenceTreeItemPtr InNode, bool bInExpansionState);
/** Callback when the editor's map changes. */
void OnEditorMapChange(uint32 InMapChangeFlags);
/** Cleans up the tree for a refresh. */
void DestroyGraphAndTree();
/** Called when the view properties menu option is chosen. */
void OnMenuViewProperties(UObject* InObject);
/** Called when the show object in editor menu option is chosen. */
void OnMenuShowEditor(UObject* InObject);
/** Toggles show script references and refreshes the tree. */
void OnShowScriptReferences();
/** Callback to see if the Show Script References should be checked. */
bool OnShowScriptReferences_Checked() const
{
return bShowScriptRefs;
}
/** Callback when the OK button is clicked. */
FReply OnOK_Clicked(void);
/** Sets the window of this dialog. */
void SetWindow(TSharedPtr<SWindow> InWindow)
{
MyWindow = InWindow;
}
private:
/** List holding the root object of the tree. */
TArray<FReferenceTreeItemPtr> ReferenceTreeRoot;
/** Slate Widget object for the Tree View. */
TSharedPtr<SReferenceTreeView> ReferenceTreeView;
/** The reference graph for all UObjects. */
FReferenceGraph ReferenceGraph;
/** If the tree should show script references. */
bool bShowScriptRefs;
/** Pointer to the containing window. */
TWeakPtr<SWindow> MyWindow;
};