A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DlgHelper.h
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#pragma once
3
4#include "CoreMinimal.h"
5#include "Math/UnrealMathUtility.h"
6#include "UObject/Object.h"
7#include "UObject/UnrealType.h"
8#include "UObject/ObjectMacros.h"
9#include <functional>
10
11#include "DlgCondition.h"
12#include "DlgEvent.h"
13#include "NYReflectionTypes.h"
14
15#include "DlgHelper.generated.h"
16
17class SDockTab;
18class FTabManager;
19struct FTabId;
21
22USTRUCT()
24{
25 GENERATED_USTRUCT_BODY()
26public:
27 UPROPERTY()
28 UClass* Class = nullptr;
29
30 UPROPERTY()
31 UObject* Object = nullptr;
32};
33
34// Const version of FScriptArrayHelper
36{
37 typedef FScriptArrayHelper Super;
38 typedef FDlgConstScriptArrayHelper Self;
39public:
40 FORCEINLINE FDlgConstScriptArrayHelper(const FNYArrayProperty* InProperty, const void *InArray)
41 : Super(InProperty, InArray) {}
42
43 FORCEINLINE const uint8* GetConstRawPtr(int32 Index = 0) const
44 {
45 return const_cast<Self*>(this)->GetRawPtr(Index);
46 }
47};
48
50// Const version of FScriptMapHelper
52{
53 typedef FScriptMapHelper Super;
55public:
56
57 FORCEINLINE FDlgConstScriptMapHelper(const FNYMapProperty* InProperty, const void* InMap)
58 : Super(InProperty, InMap) {}
61 FORCEINLINE const uint8* GetConstKeyPtr(int32 Index) const
62 {
63 return const_cast<Self*>(this)->GetKeyPtr(Index);
64 }
65
66 FORCEINLINE const uint8* GetConstValuePtr(int32 Index) const
67 {
68 return const_cast<Self*>(this)->GetValuePtr(Index);
69 }
70};
71
77template <typename KeyType, typename ValueType>
79{
80public:
81 static bool IsEqual(
82 const TMap<KeyType, ValueType>& FirstMap,
83 const TMap<KeyType, ValueType>& SecondMap,
84 std::function<bool(const ValueType& FirstMapValue,
85 const ValueType& SecondMapValue)> AreValuesEqual
86 )
87 {
88 if (FirstMap.Num() == SecondMap.Num())
89 {
90 for (const auto& ElemFirstMap : FirstMap)
91 {
92 const auto* FoundValueSecondMap = SecondMap.Find(ElemFirstMap.Key);
93 if (FoundValueSecondMap != nullptr)
94 {
95 // Key exists in second map
96 if (!AreValuesEqual(ElemFirstMap.Value, *FoundValueSecondMap))
97 {
98 // Value differs
99 return false;
100 }
101 }
102 else
103 {
104 // Key does not even exist
105 return false;
106 }
107 }
108
109 return true;
110 }
111
112 // Length differs
113 return false;
114 }
115};
116
117// Variant with default comparison
118template <typename KeyType, typename ValueType>
120{
121public:
122 static bool IsEqual(const TMap<KeyType, ValueType>& FirstMap, const TMap<KeyType, ValueType>& SecondMap)
123 {
125 [](const ValueType& FirstMapValue, const ValueType& SecondMapValue) -> bool
126 {
127 return FirstMapValue == SecondMapValue;
128 });
129 }
130};
131
132// Variant with Specialization for float ValueType
133template <typename KeyType>
134class FDlgHelper_MapEqualVariantImpl<KeyType, float>
135{
136public:
137 static bool IsEqual(const TMap<KeyType, float>& FirstMap, const TMap<KeyType, float>& SecondMap)
138 {
139 return FDlgHelper_MapEqualImpl<KeyType, float>::IsEqual(FirstMap, SecondMap,
140 [](const float& FirstMapValue, const float& SecondMapValue) -> bool
141 {
142 return FMath::IsNearlyEqual(FirstMapValue, SecondMapValue, KINDA_SMALL_NUMBER);
143 });
144 }
145};
146
147
148template <typename ArrayType>
150{
151public:
152 static bool IsEqual(
153 const TArray<ArrayType>& FirstArray,
154 const TArray<ArrayType>& SecondArray,
155 std::function<bool(const ArrayType& FirstValue,
156 const ArrayType& SecondValue)> AreValuesEqual
157 )
159 if (FirstArray.Num() == SecondArray.Num())
160 {
161 // Some value is not equal
162 for (int32 Index = 0; Index < FirstArray.Num(); Index++)
163 {
164 if (!AreValuesEqual(FirstArray[Index], SecondArray[Index]))
165 {
166 return false;
167 }
168 }
169
170 return true;
171 }
172
173 // length differs
174 return false;
175 }
176};
177
178// Variant with default comparison
179template <typename ArrayType>
181{
182public:
183 static bool IsEqual(const TArray<ArrayType>& FirstArray, const TArray<ArrayType>& SecondArray)
184 {
185 return FDlgHelper_ArrayEqualImpl<ArrayType>::IsEqual(FirstArray , SecondArray,
186 [](const ArrayType& FirstValue, const ArrayType& SecondValue) -> bool
187 {
188 return FirstValue == SecondValue;
189 });
190 }
191};
192
193// Variant with Specialization for float ArrayType
194template <>
196{
197public:
198 static bool IsEqual(const TArray<float>& FirstArray, const TArray<float>& SecondArray)
199 {
200 return FDlgHelper_ArrayEqualImpl<float>::IsEqual(FirstArray, SecondArray,
201 [](const float& FirstValue, const float& SecondValue) -> bool
202 {
203 return FMath::IsNearlyEqual(FirstValue, SecondValue, KINDA_SMALL_NUMBER);
204 });
205 }
206};
207
208
212class DLGSYSTEM_API FDlgHelper
213{
214 typedef FDlgHelper Self;
215public:
216 FORCEINLINE static int64 RandomInt64() { return static_cast<int64>(FMath::Rand()) << 32 | FMath::Rand(); }
217 FORCEINLINE static bool IsFloatEqual(const float A, const float B) { return FMath::IsNearlyEqual(A, B, KINDA_SMALL_NUMBER); }
218 FORCEINLINE static bool IsPathInProjectDirectory(const FString& Path) { return Path.StartsWith("/Game"); }
219
220 static FString GetFullNameFromObject(const UObject* Object)
221 {
222 if (!IsValid(Object))
224 return TEXT("nullptr");
225 }
226 return Object->GetFullName();
227 }
228
229 static FString GetClassNameFromObject(const UObject* Object)
230 {
231 if (!IsValid(Object))
232 {
233 return TEXT("INVALID CLASS");
234 }
235 return Object->GetClass()->GetName();
236 }
237
245 static TSharedPtr<SDockTab> InvokeTab(TSharedPtr<FTabManager> TabManager, const FTabId& TabID);
246
247 // Removes _C from the end of the Name
248 // And removes the .extension from the path names
249 static FString CleanObjectName(FString Name);
250
251 // Blueprint Helpers
252 static bool IsClassIgnored(const UClass* Class);
253 static bool IsABlueprintClass(const UClass* Class);
254 static bool IsABlueprintObject(const UObject* Object);
255
256 // This also works with Blueprints
257 static bool IsObjectAChildOf(const UObject* Object, const UClass* ParentClass);
258
259 // This also works with Blueprints
260 static bool IsObjectImplementingInterface(const UObject* Object, const UClass* InterfaceClass);
261
262 // Gets all child classes of ParentClass
263 // NOTE: this is super slow, use with care
264 static bool GetAllChildClassesOf(const UClass* ParentClass, TArray<UClass*>& OutNativeClasses, TArray<UClass*>& OutBlueprintClasses);
265
266 // Gets all classes that implement InterfaceClass
267 // NOTE: this is super slow, use with care
268 static bool GetAllClassesImplementingInterface(const UClass* InterfaceClass, TArray<UClass*>& OutNativeClasses, TArray<UClass*>& OutBlueprintClasses);
269
270 // Converts the Classes Array that represent the Dialogue Participants into a map where
271 // Key: The participant Name
272 // Value: An array of structs that contain the class and the object for that participant name
273 static TMap<FName, TArray<FDlgClassAndObject>> ConvertDialogueParticipantsClassesIntoMap(const TArray<UClass*>& Classes);
274
275 // FileSystem
276 static bool DeleteFile(const FString& PathName, bool bVerbose = true);
277 static bool RenameFile(const FString& OldPathName, const FString& NewPathName, bool bOverWrite = false, bool bVerbose = true);
278
279 // Get the Interface Function Name for this Event Type
280 static FName GetFunctionNameForEventType(EDlgEventType EventType)
281 {
282 switch (EventType)
283 {
285 return TEXT("OnDialogueEvent");
287 return TEXT("ModifyBoolValue");
289 return TEXT("ModifyFloatValue");
291 return TEXT("ModifyIntValue");
293 return TEXT("ModifyIntValue");
294 default:
295 break;
296 }
297
298 return NAME_None;
299 }
300
301 static FName GetFunctionNameForConditionType(EDlgConditionType ConditionType)
302 {
303 switch (ConditionType)
304 {
306 return TEXT("CheckCondition");
308 return TEXT("GetBoolValue");
310 return TEXT("GetFloatValue");
312 return TEXT("GetIntValue");
314 return TEXT("GetNameValue");
315 default:
316 break;
317 }
318
319 return NAME_None;
320 }
321
322 template<typename TEnum>
323 static bool ConvertEnumToString(const FString& EnumName, TEnum EnumValue, bool bWithNameSpace, FString& OutEnumValue)
324 {
325 const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *EnumName, true);
326 if (!EnumPtr)
327 {
328 OutEnumValue = FString::Printf(TEXT("INVALID EnumName = `%s`"), *EnumName);
329 return false;
330 }
331
332 OutEnumValue = bWithNameSpace ? EnumPtr->GetNameByIndex(static_cast<int32>(EnumValue)).ToString()
333 : EnumPtr->GetNameStringByIndex(static_cast<int32>(EnumValue));
334 return true;
335 }
336
337 template<typename TEnum>
338 static bool ConvertStringToEnum(const FString& String, const FString& EnumName, TEnum& OutEnumValue)
339 {
340 const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *EnumName, true);
341 if (!EnumPtr)
342 {
343 return false;
345
346 const int32 Index = EnumPtr->GetIndexByNameString(String);
347 OutEnumValue = static_cast<TEnum>(Index);
348 return true;
349 }
350
351 template<typename TEnum>
352 static bool ConvertFNameToEnum(FName Name, const FString& EnumName, TEnum& OutEnumValue)
353 {
354 const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *EnumName, true);
355 if (!EnumPtr)
356 {
357 return false;
359
360 const int32 Index = EnumPtr->GetIndexByName(Name);
361 OutEnumValue = static_cast<TEnum>(Index);
362 return true;
363 }
364
365 // Gets the first element from a set. From https://answers.unrealengine.com/questions/332443/how-to-get-the-firstonly-element-in-tset.html
366 template <typename SetType>
367 static typename TCopyQualifiersFromTo<SetType, typename SetType::ElementType>::Type* GetFirstSetElement(SetType& Set)
368 {
369 for (auto& Element : Set)
370 {
371 return &Element;
372 }
374 return nullptr;
375 }
376
377 // Is FirstSet == SecondSet
378 // NOTE for SetType = float this won't work, what are you even doing?
379 template <typename SetType>
380 static bool IsSetEqual(const TSet<SetType>& FirstSet, const TSet<SetType>& SecondSet)
381 {
382 if (FirstSet.Num() == SecondSet.Num())
383 {
384 // No duplicates should be found
385 TSet<SetType> Set = FirstSet;
386 Set.Append(SecondSet);
387
388 return Set.Num() == FirstSet.Num();
389 }
390
391 return false;
392 }
393
394 // Is FirstArray == SecondArray ?
395 template <typename ArrayType>
396 static bool IsArrayEqual(const TArray<ArrayType>& FirstArray, const TArray<ArrayType>& SecondArray,
397 std::function<bool(const ArrayType& FirstValue, const ArrayType& SecondValue)> AreValuesEqual)
398 {
399 return FDlgHelper_ArrayEqualImpl<ArrayType>::IsEqual(FirstArray, SecondArray, AreValuesEqual);
400 }
401
402 // Variant with default comparison
403 template <typename ArrayType>
404 static bool IsArrayEqual(const TArray<ArrayType>& FirstArray, const TArray<ArrayType>& SecondArray)
405 {
406 return FDlgHelper_ArrayEqualVariantImpl<ArrayType>::IsEqual(FirstArray, SecondArray);
407 }
408
409 // Variant with pointer value comparison
410 template <typename ArrayType>
411 static bool IsArrayOfPointersEqual(const TArray<ArrayType*>& FirstArray, const TArray<ArrayType*>& SecondArray)
412 {
413 return FDlgHelper_ArrayEqualImpl<ArrayType*>::IsEqual(FirstArray, SecondArray,
414 [](const auto* FirstValue, const auto* SecondValue) -> bool
415 {
416 if (FirstValue == nullptr)
418 return SecondValue == nullptr;
419 }
420 return *FirstValue == *SecondValue;
421 });
422 }
423
424 // Is FirstMap == SecondMap ?
425 template <typename KeyType, typename ValueType>
426 static bool IsMapEqual(const TMap<KeyType, ValueType>& FirstMap, const TMap<KeyType, ValueType>& SecondMap,
427 std::function<bool(const ValueType& FirstMapValue, const ValueType& SecondMapValue)> AreValuesEqual)
428 {
429 return FDlgHelper_MapEqualImpl<KeyType, ValueType>::IsEqual(FirstMap, SecondMap, AreValuesEqual);
430 }
431
432 // Variant with default comparison
433 template <typename KeyType, typename ValueType>
434 static bool IsMapEqual(const TMap<KeyType, ValueType>& FirstMap, const TMap<KeyType, ValueType>& SecondMap)
435 {
437 }
438
439 // Default comparison function
440 static bool PredicateSortFNameAlphabeticallyAscending(FName A, FName B)
441 {
442 return A.Compare(B) < 0;
443 }
444
446 static void SortDefault(TArray<FName>& OutArray)
447 {
448 OutArray.Sort(PredicateSortFNameAlphabeticallyAscending);
449 }
450 static void SortDefault(TSet<FName>& OutSet)
451 {
452 OutSet.Sort(PredicateSortFNameAlphabeticallyAscending);
453 }
454
455 template<typename ValueType>
456 static void SortDefault(TMap<FName, ValueType>& Map)
457 {
458 Map.KeySort(PredicateSortFNameAlphabeticallyAscending);
459 }
460
462 static void AppendSortedSetToArray(const TSet<FName>& InSet, TArray<FName>& OutArray)
463 {
464 TArray<FName> UniqueNamesArray = InSet.Array();
465 SortDefault(UniqueNamesArray);
466 OutArray.Append(UniqueNamesArray);
467 }
469 FORCEINLINE static bool IsPossiblyAllocatedUObjectPointer(const void* Ptr)
470 {
471 auto CountByteValues = [](UPTRINT Val, UPTRINT ByteVal) -> int32
472 {
473 int32 Result = 0;
474
475 for (int32 I = 0; I != sizeof(UPTRINT); ++I)
476 {
477 if ((Val & 0xFF) == ByteVal)
478 {
479 ++Result;
480 }
481 Val >>= 8;
482 }
483
484 return Result;
485 };
486
487 const UPTRINT PtrVal = (UPTRINT)Ptr;
488 // (void*) - 1 Is technically a valid address 0xffffffff, but is it?
489 return Ptr != nullptr && Ptr != ((void*) - 1) && PtrVal >= 0x1000 && CountByteValues(PtrVal, 0xCD) < sizeof(UPTRINT) / 2;
490 }
491
493 static bool IsValidLowLevel(const UObject* Object)
494 {
495 if (Object == nullptr)
496 {
497 return false;
498 }
500 // From IsValidLowLevelFast
501 // Check pointer range, may the gods have mercy
502 if (!::IsPossiblyAllocatedUObjectPointer(const_cast<UObject*>(Object)))
503 {
504 return false;
505 }
506
507 // As DEFAULT_ALIGNMENT is defined to 0 now, I changed that to the original numerical value here
508 static const int32 AlignmentCheck = MIN_ALIGNMENT - 1;
509 if ((UPTRINT)Object & AlignmentCheck)
510 {
511 return false;
512 }
513 //if (!FDlgHelper::IsPossiblyAllocatedUObjectPointer((void**)Object) || !FDlgHelper::IsPossiblyAllocatedUObjectPointer(*(void**)Object))
514 //{
515 // return false;
516 //}
517
518 // Virtual functions table is invalid.
519 if ((void**)Object == nullptr || *(void**)Object == nullptr)
520 {
521 return false;
522 }
523
524 if (!Object->IsValidLowLevelFast())
525 {
526 return false;
527 }
528
529 return !Object->IsPendingKillOrUnreachable();
530 }
531};
EDlgConditionType
UENUM(BlueprintType)
EDlgEventType
UENUM(BlueprintType)
Definition DlgEvent.h:16
UMapProperty FNYMapProperty
UArrayProperty FNYArrayProperty
FScriptArrayHelper Super
Definition DlgHelper.h:43
FDlgConstScriptArrayHelper Self
Definition DlgHelper.h:44
FORCEINLINE FDlgConstScriptArrayHelper(const FNYArrayProperty *InProperty, const void *InArray)
Definition DlgHelper.h:46
FORCEINLINE const uint8 * GetConstRawPtr(int32 Index=0) const
Definition DlgHelper.h:49
FDlgConstScriptMapHelper Self
Definition DlgHelper.h:60
FORCEINLINE FDlgConstScriptMapHelper(const FNYMapProperty *InProperty, const void *InMap)
Definition DlgHelper.h:63
FORCEINLINE const uint8 * GetConstValuePtr(int32 Index) const
Definition DlgHelper.h:72
FScriptMapHelper Super
Definition DlgHelper.h:59
FORCEINLINE const uint8 * GetConstKeyPtr(int32 Index) const
Definition DlgHelper.h:67
static bool IsEqual(const TArray< ArrayType > &FirstArray, const TArray< ArrayType > &SecondArray, std::function< bool(const ArrayType &FirstValue, const ArrayType &SecondValue)> AreValuesEqual)
Definition DlgHelper.h:158
static bool IsEqual(const TArray< float > &FirstArray, const TArray< float > &SecondArray)
Definition DlgHelper.h:204
static bool IsEqual(const TArray< ArrayType > &FirstArray, const TArray< ArrayType > &SecondArray)
Definition DlgHelper.h:189
static bool IsEqual(const TMap< KeyType, ValueType > &FirstMap, const TMap< KeyType, ValueType > &SecondMap, std::function< bool(const ValueType &FirstMapValue, const ValueType &SecondMapValue)> AreValuesEqual)
Definition DlgHelper.h:87
static bool IsEqual(const TMap< KeyType, float > &FirstMap, const TMap< KeyType, float > &SecondMap)
Definition DlgHelper.h:143
static bool IsEqual(const TMap< KeyType, ValueType > &FirstMap, const TMap< KeyType, ValueType > &SecondMap)
Definition DlgHelper.h:128
static FORCEINLINE bool IsPathInProjectDirectory(const FString &Path)
Definition DlgHelper.h:224
static bool IsArrayOfPointersEqual(const TArray< ArrayType * > &FirstArray, const TArray< ArrayType * > &SecondArray)
Definition DlgHelper.h:417
static bool ConvertStringToEnum(const FString &String, const FString &EnumName, TEnum &OutEnumValue)
Definition DlgHelper.h:344
static bool ConvertEnumToString(const FString &EnumName, TEnum EnumValue, bool bWithNameSpace, FString &OutEnumValue)
Definition DlgHelper.h:329
static FORCEINLINE bool IsFloatEqual(const float A, const float B)
Definition DlgHelper.h:223
static bool IsValidLowLevel(const UObject *Object)
Definition DlgHelper.h:499
static bool IsMapEqual(const TMap< KeyType, ValueType > &FirstMap, const TMap< KeyType, ValueType > &SecondMap)
Definition DlgHelper.h:440
static void SortDefault(TArray< FName > &OutArray)
Definition DlgHelper.h:452
static FString GetFullNameFromObject(const UObject *Object)
Definition DlgHelper.h:226
static FName GetFunctionNameForConditionType(EDlgConditionType ConditionType)
Definition DlgHelper.h:307
static bool IsSetEqual(const TSet< SetType > &FirstSet, const TSet< SetType > &SecondSet)
Definition DlgHelper.h:386
static bool PredicateSortFNameAlphabeticallyAscending(FName A, FName B)
Definition DlgHelper.h:446
FDlgHelper Self
Definition DlgHelper.h:220
static FString GetClassNameFromObject(const UObject *Object)
Definition DlgHelper.h:235
static FName GetFunctionNameForEventType(EDlgEventType EventType)
Definition DlgHelper.h:286
static void AppendSortedSetToArray(const TSet< FName > &InSet, TArray< FName > &OutArray)
Definition DlgHelper.h:468
static TCopyQualifiersFromTo< SetType, typenameSetType::ElementType >::Type * GetFirstSetElement(SetType &Set)
Definition DlgHelper.h:373
static void SortDefault(TMap< FName, ValueType > &Map)
Definition DlgHelper.h:462
static bool ConvertFNameToEnum(FName Name, const FString &EnumName, TEnum &OutEnumValue)
Definition DlgHelper.h:358
static void SortDefault(TSet< FName > &OutSet)
Definition DlgHelper.h:456
static FORCEINLINE bool IsPossiblyAllocatedUObjectPointer(const void *Ptr)
Definition DlgHelper.h:475
static bool IsArrayEqual(const TArray< ArrayType > &FirstArray, const TArray< ArrayType > &SecondArray)
Definition DlgHelper.h:410
static bool IsArrayEqual(const TArray< ArrayType > &FirstArray, const TArray< ArrayType > &SecondArray, std::function< bool(const ArrayType &FirstValue, const ArrayType &SecondValue)> AreValuesEqual)
Definition DlgHelper.h:402
static bool IsMapEqual(const TMap< KeyType, ValueType > &FirstMap, const TMap< KeyType, ValueType > &SecondMap, std::function< bool(const ValueType &FirstMapValue, const ValueType &SecondMapValue)> AreValuesEqual)
Definition DlgHelper.h:432
static FORCEINLINE int64 RandomInt64()
Definition DlgHelper.h:222
UCLASS(Config = Engine, DefaultConfig, meta = (DisplayName = "Dialogue System Settings"))
UObject * Object
UPROPERTY()
Definition DlgHelper.h:37
UClass * Class
UPROPERTY()
Definition DlgHelper.h:32