Added a bunch more stuff. Too much to care to mention. Still more to do though.
BIN
Resources/Slate/Editor/AdditionalDialogueData.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Resources/Slate/Editor/AutoArrangeIcon.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
Resources/Slate/Editor/BrowseIcon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/Bubble.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
Resources/Slate/Editor/CircleBox.png
Normal file
|
After Width: | Height: | Size: 295 KiB |
BIN
Resources/Slate/Editor/CloseIcon.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Resources/Slate/Editor/DialogueDecorator.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Resources/Slate/Editor/DialogueDecorator_Small.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Resources/Slate/Editor/DialogueManagerIcon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Resources/Slate/Editor/DialogueNodeIcon.png
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
Resources/Slate/Editor/DialogueParticipantIcon.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Resources/Slate/Editor/DialogueTreeIcon_128.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Resources/Slate/Editor/DialogueTreeIcon_16.png
Normal file
|
After Width: | Height: | Size: 518 B |
BIN
Resources/Slate/Editor/DiscordIcon.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Resources/Slate/Editor/DiscordIcon.png~
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
Resources/Slate/Editor/Documentation.png
Normal file
|
After Width: | Height: | Size: 382 KiB |
BIN
Resources/Slate/Editor/DocumentationIcon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/EditIcon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/ErroIcon.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Resources/Slate/Editor/FancyArrow.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
Resources/Slate/Editor/GraphSettings.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Resources/Slate/Editor/HeartIcon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Resources/Slate/Editor/HollowArrow.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
Resources/Slate/Editor/Icon128.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Resources/Slate/Editor/IndexIcon.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Resources/Slate/Editor/InfoIcon_Small.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
Resources/Slate/Editor/MoneyIcon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/Mountea_Logo.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
Resources/Slate/Editor/NodeHardCorners.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/NodeOverlay.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
Resources/Slate/Editor/NodeSoftCorners.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
Resources/Slate/Editor/OKIcon.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
Resources/Slate/Editor/PinDocksOverlay.png
Normal file
|
After Width: | Height: | Size: 124 B |
BIN
Resources/Slate/Editor/RoundedSelection_16x.PNG
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/SearchIcon.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
Resources/Slate/Editor/SimpleArrow.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/TextBlockHighlightShape.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/TextBox.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/TextBox_Hovered.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/TextBox_ReadOnly.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Slate/Editor/TextHardCorners.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/TextSoftCorners.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Resources/Slate/Editor/UnrealBucketIcon.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Resources/Slate/Editor/ValidateGraph.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@ -30,8 +30,10 @@ public class ComboInputEditor : ModuleRules
|
||||
|
||||
"ApplicationCore",
|
||||
"AssetTools",
|
||||
"BlueprintGraph",
|
||||
"DeveloperSettings",
|
||||
"GraphEditor",
|
||||
"InputCore",
|
||||
"Projects",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "Ed/AssetEditor_ComboActionGraph.h"
|
||||
#include "Ed/EdComboActionGraphEdge.h"
|
||||
#include "Ed/EdComboActionGraphNode.h"
|
||||
#include "Ed/FComboActionGraphEditorCommands.h"
|
||||
#include "Ed/SEdComboActionGraphEdge.h"
|
||||
#include "Ed/SEdComboActionGraphNode.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
@ -217,8 +218,8 @@ FComboInputSlateStyle::FComboInputSlateStyle() : FSlateStyleSet("ComboInputEdito
|
||||
|
||||
// Combo Action Graph editor brushes
|
||||
{
|
||||
this->SetContentRoot(IPluginManager::Get().FindPlugin("ComboInput")->GetBaseDir() / TEXT("Resources"));
|
||||
this->SetCoreContentRoot(IPluginManager::Get().FindPlugin("ComboInput")->GetBaseDir() / TEXT("Content"));
|
||||
this->SetContentRoot(PluginSlateDir / TEXT("Resources/Slate/Editor"));
|
||||
this->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate/Editor"));
|
||||
|
||||
this->Set("MDSStyleSet.AutoArrange.small", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon16));
|
||||
this->Set("MDSStyleSet.AutoArrange", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon40));
|
||||
@ -330,6 +331,13 @@ void FComboInputEditorModule::StartupModule()
|
||||
this->ComboActionGraphAssetActions = MakeShared<FAssetTypeActions_ComboActionGraph>();
|
||||
this->RegisterAssetTypeActions(AssetTools, this->ComboActionGraphAssetActions.ToSharedRef());
|
||||
}
|
||||
|
||||
FComboActionGraphEditorCommands::Register();
|
||||
}
|
||||
|
||||
void FComboInputEditorModule::ShutdownModule()
|
||||
{
|
||||
FComboActionGraphEditorCommands::Unregister();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
@ -24,7 +24,8 @@
|
||||
#include "Layout/ComboActionForceDirectedSolveLayoutStrategy.h"
|
||||
#include "Layout/ComboActionTreeSolveLayoutStrategy.h"
|
||||
//#include "Popups/MDSPopup_GraphValidation.h"
|
||||
//#include "Search/ComboActionSearchUtils.h"
|
||||
#include "Search/ComboActionSearchUtils.h"
|
||||
#include "Search/SComboActionSearch.h"
|
||||
#include "Settings/ComboActionGraphEditorSettings.h"
|
||||
#include "UObject/ObjectSaveContext.h"
|
||||
|
||||
@ -54,10 +55,6 @@ FAssetEditor_ComboActionGraph::~FAssetEditor_ComboActionGraph()
|
||||
this->EditingGraph = nullptr;
|
||||
UPackage::PackageSavedWithContextEvent.Remove(this->OnPackageSavedDelegateHandle);
|
||||
|
||||
FGenericCommands::Unregister();
|
||||
FGraphEditorCommands::Unregister();
|
||||
FComboActionGraphEditorCommands::Unregister();
|
||||
|
||||
this->ToolbarBuilder.Reset();
|
||||
}
|
||||
|
||||
@ -71,10 +68,6 @@ void FAssetEditor_ComboActionGraph::InitComboActionGraphAssetEditor(const EToolk
|
||||
this->EditingGraph = Graph;
|
||||
this->CreateEdGraph();
|
||||
|
||||
FGenericCommands::Register();
|
||||
FGraphEditorCommands::Register();
|
||||
FComboActionGraphEditorCommands::Register();
|
||||
|
||||
if (!this->ToolbarBuilder.IsValid())
|
||||
{
|
||||
this->ToolbarBuilder = MakeShareable(new FAssetEditorToolbarComboActionGraph(SharedThis(this)));
|
||||
@ -164,10 +157,10 @@ void FAssetEditor_ComboActionGraph::RegisterTabSpawners(const TSharedRef<FTabMan
|
||||
.SetGroup(WorkspaceMenuCategoryRef)
|
||||
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
|
||||
|
||||
//InTabManager->RegisterTabSpawner(FAssetEditorTabs_ComboActionGraph::SearchToolbarID, FOnSpawnTab::CreateSP(this, &FAssetEditor_ComboActionGraph::SpawnTab_Search))
|
||||
// .SetDisplayName(LOCTEXT("SearchTab", "Search"))
|
||||
// .SetGroup(WorkspaceMenuCategoryRef)
|
||||
// .SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "Kismet.Tabs.FindResults"));
|
||||
InTabManager->RegisterTabSpawner(FAssetEditorTabs_ComboActionGraph::SearchToolbarID, FOnSpawnTab::CreateSP(this, &FAssetEditor_ComboActionGraph::SpawnTab_Search))
|
||||
.SetDisplayName(LOCTEXT("SearchTab", "Search"))
|
||||
.SetGroup(WorkspaceMenuCategoryRef)
|
||||
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "Kismet.Tabs.FindResults"));
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::UnregisterTabSpawners(const TSharedRef<FTabManager> &InTabManager)
|
||||
@ -268,8 +261,10 @@ FString FAssetEditor_ComboActionGraph::GetReferencerName() const
|
||||
|
||||
void FAssetEditor_ComboActionGraph::SetDialogueBeingEdited(UComboActionGraph *NewDialogue)
|
||||
{
|
||||
if (NewDialogue == nullptr) return;
|
||||
if (NewDialogue == this->EditingGraph) return;
|
||||
if (NewDialogue == nullptr || NewDialogue == this->EditingGraph)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UComboActionGraph *Previous = this->EditingGraph;
|
||||
this->EditingGraph = NewDialogue;
|
||||
@ -282,7 +277,7 @@ void FAssetEditor_ComboActionGraph::CreateInternalWidgets()
|
||||
{
|
||||
this->ViewportWidget = this->CreateViewportWidget();
|
||||
|
||||
FDetailsViewArgs Args; //( false, false, true, FDetailsViewArgs::HideNameArea, false );
|
||||
FDetailsViewArgs Args;
|
||||
Args.bUpdatesFromSelection = false;
|
||||
Args.bLockable = false;
|
||||
Args.bAllowSearch = true;
|
||||
@ -292,11 +287,11 @@ void FAssetEditor_ComboActionGraph::CreateInternalWidgets()
|
||||
|
||||
FPropertyEditorModule &PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
||||
this->PropertyWidget = PropertyModule.CreateDetailView(Args);
|
||||
this->PropertyWidget->SetObject(EditingGraph);
|
||||
this->PropertyWidget->SetObject(this->EditingGraph);
|
||||
|
||||
this->PropertyWidget->OnFinishedChangingProperties().AddSP(this, &FAssetEditor_ComboActionGraph::OnFinishedChangingProperties);
|
||||
|
||||
//this->FindResultsView = SNew(SComboActionSearch, SharedThis(this));
|
||||
this->FindResultsView = SNew(SComboActionSearch, SharedThis(this));
|
||||
}
|
||||
|
||||
TSharedRef<SGraphEditor> FAssetEditor_ComboActionGraph::CreateViewportWidget()
|
||||
@ -469,11 +464,6 @@ void FAssetEditor_ComboActionGraph::SelectAllNodes()
|
||||
}
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanSelectAllNodes()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::DeleteSelectedNodes()
|
||||
{
|
||||
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
|
||||
@ -528,7 +518,7 @@ void FAssetEditor_ComboActionGraph::DeleteSelectedNodes()
|
||||
this->RebuildComboActionGraph();
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanDeleteNodes()
|
||||
bool FAssetEditor_ComboActionGraph::CanDeleteNodes() const
|
||||
{
|
||||
// If any of the nodes can be deleted then we should allow deleting
|
||||
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
|
||||
@ -584,11 +574,6 @@ void FAssetEditor_ComboActionGraph::CutSelectedNodes()
|
||||
this->DeleteSelectedDuplicatableNodes();
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanCutNodes()
|
||||
{
|
||||
return this->CanCopyNodes() && this->CanDeleteNodes();
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::CopySelectedNodes()
|
||||
{
|
||||
// Export the selected nodes and place the text on the clipboard
|
||||
@ -624,7 +609,7 @@ void FAssetEditor_ComboActionGraph::CopySelectedNodes()
|
||||
FPlatformApplicationMisc::ClipboardCopy(*ExportedText);
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanCopyNodes()
|
||||
bool FAssetEditor_ComboActionGraph::CanCopyNodes() const
|
||||
{
|
||||
// If any of the nodes can be duplicated then we should allow copying
|
||||
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
|
||||
@ -645,7 +630,7 @@ void FAssetEditor_ComboActionGraph::PasteNodes()
|
||||
TSharedPtr<SGraphEditor> CurrentGraphEditor = this->GetCurrentGraphEditor();
|
||||
if (CurrentGraphEditor.IsValid())
|
||||
{
|
||||
PasteNodesHere(CurrentGraphEditor->GetPasteLocation());
|
||||
this->PasteNodesHere(CurrentGraphEditor->GetPasteLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,7 +716,7 @@ void FAssetEditor_ComboActionGraph::PasteNodesHere(const FVector2D& Location)
|
||||
this->RebuildComboActionGraph();
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanPasteNodes()
|
||||
bool FAssetEditor_ComboActionGraph::CanPasteNodes() const
|
||||
{
|
||||
const FGraphPanelSelectionSet SelectedNodes = this->GetSelectedNodes();
|
||||
for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter)
|
||||
@ -755,17 +740,6 @@ bool FAssetEditor_ComboActionGraph::CanPasteNodes()
|
||||
return FEdGraphUtilities::CanImportNodesFromText(CurrentGraphEditor->GetCurrentGraph(), ClipboardContent);
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::DuplicateNodes()
|
||||
{
|
||||
this->CopySelectedNodes();
|
||||
this->PasteNodes();
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanDuplicateNodes()
|
||||
{
|
||||
return this->CanCopyNodes();
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::AutoArrange()
|
||||
{
|
||||
UEdComboActionGraph *EdGraph = Cast<UEdComboActionGraph>(this->EditingGraph->EdGraph);
|
||||
@ -821,21 +795,16 @@ void FAssetEditor_ComboActionGraph::ValidateGraph()
|
||||
|
||||
this->RebuildComboActionGraph();
|
||||
|
||||
//TArray<FText> ValidationMessages;
|
||||
//if (ComboActionGraph->ValidateGraph(ValidationMessages, true) == false)
|
||||
//{
|
||||
// ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// ValidationMessages.Empty();
|
||||
// ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
|
||||
//}
|
||||
}
|
||||
|
||||
bool FAssetEditor_ComboActionGraph::CanValidateGraph() const
|
||||
TArray<FText> ValidationMessages;
|
||||
if (ComboActionGraph->ValidateGraph(ValidationMessages, true) == false)
|
||||
{
|
||||
return true;
|
||||
//ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidationMessages.Empty();
|
||||
//ValidationWindow = MDSPopup_GraphValidation::Open(ValidationMessages);
|
||||
}
|
||||
}
|
||||
|
||||
void FAssetEditor_ComboActionGraph::OnRenameNode()
|
||||
@ -924,12 +893,26 @@ TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Details(const FSpaw
|
||||
auto DockTab = SNew(SDockTab)
|
||||
.Label(LOCTEXT("Details_Title", "Property"))
|
||||
[
|
||||
PropertyWidget.ToSharedRef()
|
||||
this->PropertyWidget.ToSharedRef()
|
||||
];
|
||||
|
||||
DockTab->SetTabIcon(FAppStyle::GetBrush("LevelEditor.Tabs.Details"));
|
||||
return DockTab;
|
||||
}
|
||||
|
||||
TSharedRef<SDockTab> FAssetEditor_ComboActionGraph::SpawnTab_Search(const FSpawnTabArgs &Args)
|
||||
{
|
||||
check(Args.GetTabId() == FAssetEditorTabs_ComboActionGraph::SearchToolbarID);
|
||||
|
||||
auto DockTab = SNew(SDockTab)
|
||||
.Label(LOCTEXT("Search_Title", "Search"))
|
||||
[
|
||||
this->FindResultsView.ToSharedRef()
|
||||
];
|
||||
|
||||
DockTab->SetTabIcon(FAppStyle::GetBrush("Kismet.Tabs.FindResults"));
|
||||
return DockTab;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
|
||||
@ -99,25 +99,25 @@ private:
|
||||
#pragma region GraphEditorCommands
|
||||
|
||||
void SelectAllNodes();
|
||||
bool CanSelectAllNodes();
|
||||
bool CanSelectAllNodes() const { return true; }
|
||||
void DeleteSelectedNodes();
|
||||
bool CanDeleteNodes();
|
||||
bool CanDeleteNodes() const;
|
||||
void DeleteSelectedDuplicatableNodes();
|
||||
void CutSelectedNodes();
|
||||
bool CanCutNodes();
|
||||
bool CanCutNodes() const { return this->CanCopyNodes() && this->CanDeleteNodes(); }
|
||||
void CopySelectedNodes();
|
||||
bool CanCopyNodes();
|
||||
bool CanCopyNodes() const;
|
||||
void PasteNodes();
|
||||
void PasteNodesHere(const FVector2D &Location);
|
||||
bool CanPasteNodes();
|
||||
void DuplicateNodes();
|
||||
bool CanDuplicateNodes();
|
||||
bool CanPasteNodes() const;
|
||||
void DuplicateNodes() { this->CopySelectedNodes(); this->PasteNodes(); }
|
||||
bool CanDuplicateNodes() { return this->CanCopyNodes(); }
|
||||
|
||||
void AutoArrange();
|
||||
bool CanAutoArrange() const;
|
||||
|
||||
void ValidateGraph();
|
||||
bool CanValidateGraph() const;
|
||||
bool CanValidateGraph() const { return true; }
|
||||
|
||||
void OnRenameNode();
|
||||
bool CanRenameNodes() const;
|
||||
@ -142,6 +142,7 @@ private:
|
||||
|
||||
TSharedRef<SDockTab> SpawnTab_Viewport(const FSpawnTabArgs &Args);
|
||||
TSharedRef<SDockTab> SpawnTab_Details(const FSpawnTabArgs &Args);
|
||||
TSharedRef<SDockTab> SpawnTab_Search(const FSpawnTabArgs &Args);
|
||||
|
||||
class UComboActionGraphEditorSettings *ComboActionGraphEditorSettings;
|
||||
|
||||
@ -155,7 +156,7 @@ private:
|
||||
|
||||
TSharedPtr<SGraphEditor> ViewportWidget;
|
||||
TSharedPtr<class IDetailsView> PropertyWidget;
|
||||
//TSharedPtr<class SComboActionSearch> FindResultsView;
|
||||
TSharedPtr<class SComboActionSearch> FindResultsView;
|
||||
|
||||
/** The command list for this editor */
|
||||
TSharedPtr<FUICommandList> GraphEditorCommands;
|
||||
|
||||
@ -0,0 +1,257 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#include "ComboActionGraphEditorUtilities.h"
|
||||
|
||||
#include "ComboActionGraph.h"
|
||||
#include "K2Node_Event.h"
|
||||
|
||||
#include "Ed/AssetEditor_ComboActionGraph.h"
|
||||
#include "Ed/EdComboActionGraph.h"
|
||||
#include "Ed/EdComboActionGraphNode.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "Kismet2/KismetEditorUtilities.h"
|
||||
#include "Kismet2/SClassPickerDialog.h"
|
||||
#include "Layout/AssetEditorTabs.h"
|
||||
|
||||
|
||||
bool FComboActionGraphEditorUtilities::PickChildrenOfClass(const FText &TitleText, UClass *&OutChosenClass, UClass *Class)
|
||||
{
|
||||
// Create filter
|
||||
TSharedPtr<FComboActionClassViewerFilter> Filter = MakeShareable(new FComboActionClassViewerFilter);
|
||||
Filter->AllowedChildrenOfClasses.Add(Class);
|
||||
|
||||
// Fill in options
|
||||
FClassViewerInitializationOptions Options;
|
||||
Options.Mode = EClassViewerMode::ClassPicker;
|
||||
Options.bShowUnloadedBlueprints = true;
|
||||
Options.ClassFilters.Add(Filter.ToSharedRef());
|
||||
|
||||
Options.DisplayMode = EClassViewerDisplayMode::TreeView;
|
||||
|
||||
Options.bShowNoneOption = false;
|
||||
Options.InitiallySelectedClass = Class;
|
||||
|
||||
Options.bExpandRootNodes = true;
|
||||
Options.NameTypeToDisplay = EClassViewerNameTypeToDisplay::DisplayName;
|
||||
|
||||
return SClassPickerDialog::PickClass(TitleText, Options, OutChosenClass, Class);
|
||||
}
|
||||
|
||||
bool FComboActionGraphEditorUtilities::OpenBlueprintEditor(UBlueprint *Blueprint, EComboActionBlueprintOpenType OpenType, FName FunctionNameToOpen, bool bForceFullEditor, bool bAddBlueprintFunctionIfItDoesNotExist)
|
||||
{
|
||||
if (!Blueprint)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Blueprint->bForceFullEditor = bForceFullEditor;
|
||||
|
||||
// Find Function Graph
|
||||
UObject *ObjectToFocusOn = nullptr;
|
||||
if (OpenType != EComboActionBlueprintOpenType::None && FunctionNameToOpen != NAME_None)
|
||||
{
|
||||
UClass* Class = Blueprint->GeneratedClass;
|
||||
check(Class);
|
||||
|
||||
if (OpenType == EComboActionBlueprintOpenType::Function)
|
||||
{
|
||||
ObjectToFocusOn = bAddBlueprintFunctionIfItDoesNotExist
|
||||
? FComboActionGraphEditorUtilities::BlueprintGetOrAddFunction(Blueprint, FunctionNameToOpen, Class)
|
||||
: FComboActionGraphEditorUtilities::BlueprintGetFunction(Blueprint, FunctionNameToOpen, Class);
|
||||
}
|
||||
else if (OpenType == EComboActionBlueprintOpenType::Event)
|
||||
{
|
||||
ObjectToFocusOn = bAddBlueprintFunctionIfItDoesNotExist
|
||||
? FComboActionGraphEditorUtilities::BlueprintGetOrAddEvent(Blueprint, FunctionNameToOpen, Class)
|
||||
: FComboActionGraphEditorUtilities::BlueprintGetEvent(Blueprint, FunctionNameToOpen, Class);
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the last uber graph
|
||||
if (ObjectToFocusOn == nullptr)
|
||||
{
|
||||
ObjectToFocusOn = Blueprint->GetLastEditedUberGraph();
|
||||
}
|
||||
if (ObjectToFocusOn)
|
||||
{
|
||||
FKismetEditorUtilities::BringKismetToFocusAttentionOnObject(ObjectToFocusOn);
|
||||
return true;
|
||||
}
|
||||
|
||||
return FComboActionGraphEditorUtilities::OpenEditorForAsset(Blueprint);
|
||||
}
|
||||
|
||||
UEdGraph *FComboActionGraphEditorUtilities::BlueprintGetOrAddFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature)
|
||||
{
|
||||
if (!Blueprint || Blueprint->BlueprintType != BPTYPE_Normal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Find existing function
|
||||
if (UEdGraph *GraphFunction = BlueprintGetFunction(Blueprint, FunctionName, FunctionClassSignature))
|
||||
{
|
||||
return GraphFunction;
|
||||
}
|
||||
|
||||
// Create a new function
|
||||
UEdGraph *NewGraph = FBlueprintEditorUtils::CreateNewGraph(Blueprint, FunctionName, UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
FBlueprintEditorUtils::AddFunctionGraph(Blueprint, NewGraph, /*bIsUserCreated=*/ false, FunctionClassSignature);
|
||||
Blueprint->LastEditedDocuments.Add(NewGraph);
|
||||
return NewGraph;
|
||||
}
|
||||
|
||||
UEdGraph *FComboActionGraphEditorUtilities::BlueprintGetFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature)
|
||||
{
|
||||
if (!Blueprint || Blueprint->BlueprintType != BPTYPE_Normal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Find existing function
|
||||
for (UEdGraph *GraphFunction : Blueprint->FunctionGraphs)
|
||||
{
|
||||
if (FunctionName == GraphFunction->GetFName())
|
||||
{
|
||||
return GraphFunction;
|
||||
}
|
||||
}
|
||||
|
||||
// Find in the implemented Interfaces Graphs
|
||||
for (const FBPInterfaceDescription &Interface : Blueprint->ImplementedInterfaces)
|
||||
{
|
||||
for (UEdGraph *GraphFunction : Interface.Graphs)
|
||||
{
|
||||
if (FunctionName == GraphFunction->GetFName())
|
||||
{
|
||||
return GraphFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UK2Node_Event *FComboActionGraphEditorUtilities::BlueprintGetOrAddEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature)
|
||||
{
|
||||
if (!Blueprint || Blueprint->BlueprintType != EBlueprintType::BPTYPE_Normal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Find existing event
|
||||
if (UK2Node_Event *EventNode = FComboActionGraphEditorUtilities::BlueprintGetEvent(Blueprint, EventName, EventClassSignature))
|
||||
{
|
||||
return EventNode;
|
||||
}
|
||||
|
||||
// Create a New Event
|
||||
if (Blueprint->UbergraphPages.Num())
|
||||
{
|
||||
int32 NodePositionY = 0;
|
||||
UK2Node_Event* NodeEvent = FKismetEditorUtilities::AddDefaultEventNode(
|
||||
Blueprint,
|
||||
Blueprint->UbergraphPages[0],
|
||||
EventName,
|
||||
EventClassSignature,
|
||||
NodePositionY
|
||||
);
|
||||
NodeEvent->SetEnabledState(ENodeEnabledState::Enabled);
|
||||
NodeEvent->NodeComment = "";
|
||||
NodeEvent->bCommentBubbleVisible = false;
|
||||
return NodeEvent;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UK2Node_Event *FComboActionGraphEditorUtilities::BlueprintGetEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature)
|
||||
{
|
||||
if (!Blueprint || Blueprint->BlueprintType != EBlueprintType::BPTYPE_Normal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TArray<UK2Node_Event*> AllEvents;
|
||||
FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(Blueprint, AllEvents);
|
||||
for (UK2Node_Event *EventNode : AllEvents)
|
||||
{
|
||||
if (EventNode->bOverrideFunction && EventNode->EventReference.GetMemberName() == EventName)
|
||||
{
|
||||
return EventNode;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FComboActionGraphEditorUtilities::OpenEditorForAsset(const UObject* Asset)
|
||||
{
|
||||
if (!IsValid(Asset) || !GEditor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->OpenEditorForAsset(const_cast<UObject*>(Asset));
|
||||
}
|
||||
|
||||
bool FComboActionGraphEditorUtilities::OpenEditorAndJumpToGraphNode(TWeakPtr<FAssetEditor_ComboActionGraph> DialogueEditorPtr, const UEdGraphNode *GraphNode, bool bFocusIfOpen)
|
||||
{
|
||||
if (!IsValid(GraphNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DialogueEditorPtr.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open if not already.
|
||||
UComboActionGraph *Dialogue = FComboActionGraphEditorUtilities::GetActionFromGraphNode(GraphNode);
|
||||
if (!FComboActionGraphEditorUtilities::OpenEditorForAsset(Dialogue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Could still fail focus on the graph node
|
||||
if (IAssetEditorInstance *EditorInstance = FindEditorForAsset(Dialogue, bFocusIfOpen))
|
||||
{
|
||||
EditorInstance->FocusWindow(const_cast<UEdGraphNode*>(GraphNode));
|
||||
|
||||
UEdComboActionGraph *GraphEditor = Cast<UEdComboActionGraph>(Dialogue->EdGraph);
|
||||
if (GraphEditor)
|
||||
{
|
||||
TSet<const UEdGraphNode*> SelectedNodes;
|
||||
SelectedNodes.Add(GraphNode);
|
||||
|
||||
GraphEditor->SelectNodeSet(SelectedNodes);
|
||||
DialogueEditorPtr.Pin()->JumpToNode(GraphNode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UComboActionGraph *FComboActionGraphEditorUtilities::GetActionFromGraphNode(const UEdGraphNode *GraphNode)
|
||||
{
|
||||
if (const UEdComboActionGraphNode *ComboActionBaseNode = Cast<UEdComboActionGraphNode>(GraphNode))
|
||||
{
|
||||
return ComboActionBaseNode->GetEdComboActionGraph()->GetComboActionGraph();
|
||||
}
|
||||
if (const UEdComboActionGraph *ComboActionGraph = Cast<UEdComboActionGraph>(GraphNode->GetGraph()))
|
||||
{
|
||||
return Cast<UComboActionGraph>(ComboActionGraph->GetComboActionGraph());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IAssetEditorInstance *FComboActionGraphEditorUtilities::FindEditorForAsset(UObject* Asset, bool bFocusIfOpen)
|
||||
{
|
||||
if (!IsValid(Asset) || !GEditor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->FindEditorForAsset(Asset, bFocusIfOpen);
|
||||
}
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ClassViewerFilter.h"
|
||||
|
||||
|
||||
enum class EComboActionBlueprintOpenType : uint8
|
||||
{
|
||||
None = 0,
|
||||
Function,
|
||||
Event
|
||||
};
|
||||
|
||||
class FComboActionClassViewerFilter : public IClassViewerFilter
|
||||
{
|
||||
public:
|
||||
// All children of these classes will be included unless filtered out by another setting.
|
||||
TSet<const UClass*> AllowedChildrenOfClasses;
|
||||
|
||||
virtual bool IsClassAllowed(const FClassViewerInitializationOptions &InInitOptions, const UClass *InClass, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
|
||||
{
|
||||
return !InClass->HasAnyClassFlags(this->DisallowedClassFlags)
|
||||
&& InFilterFuncs->IfInChildOfClassesSet(this->AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed;
|
||||
}
|
||||
|
||||
virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions &InInitOptions, const TSharedRef<const IUnloadedBlueprintData> InUnloadedClassData, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
|
||||
{
|
||||
return !InUnloadedClassData->HasAnyClassFlags(this->DisallowedClassFlags)
|
||||
&& InFilterFuncs->IfInChildOfClassesSet(this->AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallowed class flags.
|
||||
EClassFlags DisallowedClassFlags = CLASS_Deprecated;
|
||||
};
|
||||
|
||||
class FComboActionGraphEditorUtilities
|
||||
{
|
||||
public:
|
||||
static bool PickChildrenOfClass(const FText &TitleText, UClass *&OutChosenClass, UClass *Class);
|
||||
static bool OpenBlueprintEditor
|
||||
(
|
||||
UBlueprint *Blueprint,
|
||||
EComboActionBlueprintOpenType OpenType = EComboActionBlueprintOpenType::None,
|
||||
FName FunctionNameToOpen = NAME_None,
|
||||
bool bForceFullEditor = true,
|
||||
bool bAddBlueprintFunctionIfItDoesNotExist = false
|
||||
);
|
||||
|
||||
static UEdGraph *BlueprintGetOrAddFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature);
|
||||
|
||||
static UEdGraph *BlueprintGetFunction(UBlueprint *Blueprint, FName FunctionName, UClass *FunctionClassSignature);
|
||||
|
||||
static class UK2Node_Event *BlueprintGetOrAddEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature);
|
||||
|
||||
static class UK2Node_Event *BlueprintGetEvent(UBlueprint *Blueprint, FName EventName, UClass *EventClassSignature);
|
||||
|
||||
static bool OpenEditorForAsset(const UObject *Asset);
|
||||
|
||||
static bool IsABlueprintClass(const UClass *Class) { return Cast<UBlueprintGeneratedClass>(Class) != nullptr; }
|
||||
|
||||
static bool GetAllChildClassesOf(const UClass *ParentClass, TArray<UClass*> &OutNativeClasses, TArray<UClass*> &OutBlueprintClasses)
|
||||
{
|
||||
// Iterate over UClass, this might be heavy on performance
|
||||
for (TObjectIterator<UClass> It; It; ++It)
|
||||
{
|
||||
UClass *ChildClass = *It;
|
||||
if (!ChildClass->IsChildOf(ParentClass))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is a child of the Parent Class
|
||||
// make sure we don't include our parent class in the array
|
||||
if (ChildClass == ParentClass)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FComboActionGraphEditorUtilities::IsABlueprintClass(ChildClass))
|
||||
{
|
||||
// Blueprint
|
||||
OutBlueprintClasses.Add(ChildClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Native
|
||||
OutNativeClasses.Add(ChildClass);
|
||||
}
|
||||
}
|
||||
|
||||
return OutNativeClasses.Num() > 0 || OutBlueprintClasses.Num() > 0;
|
||||
}
|
||||
|
||||
static bool OpenEditorAndJumpToGraphNode(TWeakPtr<class FAssetEditor_ComboActionGraph> DialogueEditorPtr, const UEdGraphNode *GraphNode, bool bFocusIfOpen = false);
|
||||
|
||||
static class UComboActionGraph *GetActionFromGraphNode(const UEdGraphNode *GraphNode);
|
||||
|
||||
static IAssetEditorInstance *FindEditorForAsset(UObject *Asset, bool bFocusIfOpen);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
211
Source/ComboInputEditor/Private/Search/ComboActionSearchResult.h
Normal file
@ -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);
|
||||
};
|
||||
405
Source/ComboInputEditor/Private/Search/SComboActionSearch.cpp
Normal file
@ -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
|
||||
106
Source/ComboInputEditor/Private/Search/SComboActionSearch.h
Normal file
@ -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;
|
||||
|
||||
};
|
||||
@ -90,7 +90,7 @@ public:
|
||||
static bool IsAvailable() { return FModuleManager::Get().IsModuleLoaded("ComboInputEditor"); }
|
||||
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override{}
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
TSharedPtr<class FSlateStyleSet> GetComboInputEditorStyleSet() const { return this->ComboInputEditorStyleSet; }
|
||||
|
||||
|
||||