2019-12-26 15:33:43 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
#include "EdGraph/EdGraphSchema.h"
|
|
|
|
|
#include "SGraphActionMenu.h"
|
2014-09-05 17:51:16 -04:00
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
// Utility class for building menus of graph actions
|
2014-09-05 17:51:16 -04:00
|
|
|
struct GRAPHEDITOR_API FGraphActionNode : TSharedFromThis<FGraphActionNode>
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
public:
|
2014-09-05 17:51:16 -04:00
|
|
|
/** */
|
|
|
|
|
static const int32 INVALID_SECTION_ID = 0;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/** Identifies the named section that this node belongs to, if any (defaults to INVALID_SECTION_ID) */
|
|
|
|
|
int32 const SectionID;
|
|
|
|
|
/** Identifies the menu group that this node belongs to (defaults to zero) */
|
|
|
|
|
int32 const Grouping;
|
|
|
|
|
/** A set of actions to execute when this node is picked from a menu */
|
|
|
|
|
TArray< TSharedPtr<FEdGraphSchemaAction> > const Actions;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/** */
|
|
|
|
|
TArray< TSharedPtr<FGraphActionNode> > Children;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-09-11 17:10:00 -04:00
|
|
|
/** Lookup table for category nodes, used to speed up menu construction */
|
|
|
|
|
TMap< FString, TSharedPtr<FGraphActionNode> > CategoryNodes;
|
|
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* Static allocator for a new root node (so external users have a starting
|
|
|
|
|
* point to build graph action trees from).
|
|
|
|
|
*
|
|
|
|
|
* @return A newly allocated root node (should not be displayed in the tree view).
|
|
|
|
|
*/
|
|
|
|
|
static TSharedPtr<FGraphActionNode> NewRootNode();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
/**
|
2014-09-05 17:51:16 -04:00
|
|
|
* Inserts a new action node (and any accompanying category nodes) based off
|
|
|
|
|
* the provided ActionSet.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: This does NOT insert the node in a sorted manner. Call SortChildren()
|
|
|
|
|
* separately to accomplish that (done for performance reasons).
|
|
|
|
|
*
|
|
|
|
|
* @param ActionSet A list of actions that you want the node to execute when picked.
|
|
|
|
|
* @return The new action node.
|
|
|
|
|
*/
|
|
|
|
|
TSharedPtr<FGraphActionNode> AddChild(FGraphActionListBuilderBase::ActionGroup const& ActionSet);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2015-01-26 17:51:00 -05:00
|
|
|
TSharedPtr<FGraphActionNode> AddSection(int32 Grouping, int32 InSectionID);
|
|
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Sorts all child nodes by section, group, and type (additionally, can
|
|
|
|
|
* sort alphabetically if wanted).
|
|
|
|
|
*
|
|
|
|
|
* @param bAlphabetically Determines if we sort alphabetically on top of section/group/type.
|
2014-09-15 06:29:54 -04:00
|
|
|
* @param bRecursive Determines if we should sort all decendent nodes' children ass well.
|
2014-09-05 17:51:16 -04:00
|
|
|
*/
|
|
|
|
|
void SortChildren(bool bAlphabetically = true, bool bRecursive = true);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
2014-09-15 06:29:54 -04:00
|
|
|
* Returns a WeakPtr to the Parent Node
|
|
|
|
|
*/
|
|
|
|
|
TWeakPtr<FGraphActionNode> GetParentNode() const{ return ParentNode; }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Recursively collects all child/grandchild/decendent nodes.
|
2014-09-05 17:51:16 -04:00
|
|
|
*
|
2014-09-15 06:29:54 -04:00
|
|
|
* @param OutNodeArray The array to fill out with decendent nodes.
|
2014-09-05 17:51:16 -04:00
|
|
|
*/
|
|
|
|
|
void GetAllNodes(TArray< TSharedPtr<FGraphActionNode> >& OutNodeArray) const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
2014-09-15 06:29:54 -04:00
|
|
|
* Recursively collects all decendent action/separator nodes (leaves out
|
2014-09-05 17:51:16 -04:00
|
|
|
* branching category-nodes).
|
|
|
|
|
*
|
2014-09-15 06:29:54 -04:00
|
|
|
* @param OutLeafArray The array to fill out with decendent leaf nodes.
|
2014-09-05 17:51:16 -04:00
|
|
|
*/
|
|
|
|
|
void GetLeafNodes(TArray< TSharedPtr<FGraphActionNode> >& OutLeafArray) const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Takes the tree view and expands its elements for each child.
|
|
|
|
|
*
|
|
|
|
|
* @param TreeView The tree responsible for visualizing this node hierarchy.
|
2014-09-15 06:29:54 -04:00
|
|
|
* @param bRecursive Determines if you want children/decendents to expand their children as well.
|
2014-09-05 17:51:16 -04:00
|
|
|
*/
|
|
|
|
|
void ExpandAllChildren(TSharedPtr< STreeView< TSharedPtr<FGraphActionNode> > > TreeView, bool bRecursive = true);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Clears all children (not recursively... the TSharedPtrs should clean up
|
|
|
|
|
* appropriately).
|
|
|
|
|
*/
|
|
|
|
|
void ClearChildren();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Query to determine this node's type (there are five distinguishable node
|
|
|
|
|
* types: root, section heading, category, action, & group-divider).
|
|
|
|
|
*
|
|
|
|
|
* @return True if this is the type your queried about, otherwise false.
|
|
|
|
|
*/
|
|
|
|
|
bool IsRootNode() const;
|
|
|
|
|
bool IsSectionHeadingNode() const;
|
|
|
|
|
bool IsCategoryNode() const;
|
|
|
|
|
bool IsActionNode() const;
|
|
|
|
|
bool IsGroupDividerNode() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Determines if this node is a menu separator of some kind (either a
|
|
|
|
|
* "group-divider" or a "section heading").
|
|
|
|
|
*
|
|
|
|
|
* @return True if this is a menu divider, otherwise false.
|
|
|
|
|
*/
|
|
|
|
|
bool IsSeparator() const;
|
|
|
|
|
/**
|
|
|
|
|
* Retrieves this node's display name (for category and action nodes). The
|
|
|
|
|
* text string will be empty for separator and root nodes.
|
|
|
|
|
*
|
|
|
|
|
* @return The name to present this node with in the tree view (will be an empty text string if this is a separator node)
|
|
|
|
|
*/
|
|
|
|
|
FText const& GetDisplayName() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Walks the node chain backwards, constructing a category path (delimited
|
|
|
|
|
* by '|' characters). This includes this node's category (if it is a
|
|
|
|
|
* category node).
|
|
|
|
|
*
|
|
|
|
|
* @return A category path string, denoting the category hierarchy up to this node.
|
|
|
|
|
*/
|
2015-05-08 10:46:42 -04:00
|
|
|
FText GetCategoryPath() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Checks to see if this node contains at least one valid action.
|
|
|
|
|
*
|
|
|
|
|
* @return True is the Actions array contains a valid entry, otherwise false.
|
|
|
|
|
*/
|
|
|
|
|
bool HasValidAction() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Looks through this node's Actions array, and returns the first valid
|
|
|
|
|
* action it finds.
|
|
|
|
|
*
|
|
|
|
|
* @return This node's first valid action (will be an empty pointer if this is not an action node).
|
|
|
|
|
*/
|
|
|
|
|
TSharedPtr<FEdGraphSchemaAction> GetPrimaryAction() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Accessor to the node's RenameRequestEvent (for binding purposes). Do not
|
|
|
|
|
* Execute() the delegate from this function, instead call
|
|
|
|
|
* BroadcastRenameRequest() on the node.
|
|
|
|
|
*
|
|
|
|
|
* @return The node's internal RenameRequestEvent.
|
|
|
|
|
*/
|
|
|
|
|
FOnRenameRequestActionNode& OnRenameRequest() { return RenameRequestEvent; }
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Executes the node's RenameRequestEvent if it is bound. Otherwise, it will
|
|
|
|
|
* mark the node as having a pending rename request.
|
|
|
|
|
*
|
|
|
|
|
* @return True if the broadcast went through, false if the "pending rename request" flag was set.
|
|
|
|
|
*/
|
|
|
|
|
bool BroadcastRenameRequest();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Sometimes a call to BroadcastRenameRequest() is made before the
|
|
|
|
|
* RenameRequestEvent has been bound. When that happens, this node is
|
|
|
|
|
* marked with a pending rename request. This method determines if that is
|
|
|
|
|
* the case for this node.
|
|
|
|
|
*
|
|
|
|
|
* @return True if a call to BroadcastRenameRequest() was made without a valid RenameRequestEvent.
|
|
|
|
|
*/
|
|
|
|
|
bool IsRenameRequestPending() const;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param Grouping
|
|
|
|
|
* @param SectionID
|
|
|
|
|
*/
|
|
|
|
|
FGraphActionNode(int32 Grouping, int32 SectionID);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Constructor for action nodes. Private so that users go through AddChild().
|
|
|
|
|
*
|
|
|
|
|
* @param ActionList
|
|
|
|
|
* @param Grouping
|
|
|
|
|
* @param SectionID
|
|
|
|
|
*/
|
|
|
|
|
FGraphActionNode(TArray< TSharedPtr<FEdGraphSchemaAction> > const& ActionList, int32 Grouping, int32 SectionID);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param Parent
|
|
|
|
|
* @param Grouping
|
|
|
|
|
* @param SectionID
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
static TSharedPtr<FGraphActionNode> NewSectionHeadingNode(TWeakPtr<FGraphActionNode> Parent, int32 Grouping, int32 SectionID);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param Category
|
|
|
|
|
* @param Grouping
|
|
|
|
|
* @param SectionID
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
static TSharedPtr<FGraphActionNode> NewCategoryNode(FString const& Category, int32 Grouping, int32 SectionID);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param ActionList
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
static TSharedPtr<FGraphActionNode> NewActionNode(TArray< TSharedPtr<FEdGraphSchemaAction> > const& ActionList);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @param Parent
|
|
|
|
|
* @param Grouping
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
static TSharedPtr<FGraphActionNode> NewGroupDividerNode(TWeakPtr<FGraphActionNode> Parent, int32 Grouping);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
2015-08-19 16:36:07 -04:00
|
|
|
* Iterates the CategoryStack, adding category-nodes as needed. The
|
2014-09-05 17:51:16 -04:00
|
|
|
* last category is what the node will be inserted under.
|
|
|
|
|
*
|
|
|
|
|
* @param CategoryStack A list of categories denoting where to nest the new node (the first element is the highest category)
|
2015-08-19 16:36:07 -04:00
|
|
|
* @param Idx Current point in the category stack that we have iterated to
|
2014-09-05 17:51:16 -04:00
|
|
|
* @param NodeToAdd The node you want inserted.
|
|
|
|
|
*/
|
2015-08-19 16:36:07 -04:00
|
|
|
void AddChildRecursively(const TArray<FString>& CategoryStack, int32 Idx, TSharedPtr<FGraphActionNode> NodeToAdd);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Looks through this node's children to see if a there already exists a
|
|
|
|
|
* node matching one we'd have to spawn (to parent the supplied NodeToAdd).
|
|
|
|
|
*
|
|
|
|
|
* @param ParentName The name of the category NodeToAdd wants to nest under.
|
|
|
|
|
* @param NodeToAdd The node that we'll be adding to this child.
|
|
|
|
|
* @return A child node matching the supplied parameters (will be empty if no match was found).
|
|
|
|
|
*/
|
|
|
|
|
TSharedPtr<FGraphActionNode> FindMatchingParent(FString const& ParentName, TSharedPtr<FGraphActionNode> NodeToAdd);
|
2014-07-30 11:06:40 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
/**
|
|
|
|
|
* Adds the specified node directly to this node's Children array. Will
|
|
|
|
|
* create and insert separators if needed (if the node has a new group or
|
|
|
|
|
* section).
|
|
|
|
|
*
|
|
|
|
|
* @param NodeToAdd The node you want inserted.
|
|
|
|
|
*/
|
|
|
|
|
void InsertChild(TSharedPtr<FGraphActionNode> NodeToAdd);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-09-05 17:51:16 -04:00
|
|
|
private:
|
|
|
|
|
/** The category or action name (depends on what type of node this is) */
|
|
|
|
|
FText DisplayText;
|
|
|
|
|
/** The node that this is a direct child of (empty if this is a root node) */
|
|
|
|
|
TWeakPtr<FGraphActionNode> ParentNode;
|
|
|
|
|
|
|
|
|
|
/** Tracks what groups have already been added (so we can easily determine what group-dividers we need) */
|
|
|
|
|
TSet<int32> ChildGroupings;
|
|
|
|
|
/** Tracks what sections have already been added (so we can easily determine what heading we need) */
|
|
|
|
|
TSet<int32> ChildSections;
|
|
|
|
|
|
|
|
|
|
/** When the item is first created, a rename request may occur before everything is setup for it. This toggles to true in those cases */
|
|
|
|
|
bool bPendingRenameRequest;
|
|
|
|
|
/** Delegate to trigger when a rename was requested on this node */
|
|
|
|
|
FOnRenameRequestActionNode RenameRequestEvent;
|
|
|
|
|
|
|
|
|
|
friend struct FGraphActionNodeImpl;
|
|
|
|
|
/** For sorting, when we don't alphabetically sort (so menu items don't jump around). */
|
|
|
|
|
int32 InsertOrder;
|
2014-03-14 14:13:41 -04:00
|
|
|
};
|