// Copyright Epic Games, Inc. All Rights Reserved. #include "PropertyEditorUtils.h" #include "PropertyPathHelpers.h" namespace PropertyEditorUtils { void GetPropertyOptions(TArray& InOutContainers, FString& InOutPropertyPath, TArray>& InOutOptions) { // Check for external function references if (InOutPropertyPath.Contains(TEXT("."))) { InOutContainers.Empty(); UFunction* GetOptionsFunction = FindObject(nullptr, *InOutPropertyPath, true); if (ensureMsgf(GetOptionsFunction && GetOptionsFunction->HasAnyFunctionFlags(EFunctionFlags::FUNC_Static), TEXT("Invalid GetOptions: %s"), *InOutPropertyPath)) { UObject* GetOptionsCDO = GetOptionsFunction->GetOuterUClass()->GetDefaultObject(); GetOptionsFunction->GetName(InOutPropertyPath); InOutContainers.Add(GetOptionsCDO); } } if (InOutContainers.Num() > 0) { TArray OptionIntersection; TSet OptionIntersectionSet; for (UObject* Target : InOutContainers) { TArray StringOptions; { FEditorScriptExecutionGuard ScriptExecutionGuard; FCachedPropertyPath Path(InOutPropertyPath); if (!PropertyPathHelpers::GetPropertyValue(Target, Path, StringOptions)) { TArray NameOptions; if (PropertyPathHelpers::GetPropertyValue(Target, Path, NameOptions)) { Algo::Transform(NameOptions, StringOptions, [](const FName& InName) { return InName.ToString(); }); } } } // If this is the first time there won't be any options. if (OptionIntersection.Num() == 0) { OptionIntersection = StringOptions; OptionIntersectionSet = TSet(StringOptions); } else { TSet StringOptionsSet(StringOptions); OptionIntersectionSet = StringOptionsSet.Intersect(OptionIntersectionSet); OptionIntersection.RemoveAll([&OptionIntersectionSet](const FString& Option){ return !OptionIntersectionSet.Contains(Option); }); } // If we're out of possible intersected options, we can stop. if (OptionIntersection.Num() == 0) { break; } } Algo::Transform(OptionIntersection, InOutOptions, [](const FString& InString) { return MakeShared(InString); }); } } }