Added a bunch more stuff. Too much to care to mention. Still more to do though.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
struct FComboActionSearchFilter
|
||||
{
|
||||
public:
|
||||
bool IsEmptyFilter() const
|
||||
{
|
||||
return SearchString.IsEmpty()
|
||||
&& bIncludeNodeTitle == false
|
||||
&& bIncludeNodeType == false
|
||||
&& bIncludeNodeDecoratorsTypes == false
|
||||
&& bIncludeNodeData == true
|
||||
&& bIncludeNodeGUID == false;
|
||||
}
|
||||
|
||||
public:
|
||||
// Search term that the search items must match
|
||||
FString SearchString;
|
||||
|
||||
bool bIncludeNodeTitle = true;
|
||||
bool bIncludeNodeType = true;
|
||||
bool bIncludeNodeDecoratorsTypes = true;
|
||||
bool bIncludeNodeData = true;
|
||||
bool bIncludeNodeGUID = false;
|
||||
};
|
||||
@@ -0,0 +1,275 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#include "ComboActionSearchManager.h"
|
||||
|
||||
#include "ComboActionGraph.h"
|
||||
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "Ed/EdComboActionGraph.h"
|
||||
#include "Nodes/ComboActionGraphNode.h"
|
||||
#include "Nodes/ComboActionGraphNode_ActionNodeBase.h"
|
||||
#include "Search/ComboActionSearchFilter.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "ComboActionSearchManager"
|
||||
|
||||
FComboActionSearchManager *FComboActionSearchManager::Instance = nullptr;
|
||||
|
||||
|
||||
bool FComboActionSearchManager::QueryGraphNode(const FComboActionSearchFilter &SearchFilter, const UEdComboActionGraphNode *InGraphNode, const TSharedPtr<FComboActionSearchResult> &OutParentNode) const
|
||||
{
|
||||
if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InGraphNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bContainsSearchString = false;
|
||||
const UComboActionGraphNode *Node = InGraphNode->ComboActionGraphNode;
|
||||
|
||||
if (Node == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FString NodeType = Node->NodeTypeName.ToString();
|
||||
|
||||
const FText DisplayText = FText::Format(LOCTEXT("ComboActionNodeCategory", "Found results in {0}"), FText::FromString(NodeType));
|
||||
|
||||
const TSharedPtr<FComboActionSearchResult_GraphNode> TreeGraphNode = MakeShared<FComboActionSearchResult_GraphNode>(DisplayText, OutParentNode);
|
||||
TreeGraphNode->SetCategory(FText::FromString(NodeType));
|
||||
TreeGraphNode->SetGraphNode(InGraphNode);
|
||||
if (bContainsSearchString)
|
||||
{
|
||||
OutParentNode->AddChild(TreeGraphNode);
|
||||
}
|
||||
|
||||
// Search by Title
|
||||
if (SearchFilter.bIncludeNodeTitle)
|
||||
{
|
||||
if (Node->NodeTitle.ToString().Contains(SearchFilter.SearchString))
|
||||
{
|
||||
bContainsSearchString = true;
|
||||
MakeChildTextNode
|
||||
(
|
||||
TreeGraphNode,
|
||||
FText::FromName(FName(Node->NodeTitle.ToString() )),
|
||||
LOCTEXT("NodeTitleKey", "Node Title"),
|
||||
TEXT("Node Title")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Search by NodeTypeName
|
||||
if (SearchFilter.bIncludeNodeType)
|
||||
{
|
||||
if (Node->NodeTypeName.ToString().Contains(SearchFilter.SearchString))
|
||||
{
|
||||
bContainsSearchString = true;
|
||||
this->MakeChildTextNode(
|
||||
TreeGraphNode,
|
||||
FText::FromName(FName(Node->NodeTypeName.ToString() )),
|
||||
LOCTEXT("NodeTypeKey", "Node Type"),
|
||||
TEXT("Node Type")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Search by Decorators
|
||||
if (SearchFilter.bIncludeNodeDecoratorsTypes)
|
||||
{
|
||||
const TArray<FComboActionDecorator> &NodeDecorators = Node->GetNodeDecorators();
|
||||
for (int32 Index = 0, Num = NodeDecorators.Num(); Index < Num; Index++)
|
||||
{
|
||||
bContainsSearchString = this->QueryNodeDecorators(
|
||||
SearchFilter,
|
||||
NodeDecorators[Index],
|
||||
TreeGraphNode,
|
||||
Index,
|
||||
TEXT("DecoratorType")
|
||||
)
|
||||
|| bContainsSearchString;
|
||||
}
|
||||
}
|
||||
|
||||
// Search by Node Data
|
||||
if (SearchFilter.bIncludeNodeData)
|
||||
{
|
||||
if (const UComboActionGraphNode_ActionNodeBase *ActionNodeBase = Cast<UComboActionGraphNode_ActionNodeBase>(Node))
|
||||
{
|
||||
if (ActionNodeBase->GetRowName().ToString().Contains(SearchFilter.SearchString))
|
||||
{
|
||||
bContainsSearchString = true;
|
||||
this->MakeChildTextNode(
|
||||
TreeGraphNode,
|
||||
FText::FromName(FName(Node->NodeTypeName.ToString() )),
|
||||
LOCTEXT("NodeDataRowKey", "Node Data"),
|
||||
TEXT("Node Data")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search by GUID
|
||||
if (SearchFilter.bIncludeNodeGUID)
|
||||
{
|
||||
const FString FoundGUID = Node->GetNodeGUID().ToString();
|
||||
if (FoundGUID.Contains(SearchFilter.SearchString))
|
||||
{
|
||||
bContainsSearchString = true;
|
||||
MakeChildTextNode
|
||||
(
|
||||
TreeGraphNode,
|
||||
FText::FromString(FoundGUID),
|
||||
LOCTEXT("NodeGUID", "Node GUID"),
|
||||
TEXT("Node GUID")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bContainsSearchString)
|
||||
{
|
||||
OutParentNode->AddChild(TreeGraphNode);
|
||||
}
|
||||
|
||||
return bContainsSearchString;
|
||||
}
|
||||
|
||||
bool FComboActionSearchManager::QueryNodeDecorators(const FComboActionSearchFilter &SearchFilter, const FComboActionDecorator &InDecorator, const TSharedPtr<FComboActionSearchResult> &OutParentNode, int32 DecoratorIndex, FName DecoratorMemberName) const
|
||||
{
|
||||
if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bContainsSearchString = false;
|
||||
|
||||
if (InDecorator.DecoratorType == nullptr) return false;
|
||||
|
||||
// Search by Decorator Name
|
||||
if (InDecorator.DecoratorType->GetName().Contains(SearchFilter.SearchString))
|
||||
{
|
||||
bContainsSearchString = true;
|
||||
|
||||
FString DecoratorName = InDecorator.DecoratorType->GetClass()->GetName();
|
||||
// Format Name
|
||||
{
|
||||
if (DecoratorName.Contains(TEXT("_GEN_VARIABLE")))
|
||||
{
|
||||
DecoratorName.ReplaceInline(TEXT("_GEN_VARIABLE"), TEXT(""));
|
||||
}
|
||||
if(DecoratorName.EndsWith(TEXT("_C")) && DecoratorName.StartsWith(TEXT("Default__")))
|
||||
{
|
||||
DecoratorName.RightChopInline(9);
|
||||
DecoratorName.LeftChopInline(2);
|
||||
}
|
||||
if (DecoratorName.EndsWith(TEXT("_C")))
|
||||
{
|
||||
DecoratorName.LeftChopInline(2);
|
||||
}
|
||||
}
|
||||
|
||||
const FText Category = FText::Format
|
||||
(
|
||||
LOCTEXT("DecoratorName", "Node Decorator: {0} at Index: {1}"),
|
||||
FText::FromString(DecoratorName), FText::AsNumber(DecoratorIndex)
|
||||
);
|
||||
MakeChildTextNode
|
||||
(
|
||||
OutParentNode,
|
||||
FText::FromString(DecoratorName),
|
||||
Category,
|
||||
Category.ToString()
|
||||
);
|
||||
}
|
||||
|
||||
return bContainsSearchString;
|
||||
}
|
||||
|
||||
bool FComboActionSearchManager::QuerySingleAction(const FComboActionSearchFilter &SearchFilter, const UComboActionGraph *InAction, TSharedPtr<FComboActionSearchResult> &OutParentNode)
|
||||
{
|
||||
if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InAction))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const UEdComboActionGraph *Graph = CastChecked<UEdComboActionGraph>(InAction->EdGraph);
|
||||
|
||||
const TSharedPtr<FComboActionSearchResult_ActionNode> TreeActionNode = MakeShared<FComboActionSearchResult_ActionNode>(FText::FromString(InAction->GetPathName()), OutParentNode);
|
||||
TreeActionNode->SetActionGraph(Graph);
|
||||
|
||||
// Find in GraphNodes
|
||||
bool bFoundInAction = false;
|
||||
const TArray<UEdGraphNode*> &AllGraphNodes = Graph->Nodes;
|
||||
for (UEdGraphNode *Node : AllGraphNodes)
|
||||
{
|
||||
bool bFoundInNode = false;
|
||||
if (const UEdComboActionGraphNode *GraphNode = Cast<UEdComboActionGraphNode>(Node))
|
||||
{
|
||||
bFoundInNode = this->QueryGraphNode(SearchFilter, GraphNode, TreeActionNode);
|
||||
}
|
||||
|
||||
// Found at least one match in one of the nodes.
|
||||
bFoundInAction = bFoundInNode || bFoundInAction;
|
||||
}
|
||||
|
||||
if (bFoundInAction)
|
||||
{
|
||||
OutParentNode->AddChild(TreeActionNode);
|
||||
}
|
||||
|
||||
return bFoundInAction;
|
||||
}
|
||||
|
||||
void FComboActionSearchManager::Initialize(TSharedPtr<FWorkspaceItem> ParentTabCategory)
|
||||
{
|
||||
// Must ensure we do not attempt to load the AssetRegistry Module while saving a package, however, if it is loaded already we can safely obtain it
|
||||
this->AssetRegistry = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
|
||||
|
||||
this->OnAssetAddedHandle = this->AssetRegistry->OnAssetAdded().AddRaw(this, &FComboActionSearchManager::HandleOnAssetAdded);
|
||||
this->OnAssetRemovedHandle = this->AssetRegistry->OnAssetRemoved().AddRaw(this, &FComboActionSearchManager::HandleOnAssetRemoved);
|
||||
this->OnAssetRenamedHandle = this->AssetRegistry->OnAssetRenamed().AddRaw(this, &FComboActionSearchManager::HandleOnAssetRenamed);
|
||||
|
||||
if (this->AssetRegistry->IsLoadingAssets())
|
||||
{
|
||||
this->OnFilesLoadedHandle = this->AssetRegistry->OnFilesLoaded().AddRaw(this, &FComboActionSearchManager::HandleOnAssetRegistryFilesLoaded);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->HandleOnAssetRegistryFilesLoaded();
|
||||
}
|
||||
this->OnAssetLoadedHandle = FCoreUObjectDelegates::OnAssetLoaded.AddRaw(this, &FComboActionSearchManager::HandleOnAssetLoaded);
|
||||
}
|
||||
|
||||
void FComboActionSearchManager::UnInitialize()
|
||||
{
|
||||
if (this->AssetRegistry)
|
||||
{
|
||||
if (this->OnAssetAddedHandle.IsValid())
|
||||
{
|
||||
this->AssetRegistry->OnAssetAdded().Remove(this->OnAssetAddedHandle);
|
||||
this->OnAssetAddedHandle.Reset();
|
||||
}
|
||||
if (this->OnAssetRemovedHandle.IsValid())
|
||||
{
|
||||
this->AssetRegistry->OnAssetRemoved().Remove(this->OnAssetRemovedHandle);
|
||||
this->OnAssetRemovedHandle.Reset();
|
||||
}
|
||||
if (this->OnFilesLoadedHandle.IsValid())
|
||||
{
|
||||
this->AssetRegistry->OnFilesLoaded().Remove(this->OnFilesLoadedHandle);
|
||||
this->OnFilesLoadedHandle.Reset();
|
||||
}
|
||||
if (this->OnAssetRenamedHandle.IsValid())
|
||||
{
|
||||
this->AssetRegistry->OnAssetRenamed().Remove(this->OnAssetRenamedHandle);
|
||||
this->OnAssetRenamedHandle.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (this->OnAssetLoadedHandle.IsValid())
|
||||
{
|
||||
FCoreUObjectDelegates::OnAssetLoaded.Remove(this->OnAssetLoadedHandle);
|
||||
this->OnAssetLoadedHandle.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Search/ComboActionSearchResult.h"
|
||||
|
||||
#include "ComboActionGraph.h"
|
||||
#include "AssetRegistry/IAssetRegistry.h"
|
||||
#include "Ed/EdComboActionGraphNode.h"
|
||||
|
||||
|
||||
struct FDialogueSearchData
|
||||
{
|
||||
TWeakObjectPtr<class UComboActionGraph> Dialogue;
|
||||
};
|
||||
|
||||
class FComboActionSearchManager
|
||||
{
|
||||
public:
|
||||
static FComboActionSearchManager *Get()
|
||||
{
|
||||
if (Instance == nullptr)
|
||||
{
|
||||
Instance = new FComboActionSearchManager();
|
||||
}
|
||||
return Instance;
|
||||
}
|
||||
|
||||
public:
|
||||
FComboActionSearchManager(){}
|
||||
~FComboActionSearchManager() { this->UnInitialize(); }
|
||||
|
||||
/**
|
||||
* Searches for InSearchString in the InGraphNode. Adds the result as a child in OutParentNode.
|
||||
* @return True if found anything matching the InSearchString
|
||||
*/
|
||||
bool QueryGraphNode(const FComboActionSearchFilter &SearchFilter, const UEdComboActionGraphNode *InGraphNode, const TSharedPtr<class FComboActionSearchResult> &OutParentNode) const;
|
||||
|
||||
bool QueryNodeDecorators
|
||||
(
|
||||
const FComboActionSearchFilter &SearchFilter,
|
||||
const FComboActionDecorator &InDecorator,
|
||||
const TSharedPtr<class FComboActionSearchResult> &OutParentNode,
|
||||
int32 DecoratorIndex,
|
||||
FName DecoratorMemberName
|
||||
) const;
|
||||
|
||||
/**
|
||||
* Searches for InSearchString in the InAction. Adds the result as a child of OutParentNode.
|
||||
* @return True if found anything matching the InSearchString
|
||||
*/
|
||||
bool QuerySingleAction
|
||||
(
|
||||
const FComboActionSearchFilter &SearchFilter,
|
||||
const UComboActionGraph *InAction,
|
||||
TSharedPtr<class FComboActionSearchResult> &OutParentNode
|
||||
);
|
||||
|
||||
void Initialize(TSharedPtr<FWorkspaceItem> ParentTabCategory = nullptr);
|
||||
|
||||
void UnInitialize();
|
||||
|
||||
private:
|
||||
|
||||
// Helper method to make a Text Node and add it as a child to ParentNode
|
||||
TSharedPtr<FComboActionSearchResult> MakeChildTextNode
|
||||
(
|
||||
const TSharedPtr<FComboActionSearchResult> &ParentNode,
|
||||
const FText &DisplayName, const FText &Category,
|
||||
const FString &CommentString
|
||||
) const
|
||||
{
|
||||
TSharedPtr<FComboActionSearchResult> TextNode = MakeShared<FComboActionSearchResult>(DisplayName, ParentNode);
|
||||
TextNode->SetCategory(Category);
|
||||
if (!CommentString.IsEmpty())
|
||||
{
|
||||
TextNode->SetCommentString(CommentString);
|
||||
}
|
||||
ParentNode->AddChild(TextNode);
|
||||
return TextNode;
|
||||
}
|
||||
|
||||
// Callback hook from the Asset Registry when an asset is added
|
||||
void HandleOnAssetAdded(const FAssetData &InAssetData){}
|
||||
|
||||
// Callback hook from the Asset Registry, marks the asset for deletion from the cache
|
||||
void HandleOnAssetRemoved(const FAssetData &InAssetData){}
|
||||
|
||||
// Callback hook from the Asset Registry, marks the asset for deletion from the cache
|
||||
void HandleOnAssetRenamed(const FAssetData &InAssetData, const FString &InOldName){}
|
||||
|
||||
// Callback hook from the Asset Registry when an asset is loaded
|
||||
void HandleOnAssetLoaded(UObject *InAsset){}
|
||||
|
||||
// Callback when the Asset Registry loads all its assets
|
||||
void HandleOnAssetRegistryFilesLoaded(){}
|
||||
|
||||
private:
|
||||
static FComboActionSearchManager *Instance;
|
||||
|
||||
// Maps the Dialogue path => SearchData.
|
||||
TMap<FName, FDialogueSearchData> SearchMap;
|
||||
|
||||
// Because we are unable to query for the module on another thread, cache it for use later
|
||||
IAssetRegistry *AssetRegistry = nullptr;
|
||||
|
||||
// Handlers
|
||||
FDelegateHandle OnAssetAddedHandle;
|
||||
FDelegateHandle OnAssetRemovedHandle;
|
||||
FDelegateHandle OnAssetRenamedHandle;
|
||||
FDelegateHandle OnFilesLoadedHandle;
|
||||
FDelegateHandle OnAssetLoadedHandle;
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#include "ComboActionSearchResult.h"
|
||||
|
||||
#include "ComboActionGraph.h"
|
||||
#include "ComboActionSearchUtils.h"
|
||||
#include "Helpers/ComboActionGraphEditorUtilities.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "ComboActionSearchResult"
|
||||
|
||||
|
||||
TSharedRef<SWidget> FComboActionSearchResult::CreateIcon() const
|
||||
{
|
||||
const FLinearColor IconColor = FLinearColor::White;
|
||||
const FSlateBrush *Brush = nullptr;
|
||||
|
||||
return SNew(SImage)
|
||||
.Image(Brush)
|
||||
.ColorAndOpacity(IconColor)
|
||||
.ToolTipText(GetCategory());
|
||||
}
|
||||
|
||||
TWeakObjectPtr<const UComboActionGraph> FComboActionSearchResult::GetParentDialogue() const
|
||||
{
|
||||
if (this->Parent.IsValid())
|
||||
{
|
||||
return this->Parent.Pin()->GetParentDialogue();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#pragma region Search_Actions
|
||||
|
||||
TWeakObjectPtr<const UComboActionGraph> FComboActionSearchResult_ActionNode::GetParentDialogue() const
|
||||
{
|
||||
if (this->ComboActionGraph.IsValid())
|
||||
{
|
||||
return this->ComboActionGraph;
|
||||
}
|
||||
return FComboActionSearchResult::GetParentDialogue();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Search_Nodes
|
||||
|
||||
FReply FComboActionSearchResult_GraphNode::OnClick(TWeakPtr<FAssetEditor_ComboActionGraph> ActionEditorPtr)
|
||||
{
|
||||
if (this->GraphNode.IsValid())
|
||||
{
|
||||
return FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(ActionEditorPtr, this->GraphNode.Get()) ? FReply::Handled() : FReply::Unhandled();
|
||||
}
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> FComboActionSearchResult_GraphNode::CreateIcon() const
|
||||
{
|
||||
if (this->GraphNode.IsValid())
|
||||
{
|
||||
FLinearColor Color;
|
||||
const FSlateIcon Icon = this->GraphNode.Get()->GetIconAndTint(Color);
|
||||
return SNew(SImage)
|
||||
.Image(Icon.GetOptionalIcon())
|
||||
.ColorAndOpacity(Color)
|
||||
.ToolTipText(GetCategory());
|
||||
}
|
||||
|
||||
return FComboActionSearchResult::CreateIcon();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,211 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "Ed/EdComboActionGraph.h"
|
||||
#include "Ed/EdComboActionGraphNode.h"
|
||||
#include "Widgets/Views/STreeView.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "ComboActionSearchResult"
|
||||
|
||||
|
||||
/**
|
||||
* Template Tree Item Node class.
|
||||
*/
|
||||
template <class SelfType>
|
||||
class FComboActionTreeItemNode : public TSharedFromThis<SelfType>
|
||||
{
|
||||
|
||||
public:
|
||||
FComboActionTreeItemNode(const FText &InDisplayText, const TSharedPtr<SelfType> &InParent) : Parent(InParent), DisplayText(InDisplayText){};
|
||||
virtual ~FComboActionTreeItemNode(){};
|
||||
|
||||
#pragma region Click_Functions
|
||||
|
||||
virtual FReply OnClick(TWeakPtr<FAssetEditor_ComboActionGraph> DialogueEditorPtr)
|
||||
{
|
||||
// If there is a parent, handle it using the parent's functionality
|
||||
if (Parent.IsValid())
|
||||
{
|
||||
return Parent.Pin()->OnClick(DialogueEditorPtr);
|
||||
}
|
||||
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region DisplayText_Functions
|
||||
|
||||
FText GetDisplayText() const { return this->DisplayText; }
|
||||
FName GetDisplayTextAsFName() const { return FName(*this->DisplayText.ToString()); }
|
||||
void SetDisplayText(const FText &InText) { this->DisplayText = InText; }
|
||||
bool DoesDisplayTextContains(const FString &InSearch, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase) const
|
||||
{
|
||||
return this->DisplayText.ToString().Contains(InSearch, SearchCase);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Parent_Functions
|
||||
|
||||
bool HasParent() const { return this->Parent.IsValid(); }
|
||||
TWeakPtr<SelfType> GetParent() const { return this->Parent; }
|
||||
void SetParent(TWeakPtr<SelfType> InParentNode) { this->Parent = InParentNode; }
|
||||
void ClearParent() { this->Parent.Reset(); }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Children_Functions
|
||||
|
||||
public:
|
||||
|
||||
bool HasChildren() const { return this->Children.Num() > 0; }
|
||||
const TArray<TSharedPtr<SelfType>> &GetChildren() const { return this->Children; }
|
||||
void GetVisibleChildren(TArray<TSharedPtr<SelfType>> &OutChildren)
|
||||
{
|
||||
for (const TSharedPtr<SelfType> &Child : this->Children)
|
||||
{
|
||||
if (Child->IsVisible())
|
||||
{
|
||||
OutChildren.Add(Child);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void AddChild(const TSharedPtr<SelfType> &ChildNode)
|
||||
{
|
||||
ensure(!ChildNode->IsRoot());
|
||||
ChildNode->SetParent(this->AsShared());
|
||||
this->Children.Add(ChildNode);
|
||||
}
|
||||
virtual void SetChildren(const TArray<TSharedPtr<SelfType>> &InChildren)
|
||||
{
|
||||
this->Children = InChildren;
|
||||
for (const TSharedPtr<SelfType> &Child : this->Children)
|
||||
{
|
||||
ensure(!Child->IsRoot());
|
||||
Child->SetParent(this->AsShared());
|
||||
}
|
||||
}
|
||||
virtual void ClearChildren()
|
||||
{
|
||||
this->Children.Empty();
|
||||
}
|
||||
|
||||
void ExpandAllChildren(const TSharedPtr<STreeView<TSharedPtr<SelfType>>> &TreeView, bool bRecursive = true)
|
||||
{
|
||||
static constexpr bool bShouldExpandItem = true;
|
||||
if (!HasChildren())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TreeView->SetItemExpansion(this->AsShared(), bShouldExpandItem);
|
||||
for (const TSharedPtr<SelfType> &ChildNode : this->Children)
|
||||
{
|
||||
if (bRecursive)
|
||||
{
|
||||
// recursive on all children.
|
||||
ChildNode->ExpandAllChildren(TreeView, bRecursive);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only direct children
|
||||
TreeView->SetItemExpansion(ChildNode, bShouldExpandItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Helper_Functions
|
||||
|
||||
public:
|
||||
bool IsRoot() const { return !this->Parent.IsValid(); }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
protected:
|
||||
/** Any children listed under this node. */
|
||||
TArray<TSharedPtr<SelfType>> Children;
|
||||
|
||||
/** The node that this is a direct child of (empty if this is a root node) */
|
||||
TWeakPtr<SelfType> Parent;
|
||||
|
||||
/** The displayed text for this item. */
|
||||
FText DisplayText;
|
||||
|
||||
/** Is this node displayed? */
|
||||
bool bIsVisible = true;
|
||||
};
|
||||
|
||||
|
||||
class FComboActionSearchResult : public FComboActionTreeItemNode<FComboActionSearchResult>
|
||||
{
|
||||
public:
|
||||
FComboActionSearchResult(const FText &InDisplayText, const TSharedPtr<FComboActionSearchResult> &InParent) : FComboActionTreeItemNode(InDisplayText, InParent){}
|
||||
|
||||
public:
|
||||
// Create an icon to represent the result
|
||||
virtual TSharedRef<SWidget> CreateIcon() const;
|
||||
|
||||
// Gets the Dialogue housing all these search results. Aka the Dialogue this search result belongs to.
|
||||
virtual TWeakObjectPtr<const UComboActionGraph> GetParentDialogue() const;
|
||||
|
||||
// Category:
|
||||
FText GetCategory() const { return this->Category; }
|
||||
void SetCategory(const FText &InCategory) { this->Category = InCategory; }
|
||||
|
||||
// CommentString
|
||||
FString GetCommentString() const { return this->CommentString; }
|
||||
void SetCommentString(const FString &InCommentString) { this->CommentString = InCommentString; }
|
||||
|
||||
protected:
|
||||
// The category of this node.
|
||||
FText Category;
|
||||
|
||||
// Display text for comment information
|
||||
FString CommentString;
|
||||
};
|
||||
|
||||
// Root Node, should not be displayed.
|
||||
class FComboActionSearchResult_RootNode : public FComboActionSearchResult
|
||||
{
|
||||
public:
|
||||
FComboActionSearchResult_RootNode() : FComboActionSearchResult(FText::FromString(TEXT("INVALID")), nullptr) { this->Category = LOCTEXT("ComboActionSearchResult_RootNodeCategory", "Root"); }
|
||||
};
|
||||
|
||||
// Tree Node result that represents the Node
|
||||
class FComboActionSearchResult_ActionNode : public FComboActionSearchResult
|
||||
{
|
||||
public:
|
||||
FComboActionSearchResult_ActionNode(const FText &InDisplayText, const TSharedPtr<FComboActionSearchResult> &InParent) : FComboActionSearchResult(InDisplayText, InParent) { this->Category = LOCTEXT("ComboAcitonSearchResult_ActionNodeCategory", "Action Node"); }
|
||||
|
||||
virtual FReply OnClick(TWeakPtr<class FAssetEditor_ComboActionGraph> DialogueEditorPtr) override { return FReply::Unhandled(); }
|
||||
virtual TSharedRef<SWidget> CreateIcon() const override { return FComboActionSearchResult::CreateIcon(); }
|
||||
virtual TWeakObjectPtr<const UComboActionGraph> GetParentDialogue() const override;
|
||||
|
||||
void SetActionGraph(TWeakObjectPtr<const UEdComboActionGraph> InDialogueGraph) { this->ComboActionGraph = InDialogueGraph->GetComboActionGraph(); }
|
||||
|
||||
protected:
|
||||
TWeakObjectPtr<const UComboActionGraph> ComboActionGraph;
|
||||
};
|
||||
|
||||
// Tree Node result that represents the GraphNode
|
||||
class FComboActionSearchResult_GraphNode : public FComboActionSearchResult
|
||||
{
|
||||
public:
|
||||
FComboActionSearchResult_GraphNode(const FText &InDisplayText, const TSharedPtr<FComboActionSearchResult> &InParent) : FComboActionSearchResult(InDisplayText, InParent){}
|
||||
|
||||
virtual FReply OnClick(TWeakPtr<FAssetEditor_ComboActionGraph> ComboActionEditorPtr) override;
|
||||
virtual TSharedRef<SWidget> CreateIcon() const override;
|
||||
|
||||
void SetGraphNode(TWeakObjectPtr<const UEdComboActionGraphNode> InGraphNode) { this->GraphNode = InGraphNode; }
|
||||
|
||||
protected:
|
||||
TWeakObjectPtr<const UEdComboActionGraphNode> GraphNode;
|
||||
};
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,13 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#include "ComboActionSearchUtils.h"
|
||||
|
||||
|
||||
TSharedPtr<SDockTab> FComboActionSearchHelpers::InvokeTab(TSharedPtr<FTabManager> TabManager, const FTabId &TabID)
|
||||
{
|
||||
if (!TabManager.IsValid())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return TabManager->TryInvokeTab(TabID);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class COMBOINPUTEDITOR_API FComboActionSearchHelpers
|
||||
{
|
||||
public:
|
||||
static TSharedPtr<SDockTab> InvokeTab(TSharedPtr<FTabManager> TabManager, const FTabId &TabID);
|
||||
};
|
||||
@@ -0,0 +1,405 @@
|
||||
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
|
||||
|
||||
#include "SComboActionSearch.h"
|
||||
|
||||
#include "Ed/AssetEditor_ComboActionGraph.h"
|
||||
#include "Framework/Commands/GenericCommands.h"
|
||||
#include "Search/ComboActionSearchManager.h"
|
||||
#include "Widgets/Input/SSearchBox.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "SComboActionSearch"
|
||||
|
||||
|
||||
void SComboActionSearch::Construct(const FArguments &InArgs, const TSharedPtr<FAssetEditor_ComboActionGraph> &InDialogueEditor)
|
||||
{
|
||||
this->ComboActionEditorPtr = InDialogueEditor;
|
||||
this->HostTab = InArgs._ContainingTab;
|
||||
|
||||
if (this->HostTab.IsValid())
|
||||
{
|
||||
this->HostTab.Pin()->SetOnTabClosed(SDockTab::FOnTabClosedCallback::CreateSP(this, &SComboActionSearch::HandleHostTabClosed));
|
||||
}
|
||||
|
||||
this->ChildSlot
|
||||
[
|
||||
SAssignNew(this->MainVerticalBoxWidget, SVerticalBox)
|
||||
|
||||
// Top bar, search
|
||||
+SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
// Search field
|
||||
+SHorizontalBox::Slot()
|
||||
.FillWidth(1)
|
||||
[
|
||||
SAssignNew(this->SearchTextBoxWidget, SSearchBox)
|
||||
.HintText(LOCTEXT("ActionSearchHint", "Enter searched text..."))
|
||||
.OnTextChanged(this, &SComboActionSearch::HandleSearchTextChanged)
|
||||
.OnTextCommitted(this, &SComboActionSearch::HandleSearchTextCommitted)
|
||||
.Visibility(EVisibility::Visible)
|
||||
]
|
||||
|
||||
// Filter Options
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(2.0f, 2.0f)
|
||||
[
|
||||
SNew(SComboButton)
|
||||
.ComboButtonStyle(FAppStyle::Get(), "GenericFilters.ComboButtonStyle")
|
||||
.ForegroundColor(FLinearColor::White)
|
||||
.ContentPadding(0)
|
||||
.ToolTipText(LOCTEXT("Filters_Tooltip", "Filter options"))
|
||||
.OnGetMenuContent(this, &SComboActionSearch::FillFilterEntries)
|
||||
.HasDownArrow(true)
|
||||
.ContentPadding(FMargin(1, 0))
|
||||
.ButtonContent()
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.TextStyle(FAppStyle::Get(), "GenericFilters.TextStyle")
|
||||
.Font(FAppStyle::Get().GetFontStyle("FontAwesome.9"))
|
||||
.Text(FText::FromString(FString(TEXT("\xf0b0"))) )
|
||||
]
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(2, 0, 0, 0)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.TextStyle(FAppStyle::Get(), "GenericFilters.TextStyle")
|
||||
.Text(LOCTEXT("Filters", "Filters"))
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
// Results tree
|
||||
+SVerticalBox::Slot()
|
||||
.FillHeight(1.0f)
|
||||
.Padding(0.0f, 4.0f, 0.0f, 0.0f)
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage(FAppStyle::GetBrush("Menu.Background"))
|
||||
[
|
||||
SAssignNew(this->TreeView, STreeView<TSharedPtr<FComboActionSearchResult>>)
|
||||
.ItemHeight(24)
|
||||
.TreeItemsSource(&this->ItemsFound)
|
||||
.OnGenerateRow(this, &SComboActionSearch::HandleGenerateRow)
|
||||
.OnGetChildren(this, &SComboActionSearch::HandleGetChildren)
|
||||
.OnMouseButtonDoubleClick(this, &SComboActionSearch::HandleTreeSelectionDoubleClicked)
|
||||
.SelectionMode(ESelectionMode::Multi)
|
||||
.OnContextMenuOpening(this, &SComboActionSearch::HandleContextMenuOpening)
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
void SComboActionSearch::FocusForUse(const FComboActionSearchFilter &SearchFilter, bool bSelectFirstResult)
|
||||
{
|
||||
FWidgetPath FilterTextBoxWidgetPath;
|
||||
FSlateApplication::Get().GeneratePathToWidgetUnchecked(SearchTextBoxWidget.ToSharedRef(), FilterTextBoxWidgetPath);
|
||||
|
||||
FSlateApplication::Get().SetKeyboardFocus(FilterTextBoxWidgetPath, EFocusCause::SetDirectly);
|
||||
|
||||
if (!SearchFilter.SearchString.IsEmpty())
|
||||
{
|
||||
SearchTextBoxWidget->SetText(FText::FromString(SearchFilter.SearchString));
|
||||
MakeSearchQuery(SearchFilter);
|
||||
|
||||
if (bSelectFirstResult && this->ItemsFound.Num())
|
||||
{
|
||||
auto ItemToFocusOn = this->ItemsFound[0];
|
||||
|
||||
while (ItemToFocusOn->HasChildren())
|
||||
{
|
||||
ItemToFocusOn = ItemToFocusOn->GetChildren()[0];
|
||||
}
|
||||
this->TreeView->SetSelection(ItemToFocusOn);
|
||||
ItemToFocusOn->OnClick(this->ComboActionEditorPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SComboActionSearch::MakeSearchQuery(const FComboActionSearchFilter &SearchFilter)
|
||||
{
|
||||
this->SearchTextBoxWidget->SetText(FText::FromString(SearchFilter.SearchString));
|
||||
|
||||
if (this->ItemsFound.Num())
|
||||
{
|
||||
this->TreeView->RequestScrollIntoView(this->ItemsFound[0]);
|
||||
}
|
||||
this->ItemsFound.Empty();
|
||||
|
||||
if (SearchFilter.SearchString.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->HighlightText = FText::FromString(SearchFilter.SearchString);
|
||||
this->RootSearchResult = MakeShared<FComboActionSearchResult_RootNode>();
|
||||
|
||||
if (this->ComboActionEditorPtr.IsValid())
|
||||
{
|
||||
FComboActionSearchManager::Get()->QuerySingleAction(SearchFilter, this->ComboActionEditorPtr.Pin()->GetEditingGraphSafe(), this->RootSearchResult);
|
||||
|
||||
const TArray<TSharedPtr<FComboActionSearchResult>> &Children = this->RootSearchResult->GetChildren();
|
||||
if (Children.Num() == 1 && Children[0].IsValid())
|
||||
{
|
||||
// we must ensure reference is created so its not garbage collected, usually resulting in crash!
|
||||
TSharedPtr<FComboActionSearchResult> TempChild = Children[0];
|
||||
this->RootSearchResult = TempChild;
|
||||
this->RootSearchResult->ClearParent();
|
||||
}
|
||||
}
|
||||
|
||||
this->ItemsFound = this->RootSearchResult->GetChildren();
|
||||
if (this->ItemsFound.Num() == 0)
|
||||
{
|
||||
this->ItemsFound.Add(MakeShared<FComboActionSearchResult>(LOCTEXT("ActionSearchNoResults", "No Results found"), this->RootSearchResult));
|
||||
this->HighlightText = FText::GetEmpty();\
|
||||
}
|
||||
else
|
||||
{
|
||||
this->RootSearchResult->ExpandAllChildren(this->TreeView);
|
||||
}
|
||||
|
||||
this->TreeView->RequestTreeRefresh();
|
||||
}
|
||||
|
||||
FName SComboActionSearch::GetHostTabId() const
|
||||
{
|
||||
const TSharedPtr<SDockTab> HostTabPtr = this->HostTab.Pin();
|
||||
if (HostTabPtr.IsValid())
|
||||
{
|
||||
return HostTabPtr->GetLayoutIdentifier().TabType;
|
||||
}
|
||||
|
||||
return NAME_None;
|
||||
}
|
||||
|
||||
void SComboActionSearch::CloseHostTab()
|
||||
{
|
||||
const TSharedPtr<SDockTab> HostTabPtr = this->HostTab.Pin();
|
||||
if (HostTabPtr.IsValid())
|
||||
{
|
||||
HostTabPtr->RequestCloseTab();
|
||||
}
|
||||
}
|
||||
|
||||
void SComboActionSearch::HandleHostTabClosed(TSharedRef<SDockTab> DockTab)
|
||||
{
|
||||
// Clear cache
|
||||
}
|
||||
|
||||
void SComboActionSearch::HandleSearchTextChanged(const FText& Text)
|
||||
{
|
||||
this->CurrentFilter.SearchString = Text.ToString();
|
||||
}
|
||||
|
||||
void SComboActionSearch::HandleSearchTextCommitted(const FText& Text, ETextCommit::Type CommitType)
|
||||
{
|
||||
if (Text.IsEmpty())
|
||||
{
|
||||
this->TreeView->RequestTreeRefresh();
|
||||
}
|
||||
|
||||
if (CommitType == ETextCommit::OnEnter)
|
||||
{
|
||||
this->CurrentFilter.SearchString = Text.ToString();
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}
|
||||
}
|
||||
|
||||
void SComboActionSearch::HandleGetChildren(TSharedPtr<FComboActionSearchResult> InItem, TArray<TSharedPtr<FComboActionSearchResult>> &OutChildren)
|
||||
{
|
||||
OutChildren += InItem->GetChildren();
|
||||
}
|
||||
|
||||
void SComboActionSearch::HandleTreeSelectionDoubleClicked(TSharedPtr<FComboActionSearchResult> Item)
|
||||
{
|
||||
if (Item.IsValid())
|
||||
{
|
||||
Item->OnClick(this->ComboActionEditorPtr);
|
||||
}
|
||||
}
|
||||
|
||||
TSharedRef<ITableRow> SComboActionSearch::HandleGenerateRow(TSharedPtr<FComboActionSearchResult> InItem, const TSharedRef<STableViewBase> &OwnerTable)
|
||||
{
|
||||
// Normal entry
|
||||
FText CommentText = FText::GetEmpty();
|
||||
if (!InItem->GetCommentString().IsEmpty())
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add(TEXT("Comment"), FText::FromString(InItem->GetCommentString()));
|
||||
CommentText = FText::Format(LOCTEXT("NodeComment", "{Comment}"), Args);
|
||||
}
|
||||
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add(TEXT("Category"), InItem->GetCategory());
|
||||
Args.Add(TEXT("DisplayTitle"), InItem->GetDisplayText());
|
||||
const FText Tooltip = FText::Format(LOCTEXT("DialogueResultSearchToolTip", "{Category} : {DisplayTitle}"), Args);
|
||||
|
||||
return SNew(STableRow<TSharedPtr<FComboActionSearchResult>>, OwnerTable)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
// Icon
|
||||
+SHorizontalBox::Slot()
|
||||
.VAlign(VAlign_Center)
|
||||
.AutoWidth()
|
||||
[
|
||||
InItem->CreateIcon()
|
||||
]
|
||||
|
||||
// Display text
|
||||
+SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(2,0)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(InItem.Get(), &FComboActionSearchResult::GetDisplayText)
|
||||
.HighlightText(HighlightText)
|
||||
.ToolTipText(Tooltip)
|
||||
]
|
||||
|
||||
// Comment Block
|
||||
+SHorizontalBox::Slot()
|
||||
.FillWidth(1)
|
||||
.HAlign(HAlign_Right)
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(2,0)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(CommentText)
|
||||
.ColorAndOpacity(FLinearColor::Yellow)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
TSharedPtr<SWidget> SComboActionSearch::HandleContextMenuOpening()
|
||||
{
|
||||
const bool bShouldCloseWindowAfterMenuSelection = true;
|
||||
FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, this->CommandList);
|
||||
|
||||
MenuBuilder.BeginSection("BasicOperations");
|
||||
{
|
||||
MenuBuilder.AddMenuEntry(FGenericCommands::Get().SelectAll);
|
||||
MenuBuilder.AddMenuEntry(FGenericCommands::Get().Copy);
|
||||
}
|
||||
|
||||
return MenuBuilder.MakeWidget();
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> SComboActionSearch::FillFilterEntries()
|
||||
{
|
||||
FMenuBuilder MenuBuilder(true, nullptr);
|
||||
MenuBuilder.AddMenuEntry
|
||||
(
|
||||
LOCTEXT("IncludeNodeTitle", "Include Node Title"),
|
||||
LOCTEXT("IncludeNodeTitle_ToolTip", "Include Node Titles in the search result"),
|
||||
FSlateIcon(),
|
||||
FUIAction(
|
||||
FExecuteAction::CreateLambda([this]()
|
||||
{
|
||||
this->CurrentFilter.bIncludeNodeTitle = !this->CurrentFilter.bIncludeNodeTitle;
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([this]() -> bool
|
||||
{
|
||||
return this->CurrentFilter.bIncludeNodeTitle;
|
||||
})
|
||||
),
|
||||
NAME_None,
|
||||
EUserInterfaceActionType::ToggleButton
|
||||
);
|
||||
MenuBuilder.AddMenuEntry
|
||||
(
|
||||
LOCTEXT("IncludeNodeType", "Include Node Type"),
|
||||
LOCTEXT("IncludeNodeType_ToolTip", "Include Node Type in the search result"),
|
||||
FSlateIcon(),
|
||||
FUIAction(
|
||||
FExecuteAction::CreateLambda([this]()
|
||||
{
|
||||
this->CurrentFilter.bIncludeNodeType = !this->CurrentFilter.bIncludeNodeType;
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([this]() -> bool
|
||||
{
|
||||
return this->CurrentFilter.bIncludeNodeType;
|
||||
})
|
||||
),
|
||||
NAME_None,
|
||||
EUserInterfaceActionType::ToggleButton
|
||||
);
|
||||
MenuBuilder.AddMenuEntry
|
||||
(
|
||||
LOCTEXT("IncludeNodeDecoratorsTypes", "Include Node Decorators"),
|
||||
LOCTEXT("IncludeNodeDecoratorsTypes_ToolTip", "Include Node Decorators Types (by name) in the search result"),
|
||||
FSlateIcon(),
|
||||
FUIAction(
|
||||
FExecuteAction::CreateLambda([this]()
|
||||
{
|
||||
this->CurrentFilter.bIncludeNodeDecoratorsTypes = !this->CurrentFilter.bIncludeNodeDecoratorsTypes;
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([this]() -> bool
|
||||
{
|
||||
return this->CurrentFilter.bIncludeNodeDecoratorsTypes;
|
||||
})
|
||||
),
|
||||
NAME_None,
|
||||
EUserInterfaceActionType::ToggleButton
|
||||
);
|
||||
MenuBuilder.AddMenuEntry
|
||||
(
|
||||
LOCTEXT("IncludeNodeData", "Include Node Data Row"),
|
||||
LOCTEXT("IncludeNodeDecoratorsTypes_ToolTip", "Include Node Data Row in the search result"),
|
||||
FSlateIcon(),
|
||||
FUIAction(
|
||||
FExecuteAction::CreateLambda([this]()
|
||||
{
|
||||
this->CurrentFilter.bIncludeNodeData = !this->CurrentFilter.bIncludeNodeData;
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([this]() -> bool
|
||||
{
|
||||
return this->CurrentFilter.bIncludeNodeData;
|
||||
})
|
||||
),
|
||||
NAME_None,
|
||||
EUserInterfaceActionType::ToggleButton
|
||||
);
|
||||
MenuBuilder.AddMenuEntry
|
||||
(
|
||||
LOCTEXT("IncludeNodeGUID", "Include Node GUID"),
|
||||
LOCTEXT("IncludeNodeGUID_ToolTip", "Include Node GUID in the search result"),
|
||||
FSlateIcon(),
|
||||
FUIAction(
|
||||
FExecuteAction::CreateLambda([this]()
|
||||
{
|
||||
this->CurrentFilter.bIncludeNodeGUID = !this->CurrentFilter.bIncludeNodeGUID;
|
||||
MakeSearchQuery(this->CurrentFilter);
|
||||
}),
|
||||
FCanExecuteAction(),
|
||||
FIsActionChecked::CreateLambda([this]() -> bool
|
||||
{
|
||||
return this->CurrentFilter.bIncludeNodeGUID;
|
||||
})
|
||||
),
|
||||
NAME_None,
|
||||
EUserInterfaceActionType::ToggleButton
|
||||
);
|
||||
|
||||
return MenuBuilder.MakeWidget();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright Dominik Pavlicek 2023. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
#include "Widgets/Views/STreeView.h"
|
||||
|
||||
#include "Framework/Commands/UICommandList.h"
|
||||
|
||||
#include "Search/ComboActionSearchFilter.h"
|
||||
#include "Search/ComboActionSearchResult.h"
|
||||
|
||||
|
||||
/**
|
||||
* Widget handling Search in Combo Action Graph
|
||||
*/
|
||||
class SComboActionSearch : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SComboActionSearch)
|
||||
: _bIsSearchWindow(true)
|
||||
, _bHideSearchBar(false)
|
||||
, _ContainingTab()
|
||||
{}
|
||||
SLATE_ARGUMENT(bool, bIsSearchWindow)
|
||||
SLATE_ARGUMENT(bool, bHideSearchBar)
|
||||
SLATE_ARGUMENT(TSharedPtr<SDockTab>, ContainingTab)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments &InArgs, const TSharedPtr<FAssetEditor_ComboActionGraph> &InDialogueEditor = nullptr);
|
||||
|
||||
/** Focuses this widget's search box, and changes the mode as well, and optionally the search terms */
|
||||
void FocusForUse(const FComboActionSearchFilter &SearchFilter = FComboActionSearchFilter(), bool bSelectFirstResult = false);
|
||||
|
||||
/**
|
||||
* Submits a search query
|
||||
*
|
||||
* @param SearchFilter Filter for search
|
||||
* @param bInIsFindWithinDialogue TRUE if searching within the current Dialogue only
|
||||
*/
|
||||
void MakeSearchQuery(const FComboActionSearchFilter &SearchFilter);
|
||||
|
||||
/** If this is a global find results widget, returns the host tab's unique ID. Otherwise, returns NAME_None. */
|
||||
FName GetHostTabId() const;
|
||||
|
||||
/** If this is a global find results widget, ask the host tab to close */
|
||||
void CloseHostTab();
|
||||
|
||||
private:
|
||||
/** Called when the host tab is closed (if valid) */
|
||||
void HandleHostTabClosed(TSharedRef<SDockTab> DockTab);
|
||||
|
||||
/** Called when user changes the text they are searching for */
|
||||
void HandleSearchTextChanged(const FText &Text);
|
||||
|
||||
/** Called when user changes commits text to the search box */
|
||||
void HandleSearchTextCommitted(const FText &Text, ETextCommit::Type CommitType);
|
||||
|
||||
/* Get the children of a row */
|
||||
void HandleGetChildren(TSharedPtr<FComboActionSearchResult> InItem, TArray<TSharedPtr<FComboActionSearchResult>> &OutChildren);
|
||||
|
||||
/* Called when user double clicks on a new result */
|
||||
void HandleTreeSelectionDoubleClicked(TSharedPtr<FComboActionSearchResult> Item);
|
||||
|
||||
/* Called when a new row is being generated */
|
||||
TSharedRef<ITableRow> HandleGenerateRow(TSharedPtr<FComboActionSearchResult> InItem, const TSharedRef<STableViewBase> &OwnerTable);
|
||||
|
||||
/** Callback to build the context menu when right clicking in the tree */
|
||||
TSharedPtr<SWidget> HandleContextMenuOpening();
|
||||
|
||||
/** Fills in the filter menu. */
|
||||
TSharedRef<SWidget> FillFilterEntries();
|
||||
|
||||
private:
|
||||
/** Pointer back to the ComboAction editor that owns us */
|
||||
TWeakPtr<FAssetEditor_ComboActionGraph> ComboActionEditorPtr;
|
||||
|
||||
/* The tree view displays the results */
|
||||
TSharedPtr<STreeView<TSharedPtr<FComboActionSearchResult>>> TreeView;
|
||||
|
||||
/** The search text box */
|
||||
TSharedPtr<SSearchBox> SearchTextBoxWidget;
|
||||
|
||||
/** Vertical box, used to add and remove widgets dynamically */
|
||||
TWeakPtr<SVerticalBox> MainVerticalBoxWidget;
|
||||
|
||||
/** In Find Within Action mode, we need to keep a handle on the root result, because it won't show up in the tree. */
|
||||
TSharedPtr<FComboActionSearchResult> RootSearchResult;
|
||||
|
||||
/* This buffer stores the currently displayed results */
|
||||
TArray<TSharedPtr<FComboActionSearchResult>> ItemsFound;
|
||||
|
||||
/* The string to highlight in the results */
|
||||
FText HighlightText;
|
||||
|
||||
/** The current searach filter */
|
||||
FComboActionSearchFilter CurrentFilter;
|
||||
|
||||
/** Tab hosting this widget. May be invalid. */
|
||||
TWeakPtr<SDockTab> HostTab;
|
||||
|
||||
/** Commands handled by this widget */
|
||||
TSharedPtr<FUICommandList> CommandList;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user