4#include "Logging/LogMacros.h"
5#include "Misc/FileHelper.h"
7#include "UObject/UnrealType.h"
8#include "UObject/EnumProperty.h"
9#include "UObject/UObjectIterator.h"
10#include "UObject/TextProperty.h"
38 if (!FFileHelper::LoadFileToString(
String, *FilePath))
40 UE_LOG(LogDlgConfigParser,
Error, TEXT(
"Failed to load config file %s"), *FilePath)
48 FileName = FPaths::GetBaseFilename(FilePath,
true);
65 while (
ReadProperty(ReferenceClass, TargetObject, DefaultObjectOuter));
87 auto* PropertyBase = ReferenceClass->FindPropertyByName(*PropertyName);
88 if (PropertyBase !=
nullptr)
97 auto* MapProperty = FNYReflectionHelper::CastProperty<FNYMapProperty>(PropertyBase);
98 if (MapProperty !=
nullptr)
100 return ReadMap(TargetObject, *MapProperty, DefaultObjectOuter);
104 auto* SetProperty = FNYReflectionHelper::CastProperty<FNYSetProperty>(PropertyBase);
105 if (SetProperty !=
nullptr)
107 return ReadSet(TargetObject, *SetProperty, DefaultObjectOuter);
111 auto* ComplexPropBase = ReferenceClass->FindPropertyByName(*PropertyName);
114 if (
auto* StructProperty = FNYReflectionHelper::SmartCastProperty<FNYStructProperty>(ComplexPropBase))
116 return ReadComplexProperty<FNYStructProperty>(TargetObject,
118 StructProperty->Struct,
119 [](
void* Ptr,
const UClass*,
UObject*) { return Ptr; },
124 const FString TypeName =
PreTag + PropertyName;
137 if (FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(ComplexPropBase) ==
nullptr)
142 auto* ObjectPtrPtr =
static_cast<UObject**
>(ComplexPropBase->template ContainerPtrToValuePtr<void>(TargetObject));
143 *ObjectPtrPtr =
nullptr;
144 if (!VariableName.TrimStartAndEnd().IsEmpty())
146 *ObjectPtrPtr = StaticLoadObject(UObject::StaticClass(), DefaultObjectOuter, *VariableName);
157 ComplexPropBase = ReferenceClass->FindPropertyByName(*PropertyName);
161 ComplexPropBase = ReferenceClass->FindPropertyByName(*VariableName);
163 if (
auto* ObjectProperty = FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(ComplexPropBase))
166 if (Class ==
nullptr)
171 return ReadComplexProperty<FNYObjectProperty>(TargetObject, ComplexPropBase, Class, ObjectInitializer, DefaultObjectOuter);
174 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Invalid token `%s` in script `%s` (line: %d) (Property expected for PropertyName = `%s`)"),
213 if (FloatString.Len() == 0 || !FloatString.IsNumeric())
240 while (Index <
String.Len() && FChar::IsWhitespace(
String[Index]))
251 const int32 Index =
From - 1;
252 return String.IsValidIndex(Index) &&
String[Index] ==
'"';
357 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Unexpected end of file while reading %s (expected: %s)"), *
FileName, *ExpectedStuff);
368 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Block start signal expected but not found for %s block in script %s (line: %d)"),
380 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"End of file found but block %s is not yet closed in script %s (line: %d)"),
392 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"End of file found but block %s is not yet closed in script %s (line: %d)"),
410 for (int32 i = 0; i <
Len; ++i)
412 if (SubStr[i] != StringToCompare[i])
430 for (int32 i = 0; i <
String.Len() && i <
From; ++i)
455 auto* BoolProp = FNYReflectionHelper::CastProperty<FNYBoolProperty>(Field);
456 if (BoolProp !=
nullptr)
458 OutString += BoolProp->GetName() +
" " + (BoolProp->GetPropertyValue_InContainer(SourceObject) ?
"True\n" :
"False\n");
466 if (ReadPrimitiveProperty<bool, FNYBoolProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsBool,
this),
"Bool",
false))
470 if (ReadPrimitiveProperty<float, FNYFloatProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsFloat,
this),
"float",
false))
474 if (ReadPrimitiveProperty<int32, FNYIntProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsInt32,
this),
"int32",
false))
478 if (ReadPrimitiveProperty<int64, FNYInt64Property>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsInt64,
this),
"int64",
false))
482 if (ReadPrimitiveProperty<FName, FNYNameProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsName,
this),
"FName",
false))
486 if (ReadPrimitiveProperty<FString, FNYStrProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsString,
this),
"FString",
true))
490 if (ReadPrimitiveProperty<FText, FNYTextProperty>(TargetObject, PropertyBase, std::bind(&
FDlgConfigParser::GetAsText,
this),
"FText",
true))
501 auto OnGetAsEnum = [
this, &PropertyBase]() -> uint8
503 FName Value = NAME_None;
513 auto* Prop = FNYReflectionHelper::SmartCastProperty<FNYEnumProperty>(PropertyBase);
514 if (Prop ==
nullptr || Prop->GetEnum() ==
nullptr)
519 check(FNYReflectionHelper::CastProperty<FNYByteProperty>(Prop->GetUnderlyingProperty()));
520 return uint8(Prop->GetEnum()->GetIndexByName(Value));
524 auto* EnumProp = FNYReflectionHelper::CastProperty<FNYEnumProperty>(PropertyBase);
525 if (EnumProp !=
nullptr)
531 void* Value = EnumProp->ContainerPtrToValuePtr<uint8>(Target);
532 EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(Value,
static_cast<int64
>(OnGetAsEnum()));
536 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Unexpected end of file while enum value was expected (config %s)"), *
FileName);
549 FScriptSetHelper Helper(&Property, Property.ContainerPtrToValuePtr<uint8>(TargetObject));
550 Helper.EmptyElements();
559 const int32 Index = Helper.AddDefaultValue_Invalid_NeedsRehash();
561 uint8* ElementPtr = Helper.GetElementPtr(Index);
562 if (FNYReflectionHelper::CastProperty<FNYBoolProperty>(Helper.ElementProp)) { *(
bool*)ElementPtr =
GetAsBool(); bDone =
true; }
563 else if (FNYReflectionHelper::CastProperty<FNYFloatProperty>(Helper.ElementProp)) { *(
float*)ElementPtr =
GetAsFloat(); bDone =
true; }
564 else if (FNYReflectionHelper::CastProperty<FNYIntProperty>(Helper.ElementProp)) { *(int32*)ElementPtr =
GetAsInt32(); bDone =
true; }
565 else if (FNYReflectionHelper::CastProperty<FNYInt64Property>(Helper.ElementProp)) { *(int64*)ElementPtr =
GetAsInt64(); bDone =
true; }
566 else if (FNYReflectionHelper::CastProperty<FNYNameProperty>(Helper.ElementProp)) { *(FName*)ElementPtr =
GetAsName(); bDone =
true; }
567 else if (FNYReflectionHelper::CastProperty<FNYStrProperty>(Helper.ElementProp)) { *(FString*)ElementPtr =
GetAsString(); bDone =
true; }
568 else if (FNYReflectionHelper::CastProperty<FNYTextProperty>(Helper.ElementProp)) { *(
FText*)ElementPtr =
GetAsText(); bDone =
true; }
573 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Unsupported set element type %s in script %s(:%d)"),
586 FScriptMapHelper Helper(&Property, Property.ContainerPtrToValuePtr<uint8>(TargetObject));
587 Helper.EmptyValues();
596 const int32 Index = Helper.AddDefaultValue_Invalid_NeedsRehash();
597 void* Ptrs[] = { Helper.GetKeyPtr(Index), Helper.GetValuePtr(Index) };
598 FNYProperty* Props[] = { Helper.KeyProp, Helper.ValueProp };
601 for (int32 i = 0; i < 2; ++i)
603 if (FNYReflectionHelper::CastProperty<FNYBoolProperty>(Props[i])) { *(
bool*)Ptrs[i] =
GetAsBool(); bDone =
true; }
604 else if (FNYReflectionHelper::CastProperty<FNYFloatProperty>(Props[i])) { *(
float*)Ptrs[i] =
GetAsFloat(); bDone =
true; }
605 else if (FNYReflectionHelper::CastProperty<FNYIntProperty>(Props[i])) { *(int32*)Ptrs[i] =
GetAsInt32(); bDone =
true; }
606 else if (FNYReflectionHelper::CastProperty<FNYInt64Property>(Props[i])) { *(int64*)Ptrs[i] =
GetAsInt64(); bDone =
true; }
607 else if (FNYReflectionHelper::CastProperty<FNYNameProperty>(Props[i])) { *(FName*)Ptrs[i] =
GetAsName(); bDone =
true; }
608 else if (FNYReflectionHelper::CastProperty<FNYStrProperty>(Props[i])) { *(FString*)Ptrs[i] =
GetAsString(); bDone =
true; }
609 else if (FNYReflectionHelper::CastProperty<FNYTextProperty>(Props[i])) { *(
FText*)Ptrs[i] =
GetAsText(); bDone =
true; }
613 auto* StructVal = FNYReflectionHelper::CastProperty<FNYStructProperty>(Props[i]);
614 if (StructVal !=
nullptr)
618 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Syntax error: missing struct block start '{' in script %s(:%d)"),
650 if (ChildClass !=
nullptr)
657 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"OnInitValue called without class!"));
664 auto* ObjectProperty = FNYReflectionHelper::SmartCastProperty<FNYObjectProperty>(Property);
665 check(ObjectProperty !=
nullptr);
667 const UClass* Class =
nullptr;
668 if (FNYReflectionHelper::CastProperty<FNYArrayProperty>(Property) !=
nullptr)
670 Class = ObjectProperty->PropertyClass;
677 if (Class ==
nullptr)
679 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Could not find class `%s` for `%s` in config `%s` (Line=%d)"),
692 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Invalid %s property value %s in script %s (line %d)"),
696 UE_LOG(LogDlgConfigParser,
Warning, TEXT(
"Unexepcted end of file while expecting %s value in script %s"), *PropType, *
FileName);
723 if (IntString.Len() == 0 || (!IntString.IsNumeric()))
726 Value = FCString::Atoi(*IntString);
735 if (IntString.Len() == 0 || (!IntString.IsNumeric()))
738 Value = FCString::Atoi64(*IntString);
745 FName Value = NAME_None;
769 return FText::FromString(Input);
DEFINE_LOG_CATEGORY(LogDlgConfigParser)
UMapProperty FNYMapProperty
USetProperty FNYSetProperty
static void ConstructConfigFileInternal(const UStruct *ReferenceType, int32 TabCount, void *SourceObject, FString &OutString)
bool IsActualWordString() const
bool GetActiveWordAsFloat(float &FloatValue) const
bool CompareToActiveWord(const FString &StringToCompare) const
FString GetActiveWord() const
static FString ConstructConfigFile(const UStruct *ReferenceType, void *SourceObject)
bool IsNextWordString() const
void InitializeParser(const FString &FilePath) override
bool FindNextWordAndCheckIfBlockEnd(const FString &BlockName)
bool CheckIfBlockEnd(const FString &BlockName)
bool ReadPurePropertyBlock(void *TargetObject, const UStruct *ReferenceClass, bool bBlockStartAlreadyRead=false, UObject *DefaultObjectOuter=nullptr)
void ReadAllProperty(const UStruct *ReferenceClass, void *TargetObject, UObject *DefaultObjectOuter=nullptr) override
void * OnInitObject(void *ValuePtr, const UClass *ChildClass, UObject *OuterInit)
bool ReadProperty(const UStruct *ReferenceClass, void *TargetObject, UObject *DefaultObjectOuter=nullptr)
FString GetAsString() const
bool TryToReadPrimitiveProperty(void *Target, FNYProperty *PropertyBase)
bool FindNextWordAndCheckIfBlockStart(const FString &BlockName)
bool ReadMap(void *TargetObject, FNYMapProperty &Property, UObject *DefaultObjectOuter)
void InitializeParserFromString(const FString &Text) override
FDlgConfigParser(const FString InPreTag="")
const UClass * SmartGetPropertyClass(FNYProperty *Property, const FString &TypeName)
bool ReadSet(void *TargetObject, FNYSetProperty &Property, UObject *DefaultObjectOuter)
bool TryToReadEnum(void *TargetObject, FNYProperty *PropertyBase)
int32 GetActiveLineNumber() const
void OnInvalidValue(const FString &PropType) const
bool HasValidWord() const
static FORCEINLINE UField * GetStructChildren(const UStruct *Struct)
const UClass * GetChildClassFromName(const UClass *ParentClass, const FString &Name)
static UObject * CreateNewUObject(const UClass *StructDefinition, UObject *ObjectOuter)