// ©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 &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 TreeGraphNode = MakeShared(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 &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(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 &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 &OutParentNode) { if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InAction)) { return false; } const UEdComboActionGraph *Graph = CastChecked(InAction->EdGraph); const TSharedPtr TreeActionNode = MakeShared(FText::FromString(InAction->GetPathName()), OutParentNode); TreeActionNode->SetActionGraph(Graph); // Find in GraphNodes bool bFoundInAction = false; const TArray &AllGraphNodes = Graph->Nodes; for (UEdGraphNode *Node : AllGraphNodes) { bool bFoundInNode = false; if (const UEdComboActionGraphNode *GraphNode = Cast(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 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("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