void GetInterpPropertyNames(UObject* InObject, const FString& Prefix) { UClass* ObjectClass = InObject->GetClass(); // First search for any properties in this object for (TFieldIterator<UProperty> ClassFieldIt(ObjectClass); ClassFieldIt; ++ClassFieldIt) { UProperty* ClassMemberProperty = *ClassFieldIt; if (ClassMemberProperty->HasAnyPropertyFlags(CPF_Interp)) { // Is this property the desired type? if (IsDesiredProperty(ClassMemberProperty)) { const FString QualifiedFullPath = FString::Printf(TEXT("%s%s"), *Prefix, *ClassMemberProperty->GetName()); GatheredPropertyPaths.Add(*QualifiedFullPath); } // If this is a struct, look for any desired properties inside of it if (UStructProperty* OuterStructProperty = Cast<UStructProperty>(ClassMemberProperty)) { for (TFieldIterator<UProperty> StructFieldIt(OuterStructProperty->Struct); StructFieldIt; ++StructFieldIt) { UProperty* StructMemberProperty = *StructFieldIt; if (StructMemberProperty->HasAnyPropertyFlags(CPF_Interp) && IsDesiredProperty(StructMemberProperty)) { const FString QualifiedFullPath = FString::Printf(TEXT("%s%s.%s"), *Prefix, *OuterStructProperty->GetName(), *StructMemberProperty->GetName()); GatheredPropertyPaths.Add(*QualifiedFullPath); } } } } } // Then iterate over each subobject of this object looking for interp properties. TArray<UObject*> DefaultSubObjects; ObjectClass->GetDefaultObjectSubobjects(DefaultSubObjects); for (int32 SubObjectIndex = 0; SubObjectIndex < DefaultSubObjects.Num(); ++SubObjectIndex) { UObject* Component = DefaultSubObjects[SubObjectIndex]; const FString ComponentPrefix = Component->GetName() + TEXT("."); GetInterpPropertyNames(Component, ComponentPrefix); } }