A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DialogueSearchManager.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
3
4#include "Widgets/Docking/SDockTab.h"
5#include "AssetRegistryModule.h"
7#include "WorkspaceMenuStructureModule.h"
8#include "WorkspaceMenuStructure.h"
9#include "EdGraphNode_Comment.h"
10
12#include "DlgDialogue.h"
13#include "DlgManager.h"
14#include "DlgHelper.h"
15#include "SFindInDialogues.h"
19#include "DialogueStyle.h"
20#include "DlgConstants.h"
21
22#define LOCTEXT_NAMESPACE "SDialogueBrowser"
23
24#if ENGINE_MINOR_VERSION >= 24
25 #define NY_ARRAY_COUNT UE_ARRAY_COUNT
26#else
27 #define NY_ARRAY_COUNT ARRAY_COUNT
28#endif
29
31
33// FDialogueSearchManager
35{
36 if (Instance == nullptr)
37 {
38 Instance = new Self();
39 }
40
41 return Instance;
42}
43
45{
46 // Create the Tab Ids
47 for (int32 TabIdx = 0; TabIdx < NY_ARRAY_COUNT(GlobalFindResultsTabIDs); TabIdx++)
48 {
49 const FName TabID = FName(*FString::Printf(TEXT("GlobalNotYetDialogueFindResults_%02d"), TabIdx + 1));
50 GlobalFindResultsTabIDs[TabIdx] = TabID;
51 }
52}
53
58
60 const FDialogueSearchFilter& SearchFilter,
61 const FDlgTextArgument& InDlgTextArgument,
62 const TSharedPtr<FDialogueSearchResult>& OutParentNode,
63 int32 ArgumentIndex
64)
65{
66 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid())
67 {
68 return false;
69 }
70 bool bContainsSearchString = false;
71
72 // Test DisplayString
73 if (InDlgTextArgument.DisplayString.Contains(SearchFilter.SearchString))
74 {
75 bContainsSearchString = true;
76 const FText Category = FText::Format(
77 LOCTEXT("DlgTextArgumentDisplayString", "TextArgument.DisplayString at index = {0}"),
78 FText::AsNumber(ArgumentIndex)
79 );
81 OutParentNode,
82 FText::FromString(InDlgTextArgument.DisplayString),
83 Category,
84 Category.ToString()
85 );
86 }
87
88 // Test ParticipantName
89 if (!InDlgTextArgument.ParticipantName.IsNone() &&
90 InDlgTextArgument.ParticipantName.ToString().Contains(SearchFilter.SearchString))
91 {
92 bContainsSearchString = true;
93 const FText Category = FText::Format(
94 LOCTEXT("DlgTextArgumentParticipantName", "TextArgument.ParticipantName at index = {0}"),
95 FText::AsNumber(ArgumentIndex)
96 );
98 OutParentNode,
99 FText::FromName(InDlgTextArgument.ParticipantName),
100 Category,
101 Category.ToString()
102 );
103 }
104
105 // Test VariableName
106 if (!InDlgTextArgument.VariableName.IsNone() &&
107 InDlgTextArgument.VariableName.ToString().Contains(SearchFilter.SearchString))
108 {
109 bContainsSearchString = true;
110 const FText Category = FText::Format(
111 LOCTEXT("DlgTextArgumentVariableName", "TextArgument.VariableName at index = {0}"),
112 FText::AsNumber(ArgumentIndex)
113 );
115 OutParentNode,
116 FText::FromName(InDlgTextArgument.VariableName),
117 Category,
118 Category.ToString()
119 );
120 }
121
122 if (SearchFilter.bIncludeCustomObjectNames)
123 {
124 // Test CustomTextArgument
125 FString FoundName;
127 {
128 bContainsSearchString = true;
129 const FText Category = FText::Format(
130 LOCTEXT("DlgTextArgumentCustomTextArgument", "TextArgument.CustomTextArgument at index = {0}"),
131 FText::AsNumber(ArgumentIndex)
132 );
134 OutParentNode,
135 FText::FromString(FoundName),
136 Category,
137 Category.ToString()
138 );
139 }
140 }
141
142 return bContainsSearchString;
143}
144
146 const FDialogueSearchFilter& SearchFilter,
147 const FDlgCondition& InDlgCondition,
148 const TSharedPtr<FDialogueSearchResult>& OutParentNode,
149 int32 ConditionIndex,
150 FName ConditionMemberName
151)
152{
153 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid())
154 {
155 return false;
156 }
157 bool bContainsSearchString = false;
158
159 // Test ParticipantName
160 if (!InDlgCondition.ParticipantName.IsNone() &&
161 InDlgCondition.ParticipantName.ToString().Contains(SearchFilter.SearchString))
162 {
163 bContainsSearchString = true;
164 const FText Category = FText::Format(
165 LOCTEXT("DlgConditionParticipantName", "{0}.ParticipantName at index = {1}"),
166 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
167 );
169 OutParentNode,
170 FText::FromName(InDlgCondition.ParticipantName),
171 Category,
172 Category.ToString()
173 );
174 }
175
176 // Test CallBackName
177 if (!InDlgCondition.CallbackName.IsNone() &&
178 InDlgCondition.CallbackName.ToString().Contains(SearchFilter.SearchString))
179 {
180 bContainsSearchString = true;
181 const FText Category = FText::Format(
182 LOCTEXT("DlgConditionCallbackName", "{0}.CallbackName at index = {01}"),
183 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
184 );
186 OutParentNode,
187 FText::FromName(InDlgCondition.CallbackName),
188 Category,
189 Category.ToString()
190 );
191 }
192
193 // Test NameValue
194 if (!InDlgCondition.NameValue.IsNone() &&
195 InDlgCondition.NameValue.ToString().Contains(SearchFilter.SearchString))
196 {
197 bContainsSearchString = true;
198 const FText Category = FText::Format(
199 LOCTEXT("DlgConditionNameValue", "{0}.NameValue at index = {1}"),
200 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
201 );
203 OutParentNode,
204 FText::FromName(InDlgCondition.NameValue),
205 Category,
206 Category.ToString()
207 );
208 }
209
210 // Test OtherParticipantName
211 if (!InDlgCondition.OtherParticipantName.IsNone() &&
212 InDlgCondition.OtherParticipantName.ToString().Contains(SearchFilter.SearchString))
213 {
214 bContainsSearchString = true;
215 const FText Category = FText::Format(
216 LOCTEXT("DlgConditionOtherParticipantName", "{0}.OtherParticipantName at index = {1}"),
217 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
218 );
220 OutParentNode,
221 FText::FromName(InDlgCondition.OtherParticipantName),
222 Category,
223 Category.ToString()
224 );
225 }
226
227 // Test OtherVariableName
228 if (!InDlgCondition.OtherVariableName.IsNone() &&
229 InDlgCondition.OtherVariableName.ToString().Contains(SearchFilter.SearchString))
230 {
231 bContainsSearchString = true;
232 const FText Category = FText::Format(
233 LOCTEXT("DlgConditionOtherVariableName", "{0}.OtherVariableName at index = {1}"),
234 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
235 );
237 OutParentNode,
238 FText::FromName(InDlgCondition.OtherVariableName),
239 Category,
240 Category.ToString()
241 );
242 }
243
244 if (SearchFilter.bIncludeCustomObjectNames)
245 {
246 // Test Custom Condition
247 FString FoundName;
249 {
250 bContainsSearchString = true;
251 const FText Category = FText::Format(
252 LOCTEXT("DlgConditionCustomCondition", "{0}.CustomCondition at index = {1}"),
253 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
254 );
256 OutParentNode,
257 FText::FromString(FoundName),
258 Category,
259 Category.ToString()
260 );
261 }
262 }
263
264 if (SearchFilter.bIncludeNodeGUID)
265 {
266 // Test Node GUID
267 FString FoundGUID;
268 if (FDialogueSearchUtilities::DoesGUIDContainString(InDlgCondition.GUID, SearchFilter.SearchString, FoundGUID))
269 {
270 bContainsSearchString = true;
271 const FText Category = FText::Format(
272 LOCTEXT("DlgConditioGUID", "{0}.GUID at index = {1}"),
273 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
274 );
276 OutParentNode,
277 FText::FromString(FoundGUID),
278 Category,
279 Category.ToString()
280 );
281 }
282 }
283
284 if (SearchFilter.bIncludeNumericalTypes)
285 {
286 // Test IntValue
287 const FString IntValue = FString::FromInt(InDlgCondition.IntValue);
288 if (IntValue.Contains(SearchFilter.SearchString))
289 {
290 bContainsSearchString = true;
291 const FText Category = FText::Format(
292 LOCTEXT("DlgConditionIntValue", "{0}.IntValue at index = {1}"),
293 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
294 );
296 OutParentNode,
297 FText::FromString(IntValue),
298 Category,
299 Category.ToString()
300 );
301 }
302
303 // Test FloatValue
304 const FString FloatValue = FString::SanitizeFloat(InDlgCondition.FloatValue);
305 if (FloatValue.Contains(SearchFilter.SearchString))
306 {
307 bContainsSearchString = true;
308 const FText Category = FText::Format(
309 LOCTEXT("DlgConditionFloatValue", "{0}.FloatValue at index = {1}"),
310 FText::FromName(ConditionMemberName), FText::AsNumber(ConditionIndex)
311 );
313 OutParentNode,
314 FText::FromString(FloatValue),
315 Category,
316 Category.ToString()
317 );
318 }
319 }
320
321 return bContainsSearchString;
322}
323
325 const FDialogueSearchFilter& SearchFilter,
326 const FDlgEvent& InDlgEvent,
327 const TSharedPtr<FDialogueSearchResult>& OutParentNode,
328 int32 EventIndex,
329 FName EventMemberName
330)
331{
332 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid())
333 {
334 return false;
335 }
336 bool bContainsSearchString = false;
337
338 // Test ParticipantName
339 if (!InDlgEvent.ParticipantName.IsNone() &&
340 InDlgEvent.ParticipantName.ToString().Contains(SearchFilter.SearchString))
341 {
342 bContainsSearchString = true;
343 const FText Category = FText::Format(
344 LOCTEXT("DlgEventParticipantName", "{0}.ParticipantName at index = {1}"),
345 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
346 );
348 OutParentNode,
349 FText::FromName(InDlgEvent.ParticipantName),
350 Category,
351 Category.ToString()
352 );
353 }
354
355 // Test EventName
356 if (!InDlgEvent.EventName.IsNone() &&
357 InDlgEvent.EventName.ToString().Contains(SearchFilter.SearchString))
358 {
359 bContainsSearchString = true;
360 const FText Category = FText::Format(
361 LOCTEXT("DlgEventCallbackName", "{0}.EventName at index = {1}"),
362 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
363 );
365 OutParentNode,
366 FText::FromName(InDlgEvent.EventName),
367 Category,
368 Category.ToString()
369 );
370 }
371
372 // Test NameValue
373 if (!InDlgEvent.NameValue.IsNone() &&
374 InDlgEvent.NameValue.ToString().Contains(SearchFilter.SearchString))
375 {
376 bContainsSearchString = true;
377 const FText Category = FText::Format(
378 LOCTEXT("DlgEventNameValue", "{0}.NameValue at index = {1}"),
379 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
380 );
382 OutParentNode,
383 FText::FromName(InDlgEvent.NameValue),
384 Category,
385 Category.ToString()
386 );
387 }
388
389 if (SearchFilter.bIncludeCustomObjectNames)
390 {
391 FString FoundName;
393 {
394 bContainsSearchString = true;
395 const FText Category = FText::Format(
396 LOCTEXT("DlgEventCustomEvent", "{0}.CustomEvent at index = {1}"),
397 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
398 );
400 OutParentNode,
401 FText::FromString(FoundName),
402 Category,
403 Category.ToString()
404 );
405 }
406 }
407
408 if (SearchFilter.bIncludeNumericalTypes)
409 {
410 // Test IntValue
411 const FString IntValue = FString::FromInt(InDlgEvent.IntValue);
412 if (IntValue.Contains(SearchFilter.SearchString))
413 {
414 bContainsSearchString = true;
415 const FText Category = FText::Format(
416 LOCTEXT("DlgEventIntValue", "{0}.IntValue at index = {1}"),
417 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
418 );
420 OutParentNode,
421 FText::FromString(IntValue),
422 Category,
423 Category.ToString()
424 );
425 }
426
427 // Test FloatValue
428 const FString FloatValue = FString::SanitizeFloat(InDlgEvent.FloatValue);
429 if (FloatValue.Contains(SearchFilter.SearchString))
430 {
431 bContainsSearchString = true;
432 const FText Category = FText::Format(
433 LOCTEXT("DlgEventFloatValue", "{0}.FloatValue at index = {1}"),
434 FText::FromName(EventMemberName), FText::AsNumber(EventIndex)
435 );
437 OutParentNode,
438 FText::FromString(FloatValue),
439 Category,
440 Category.ToString()
441 );
442 }
443 }
444
445 return bContainsSearchString;
446}
447
449 const FDialogueSearchFilter& SearchFilter,
450 const FDlgEdge& InDlgEdge,
451 const TSharedPtr<FDialogueSearchResult>& OutParentNode
452)
453{
454 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid())
455 {
456 return false;
457 }
458 bool bContainsSearchString = false;
459
460 // Test Text
461 if (InDlgEdge.GetUnformattedText().ToString().Contains(SearchFilter.SearchString))
462 {
463 bContainsSearchString = true;
464 const FText Category = LOCTEXT("DlgEdgText", "Edge.Text");
466 OutParentNode,
467 InDlgEdge.GetUnformattedText(),
468 Category,
469 Category.ToString()
470 );
471 }
472 // Test the Node Text Data
473 if (SearchFilter.bIncludeTextLocalizationData)
474 {
475 bContainsSearchString = SearchForTextLocalizationData(
476 OutParentNode,
477 SearchFilter.SearchString,
478 InDlgEdge.GetUnformattedText(),
479 LOCTEXT("EdgeTextNamespaceName_Found", "Edge Text Namespace"), TEXT("Edge Text Localization Namespace"),
480 LOCTEXT("EdgeTextKey_Found", "Edge Text Key"), TEXT("Edge Text Localization Key")
481 ) || bContainsSearchString;
482 }
483
484 // Test Condition
485 for (int32 Index = 0, Num = InDlgEdge.Conditions.Num(); Index < Num; Index++)
486 {
487 bContainsSearchString = QueryDlgCondition(
488 SearchFilter,
489 InDlgEdge.Conditions[Index],
490 OutParentNode,
491 Index,
492 TEXT("Condition")
493 ) || bContainsSearchString;
494 }
495
496 // Test SpeakerState
497 if (!InDlgEdge.SpeakerState.IsNone() &&
498 InDlgEdge.SpeakerState.ToString().Contains(SearchFilter.SearchString))
499 {
500 bContainsSearchString = true;
501 const FText Category = LOCTEXT("DlgEdgeSpeakerState", "Edge.SpeakerState");
503 OutParentNode,
504 FText::FromName(InDlgEdge.SpeakerState),
505 Category,
506 Category.ToString()
507 );
508 }
509
510 // Test TextArguments
511 const TArray<FDlgTextArgument>& TextArguments = InDlgEdge.GetTextArguments();
512 for (int32 Index = 0, Num = TextArguments.Num(); Index < Num; Index++)
513 {
514 bContainsSearchString = QueryDlgTextArgument(SearchFilter, TextArguments[Index], OutParentNode, Index) || bContainsSearchString;
515 }
516
517 return bContainsSearchString;
518}
519
521 const FDialogueSearchFilter& SearchFilter,
522 const UDialogueGraphNode* InGraphNode,
523 const TSharedPtr<FDialogueSearchResult>& OutParentNode
524)
525{
526 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InGraphNode))
527 {
528 return false;
529 }
530
531 bool bContainsSearchString = false;
532 const UDlgNode& Node = InGraphNode->GetDialogueNode();
533 const int32 NodeIndex = InGraphNode->GetDialogueNodeIndex();
534 const FString NodeType = Node.GetNodeTypeString();
535
536 // Create the GraphNode Node
537 const FText DisplayText = FText::Format(
538 LOCTEXT("TreeGraphNodeCategory", "{0} Node at index {1}"),
539 FText::FromString(NodeType), FText::AsNumber(NodeIndex)
540 );
541 TSharedPtr<FDialogueSearchResult_GraphNode> TreeGraphNode = MakeShared<FDialogueSearchResult_GraphNode>(DisplayText, OutParentNode);
542 TreeGraphNode->SetCategory(FText::FromString(NodeType));
543 TreeGraphNode->SetGraphNode(InGraphNode);
544
545 // Test the NodeIndex
546 if (SearchFilter.bIncludeIndices && !InGraphNode->IsRootNode())
547 {
548 // NOTE: We do not create another node, we just use the Node DisplayText as the search node.
549 if (FString::FromInt(NodeIndex).Contains(SearchFilter.SearchString))
550 {
551 bContainsSearchString = true;
552 }
553 }
554
555 // Test the Node Comment
556 if (SearchFilter.bIncludeComments)
557 {
558 if (InGraphNode->NodeComment.Contains(SearchFilter.SearchString))
559 {
560 bContainsSearchString = true;
562 TreeGraphNode,
563 FText::FromString(InGraphNode->NodeComment),
564 LOCTEXT("NodeCommentKey", "Comment on Node"),
565 TEXT("Comment on Node")
566 );
567 }
568 }
569
570 // Test the ParticipantName
571 if (Node.GetNodeParticipantName().ToString().Contains(SearchFilter.SearchString))
572 {
573 bContainsSearchString = true;
575 TreeGraphNode,
576 FText::FromName(Node.GetNodeParticipantName()),
577 LOCTEXT("ParticipantNameKey", "Participant Name"),
578 TEXT("Participant Name")
579 );
580 }
581
582 // Test the Node text
583 if (Node.GetNodeUnformattedText().ToString().Contains(SearchFilter.SearchString))
584 {
585 bContainsSearchString = true;
587 TreeGraphNode,
589 LOCTEXT("DescriptionKey", "Text"),
590 TEXT("Text")
591 );
592 }
593 // Test the Node Text Data
594 if (SearchFilter.bIncludeTextLocalizationData)
595 {
596 bContainsSearchString = SearchForTextLocalizationData(
597 TreeGraphNode,
598 SearchFilter.SearchString, Node.GetNodeUnformattedText(),
599 LOCTEXT("TextNamespaceName_Found", "Text Namespace"), TEXT("Text Localization Namespace"),
600 LOCTEXT("TextKey_Found", "Text Key"), TEXT("Text Localization Key")
601 ) || bContainsSearchString;
602 }
603
604 // Test the EnterConditions
605 const TArray<FDlgCondition>& EnterConditions = Node.GetNodeEnterConditions();
606 for (int32 Index = 0, Num = EnterConditions.Num(); Index < Num; Index++)
607 {
608 bContainsSearchString = QueryDlgCondition(
609 SearchFilter,
610 EnterConditions[Index],
611 TreeGraphNode,
612 Index,
613 TEXT("EnterCondition")
614 ) || bContainsSearchString;
615 }
616
617 // Test the EnterEvents
618 const TArray<FDlgEvent>& EnterEvents = Node.GetNodeEnterEvents();
619 for (int32 Index = 0, Num = EnterEvents.Num(); Index < Num; Index++)
620 {
621 bContainsSearchString = QueryDlgEvent(
622 SearchFilter,
623 EnterEvents[Index],
624 TreeGraphNode,
625 Index,
626 TEXT("EnterEvent")
627 ) || bContainsSearchString;
628 }
629
630 // Test SpeakerState
631 if (!Node.GetSpeakerState().IsNone() &&
632 Node.GetSpeakerState().ToString().Contains(SearchFilter.SearchString))
633 {
634 bContainsSearchString = true;
636 TreeGraphNode,
637 FText::FromName(Node.GetSpeakerState()),
638 LOCTEXT("SpeakerStateKey", "Speaker State"),
639 TEXT("Speaker State")
640 );
641 }
642
643 // Test TextArguments
644 const TArray<FDlgTextArgument>& TextArguments = Node.GetTextArguments();
645 for (int32 Index = 0, Num = TextArguments.Num(); Index < Num; Index++)
646 {
647 bContainsSearchString = QueryDlgTextArgument(SearchFilter, TextArguments[Index], TreeGraphNode, Index) || bContainsSearchString;
648 }
649
650 if (SearchFilter.bIncludeCustomObjectNames)
651 {
652 // Test Node Data
653 FString FoundName;
655 {
656 bContainsSearchString = true;
658 TreeGraphNode,
659 FText::FromString(FoundName),
660 LOCTEXT("NodeDataKey", "Node Data"),
661 TEXT("Node Data")
662 );
663 }
664 }
665
666 if (SearchFilter.bIncludeNodeGUID)
667 {
668 // Test Node GUID
669 FString FoundGUID;
670 if (FDialogueSearchUtilities::DoesGUIDContainString(Node.GetGUID(), SearchFilter.SearchString, FoundGUID))
671 {
672 bContainsSearchString = true;
674 TreeGraphNode,
675 FText::FromString(FoundGUID),
676 LOCTEXT("NodeGUID", "Node GUID"),
677 TEXT("Node GUID")
678 );
679 }
680 }
681
682 // Handle Speech sequences
683 if (const UDlgNode_SpeechSequence* SpeechSequence = Cast<UDlgNode_SpeechSequence>(&Node))
684 {
685 const TArray<FDlgSpeechSequenceEntry>& SpeechSequenceArray = SpeechSequence->GetNodeSpeechSequence();
686 for (int32 Index = 0, Num = SpeechSequenceArray.Num(); Index < Num; Index++)
687 {
688 const FDlgSpeechSequenceEntry& SequenceEntry = SpeechSequenceArray[Index];
689
690 // Test Speaker
691 if (SequenceEntry.Speaker.ToString().Contains(SearchFilter.SearchString))
692 {
693 bContainsSearchString = true;
694 const FText Category = FText::Format(LOCTEXT("SequenceEntrySpeaker", "SequenceEntry.Speaker at index = {0}"), FText::AsNumber(Index));
695 MakeChildTextNode(TreeGraphNode, FText::FromName(SequenceEntry.Speaker), Category, Category.ToString());
696 }
697
698 // Test Text Description
699 const FText TextCategory = FText::Format(LOCTEXT("SequenceEntryText", "SequenceEntry.Text at index = {0}"), FText::AsNumber(Index));
700 if (SequenceEntry.Text.ToString().Contains(SearchFilter.SearchString))
701 {
702 bContainsSearchString = true;
703 MakeChildTextNode(TreeGraphNode, SequenceEntry.Text, TextCategory, TextCategory.ToString());
704 }
705 if (SearchFilter.bIncludeTextLocalizationData)
706 {
707 const FText NamespaceCategory = FText::FromString(TEXT("Namespace ") + TextCategory.ToString());
708 const FText KeyCategory = FText::FromString(TEXT("Key ") + TextCategory.ToString());
709 bContainsSearchString = SearchForTextLocalizationData(
710 TreeGraphNode,
711 SearchFilter.SearchString, SequenceEntry.Text,
712 NamespaceCategory, NamespaceCategory.ToString(),
713 KeyCategory, KeyCategory.ToString()
714 ) || bContainsSearchString;
715 }
716
717 // Test EdgeText
718 const FText EdgeTextCategory = FText::Format(LOCTEXT("SequenceEntryEdgeText", "SequenceEntry.EdgeText at index = {0}"), FText::AsNumber(Index));
719 if (SequenceEntry.EdgeText.ToString().Contains(SearchFilter.SearchString))
720 {
721 bContainsSearchString = true;
722 MakeChildTextNode(TreeGraphNode, SequenceEntry.EdgeText, EdgeTextCategory, EdgeTextCategory.ToString());
723 }
724 if (SearchFilter.bIncludeTextLocalizationData)
725 {
726 const FText NamespaceCategory = FText::FromString(TEXT("Namespace ") + EdgeTextCategory.ToString());
727 const FText KeyCategory = FText::FromString(TEXT("Key ") + EdgeTextCategory.ToString());
728 bContainsSearchString = SearchForTextLocalizationData(
729 TreeGraphNode,
730 SearchFilter.SearchString, SequenceEntry.EdgeText,
731 NamespaceCategory, NamespaceCategory.ToString(),
732 KeyCategory, KeyCategory.ToString()
733 ) || bContainsSearchString;
734 }
735
736 // Test SpeakerState
737 if (!SequenceEntry.SpeakerState.IsNone() &&
738 SequenceEntry.SpeakerState.ToString().Contains(SearchFilter.SearchString))
739 {
740 bContainsSearchString = true;
741 const FText Category = FText::Format(LOCTEXT("SequenceEntrySpeakerState", "SequenceEntry.SpeakerState at index = {0}"), FText::AsNumber(Index));
742 MakeChildTextNode(TreeGraphNode, FText::FromName(SequenceEntry.SpeakerState), Category, Category.ToString());
743 }
744 }
745 }
746
747 if (bContainsSearchString)
748 {
749 OutParentNode->AddChild(TreeGraphNode);
750 }
751
752 return bContainsSearchString;
753}
754
756 const FDialogueSearchFilter& SearchFilter,
757 const UDialogueGraphNode_Edge* InEdgeNode,
758 const TSharedPtr<FDialogueSearchResult>& OutParentNode
759)
760{
761 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InEdgeNode))
762 {
763 return false;
764 }
765 bool bContainsSearchString = false;
766
767 // Build up the Display Text
768 int32 FromParent = -1;
769 int32 ToChild = -1;
770 if (InEdgeNode->HasParentNode())
771 {
772 FromParent = InEdgeNode->GetParentNode()->GetDialogueNodeIndex();
773 }
774 if (InEdgeNode->HasChildNode())
775 {
776 ToChild = InEdgeNode->GetChildNode()->GetDialogueNodeIndex();
777 }
778 const FText DisplayText = FText::Format(LOCTEXT("EdgeNodeDisplaytext", "Edge between {0} -> {1}"),
779 FText::AsNumber(FromParent), FText::AsNumber(ToChild));
780 TSharedPtr<FDialogueSearchResult_EdgeNode> TreeEdgeNode = MakeShared<FDialogueSearchResult_EdgeNode>(DisplayText, OutParentNode);
781 TreeEdgeNode->SetCategory(DisplayText);
782 TreeEdgeNode->SetEdgeNode(InEdgeNode);
783
784 // Search in the DlgEdge
785 const FDlgEdge& DialogueEdge = InEdgeNode->GetDialogueEdge();
786 bContainsSearchString = QueryDlgEdge(SearchFilter, DialogueEdge, TreeEdgeNode) || bContainsSearchString;
787
788 if (bContainsSearchString)
789 {
790 OutParentNode->AddChild(TreeEdgeNode);
791 }
792
793 return bContainsSearchString;
794}
795
797 const FDialogueSearchFilter& SearchFilter,
798 const UEdGraphNode_Comment* InCommentNode,
799 const TSharedPtr<FDialogueSearchResult>& OutParentNode
800)
801{
802 if (!SearchFilter.bIncludeComments || SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InCommentNode))
803 {
804 return false;
805 }
806
807 if (InCommentNode->NodeComment.Contains(SearchFilter.SearchString))
808 {
809 const FText Category = LOCTEXT("TreeNodeCommentCategory", "Comment Node");
810 TSharedPtr<FDialogueSearchResult_CommentNode> TreeCommentNode = MakeShared<FDialogueSearchResult_CommentNode>(Category, OutParentNode);
811 TreeCommentNode->SetCategory(Category);
812 TreeCommentNode->SetCommentNode(InCommentNode);
813
815 TreeCommentNode,
816 FText::FromString(InCommentNode->NodeComment),
817 Category,
818 TEXT("")
819 );
820
821 OutParentNode->AddChild(TreeCommentNode);
822 return true;
823 }
824 return false;
825}
826
828 const FDialogueSearchFilter& SearchFilter,
829 const UDlgDialogue* InDialogue,
830 TSharedPtr<FDialogueSearchResult>& OutParentNode
831)
832{
833 if (SearchFilter.SearchString.IsEmpty() || !OutParentNode.IsValid() || !IsValid(InDialogue))
834 {
835 return false;
836 }
837
838 const UDialogueGraph* Graph = CastChecked<UDialogueGraph>(InDialogue->GetGraph());
839 TSharedPtr<FDialogueSearchResult_DialogueNode> TreeDialogueNode = MakeShared<FDialogueSearchResult_DialogueNode>(
840 FText::FromString(InDialogue->GetPathName()), OutParentNode
841 );
842 TreeDialogueNode->SetDialogue(InDialogue);
843
844 // Find in GraphNodes
845 bool bFoundInDialogue = false;
846 const TArray<UEdGraphNode*>& AllGraphNodes = Graph->GetAllGraphNodes();
847 for (UEdGraphNode* Node : AllGraphNodes)
848 {
849 bool bFoundInNode = false;
850 if (UDialogueGraphNode* GraphNode = Cast<UDialogueGraphNode>(Node))
851 {
852 bFoundInNode = QueryGraphNode(SearchFilter, GraphNode, TreeDialogueNode);
853 }
854 else if (UDialogueGraphNode_Edge* EdgeNode = Cast<UDialogueGraphNode_Edge>(Node))
855 {
856 bFoundInNode = QueryEdgeNode(SearchFilter, EdgeNode, TreeDialogueNode);
857 }
858 else if (UEdGraphNode_Comment* CommentNode = Cast<UEdGraphNode_Comment>(Node))
859 {
860 bFoundInNode = QueryCommentNode(SearchFilter, CommentNode, TreeDialogueNode);
861 }
862 else
863 {
864 // ignore everything else
865 }
866
867 // Found at least one match in one of the nodes.
868 bFoundInDialogue = bFoundInNode || bFoundInDialogue;
869 }
870
871 // Search for GUID
872 if (SearchFilter.bIncludeDialogueGUID)
873 {
874 FString FoundGUID;
875 if (FDialogueSearchUtilities::DoesGUIDContainString(InDialogue->GetGUID(), SearchFilter.SearchString, FoundGUID))
876 {
877 bFoundInDialogue = true;
879 TreeDialogueNode,
880 FText::FromString(FoundGUID),
881 LOCTEXT("DialogueGUID", "Dialogue GUID"),
882 TEXT("Dialogue.GUID")
883 );
884 }
885 }
886
887 if (bFoundInDialogue)
888 {
889 OutParentNode->AddChild(TreeDialogueNode);
890 }
891
892 return bFoundInDialogue;
893}
894
896 const FDialogueSearchFilter& SearchFilter,
897 TSharedPtr<FDialogueSearchResult>& OutParentNode
898)
899{
900 // Iterate over all cached dialogues
901 for (auto& Elem : SearchMap)
902 {
903 const FDialogueSearchData& SearchData = Elem.Value;
904 if (SearchData.Dialogue.IsValid())
905 {
906 QuerySingleDialogue(SearchFilter, SearchData.Dialogue.Get(), OutParentNode);
907 }
908 }
909}
910
912{
913 // Count the number of opened global Dialogues
914 int32 NumOpenGlobalFindResultsTabs = 0;
915 for (int32 i = GlobalFindResultsWidgets.Num() - 1; i >= 0; --i)
916 {
917 if (GlobalFindResultsWidgets[i].IsValid())
918 {
919 NumOpenGlobalFindResultsTabs++;
920 }
921 else
922 {
923 // Invalid :O remove it
924 GlobalFindResultsWidgets.RemoveAt(i);
925 }
926 }
927
928 if (NumOpenGlobalFindResultsTabs > 1 || TabIdx > 0)
929 {
930 // Format TabIdx + 1
931 return FText::Format(
932 LOCTEXT("GlobalFindResultsTabNameWithIndex", "Find in Dialogues {0}"),
933 FText::AsNumber(TabIdx + 1)
934 );
935 }
936
937 // No Number
938 return LOCTEXT("GlobalFindResultsTabName", "Find in Dialogues");
939}
940
941void FDialogueSearchManager::CloseGlobalFindResults(const TSharedRef<SFindInDialogues>& FindResults)
942{
943 for (TWeakPtr<SFindInDialogues> FindResultsPtr : GlobalFindResultsWidgets)
944 {
945 // Remove it from the opened find results
946 if (FindResultsPtr.Pin() == FindResults)
947 {
948 GlobalFindResultsWidgets.Remove(FindResultsPtr);
949 break;
950 }
951 }
952}
953
954TSharedRef<SDockTab> FDialogueSearchManager::SpawnGlobalFindResultsTab(const FSpawnTabArgs& SpawnTabArgs, int32 TabIdx)
955{
956 // Label is Dynamic depending on the number of global tabs
957 TAttribute<FText> Label = TAttribute<FText>::Create(
958 TAttribute<FText>::FGetter::CreateRaw(this, &Self::GetGlobalFindResultsTabLabel, TabIdx)
959 );
960
961 TSharedRef<SDockTab> NewTab = SNew(SDockTab)
962 .TabRole(ETabRole::NomadTab) // can be docked anywhere
963 .Label(Label)
964 .ToolTipText(LOCTEXT("GlobalFindResultsTabTooltip", "Search for a string in all Dialogue assets."));
965
966 TSharedRef<SFindInDialogues> FindResults = SNew(SFindInDialogues)
967 .bIsSearchWindow(false)
968 .ContainingTab(NewTab);
969
970 NewTab->SetContent(FindResults);
971 GlobalFindResultsWidgets.Add(FindResults);
972
973 return NewTab;
974}
975
977{
978 TSet<FName> OpenGlobalTabIDs;
979
980 // Check all opened global tabs
981 for (TWeakPtr<SFindInDialogues> FindResultsPtr : GlobalFindResultsWidgets)
982 {
983 TSharedPtr<SFindInDialogues> FindResults = FindResultsPtr.Pin();
984 if (FindResults.IsValid())
985 {
986 OpenGlobalTabIDs.Add(FindResults->GetHostTabId());
987 }
988 }
989
990 // Find the unopened tab, that we can open
991 for (int32 Idx = 0; Idx < NY_ARRAY_COUNT(GlobalFindResultsTabIDs); ++Idx)
992 {
993 const FName GlobalTabId = GlobalFindResultsTabIDs[Idx];
994 if (!OpenGlobalTabIDs.Contains(GlobalTabId))
995 {
996 // GlobalTabId is not opened, open it now
997 TSharedPtr<SDockTab> NewTab = FDlgHelper::InvokeTab(FGlobalTabmanager::Get(), GlobalTabId);
998 if (NewTab.IsValid())
999 {
1000 return StaticCastSharedRef<SFindInDialogues>(NewTab->GetContent());
1001 }
1002 }
1003 }
1004
1005 return TSharedPtr<SFindInDialogues>();
1006}
1007
1009{
1010 // Find opened find tab
1011 TSharedPtr<SFindInDialogues> FindResultsToUse;
1012 for (TWeakPtr<SFindInDialogues> FindResultsPtr : GlobalFindResultsWidgets)
1013 {
1014 TSharedPtr<SFindInDialogues> FindResults = FindResultsPtr.Pin();
1015 if (FindResults.IsValid())
1016 {
1017 FindResultsToUse = FindResults;
1018 break;
1019 }
1020 }
1021
1022 if (FindResultsToUse.IsValid())
1023 {
1024 // found invoke it
1025 FDlgHelper::InvokeTab(FGlobalTabmanager::Get(), FindResultsToUse->GetHostTabId());
1026 }
1027 else
1028 {
1029 // not found, open a new tab.
1030 FindResultsToUse = OpenGlobalFindResultsTab();
1031 }
1032
1033 return FindResultsToUse;
1034}
1035
1036void FDialogueSearchManager::EnableGlobalFindResults(TSharedPtr<FWorkspaceItem> ParentTabCategory)
1037{
1038 const TSharedRef<FGlobalTabmanager>& GlobalTabManager = FGlobalTabmanager::Get();
1039
1040 // Register the spawners for all global Find Results tabs
1042
1043 // Add the menu item
1044 if (!ParentTabCategory.IsValid())
1045 {
1046 ParentTabCategory = WorkspaceMenu::GetMenuStructure().GetToolsCategory();
1047 }
1048
1049 GlobalFindResultsMenuItem = ParentTabCategory->AddGroup(
1050 LOCTEXT("WorkspaceMenu_GlobalFindResultsCategory", "Find in Dialogues"),
1051 LOCTEXT("GlobalFindResultsMenuTooltipText", "Find references to conditions, events, text and variables in all Dialogues."),
1052 GlobalFindResultsIcon,
1053 true
1054 );
1055
1056 // Register tab spawners
1057 for (int32 TabIdx = 0; TabIdx < NY_ARRAY_COUNT(GlobalFindResultsTabIDs); TabIdx++)
1058 {
1059 const FName TabID = GlobalFindResultsTabIDs[TabIdx];
1060
1061 // Tab not registered yet, good.
1062#if ENGINE_MINOR_VERSION >= 23
1063 if (!GlobalTabManager->HasTabSpawner(TabID))
1064#else
1065 if (!GlobalTabManager->CanSpawnTab(TabID))
1066#endif
1067 {
1068 const FText DisplayName = FText::Format(
1069 LOCTEXT("GlobalFindResultsDisplayName", "Find in Dialogues {0}"),
1070 FText::AsNumber(TabIdx + 1)
1071 );
1072 GlobalTabManager->RegisterNomadTabSpawner(
1073 TabID,
1074 FOnSpawnTab::CreateRaw(this, &Self::SpawnGlobalFindResultsTab, TabIdx))
1075 .SetDisplayName(DisplayName)
1076 .SetIcon(GlobalFindResultsIcon)
1077 .SetGroup(GlobalFindResultsMenuItem.ToSharedRef()
1078 );
1079 }
1080 }
1081}
1082
1084{
1085 const TSharedRef<FGlobalTabmanager>& GlobalTabManager = FGlobalTabmanager::Get();
1086
1087 // Close all Global Find Results tabs when turning the feature off, since these may not get closed along with the Blueprint Editor contexts above.
1088 for (TWeakPtr<SFindInDialogues> FindResultsPtr : GlobalFindResultsWidgets)
1089 {
1090 TSharedPtr<SFindInDialogues> FindResults = FindResultsPtr.Pin();
1091 if (FindResults.IsValid())
1092 {
1093 FindResults->CloseHostTab();
1094 }
1095 }
1097
1098 // Unregister tab spawners
1099 for (int32 TabIdx = 0; TabIdx < NY_ARRAY_COUNT(GlobalFindResultsTabIDs); TabIdx++)
1100 {
1101 const FName TabID = GlobalFindResultsTabIDs[TabIdx];
1102
1103#if ENGINE_MINOR_VERSION >= 23
1104 if (!GlobalTabManager->HasTabSpawner(TabID))
1105#else
1106 if (!GlobalTabManager->CanSpawnTab(TabID))
1107#endif
1108 {
1109 GlobalTabManager->UnregisterNomadTabSpawner(TabID);
1110 }
1111 }
1112
1113 // Remove the menu item
1114 if (GlobalFindResultsMenuItem.IsValid())
1115 {
1116 WorkspaceMenu::GetMenuStructure().GetToolsCategory()->RemoveItem(GlobalFindResultsMenuItem.ToSharedRef());
1118 }
1119}
1120
1121void FDialogueSearchManager::Initialize(TSharedPtr<FWorkspaceItem> ParentTabCategory)
1122{
1123 // 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
1124 AssetRegistry = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>(NAME_MODULE_AssetRegistry).Get();
1125
1126 OnAssetAddedHandle = AssetRegistry->OnAssetAdded().AddRaw(this, &Self::HandleOnAssetAdded);
1127 OnAssetRemovedHandle = AssetRegistry->OnAssetRemoved().AddRaw(this, &Self::HandleOnAssetRemoved);
1128 OnAssetRenamedHandle = AssetRegistry->OnAssetRenamed().AddRaw(this, &Self::HandleOnAssetRenamed);
1129
1130 if (AssetRegistry->IsLoadingAssets())
1131 {
1133 }
1134 else
1135 {
1136 // Already loaded
1138 }
1139 OnAssetLoadedHandle = FCoreUObjectDelegates::OnAssetLoaded.AddRaw(this, &Self::HandleOnAssetLoaded);
1140
1141 // Register global find results tabs
1142 EnableGlobalFindResults(ParentTabCategory);
1143}
1144
1146{
1147 if (AssetRegistry)
1148 {
1149 if (OnAssetAddedHandle.IsValid())
1150 {
1151 AssetRegistry->OnAssetAdded().Remove(OnAssetAddedHandle);
1152 OnAssetAddedHandle.Reset();
1153 }
1154 if (OnAssetRemovedHandle.IsValid())
1155 {
1156 AssetRegistry->OnAssetRemoved().Remove(OnAssetRemovedHandle);
1157 OnAssetRemovedHandle.Reset();
1158 }
1159 if (OnFilesLoadedHandle.IsValid())
1160 {
1161 AssetRegistry->OnFilesLoaded().Remove(OnFilesLoadedHandle);
1162 OnFilesLoadedHandle.Reset();
1163 }
1164 if (OnAssetRenamedHandle.IsValid())
1165 {
1166 AssetRegistry->OnAssetRenamed().Remove(OnAssetRenamedHandle);
1167 OnAssetRenamedHandle.Reset();
1168 }
1169 }
1170
1171 if (OnAssetLoadedHandle.IsValid())
1172 {
1173 FCoreUObjectDelegates::OnAssetLoaded.Remove(OnAssetLoadedHandle);
1174 OnAssetLoadedHandle.Reset();
1175 }
1176
1177 // Shut down the global find results tab feature.
1179}
1180
1182{
1183 // Difference between this and the UDlgManager::GetAllDialoguesFromMemory is that this loads all Dialogues
1184 // even those that are not loaded into memory.
1185 // TODO this seems slow :(
1186 // AssetRegistryModule = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
1187 // FARFilter ClassFilter;
1188 // ClassFilter.bRecursiveClasses = true;
1189 // ClassFilter.ClassNames.Add(UDlgDialogue::StaticClass()->GetFName());
1190 // TArray<FAssetData> DialogueAssets;
1191 // AssetRegistryModule->Get().GetAssets(ClassFilter, DialogueAssets);
1192 // for (FAssetData& Asset : DialogueAssets)
1193 // {
1194 // HandleOnAssetAdded(Asset);
1195 // }
1196
1197 // We already loaded all Dialogues into memory in the StartupModule.
1199 {
1200 FAssetData AssetData(Dialogue);
1201 HandleOnAssetAdded(AssetData);
1202 }
1203}
1204
1205void FDialogueSearchManager::HandleOnAssetAdded(const FAssetData& InAssetData)
1206{
1207 // Confirm that the Dialogue has not been added already, this can occur during duplication of Dialogues.
1208 FDialogueSearchData* SearchDataPtr = SearchMap.Find(InAssetData.ObjectPath);
1209 if (SearchDataPtr != nullptr)
1210 {
1211 // Already exists
1212 return;
1213 }
1214
1215 // Ignore other assets
1216 if (InAssetData.GetClass() && !InAssetData.GetClass()->IsChildOf<UDlgDialogue>())
1217 {
1218 return;
1219 }
1220
1221 // Load the Dialogue
1222 UDlgDialogue* Dialogue = Cast<UDlgDialogue>(InAssetData.GetAsset());
1223 if (!IsValid(Dialogue))
1224 {
1225 return;
1226 }
1227
1228 // Add to the loaded cached map
1229 FDialogueSearchData SearchData;
1230 SearchData.Dialogue = Dialogue;
1231 SearchMap.Add(InAssetData.ObjectPath, MoveTemp(SearchData));
1232}
1233
1234void FDialogueSearchManager::HandleOnAssetRemoved(const FAssetData& InAssetData)
1235{
1236 // TODO
1237}
1238
1239void FDialogueSearchManager::HandleOnAssetRenamed(const FAssetData& InAssetData, const FString& InOldName)
1240{
1241 // TODO
1242}
1243
1248
1250{
1251 // TODO Pause search if garbage collecting?
1253 if (AssetRegistry)
1254 {
1255 // Do an immediate load of the cache to catch any Blueprints that were discovered by the asset registry before we initialized.
1256 BuildCache();
1257 }
1258}
1259
1260#undef LOCTEXT_NAMESPACE
1261#undef NY_ARRAY_COUNT
static const FName NAME_MODULE_AssetRegistry(TEXT("AssetRegistry"))
#define NY_ARRAY_COUNT
Definition INYLogger.cpp:21
bool QueryEdgeNode(const FDialogueSearchFilter &SearchFilter, const UDialogueGraphNode_Edge *InEdgeNode, const TSharedPtr< FDialogueSearchResult > &OutParentNode)
void HandleOnAssetAdded(const FAssetData &InAssetData)
bool SearchForTextLocalizationData(const TSharedPtr< FDialogueSearchResult > &ParentNode, const FString &SearchString, const FText &Text, const FText &NamespaceCategory, const FString &NamespaceCommentString, const FText &KeyCategory, const FString &KeyCommentString)
TMap< FName, FDialogueSearchData > SearchMap
TSharedPtr< FWorkspaceItem > GlobalFindResultsMenuItem
TSharedRef< SDockTab > SpawnGlobalFindResultsTab(const FSpawnTabArgs &SpawnTabArgs, int32 TabIdx)
TArray< TWeakPtr< SFindInDialogues > > GlobalFindResultsWidgets
TSharedPtr< SFindInDialogues > OpenGlobalFindResultsTab()
bool QueryDlgCondition(const FDialogueSearchFilter &SearchFilter, const FDlgCondition &InDlgCondition, const TSharedPtr< FDialogueSearchResult > &OutParentNode, int32 ConditionIndex=INDEX_NONE, FName ConditionMemberName=TEXT("Condition"))
bool QueryCommentNode(const FDialogueSearchFilter &SearchFilter, const UEdGraphNode_Comment *InCommentNode, const TSharedPtr< FDialogueSearchResult > &OutParentNode)
FText GetGlobalFindResultsTabLabel(int32 TabIdx)
void HandleOnAssetRemoved(const FAssetData &InAssetData)
bool QuerySingleDialogue(const FDialogueSearchFilter &SearchFilter, const UDlgDialogue *InDialogue, TSharedPtr< FDialogueSearchResult > &OutParentNode)
bool QueryGraphNode(const FDialogueSearchFilter &SearchFilter, const UDialogueGraphNode *InGraphNode, const TSharedPtr< FDialogueSearchResult > &OutParentNode)
FName GlobalFindResultsTabIDs[MAX_GLOBAL_DIALOGUE_SEARCH_RESULTS]
bool QueryDlgTextArgument(const FDialogueSearchFilter &SearchFilter, const FDlgTextArgument &InDlgTextArgument, const TSharedPtr< FDialogueSearchResult > &OutParentNode, int32 ArgumentIndex=INDEX_NONE)
void HandleOnAssetRenamed(const FAssetData &InAssetData, const FString &InOldName)
void QueryAllDialogues(const FDialogueSearchFilter &SearchFilter, TSharedPtr< FDialogueSearchResult > &OutParentNode)
bool QueryDlgEdge(const FDialogueSearchFilter &SearchFilter, const FDlgEdge &InDlgEdge, const TSharedPtr< FDialogueSearchResult > &OutParentNode)
void Initialize(TSharedPtr< FWorkspaceItem > ParentTabCategory=nullptr)
void HandleOnAssetLoaded(UObject *InAsset)
void EnableGlobalFindResults(TSharedPtr< FWorkspaceItem > ParentTabCategory=nullptr)
TSharedPtr< FDialogueSearchResult > MakeChildTextNode(const TSharedPtr< FDialogueSearchResult > &ParentNode, const FText &DisplayName, const FText &Category, const FString &CommentString)
bool QueryDlgEvent(const FDialogueSearchFilter &SearchFilter, const FDlgEvent &InDlgEvent, const TSharedPtr< FDialogueSearchResult > &OutParentNode, int32 EventIndex=INDEX_NONE, FName EventMemberName=TEXT("Event"))
FDialogueSearchManager Self
TSharedPtr< SFindInDialogues > GetGlobalFindResults()
void CloseGlobalFindResults(const TSharedRef< SFindInDialogues > &FindResults)
static bool DoesGUIDContainString(const FGuid &GUID, const FString &SearchString, FString &OutGUIDString)
static bool DoesObjectClassNameContainString(const UObject *Object, const FString &SearchString, FString &OutNameString)
static const FName PROPERTY_DialogueSearch_TabIcon
static FName GetStyleSetName()
static TSharedPtr< SDockTab > InvokeTab(TSharedPtr< FTabManager > TabManager, const FTabId &TabID)
Definition DlgHelper.cpp:90
const TArray< UEdGraphNode * > & GetAllGraphNodes() const
UDialogueGraphNode * GetChildNode() const
const FDlgEdge & GetDialogueEdge() const
UDialogueGraphNode * GetParentNode() const
virtual int32 GetDialogueNodeIndex() const
const DlgNodeType & GetDialogueNode() const
virtual bool IsRootNode() const
UCLASS(BlueprintType, Meta = (DisplayThumbnail = "true"))
Definition DlgDialogue.h:85
FGuid GetGUID() const
UFUNCTION(BlueprintPure, Category = "Dialogue|GUID")
static TArray< UDlgDialogue * > GetAllDialoguesFromMemory()
UCLASS(BlueprintType, ClassGroup = "Dialogue")
UCLASS(BlueprintType, Abstract, EditInlineNew, ClassGroup = "Dialogue")
Definition DlgNode.h:40
virtual const TArray< FDlgTextArgument > & GetTextArguments() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:254
FGuid GetGUID() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:105
virtual FName GetNodeParticipantName() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:127
virtual const TArray< FDlgEvent > & GetNodeEnterEvents() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:170
virtual UDlgNodeData * GetNodeData() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:323
virtual FName GetSpeakerState() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:309
virtual const FText & GetNodeUnformattedText() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:281
virtual const TArray< FDlgCondition > & GetNodeEnterConditions() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
Definition DlgNode.h:145
TWeakObjectPtr< UDlgDialogue > Dialogue
USTRUCT(Blueprintable)
float FloatValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
UDlgConditionCustom * CustomCondition
UPROPERTY(Instanced, EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FName OtherParticipantName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FGuid GUID
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
int32 IntValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FName OtherVariableName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FName NameValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FName ParticipantName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
FName CallbackName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Condition")
USTRUCT(BlueprintType)
Definition DlgEdge.h:25
TArray< FDlgCondition > Conditions
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Edge")
Definition DlgEdge.h:134
const FText & GetUnformattedText() const
Definition DlgEdge.h:103
FName SpeakerState
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Edge")
Definition DlgEdge.h:142
const TArray< FDlgTextArgument > & GetTextArguments() const
Definition DlgEdge.h:76
USTRUCT(BlueprintType)
Definition DlgEvent.h:59
int32 IntValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Event")
Definition DlgEvent.h:156
FName NameValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Event")
Definition DlgEvent.h:172
FName EventName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Event")
Definition DlgEvent.h:148
UDlgEventCustom * CustomEvent
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Dialogue|Event")
Definition DlgEvent.h:200
float FloatValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Event")
Definition DlgEvent.h:164
FName ParticipantName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Event")
Definition DlgEvent.h:132
USTRUCT(BlueprintType)
FText Text
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Node", Meta = (MultiLine = true))
FName Speaker
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Node", Meta = (DisplayName = "Partic...
FName SpeakerState
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Node")
FText EdgeText
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|Node", Meta = (MultiLine = true))
USTRUCT(BlueprintType)
UDlgTextArgumentCustom * CustomTextArgument
UPROPERTY(Instanced, EditAnywhere, BlueprintReadWrite, Category = "Dialogue|TextArgument")
FString DisplayString
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Dialogue|TextArgument")
FName ParticipantName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|TextArgument")
FName VariableName
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dialogue|TextArgument")