A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
SDialogueBrowser.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#include "SDialogueBrowser.h"
3
4#include "Editor.h"
5#include "Toolkits/AssetEditorManager.h"
6#include "Widgets/Input/SComboBox.h"
7#include "Widgets/Input/SSearchBox.h"
8#include "Widgets/Images/SImage.h"
9#include "Widgets/Layout/SMissingWidget.h"
10#include "Widgets/Layout/SWrapBox.h"
11#include "Widgets/Input/SButton.h"
12
13#include "DlgManager.h"
14#include "DlgDialogue.h"
15#include "DialogueStyle.h"
20#include "SourceCodeNavigation.h"
21#include "Engine/BlueprintGeneratedClass.h"
23#include "Framework/MultiBox/MultiBoxBuilder.h"
24#include "Kismet2/KismetEditorUtilities.h"
25
26#define LOCTEXT_NAMESPACE "SDialogueBrowser"
27#define DEFAULT_FONT(...) FCoreStyle::GetDefaultFontStyle(__VA_ARGS__)
28
30template<typename ItemType>
31class SCategoryHeaderTableRow : public STableRow<ItemType>
32{
33private:
35
36public:
39 SLATE_DEFAULT_SLOT(typename SCategoryHeaderTableRow::FArguments, Content)
40 SLATE_END_ARGS()
41
42 void Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
43 {
45 .Padding(8.0f, 2.0f, 0.0f, 0.0f)
46 [
47 SAssignNew(ContentBorder, SBorder)
48 .BorderImage(this, &Self::GetBackgroundImage)
49 .Padding(FMargin(1.0f, 3.0f))
50 .BorderBackgroundColor(FLinearColor(.6, .6, .6, 1.0f))
51 [
52 SNew(SHorizontalBox)
53
54 +SHorizontalBox::Slot()
55 .VAlign(VAlign_Center)
56 .Padding(2.0f, 2.0f, 2.0f, 2.0f)
57 .AutoWidth()
58 [
59 SNew(SExpanderArrow, STableRow<ItemType>::SharedThis(this))
60 ]
61
62 +SHorizontalBox::Slot()
63 .VAlign(VAlign_Center)
64 [
65 InArgs._Content.Widget
66 ]
67 ]
68 ];
69
72 .Style(FEditorStyle::Get(), "DetailsView.TreeView.TableRow")
73 .ShowSelection(false),
74 InOwnerTableView
75 );
76 }
77
78 const FSlateBrush* GetBackgroundImage() const
79 {
81 {
82 return STableRow<ItemType>::IsItemExpanded() ? FEditorStyle::GetBrush("DetailsView.CategoryTop_Hovered") : FEditorStyle::GetBrush("DetailsView.CollapsedCategory_Hovered");
83 }
84
85 return STableRow<ItemType>::IsItemExpanded() ? FEditorStyle::GetBrush("DetailsView.CategoryTop") : FEditorStyle::GetBrush("DetailsView.CollapsedCategory");
86 }
87
88 void SetContent(TSharedRef<SWidget> InContent) override
89 {
90 ContentBorder->SetContent(InContent);
91 }
92
93 void SetRowContent(TSharedRef< SWidget > InContent) override
94 {
95 ContentBorder->SetContent(InContent);
96 }
97
98private:
99 TSharedPtr<SBorder> ContentBorder;
100};
101
103// SDialogueBrowser
104void SDialogueBrowser::Construct(const FArguments& InArgs)
105{
106 DefaultSortOption = MakeShared<FDialogueBrowserSortOption>(EDialogueBrowserSortOption::DialogueReferences, TEXT("Dialogue References"));
108 SortOptions = {
110 MakeShared<FDialogueBrowserSortOption>(EDialogueBrowserSortOption::Name, TEXT("Name"))
111 };
112
113 RootTreeItem = MakeShared<FDialogueBrowserTreeRootNode>();
114 ParticipantsTreeView = SNew(STreeView<TSharedPtr<FDialogueBrowserTreeNode>>)
115 .ItemHeight(32)
116 .TreeItemsSource(&RootChildren)
117 .OnGenerateRow(this, &Self::HandleGenerateRow)
118 .OnSelectionChanged(this, &Self::HandleTreeSelectionChanged)
119 .OnGetChildren(this, &Self::HandleGetChildren)
120 .SelectionMode(ESelectionMode::Single)
121 .OnMouseButtonDoubleClick(this, &Self::HandleDoubleClick)
122 .OnSetExpansionRecursive(this, &Self::HandleSetExpansionRecursive)
123 .HeaderRow(
124 SNew(SHeaderRow)
125 .Visibility(EVisibility::Visible)
126 +SHeaderRow::Column(NAME_Name)
127 .DefaultLabel(LOCTEXT("Name", "Participant Name"))
128 );
129
130 ChildSlot
131 [
132 SNew(SBorder)
133 .Padding(FMargin(3.f))
134 .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
135 [
136 SNew(SVerticalBox)
137
138 // Top bar
139 +SVerticalBox::Slot()
140 .AutoHeight()
141 .Padding(2.f, 1.f)
142 [
143 SNew(SHorizontalBox)
144
145 // Search Input
146 +SHorizontalBox::Slot()
147 .FillWidth(1.0f)
148 .Padding(0.f, 0.f, 4.f, 0.f)
149 [
151 ]
152
153 // View Options
154 +SHorizontalBox::Slot()
155 .AutoWidth()
156 .Padding(2.0f, 2.0f)
157 [
158 SNew(SComboButton)
159 .ComboButtonStyle(FEditorStyle::Get(), "GenericFilters.ComboButtonStyle")
160 .ForegroundColor(FLinearColor::White)
161 .ContentPadding(0)
162 .ToolTipText(LOCTEXT("View_Tooltip", "View Options for the Dialogue Browser"))
163 .OnGetMenuContent(this, &Self::FillViewOptionsEntries)
164 .HasDownArrow(true)
165 .ContentPadding(FMargin(1, 0))
166 .ButtonContent()
167 [
168 SNew(SHorizontalBox)
169 +SHorizontalBox::Slot()
170 .AutoWidth()
171 [
172 SNew(STextBlock)
173 .TextStyle(FEditorStyle::Get(), "GenericFilters.TextStyle")
174 .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.9"))
175 .Text(FText::FromString(FString(TEXT("\xf0b0"))) /*fa-filter*/)
176 ]
177 +SHorizontalBox::Slot()
178 .AutoWidth()
179 .Padding(2, 0, 0, 0)
180 [
181 SNew(STextBlock)
182 .TextStyle(FEditorStyle::Get(), "GenericFilters.TextStyle")
183 .Text(LOCTEXT("View_Key", "View Options"))
184 ]
185 ]
186 ]
187
188 // Sort menu
189 +SHorizontalBox::Slot()
190 .AutoWidth()
191 [
192 SNew(SComboBox<SortOptionType>)
193 .OptionsSource(&SortOptions)
194 .InitiallySelectedItem(DefaultSortOption)
195 .ContentPadding(FMargin(4.0, 2.0))
196 .OnGenerateWidget_Lambda([](SortOptionType NameItem)
197 {
198 return SNew(STextBlock)
199 .Text(NameItem->GetFText());
200 })
201 .OnSelectionChanged(this, &Self::HandleSortSelectionChanged)
202 .ToolTipText(LOCTEXT("AddFilterToolTip", "Sort by a specific criteria."))
203 [
204 SNew(STextBlock)
205 .Text(LOCTEXT("Sort", "Sort By"))
206 ]
207 ]
208
209 // Refresh dialogues
210 +SHorizontalBox::Slot()
211 .AutoWidth()
212 [
213 SNew(SButton)
214 .ToolTipText(LOCTEXT("RefreshToolTip", "Refreshes/Reloads the Dialogue Browser view."))
215 .OnClicked(this, &Self::HandleOnRefresh)
216 [
218 LOCTEXT("RefreshDialogues", "Refresh"),
220 )
221 ]
222 ]
223 ]
224
225 // The Tree view
226 +SVerticalBox::Slot()
227 .AutoHeight()
228 .FillHeight(1.0f)
229 [
230 SNew(SBorder)
231 .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
232 .Padding(FMargin(0.0f, 4.0f))
233 [
234 ParticipantsTreeView.ToSharedRef()
235 ]
236 ]
237 ]
238 ];
239
240 RefreshTree(false);
241}
242
243void SDialogueBrowser::RefreshTree(bool bPreserveExpansion)
244{
245 // First, save off current expansion state
246 TSet<TSharedPtr<FDialogueBrowserTreeNode>> OldExpansionState;
247 if (bPreserveExpansion)
248 {
249 ParticipantsTreeView->GetExpandedItems(OldExpansionState);
250 }
251
252 RootTreeItem->ClearChildren();
253 RootChildren.Empty();
255
256 auto PopulateVariablePropertiesFromSearchResult = [](
257 const TSharedPtr<FDialogueBrowserTreeVariableProperties> VariableProperties,
258 const TSharedPtr<FDialogueSearchFoundResult> SearchResult,
259 const FGuid& DialogueGUID
260 )
261 {
262 if (VariableProperties->HasGraphNodeSet(DialogueGUID))
263 {
264 VariableProperties
265 ->GetMutableGraphNodeSet(DialogueGUID)
266 ->Append(SearchResult->GraphNodes);
267 }
268 if (VariableProperties->HasEdgeNodeSet(DialogueGUID))
269 {
270 VariableProperties
271 ->GetMutableEdgeNodeSet(DialogueGUID)
272 ->Append(SearchResult->EdgeNodes);
273 }
274 };
275
276 // Build fast lookup structure for participants (the ParticipantsProperties)
277 TArray<UDlgDialogue*> Dialogues = UDlgManager::GetAllDialoguesFromMemory();
278 for (const UDlgDialogue* Dialogue : Dialogues)
279 {
280 const FGuid DialogueGUID = Dialogue->GetGUID();
281
282 // Populate Participants
283 TSet<FName> ParticipantsNames;
284 Dialogue->GetAllParticipantNames(ParticipantsNames);
285 for (const FName& ParticipantName : ParticipantsNames)
286 {
287 TSharedPtr<FDialogueBrowserTreeParticipantProperties>* ParticipantPropsPtr = ParticipantsProperties.Find(ParticipantName);
288 TSharedPtr<FDialogueBrowserTreeParticipantProperties> ParticipantProps;
289 if (ParticipantPropsPtr == nullptr)
290 {
291 // participant does not exist, create it
292 const TSet<TWeakObjectPtr<const UDlgDialogue>> SetArgument{Dialogue};
293 ParticipantProps = MakeShared<FDialogueBrowserTreeParticipantProperties>(SetArgument);
294 ParticipantsProperties.Add(ParticipantName, ParticipantProps);
295 }
296 else
297 {
298 // exists
299 ParticipantProps = *ParticipantPropsPtr;
300 ParticipantProps->AddDialogue(Dialogue);
301 }
302
303 // Populate events
304 TSet<FName> EventsNames;
305 Dialogue->GetEvents(ParticipantName, EventsNames);
306 for (const FName& EventName : EventsNames)
307 {
308 PopulateVariablePropertiesFromSearchResult(
309 ParticipantProps->AddDialogueToEvent(EventName, Dialogue),
311 DialogueGUID
312 );
313 }
314
315 // Populate Custom events
316 TSet<UClass*> CustomEventsClasses;
317 Dialogue->GetCustomEvents(ParticipantName, CustomEventsClasses);
318 for (UClass* EventClass : CustomEventsClasses)
319 {
320 PopulateVariablePropertiesFromSearchResult(
321 ParticipantProps->AddDialogueToCustomEvent(EventClass, Dialogue),
323 DialogueGUID
324 );
325 }
326
327 // Populate conditions
328 TSet<FName> ConditionNames;
329 Dialogue->GetConditions(ParticipantName, ConditionNames);
330 for (const FName& ConditionName : ConditionNames)
331 {
332 PopulateVariablePropertiesFromSearchResult(
333 ParticipantProps->AddDialogueToCondition(ConditionName, Dialogue),
335 DialogueGUID
336 );
337 }
338
339 // Populate int variable names
340 TSet<FName> IntVariableNames;
341 Dialogue->GetIntNames(ParticipantName, IntVariableNames);
342 for (const FName& IntVariableName : IntVariableNames)
343 {
344 PopulateVariablePropertiesFromSearchResult(
345 ParticipantProps->AddDialogueToIntVariable(IntVariableName, Dialogue),
347 DialogueGUID
348 );
349 }
350
351 // Populate float variable names
352 TSet<FName> FloatVariableNames;
353 Dialogue->GetFloatNames(ParticipantName, FloatVariableNames);
354 for (const FName& FloatVariableName : FloatVariableNames)
355 {
356 PopulateVariablePropertiesFromSearchResult(
357 ParticipantProps->AddDialogueToFloatVariable(FloatVariableName, Dialogue),
359 DialogueGUID
360 );
361 }
362
363 // Populate bool variable names
364 TSet<FName> BoolVariableNames;
365 Dialogue->GetBoolNames(ParticipantName, BoolVariableNames);
366 for (const FName& BoolVariableName : BoolVariableNames)
367 {
368 PopulateVariablePropertiesFromSearchResult(
369 ParticipantProps->AddDialogueToBoolVariable(BoolVariableName, Dialogue),
371 DialogueGUID
372 );
373 }
374
375 // Populate FName variable names
376 TSet<FName> FNameVariableNames;
377 Dialogue->GetNameNames(ParticipantName, FNameVariableNames);
378 for (const FName& NameVariableName : FNameVariableNames)
379 {
380 PopulateVariablePropertiesFromSearchResult(
381 ParticipantProps->AddDialogueToFNameVariable(NameVariableName, Dialogue),
383 DialogueGUID
384 );
385 }
386
387 // Populate UClass int variable names
388 TSet<FName> ClassIntVariableNames;
389 Dialogue->GetClassIntNames(ParticipantName, ClassIntVariableNames);
390 for (const FName& IntVariableName : ClassIntVariableNames)
391 {
392 PopulateVariablePropertiesFromSearchResult(
393 ParticipantProps->AddDialogueToClassIntVariable(IntVariableName, Dialogue),
395 DialogueGUID
396 );
397 }
398
399 // Populate UClass float variable names
400 TSet<FName> ClassFloatVariableNames;
401 Dialogue->GetClassFloatNames(ParticipantName, ClassFloatVariableNames);
402 for (const FName& FloatVariableName : ClassFloatVariableNames)
403 {
404 PopulateVariablePropertiesFromSearchResult(
405 ParticipantProps->AddDialogueToClassFloatVariable(FloatVariableName, Dialogue),
407 DialogueGUID
408 );
409 }
410
411 // Populate UClass bool variable names
412 TSet<FName> ClassBoolVariableNames;
413 Dialogue->GetClassBoolNames(ParticipantName, ClassBoolVariableNames);
414 for (const FName& BoolVariableName : ClassBoolVariableNames)
415 {
416 PopulateVariablePropertiesFromSearchResult(
417 ParticipantProps->AddDialogueToClassBoolVariable(BoolVariableName, Dialogue),
419 DialogueGUID
420 );
421 }
422
423 // Populate UClass FName variable names
424 TSet<FName> ClassFNameVariableNames;
425 Dialogue->GetClassNameNames(ParticipantName, ClassFNameVariableNames);
426 for (const FName& NameVariableName : ClassFNameVariableNames)
427 {
428 PopulateVariablePropertiesFromSearchResult(
429 ParticipantProps->AddDialogueToClassFNameVariable(NameVariableName, Dialogue),
431 DialogueGUID
432 );
433 }
434
435 // Populate UClass FText variable names
436 TSet<FName> ClassFTextVariableNames;
437 Dialogue->GetClassTextNames(ParticipantName, ClassFTextVariableNames);
438 for (const FName& TextVariableName : ClassFTextVariableNames)
439 {
440 PopulateVariablePropertiesFromSearchResult(
441 ParticipantProps->AddDialogueToClassFTextVariable(TextVariableName, Dialogue),
443 DialogueGUID
444 );
445 }
446 }
447 }
448
449 // Sort the properties
450 TArray<FName> AllParticipants;
451 for (const auto & Elem : ParticipantsProperties)
452 {
453 AllParticipants.Add(Elem.Key);
454 TSharedPtr<FDialogueBrowserTreeParticipantProperties> Property = Elem.Value;
455
456 // sort
457 Property->Sort();
458 }
459
460 // Sort the participant names
461 if (SelectedSortOption->IsByName())
462 {
463 // Sort by name
464 FDlgHelper::SortDefault(AllParticipants);
465 }
466 else
467 {
468 // Sort by dialogue references
469 AllParticipants.Sort([this](const FName& A, const FName& B)
470 {
472 });
473 }
474
475 // Build the tree
476 for (const FName& Name : AllParticipants)
477 {
478 const TSharedPtr<FDialogueBrowserTreeNode> Participant =
479 MakeShared<FDialogueBrowserTreeCategoryParticipantNode>(FText::FromName(Name), RootTreeItem, Name);
480
482 RootTreeItem->AddChild(Participant);
483 RootTreeItem->AddChild(MakeShared<FDialogueBrowserTreeSeparatorNode>(RootTreeItem));
484 }
485 RootTreeItem->GetVisibleChildren(RootChildren);
486
487 // Clear Previous states
488 ParticipantsTreeView->ClearSelection();
489 // Triggers RequestTreeRefresh
490 ParticipantsTreeView->ClearExpandedItems();
491
492 // Restore old expansion
493 if (bPreserveExpansion && OldExpansionState.Num() > 0)
494 {
495 // Flattened tree
496 TArray<TSharedPtr<FDialogueBrowserTreeNode>> AllNodes;
497 RootTreeItem->GetAllNodes(AllNodes);
498
499 // Expand to match the old state
500 FDlgTreeViewHelper::RestoreTreeExpansionState<TSharedPtr<FDialogueBrowserTreeNode>>(
502 AllNodes,
503 OldExpansionState,
505 );
506 }
507}
508
510{
511 if (FilterString.IsEmpty())
512 {
513 // No filtering, empty filter, restore original
514 RefreshTree(false);
515 return;
516 }
517
518 // Get all valid paths
519 TArray<TArray<TSharedPtr<FDialogueBrowserTreeNode>>> OutPaths;
520 RootTreeItem->FilterPathsToNodesThatContainText(FilterString, OutPaths);
521 RootChildren.Empty();
522 RootTreeItem->GetVisibleChildren(RootChildren);
523
524 // Refresh, clear expansion
525 ParticipantsTreeView->ClearExpandedItems(); // Triggers RequestTreeRefresh
526
527 // Mark paths as expanded
528 for (const TArray<TSharedPtr<FDialogueBrowserTreeNode>>& Path : OutPaths)
529 {
530 const int32 PathNum = Path.Num();
531 for (int32 PathIndex = 0; PathIndex < PathNum; PathIndex++)
532 {
533 Path[PathIndex]->SetIsVisible(true);
534 ParticipantsTreeView->SetItemExpansion(Path[PathIndex], true);
535 }
536 }
537
538 // TODO tokens
539}
540
542{
543 // Is it cached?
544 if (FilterTextBoxWidget.IsValid())
545 {
546 return FilterTextBoxWidget.ToSharedRef();
547 }
548
549 // Cache it
550 FilterTextBoxWidget = SNew(SSearchBox)
551 .HintText(LOCTEXT("SearchBoxHintText", "Search by Name"))
552 .OnTextChanged(this, &Self::HandleSearchTextCommitted, ETextCommit::Default)
553 .OnTextCommitted(this, &Self::HandleSearchTextCommitted)
554 .SelectAllTextWhenFocused(false)
555 .DelayChangeNotificationsWhileTyping(false);
556
557 // Should return a valid widget
558 return GetFilterTextBoxWidget();
559}
560
562 const TSharedPtr<FDialogueBrowserTreeNode>& InItem,
563 const TSharedPtr<FDialogueBrowserTreeVariableProperties>* PropertyPtr,
565)
566{
567 // List the dialogues that contain this event for this property
568 TSet<TWeakObjectPtr<const UDlgDialogue>> Dialogues;
569 if (PropertyPtr != nullptr)
570 {
571 Dialogues = (*PropertyPtr)->GetDialogues();
572 }
573
574 for (TWeakObjectPtr<const UDlgDialogue> Dialogue : Dialogues)
575 {
576 if (!Dialogue.IsValid())
577 {
578 continue;
579 }
580
581 const TSharedPtr<FDialogueBrowserTreeNode> DialogueItem = MakeShared<FDialogueBrowserTreeDialogueNode>(
582 FText::FromName(Dialogue->GetDialogueFName()),
583 InItem,
585 );
586 DialogueItem->SetTextType(TextType);
587 InItem->AddChild(DialogueItem);
588 }
589}
590
592 const TSharedPtr<FDialogueBrowserTreeNode>& InItem,
593 const TSet<TWeakObjectPtr<const UDialogueGraphNode>>& GraphNodes,
595)
596{
597 for (TWeakObjectPtr<const UDialogueGraphNode> GraphNode : GraphNodes)
598 {
599 if (!GraphNode.IsValid())
600 {
601 continue;
602 }
603
604 const FName Text = *FString::Printf(TEXT("%d"), GraphNode->GetDialogueNodeIndex());
605 const TSharedPtr<FDialogueBrowserTreeNode> NodeItem =
606 MakeShared<FDialogueBrowserTreeGraphNode>(FText::FromName(Text), InItem, GraphNode);
607 NodeItem->SetTextType(TextType);
608 InItem->AddInlineChild(NodeItem);
609 }
610}
611
613 const TSharedPtr<FDialogueBrowserTreeNode>& InItem,
614 const TSet<TWeakObjectPtr<const UDialogueGraphNode_Edge>>& EdgeNodes,
616)
617{
618 for (TWeakObjectPtr<const UDialogueGraphNode_Edge> EdgeNode : EdgeNodes)
619 {
620 if (!EdgeNode.IsValid())
621 {
622 continue;
623 }
624
625 int32 FromParent = -1;
626 int32 ToChild = -1;
627 if (EdgeNode->HasParentNode())
628 {
629 FromParent = EdgeNode->GetParentNode()->GetDialogueNodeIndex();
630 }
631 if (EdgeNode->HasChildNode())
632 {
633 ToChild = EdgeNode->GetChildNode()->GetDialogueNodeIndex();
634 }
635 const FName Text = *FString::Printf(TEXT("%d -> %d"), FromParent, ToChild);
636 const TSharedPtr<FDialogueBrowserTreeNode> NodeItem =
637 MakeShared<FDialogueBrowserTreeEdgeNode>(FText::FromName(Text), InItem, EdgeNode);
638 NodeItem->SetTextType(TextType);
639 InItem->AddInlineChild(NodeItem);
640 }
641}
642
644 const TSharedPtr<FDialogueBrowserTreeNode>& InItem,
645 const TSharedPtr<FDialogueBrowserTreeVariableProperties>* PropertyPtr,
646 EDialogueTreeNodeTextType GraphNodeTextType,
647 EDialogueTreeNodeTextType EdgeNodeTextType
648)
649{
650 TSharedPtr<FDialogueBrowserTreeDialogueNode> DialogueItem =
651 StaticCastSharedPtr<FDialogueBrowserTreeDialogueNode>(InItem);
652 if (!DialogueItem.IsValid())
653 {
654 return;
655 }
656 if (PropertyPtr == nullptr || !DialogueItem->GetDialogue().IsValid())
657 {
658 return;
659 }
660
661 const TSharedPtr<FDialogueBrowserTreeVariableProperties> Property = *PropertyPtr;
662 const UDlgDialogue* Dialogue = DialogueItem->GetDialogue().Get();
663 const FGuid DialogueGUID = Dialogue->GetGUID();
664
665 // Display the GraphNode
666 if (Property->HasGraphNodeSet(DialogueGUID))
667 {
668 AddGraphNodeChildrenToItem(DialogueItem, Property->GetGraphNodeSet(DialogueGUID), GraphNodeTextType);
669 }
670 if (Property->HasEdgeNodeSet(DialogueGUID))
671 {
672 AddEdgeNodeChildrenToItem(DialogueItem, Property->GetEdgeNodeSet(DialogueGUID), EdgeNodeTextType);
673 }
674}
675
677 const TSharedPtr<FDialogueBrowserTreeNode>& Item,
678 const TMap<FName, TSharedPtr<FDialogueBrowserTreeVariableProperties>>& Variables,
679 EDialogueTreeNodeTextType VariableType
680)
681{
682 for (const auto& Pair : Variables)
683 {
684 const FName VariableName = Pair.Key;
685 const TSharedPtr<FDialogueBrowserTreeNode> ChildItem =
686 MakeShared<FDialogueBrowserTreeVariableNode>(FText::FromName(VariableName), Item, VariableName);
687 ChildItem->SetTextType(VariableType);
688 Item->AddChild(ChildItem);
689 }
690}
691
692void SDialogueBrowser::BuildTreeViewItem(const TSharedPtr<FDialogueBrowserTreeNode>& Item)
693{
694 const FName ParticipantName = Item->GetParentParticipantName();
695 if (!ParticipantName.IsValid() || ParticipantName.IsNone())
696 {
697 return;
698 }
699
700 // Do we have the Participant cached?
701 TSharedPtr<FDialogueBrowserTreeParticipantProperties>* ParticipantPropertiesPtr = ParticipantsProperties.Find(ParticipantName);
702 if (ParticipantPropertiesPtr == nullptr)
703 {
704 return;
705 }
706
707 TSharedPtr<FDialogueBrowserTreeParticipantProperties> ParticipantProperties = *ParticipantPropertiesPtr;
708 if (Item->IsCategory())
709 {
710 switch (Item->GetCategoryType())
711 {
713 {
714 // Display the categories for the participant
715 const bool bHideEmptyCategories = GetDefault<UDlgSystemSettings>()->bHideEmptyDialogueBrowserCategories;
716 Item->SetChildren(MakeParticipantCategoriesChildren(Item, ParticipantProperties, bHideEmptyCategories));
717 break;
718 }
720 {
721 // Add the dialogues
722 for (TWeakObjectPtr<const UDlgDialogue> Dialogue : ParticipantProperties->GetDialogues())
723 {
724 if (!Dialogue.IsValid())
725 {
726 continue;
727 }
728
729 const TSharedPtr<FDialogueBrowserTreeNode> DialogueItem =
730 MakeShared<FDialogueBrowserTreeDialogueNode>(FText::FromName(Dialogue->GetDialogueFName()), Item, Dialogue);
731 DialogueItem->SetTextType(EDialogueTreeNodeTextType::ParticipantDialogue);
732 Item->AddChild(DialogueItem);
733
734 }
735 break;
736 }
738 {
739 // Display the events for this category
740 for (const auto& Pair : ParticipantProperties->GetEvents())
741 {
742 const TSharedPtr<FDialogueBrowserTreeNode> EventItem =
743 MakeShared<FDialogueBrowserTreeVariableNode>(FText::FromName(Pair.Key), Item, Pair.Key);
744 EventItem->SetTextType(EDialogueTreeNodeTextType::ParticipantEvent);
745 Item->AddChild(EventItem);
746 }
747
748 // Display the custom events for this category
749 for (const auto& Pair : ParticipantProperties->GetCustomEvents())
750 {
751 UClass* Class = Pair.Key;
752 const TSharedPtr<FDialogueBrowserTreeNode> CustomEventItem = MakeShared<FDialogueBrowserTreeCustomObjectNode>(
753 FText::FromString(FDlgHelper::CleanObjectName(Class->GetPathName())),
754 Item,
755 Class
756 );
757 CustomEventItem->SetTextType(EDialogueTreeNodeTextType::ParticipantCustomEvent);
758 Item->AddChild(CustomEventItem);
759 }
760 break;
761 }
763 {
764 for (const auto& Pair : ParticipantProperties->GetConditions())
765 {
766 const TSharedPtr<FDialogueBrowserTreeNode> ConditionItem =
767 MakeShared<FDialogueBrowserTreeVariableNode>(FText::FromName(Pair.Key), Item, Pair.Key);
768 ConditionItem->SetTextType(EDialogueTreeNodeTextType::ParticipantCondition);
769 Item->AddChild(ConditionItem);
770 }
771 break;
772 }
773
775 {
776 // Only display the categories if the Participant has at least one variable.
777 if (ParticipantProperties->HasDialogueValues())
778 {
779 const bool bHideEmptyCategories = GetDefault<UDlgSystemSettings>()->bHideEmptyDialogueBrowserCategories;
780 Item->SetChildren(MakeVariableCategoriesChildren(Item, ParticipantProperties, bHideEmptyCategories));
781 }
782 break;
783 }
786 Item,
787 ParticipantProperties->GetIntegers(),
789 );
790 break;
793 Item,
794 ParticipantProperties->GetFloats(),
796 );
797 break;
800 Item,
801 ParticipantProperties->GetBools(),
803 );
804 break;
807 Item,
808 ParticipantProperties->GetFNames(),
810 );
811 break;
812
814 {
815 // Only display the categories if the Participant has at least one class variable.
816 if (ParticipantProperties->HasClassVariables())
817 {
818 const bool bHideEmptyCategories = GetDefault<UDlgSystemSettings>()->bHideEmptyDialogueBrowserCategories;
819 Item->SetChildren(MakeClassVariableCategoriesChildren(Item, ParticipantProperties, bHideEmptyCategories));
820 }
821 break;
822 }
825 Item,
826 ParticipantProperties->GetClassIntegers(),
828 );
829 break;
832 Item,
833 ParticipantProperties->GetClassFloats(),
835 );
836 break;
839 Item,
840 ParticipantProperties->GetClassBools(),
842 );
843 break;
846 Item,
847 ParticipantProperties->GetClassFNames(),
849 );
850 break;
853 Item,
854 ParticipantProperties->GetClassFTexts(),
856 );
857 break;
858
859 default:
860 break;
861 }
862 }
863 else if (Item->IsText())
864 {
865 switch (Item->GetTextType())
866 {
868 // List the dialogues that contain this event for this participant
870 Item,
871 ParticipantProperties->GetEvents().Find(Item->GetParentVariableName()),
873 );
874 break;
875
877 // List the dialogues that contain this event for this custom event participant
879 Item,
880 ParticipantProperties->GetCustomEvents().Find(Item->GetParentClass()),
882 );
883 break;
884
886 // List the dialogues that contain this condition for this participant
888 Item,
889 ParticipantProperties->GetConditions().Find(Item->GetParentVariableName()),
891 );
892 break;
893
895 // List the dialogues that contain this int variable for this participant
897 Item,
898 ParticipantProperties->GetIntegers().Find(Item->GetParentVariableName()),
900 );
901 break;
903 // List the dialogues that contain this float variable for this participant
905 Item,
906 ParticipantProperties->GetFloats().Find(Item->GetParentVariableName()),
908 );
909 break;
911 // List the dialogues that contain this bool variable for this participant
913 Item,
914 ParticipantProperties->GetBools().Find(Item->GetParentVariableName()),
916 );
917 break;
919 // List the dialogues that contain this Fname variable for this participant
921 Item,
922 ParticipantProperties->GetFNames().Find(Item->GetParentVariableName()),
924 );
925 break;
926
928 // List the dialogues that contain this UClass int variable for this participant
930 Item,
931 ParticipantProperties->GetClassIntegers().Find(Item->GetParentVariableName()),
933 );
934 break;
936 // List the dialogues that contain this UClass float variable for this participant
938 Item,
939 ParticipantProperties->GetClassFloats().Find(Item->GetParentVariableName()),
941 );
942 break;
944 // List the dialogues that contain this UClass bool variable for this participant
946 Item,
947 ParticipantProperties->GetClassBools().Find(Item->GetParentVariableName()),
949 );
950 break;
952 // List the dialogues that contain this UClass Fname variable for this participant
954 Item,
955 ParticipantProperties->GetClassFNames().Find(Item->GetParentVariableName()),
957 );
958 break;
960 // List the dialogues that contain this UClass FText variable for this participant
962 Item,
963 ParticipantProperties->GetClassFTexts().Find(Item->GetParentVariableName()),
965 );
966 break;
967
969 // List the graph nodes for the dialogue that contains this event
971 Item,
972 ParticipantProperties->GetEvents().Find(Item->GetParentVariableName()),
975 );
976 break;
977
979 // List the graph nodes for the dialogue that contains this event
981 Item,
982 ParticipantProperties->GetCustomEvents().Find(Item->GetParentClass()),
985 );
986 break;
987
989 // List the graph nodes for the dialogue that contains this condition
991 ParticipantProperties->GetConditions().Find(Item->GetParentVariableName()),
994 break;
995
997 // List the graph nodes for the dialogue that contains this int variable
999 Item,
1000 ParticipantProperties->GetIntegers().Find(Item->GetParentVariableName()),
1003 );
1004 break;
1006 // List the graph nodes for the dialogue that contains this float variable
1008 Item,
1009 ParticipantProperties->GetFloats().Find(Item->GetParentVariableName()),
1012 );
1013 break;
1015 // List the graph nodes for the dialogue that contains this bool variable
1017 Item,
1018 ParticipantProperties->GetBools().Find(Item->GetParentVariableName()),
1021 );
1022 break;
1024 // List the graph nodes for the dialogue that contains this FName variable
1026 Item,
1027 ParticipantProperties->GetFNames().Find(Item->GetParentVariableName()),
1030 );
1031 break;
1032
1034 // List the graph nodes for the dialogue that contains this UClass int variable
1036 Item,
1037 ParticipantProperties->GetClassIntegers().Find(Item->GetParentVariableName()),
1040 );
1041 break;
1043 // List the graph nodes for the dialogue that contains this UClass float variable
1045 Item,
1046 ParticipantProperties->GetClassFloats().Find(Item->GetParentVariableName()),
1049 );
1050 break;
1052 // List the graph nodes for the dialogue that contains this UClass bool variable
1054 Item,
1055 ParticipantProperties->GetClassBools().Find(Item->GetParentVariableName()),
1058 );
1059 break;
1061 // List the graph nodes for the dialogue that contains this UClass FName variable
1063 Item,
1064 ParticipantProperties->GetClassFNames().Find(Item->GetParentVariableName()),
1067 );
1068 break;
1069
1071 // List the graph nodes for the dialogue that contains this UClass FText variable
1073 Item,
1074 ParticipantProperties->GetClassFTexts().Find(Item->GetParentVariableName()),
1077 );
1078 break;
1079
1080 default:
1081 break;
1082 }
1083 }
1084
1085 // Recursively call on children
1086 for (const TSharedPtr<FDialogueBrowserTreeNode>& ChildItem : Item->GetChildren())
1087 {
1088 BuildTreeViewItem(ChildItem);
1089 }
1090
1091 // The same for the inline children, handled separately.
1092 for (const TSharedPtr<FDialogueBrowserTreeNode>& ChildItem : Item->GetInlineChildren())
1093 {
1094 BuildTreeViewItem(ChildItem);
1095 }
1096}
1097
1099 const TArray<TSharedPtr<FDialogueBrowserTreeNode>>& InChildren
1100)
1101{
1102 TSharedPtr<SWrapBox> Buttons = SNew(SWrapBox)
1103 .PreferredWidth(600.f);
1104
1105 // Constructs [Node 1] [Node 2]
1106 const FText GraphNodeTooltip = LOCTEXT("JumpToNodeTipGraphNode", "Opens the Dialogue Editor and jumps to the Node");
1107 const FText EdgeNodeTooltip = LOCTEXT("JumpToNodeTipEdgeNode", "Opens the Dialogue Editor and jumps to the Edge");
1108 for (const TSharedPtr<FDialogueBrowserTreeNode>& ChildItem : InChildren)
1109 {
1110 const bool bIsEdgeNodeText = ChildItem->IsEdgeNodeText();
1111 if (ChildItem->IsGraphNodeText() || bIsEdgeNodeText)
1112 {
1113 Buttons->AddSlot()
1114 .HAlign(HAlign_Fill)
1115 .VAlign(VAlign_Fill)
1116 .Padding(2.f, 0.f, 0.f, 0.f)
1117 [
1118 // Jump To node
1119 SNew(SButton)
1120 .ToolTipText(bIsEdgeNodeText ? EdgeNodeTooltip : GraphNodeTooltip)
1121 .OnClicked(ChildItem.Get(), &FDialogueBrowserTreeNode::OnClick)
1122 [
1123 SNew(STextBlock)
1124 .Text(ChildItem->GetDisplayText())
1125 .Font(DEFAULT_FONT("Regular", 10))
1126 ]
1127 ];
1128 }
1129 }
1130
1131 return Buttons.ToSharedRef();
1132}
1133
1134TSharedRef<SWidget> SDialogueBrowser::MakeInlineWidget(const TSharedPtr<FDialogueBrowserTreeNode>& InItem)
1135{
1136 if (!InItem.IsValid())
1137 {
1138 return SMissingWidget::MakeMissingWidget();
1139 }
1140 if (!InItem->HasInlineChildren() || !InItem->IsText())
1141 {
1142 return SMissingWidget::MakeMissingWidget();
1143 }
1144
1145 if (InItem->IsDialogueText())
1146 {
1147 // Display the [Dialogue] [Node1] [Node2] [Node3] [Jump to Content Browser] [Open Dialogue]
1148 return SNew(SHorizontalBox)
1149 // Icon and Dialogue Name
1150 +SHorizontalBox::Slot()
1151 .HAlign(HAlign_Left)
1152 .VAlign(VAlign_Center)
1153 .Padding(0.f, 0.f, 10.f, 0.f)
1154 [
1156 ]
1157
1158 // Graph Nodes
1159 +SHorizontalBox::Slot()
1160 .HAlign(HAlign_Left)
1161 .VAlign(VAlign_Center)
1162 [
1163 MakeButtonWidgetForGraphNodes(InItem->GetInlineChildren())
1164 ]
1165
1166 // Buttons on the right side
1167 +SHorizontalBox::Slot()
1168 .HAlign(HAlign_Right)
1169 .VAlign(VAlign_Center)
1170 [
1172 ];
1173 }
1174
1175 return SMissingWidget::MakeMissingWidget();
1176}
1177
1178TSharedRef<SWidget> SDialogueBrowser::MakeButtonsWidgetForDialogue(const TSharedPtr<FDialogueBrowserTreeNode>& InItem)
1179{
1180 return SNew(SHorizontalBox)
1181 // Find in Content Browser
1182 +SHorizontalBox::Slot()
1183 .AutoWidth()
1184 .HAlign(HAlign_Left)
1185 [
1186 SNew(SButton)
1187 .ButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
1188 .ToolTipText(LOCTEXT("FindInContentBrowserToolTip", "Find the Dialogue in the Context Browser"))
1189 .OnClicked(this, &Self::FindInContentBrowserForItem, InItem)
1190 [
1191 SNew(SBox)
1192 .HAlign(HAlign_Fill)
1193 .VAlign(VAlign_Fill)
1194 .WidthOverride(16)
1195 .HeightOverride(16)
1196 [
1197 SNew(SImage)
1199 ]
1200 ]
1201 ]
1202
1203 // Open Editor
1204 +SHorizontalBox::Slot()
1205 .AutoWidth()
1206 .HAlign(HAlign_Left)
1207 [
1208 SNew(SButton)
1209 .ButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
1210 .ToolTipText(LOCTEXT("OpenDialogueToolTip", "Opens the dialogue editor."))
1211 .OnClicked(InItem.Get(), &FDialogueBrowserTreeNode::OnClick)
1212 [
1213 SNew(SBox)
1214 .HAlign(HAlign_Fill)
1215 .VAlign(VAlign_Fill)
1216 .WidthOverride(16)
1217 .HeightOverride(16)
1218 [
1219 SNew(SImage)
1221 ]
1222 ]
1223 ];
1224}
1225
1226void SDialogueBrowser::HandleSearchTextCommitted(const FText& InText, ETextCommit::Type InCommitType)
1227{
1228 // Trim and sanitized the filter text (so that it more likely matches)
1229 FilterString = FText::TrimPrecedingAndTrailing(InText).ToString();
1231// RefreshTree(false);
1232}
1233
1235 TSharedPtr<FDialogueBrowserTreeNode> InItem,
1236 const TSharedRef<STableViewBase>& OwnerTable
1237)
1238{
1239 // Build row
1240 TSharedPtr<STableRow<TSharedPtr<FDialogueBrowserTreeNode>>> TableRow;
1241 FMargin RowPadding = FMargin(2.f, 2.f);
1242 const bool bIsCategory = InItem->IsCategory();
1243 const bool bIsSeparator = InItem->IsSeparator();
1244
1245 if (bIsCategory)
1246 {
1247 TableRow =
1248 SNew(SCategoryHeaderTableRow<TSharedPtr<FDialogueBrowserTreeNode>>, OwnerTable)
1249 .Visibility(InItem->IsVisible() ? EVisibility::Visible : EVisibility::Collapsed);
1250 }
1251 else
1252 {
1253 TableRow =
1254 SNew(STableRow<TSharedPtr<FDialogueBrowserTreeNode>>, OwnerTable)
1255 .Padding(1.0f)
1256 .Visibility(InItem->IsVisible() ? EVisibility::Visible : EVisibility::Collapsed)
1257 .ShowSelection(!bIsSeparator);
1258 }
1259
1260 // Not visible.
1261 // NOTE should not be used normally, but only after the tree view is dirty.
1262 if (!InItem->IsVisible())
1263 {
1264 checkNoEntry();
1265 return TableRow.ToSharedRef();
1266 }
1267
1268 // Default row content
1269 TSharedPtr<STextBlock> DefaultTextBlock =
1270 SNew(STextBlock)
1271 .Text(InItem->GetDisplayText())
1272 .HighlightText(this, &Self::GetFilterText)
1273 .Font(DEFAULT_FONT("Regular", 10));
1274
1275 TSharedPtr<SWidget> RowContent = DefaultTextBlock;
1276 TSharedPtr<SHorizontalBox> RowContainer;
1277 TableRow->SetRowContent(SAssignNew(RowContainer, SHorizontalBox));
1278
1279 // Build content
1280 if (bIsSeparator)
1281 {
1282 RowPadding = FMargin(0);
1283 RowContent = SNew(SVerticalBox)
1284 .Visibility(EVisibility::HitTestInvisible)
1285
1286 +SVerticalBox::Slot()
1287 .AutoHeight()
1288 // Add some empty space before the line, and a tiny bit after it
1289 .Padding(0.0f, 5.f, 0.0f, 5.f)
1290 [
1291 SNew(SBorder)
1292
1293 // We'll use the border's padding to actually create the horizontal line
1294 .Padding(FEditorStyle::GetMargin(TEXT("Menu.Separator.Padding")))
1295
1296 // Separator graphic
1297 .BorderImage(FEditorStyle::GetBrush(TEXT("Menu.Separator")))
1298 ];
1299 }
1300 else if (bIsCategory)
1301 {
1302 if (InItem->GetCategoryType() == EDialogueTreeNodeCategoryType::Participant)
1303 {
1304 int32 DialogueReferences = 0;
1305 TSharedPtr<FDialogueBrowserTreeParticipantProperties>* ParticipantPropertiesPtr =
1306 ParticipantsProperties.Find(InItem->GetParentParticipantName());
1307 if (ParticipantPropertiesPtr)
1308 {
1309 DialogueReferences = (*ParticipantPropertiesPtr)->GetDialogues().Num();
1310 }
1311
1312 RowContent = SNew(SHorizontalBox)
1313
1314 // Name of participant
1315 +SHorizontalBox::Slot()
1316 .HAlign(HAlign_Left)
1317 .VAlign(VAlign_Center)
1318 [
1319 SNew(STextBlock)
1320 .Font(DEFAULT_FONT("Regular", 16))
1321 .Text(InItem->GetDisplayText())
1322 .HighlightText(this, &Self::GetFilterText)
1323 ]
1324
1325 // Number of dialogue references
1326 +SHorizontalBox::Slot()
1327 .HAlign(HAlign_Right)
1328 .VAlign(VAlign_Center)
1329 [
1330 SNew(STextBlock)
1331 .Font(DEFAULT_FONT("Regular", 9))
1332 .Text(FText::FromString(FString::Printf(TEXT("Dialogue references %d"), DialogueReferences)))
1333 ];
1334 }
1335 else
1336 {
1337 RowContent = SNew(STextBlock)
1338 .Font(DEFAULT_FONT("Regular", 12))
1339 .Text(InItem->GetDisplayText())
1340 .HighlightText(this, &Self::GetFilterText);
1341 }
1342 }
1343 else if (InItem->IsText())
1344 {
1345 if (InItem->HasInlineChildren())
1346 {
1347 RowContent = MakeInlineWidget(InItem);
1348 }
1349 else if (InItem->IsDialogueText())
1350 {
1351 RowContent = SNew(SHorizontalBox)
1352
1353 // Icon and Dialogue Name
1354 +SHorizontalBox::Slot()
1355 .HAlign(HAlign_Left)
1356 .VAlign(VAlign_Center)
1357 [
1358 MakeIconAndTextWidget(InItem->GetDisplayText(),
1360 ]
1361
1362 // Buttons on the right side
1363 +SHorizontalBox::Slot()
1364 .HAlign(HAlign_Right)
1365 .VAlign(VAlign_Center)
1366 [
1368 ];
1369 }
1370 else if (InItem->IsEventText())
1371 {
1372 RowContent = MakeIconAndTextWidget(
1373 InItem->GetDisplayText(),
1375 );
1376 }
1377 else if (InItem->IsCustomEventText())
1378 {
1380 InItem->GetDisplayText(),
1382 InItem->GetParentClass(),
1384 GET_FUNCTION_NAME_CHECKED(UDlgEventCustom, EnterEvent)
1385 );
1386 }
1387 else if (InItem->IsConditionText())
1388 {
1389 RowContent = MakeIconAndTextWidget(
1390 InItem->GetDisplayText(),
1392 );
1393 }
1394 else if (InItem->IsGraphNodeText() || InItem->IsEdgeNodeText())
1395 {
1396 RowContent = SNew(SHorizontalBox)
1397
1398 // Text
1399 +SHorizontalBox::Slot()
1400 .HAlign(HAlign_Left)
1401 .VAlign(VAlign_Center)
1402 [
1403 DefaultTextBlock.ToSharedRef()
1404 ]
1405
1406 // Jump To node
1407 +SHorizontalBox::Slot()
1408 .HAlign(HAlign_Right)
1409 .VAlign(VAlign_Center)
1410 [
1411 SNew(SButton)
1412 .ToolTipText(LOCTEXT("JumpToNodeTip", "Opens the Editor for the Dialogue and jumps to the node"))
1413 .OnClicked(InItem.Get(), &FDialogueBrowserTreeNode::OnClick)
1414 [
1415 SNew(STextBlock)
1416 .Text(LOCTEXT("JumpToNode", "Jump"))
1417 ]
1418 ];
1419 }
1420 }
1421 else
1422 {
1423 // did we miss something?
1424 }
1425
1426 RowContainer->AddSlot()
1427 .AutoWidth()
1428 .VAlign(VAlign_Fill)
1429 .HAlign(HAlign_Right)
1430 [
1431 SNew(SExpanderArrow, TableRow)
1432 ];
1433
1434 RowContainer->AddSlot()
1435 .FillWidth(1.0)
1436 .Padding(RowPadding)
1437 [
1438 RowContent.ToSharedRef()
1439 ];
1440
1441 return TableRow.ToSharedRef();
1442}
1443
1444void SDialogueBrowser::HandleGetChildren(TSharedPtr<FDialogueBrowserTreeNode> InItem, TArray<TSharedPtr<FDialogueBrowserTreeNode>>& OutChildren)
1445{
1446 if (!InItem.IsValid() || InItem->IsSeparator())
1447 {
1448 return;
1449 }
1450 if (InItem->HasChildren())
1451 {
1452 InItem->GetVisibleChildren(OutChildren);
1453 }
1454}
1455
1456void SDialogueBrowser::HandleTreeSelectionChanged(TSharedPtr<FDialogueBrowserTreeNode> NewValue, ESelectInfo::Type SelectInfo)
1457{
1458 // Ignore
1459}
1460
1461void SDialogueBrowser::HandleDoubleClick(TSharedPtr<FDialogueBrowserTreeNode> InItem)
1462{
1463 if (!InItem.IsValid())
1464 {
1465 return;
1466 }
1467
1468 if (InItem->IsText())
1469 {
1470 InItem->OnClick();
1471 }
1472
1473 // Expand on double click
1474 if (InItem->HasChildren())
1475 {
1476 ParticipantsTreeView->SetItemExpansion(InItem, !ParticipantsTreeView->IsItemExpanded(InItem));
1477 }
1478}
1479
1480void SDialogueBrowser::HandleSetExpansionRecursive(TSharedPtr<FDialogueBrowserTreeNode> InItem, bool bInIsItemExpanded)
1481{
1482 if (InItem.IsValid() && InItem->HasChildren())
1483 {
1484 ParticipantsTreeView->SetItemExpansion(InItem, bInIsItemExpanded);
1485 for (const TSharedPtr<FDialogueBrowserTreeNode> & Child : InItem->GetChildren())
1486 {
1487 HandleSetExpansionRecursive(Child, bInIsItemExpanded);
1488 }
1489 }
1490}
1491
1492void SDialogueBrowser::HandleSortSelectionChanged(SortOptionType Selection, ESelectInfo::Type SelectInfo)
1493{
1494 if (Selection.IsValid())
1495 {
1496 SelectedSortOption = Selection;
1497 RefreshTree(true);
1498 }
1499}
1500
1501FReply SDialogueBrowser::FindInContentBrowserForItem(TSharedPtr<FDialogueBrowserTreeNode> InItem)
1502{
1503 TSharedPtr<FDialogueBrowserTreeDialogueNode> DialogueItem =
1504 StaticCastSharedPtr<FDialogueBrowserTreeDialogueNode>(InItem);
1505 if (!DialogueItem.IsValid())
1506 {
1507 return FReply::Unhandled();
1508 }
1509
1510 static constexpr bool bFocusContentBrowser = true;
1511 if (GEditor && DialogueItem->GetDialogue().IsValid())
1512 {
1513 TArray<UObject*> ObjectsToSyncTo{const_cast<UDlgDialogue*>(DialogueItem->GetDialogue().Get())};
1514 GEditor->SyncBrowserToObjects(ObjectsToSyncTo, bFocusContentBrowser);
1515 return FReply::Handled();
1516 }
1517
1518 return FReply::Unhandled();
1519}
1520
1521TArray<TSharedPtr<FDialogueBrowserTreeNode>> SDialogueBrowser::MakeParticipantCategoriesChildren(
1522 const TSharedPtr<FDialogueBrowserTreeNode>& Parent,
1523 const TSharedPtr<FDialogueBrowserTreeParticipantProperties>& ParticipantProperties,
1524 bool bHideEmptyCategories
1525) const
1526{
1527 TArray<TSharedPtr<FDialogueBrowserTreeNode>> Categories;
1528 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasDialogues()))
1529 {
1530 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1531 FText::FromString(TEXT("Dialogues")),
1532 Parent,
1534 );
1535 Categories.Add(Category);
1536 }
1537
1538 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasEvents()))
1539 {
1540 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1541 FText::FromString(TEXT("Events")),
1542 Parent,
1544 );
1545 Categories.Add(Category);
1546 }
1547
1548 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasConditions()))
1549 {
1550 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1551 FText::FromString(TEXT("Conditions")),
1552 Parent,
1554 );
1555 Categories.Add(Category);
1556 }
1557
1558 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasDialogueValues()))
1559 {
1560 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1561 FText::FromString(TEXT("Dialogue Values")),
1562 Parent,
1564 );
1565 Categories.Add(Category);
1566 }
1567
1568 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassVariables()))
1569 {
1570 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1571 FText::FromString(TEXT("Class Variables")),
1572 Parent,
1574 );
1575 Categories.Add(Category);
1576 }
1577 return Categories;
1578}
1579
1580TArray<TSharedPtr<FDialogueBrowserTreeNode>> SDialogueBrowser::MakeVariableCategoriesChildren(
1581 const TSharedPtr<FDialogueBrowserTreeNode>& Parent,
1582 const TSharedPtr<FDialogueBrowserTreeParticipantProperties>& ParticipantProperties,
1583 bool bHideEmptyCategories
1584) const
1585{
1586 TArray<TSharedPtr<FDialogueBrowserTreeNode>> Categories;
1587 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasIntegers()))
1588 {
1589 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1590 FText::FromString(TEXT("Integers")),
1591 Parent,
1593 );
1594 Categories.Add(Category);
1595 }
1596
1597 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasFloats()))
1598 {
1599 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1600 FText::FromString(TEXT("Floats")),
1601 Parent,
1603 );
1604 Categories.Add(Category);
1605 }
1606
1607 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasBools()))
1608 {
1609 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1610 FText::FromString(TEXT("Bools")),
1611 Parent,
1613 );
1614 Categories.Add(Category);
1615 }
1616
1617 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasFNames()))
1618 {
1619 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1620 FText::FromString(TEXT("FNames")),
1621 Parent,
1623 );
1624 Categories.Add(Category);
1625 }
1626
1627 return Categories;
1628}
1629
1630TArray<TSharedPtr<FDialogueBrowserTreeNode>> SDialogueBrowser::MakeClassVariableCategoriesChildren(
1631 const TSharedPtr<FDialogueBrowserTreeNode>& Parent,
1632 const TSharedPtr<FDialogueBrowserTreeParticipantProperties>& ParticipantProperties,
1633 bool bHideEmptyCategories
1634) const
1635{
1636 TArray<TSharedPtr<FDialogueBrowserTreeNode>> Categories;
1637
1638 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassIntegers()))
1639 {
1640 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1641 FText::FromString(TEXT("Integers")),
1642 Parent,
1644 );
1645 Categories.Add(Category);
1646 }
1647
1648 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassFloats()))
1649 {
1650 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1651 FText::FromString(TEXT("Floats")),
1652 Parent,
1654 );
1655 Categories.Add(Category);
1656 }
1657
1658 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassBools()))
1659 {
1660 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1661 FText::FromString(TEXT("Bools")),
1662 Parent,
1664 );
1665 Categories.Add(Category);
1666 }
1667
1668 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassFNames()))
1669 {
1670 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1671 FText::FromString(TEXT("FNames")),
1672 Parent,
1674 );
1675 Categories.Add(Category);
1676 }
1677
1678 if (!bHideEmptyCategories || (bHideEmptyCategories && ParticipantProperties->HasClassFTexts()))
1679 {
1680 TSharedPtr<FDialogueBrowserTreeNode> Category = MakeShared<FDialogueBrowserTreeCategoryNode>(
1681 FText::FromString(TEXT("FTexts")),
1682 Parent,
1684 );
1685 Categories.Add(Category);
1686 }
1687
1688 return Categories;
1689}
1690
1692 const FText& InText,
1693 const FSlateBrush* IconBrush,
1694 int32 IconSize
1695)
1696{
1697 return SNew(SHorizontalBox)
1698 +SHorizontalBox::Slot()
1699 .VAlign(VAlign_Center)
1700 .AutoWidth()
1701 [
1702 SNew(SBox)
1703 .HAlign(HAlign_Fill)
1704 .VAlign(VAlign_Fill)
1705 .WidthOverride(IconSize)
1706 .HeightOverride(IconSize)
1707 [
1708 SNew(SImage)
1709 .Image(IconBrush)
1710 ]
1711 ]
1712
1713 +SHorizontalBox::Slot()
1714 .VAlign(VAlign_Center)
1715 .AutoWidth()
1716 .Padding(2.f, 0.f)
1717 [
1718 SNew(STextBlock)
1719 .Text(InText)
1720 .HighlightText(this, &Self::GetFilterText)
1721 ];
1722}
1723
1725 const FText& InText,
1726 const FSlateBrush* IconBrush,
1727 UClass* Class,
1729 FName FunctionNameToOpen,
1730 int32 IconSize
1731)
1732{
1733 TSharedRef<SHorizontalBox> HorizontalBox = MakeIconAndTextWidget(InText, IconBrush, IconSize);
1734
1735 // Browse Asset
1736 HorizontalBox->AddSlot()
1737 .AutoWidth()
1738 .VAlign(VAlign_Center)
1739 .Padding(4.f)
1740 [
1741 SNew(SButton)
1742 .ButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
1743 .ToolTipText_Static(&Self::GetBrowseAssetText, Class)
1744 .ContentPadding(4.f)
1745 .ForegroundColor(FSlateColor::UseForeground())
1746 .Visibility_Static(&Self::GetBrowseAssetButtonVisibility, Class)
1747 .OnClicked_Static(&Self::OnBrowseAssetClicked, Class)
1748 [
1749 SNew(SImage)
1750 .Image(FEditorStyle::GetBrush("PropertyWindow.Button_Browse"))
1751 .ColorAndOpacity(FSlateColor::UseForeground())
1752 ]
1753 ];
1754
1755 // Jump to Object
1756 HorizontalBox->AddSlot()
1757 .AutoWidth()
1758 .VAlign(VAlign_Center)
1759 .Padding(4.f, 2.f)
1760 [
1761 SNew(SButton)
1762 .ButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
1763 .ToolTipText_Static(&Self::GetJumpToAssetText, Class)
1764 .ContentPadding(4.f)
1765 .ForegroundColor(FSlateColor::UseForeground())
1766 .Visibility_Static(&Self::GetOpenAssetButtonVisibility, Class)
1767 .OnClicked_Static(&Self::OnOpenAssetClicked, Class, OpenType, FunctionNameToOpen)
1768 [
1769 SNew(SImage)
1770 .Image(FEditorStyle::GetBrush("PropertyWindow.Button_Edit"))
1771 .ColorAndOpacity( FSlateColor::UseForeground() )
1772 ]
1773 ];
1774
1775 return HorizontalBox;
1776}
1777
1779{
1780 // Blueprint, always visible
1782 {
1783 return EVisibility::Visible;
1784 }
1785
1786 // Native
1787 return FSourceCodeNavigation::CanNavigateToClass(Class) ? EVisibility::Visible : EVisibility::Collapsed;
1788}
1789
1791{
1792 // Blueprint, always Visible
1794 {
1795 return EVisibility::Visible;
1796 }
1797
1798 // Native Hide
1799 return EVisibility::Collapsed;
1800}
1801
1803{
1804 UBlueprint* Blueprint = nullptr;
1805 if (const UBlueprintGeneratedClass* BlueprintClass = Cast<UBlueprintGeneratedClass>(Class))
1806 {
1807 Blueprint = Cast<UBlueprint>(BlueprintClass->ClassGeneratedBy);
1808 }
1809
1810 static constexpr bool bFocusContentBrowser = true;
1811 TArray<UObject*> ObjectsToSyncTo;
1812 if (Blueprint)
1813 {
1814 ObjectsToSyncTo.Add(Blueprint);
1815 }
1816 GEditor->SyncBrowserToObjects(ObjectsToSyncTo, bFocusContentBrowser);
1817
1818 return FReply::Handled();
1819}
1820
1822 UClass* Class,
1824 FName FunctionNameToOpen
1825)
1826{
1827 UBlueprint* Blueprint = nullptr;
1828 if (const UBlueprintGeneratedClass* BlueprintClass = Cast<UBlueprintGeneratedClass>(Class))
1829 {
1830 Blueprint = Cast<UBlueprint>(BlueprintClass->ClassGeneratedBy);
1831 }
1832
1833 if (Blueprint)
1834 {
1835 static constexpr bool bForceFullEditor = true;
1836 static constexpr bool bAddBlueprintFunctionIfItDoesNotExist = true;
1838 Blueprint,
1839 OpenType,
1840 FunctionNameToOpen,
1841 bForceFullEditor,
1842 bAddBlueprintFunctionIfItDoesNotExist
1843 );
1844 }
1845 else if (UObject* Object = Class->GetDefaultObject())
1846 {
1847 // Native
1848 FSourceCodeNavigation::NavigateToClass(Object->GetClass());
1849 }
1850
1851 return FReply::Handled();
1852}
1853
1855{
1856 // Blueprint, always visible
1858 {
1859 return LOCTEXT("OpenObjectBlueprintTooltipKey", "Open Blueprint Editor");
1860 }
1861
1862 // Native
1863 return FText::Format(
1864 LOCTEXT("OpenObjectBlueprintTooltipKey", "Open Source File in {0}"),
1865 FSourceCodeNavigation::GetSelectedSourceCodeIDE()
1866 );
1867}
1868
1870{
1871 return LOCTEXT("BrowseButtonToolTipText", "Browse to Asset in Content Browser");
1872}
1873
1875{
1876 FMenuBuilder MenuBuilder(true, nullptr);
1877 MenuBuilder.AddMenuEntry(
1878 LOCTEXT("HideEmptyCategories", "Hide empty categories"),
1879 LOCTEXT("HideEmptyCategories_ToolTip", "Hides categories that do not have any children"),
1880 FSlateIcon(),
1881 FUIAction(
1882 FExecuteAction::CreateLambda([this]()
1883 {
1884 UDlgSystemSettings* Settings = GetMutableDefault<UDlgSystemSettings>();
1886 RefreshTree(true);
1887 }),
1888 FCanExecuteAction(),
1889 FIsActionChecked::CreateLambda([]() -> bool
1890 {
1891 return GetDefault<UDlgSystemSettings>()->bHideEmptyDialogueBrowserCategories;
1892 })
1893 ),
1894 NAME_None,
1895 EUserInterfaceActionType::ToggleButton
1896 );
1897
1898 return MenuBuilder.MakeWidget();
1899}
1900
1901#undef LOCTEXT_NAMESPACE
1902#undef DEFAULT_FONT
EDialogueTreeNodeTextType
EDialogueBlueprintOpenType
#define DEFAULT_FONT(...)
static bool PredicateSortByDialoguesNumDescending(FName FirstParticipant, FName SecondParticipant, const TMap< FName, TSharedPtr< FDialogueBrowserTreeParticipantProperties > > &ParticipantsProperties)
static bool PredicateCompareDialogueTreeNode(const TSharedPtr< FDialogueBrowserTreeNode > &FirstNode, const TSharedPtr< FDialogueBrowserTreeNode > SecondNode)
static bool OpenBlueprintEditor(UBlueprint *Blueprint, EDialogueBlueprintOpenType OpenType=EDialogueBlueprintOpenType::None, FName FunctionNameToOpen=NAME_None, bool bForceFullEditor=true, bool bAddBlueprintFunctionIfItDoesNotExist=false)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForClassFloatVariableName(FName FloatVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForClassFNameVariableName(FName FNameVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForCustomEvent(const UClass *EventClass, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForEventEventName(FName EventName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForConditionEventCallName(FName ConditionName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForFNameVariableName(FName FNameVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForFloatVariableName(FName FloatVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForBoolVariableName(FName BoolVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForClassIntVariableName(FName IntVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForIntVariableName(FName IntVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForClassBoolVariableName(FName BoolVariableName, const UDlgDialogue *Dialogue)
static TSharedPtr< FDialogueSearchFoundResult > GetGraphNodesForClassFTextVariableName(FName FTextVariableName, const UDlgDialogue *Dialogue)
static const FName PROPERTY_ReloadAssetIcon
static const FName PROPERTY_OpenAssetIcon
static TSharedPtr< ISlateStyle > Get()
static const FName PROPERTY_FindAssetIcon
static const FName PROPERTY_ConditionIcon
static const FName PROPERTY_DlgDialogueClassThumbnail
static const FName PROPERTY_EventIcon
static void SortDefault(TArray< FName > &OutArray)
Definition DlgHelper.h:452
static FString CleanObjectName(FString Name)
static bool IsABlueprintClass(const UClass *Class)
SCategoryHeaderTableRow Self
TSharedPtr< SBorder > ContentBorder
void SetContent(TSharedRef< SWidget > InContent) override
const FSlateBrush * GetBackgroundImage() const
SLATE_BEGIN_ARGS(SCategoryHeaderTableRow)
void SetRowContent(TSharedRef< SWidget > InContent) override
void Construct(const FArguments &InArgs, const TSharedRef< STableViewBase > &InOwnerTableView)
void AddGraphNodeChildrenToItem(const TSharedPtr< FDialogueBrowserTreeNode > &InItem, const TSet< TWeakObjectPtr< const UDialogueGraphNode > > &GraphNodes, EDialogueTreeNodeTextType TextType)
TMap< FName, TSharedPtr< FDialogueBrowserTreeParticipantProperties > > ParticipantsProperties
TArray< TSharedPtr< FDialogueBrowserTreeNode > > MakeClassVariableCategoriesChildren(const TSharedPtr< FDialogueBrowserTreeNode > &Parent, const TSharedPtr< FDialogueBrowserTreeParticipantProperties > &ParticipantProperties, bool bHideEmptyCategories) const
void HandleSetExpansionRecursive(TSharedPtr< FDialogueBrowserTreeNode > InItem, bool bInIsItemExpanded)
static EVisibility GetOpenAssetButtonVisibility(UClass *Class)
TSharedPtr< FDialogueBrowserSortOption > SortOptionType
TArray< TSharedPtr< FDialogueBrowserTreeNode > > MakeParticipantCategoriesChildren(const TSharedPtr< FDialogueBrowserTreeNode > &Parent, const TSharedPtr< FDialogueBrowserTreeParticipantProperties > &ParticipantProperties, bool bHideEmptyCategories) const
SortOptionType DefaultSortOption
TSharedPtr< STreeView< TSharedPtr< FDialogueBrowserTreeNode > > > ParticipantsTreeView
void HandleDoubleClick(TSharedPtr< FDialogueBrowserTreeNode > InItem)
TArray< SortOptionType > SortOptions
void AddEdgeNodeChildrenToItem(const TSharedPtr< FDialogueBrowserTreeNode > &InItem, const TSet< TWeakObjectPtr< const UDialogueGraphNode_Edge > > &EdgeNodes, EDialogueTreeNodeTextType TextType)
TArray< TSharedPtr< FDialogueBrowserTreeNode > > MakeVariableCategoriesChildren(const TSharedPtr< FDialogueBrowserTreeNode > &Parent, const TSharedPtr< FDialogueBrowserTreeParticipantProperties > &ParticipantProperties, bool bHideEmptyCategories) const
TSharedRef< SWidget > FillViewOptionsEntries()
void BuildTreeViewItem(const TSharedPtr< FDialogueBrowserTreeNode > &Item)
void HandleSortSelectionChanged(SortOptionType Selection, ESelectInfo::Type SelectInfo)
TArray< TSharedPtr< FDialogueBrowserTreeNode > > RootChildren
static EVisibility GetBrowseAssetButtonVisibility(UClass *Class)
void HandleGetChildren(TSharedPtr< FDialogueBrowserTreeNode > InItem, TArray< TSharedPtr< FDialogueBrowserTreeNode > > &OutChildren)
TSharedRef< ITableRow > HandleGenerateRow(TSharedPtr< FDialogueBrowserTreeNode > InItem, const TSharedRef< STableViewBase > &OwnerTable)
FText GetFilterText() const
FReply FindInContentBrowserForItem(TSharedPtr< FDialogueBrowserTreeNode > InItem)
TSharedRef< SWidget > MakeInlineWidget(const TSharedPtr< FDialogueBrowserTreeNode > &InItem)
TSharedRef< SWidget > GetFilterTextBoxWidget()
TSharedRef< SWidget > MakeButtonsWidgetForDialogue(const TSharedPtr< FDialogueBrowserTreeNode > &InItem)
TSharedPtr< SSearchBox > FilterTextBoxWidget
void RefreshTree(bool bPreserveExpansion)
void Construct(const FArguments &InArgs)
static FReply OnOpenAssetClicked(UClass *Class, EDialogueBlueprintOpenType OpenType, FName FunctionNameToOpen)
TSharedPtr< FDialogueBrowserTreeNode > RootTreeItem
void AddVariableChildrenToItem(const TSharedPtr< FDialogueBrowserTreeNode > &Item, const TMap< FName, TSharedPtr< FDialogueBrowserTreeVariableProperties > > &Variables, EDialogueTreeNodeTextType VariableType)
static FText GetBrowseAssetText(UClass *Class)
void HandleSearchTextCommitted(const FText &InText, ETextCommit::Type InCommitType)
TSharedRef< SHorizontalBox > MakeCustomObjectIconAndTextWidget(const FText &InText, const FSlateBrush *IconBrush, UClass *Class, EDialogueBlueprintOpenType OpenType, FName FunctionNameToOpen, int32 IconSize=24)
TSharedRef< SWidget > MakeButtonWidgetForGraphNodes(const TArray< TSharedPtr< FDialogueBrowserTreeNode > > &InChildren)
void AddDialogueChildrenToItemFromProperty(const TSharedPtr< FDialogueBrowserTreeNode > &InItem, const TSharedPtr< FDialogueBrowserTreeVariableProperties > *PropertyPtr, EDialogueTreeNodeTextType TextType)
SortOptionType SelectedSortOption
void HandleTreeSelectionChanged(TSharedPtr< FDialogueBrowserTreeNode > NewValue, ESelectInfo::Type SelectInfo)
TSharedRef< SHorizontalBox > MakeIconAndTextWidget(const FText &InText, const FSlateBrush *IconBrush, int32 IconSize=24)
void AddGraphNodeBaseChildrenToItemFromProperty(const TSharedPtr< FDialogueBrowserTreeNode > &InItem, const TSharedPtr< FDialogueBrowserTreeVariableProperties > *PropertyPtr, EDialogueTreeNodeTextType GraphNodeTextType, EDialogueTreeNodeTextType EdgeNodeTextType)
static FText GetJumpToAssetText(UClass *Class)
static FReply OnBrowseAssetClicked(UClass *Class)
UCLASS(BlueprintType, Meta = (DisplayThumbnail = "true"))
Definition DlgDialogue.h:85
FGuid GetGUID() const
UFUNCTION(BlueprintPure, Category = "Dialogue|GUID")
UCLASS(Blueprintable, BlueprintType, Abstract, EditInlineNew)
static TArray< UDlgDialogue * > GetAllDialoguesFromMemory()
UCLASS(Config = Engine, DefaultConfig, meta = (DisplayName = "Dialogue System Settings"))
void SetHideEmptyDialogueBrowserCategories(bool InVariableValue)
bool bHideEmptyDialogueBrowserCategories
UPROPERTY(Category = "Browser", Config, EditAnywhere)