void FDetailsDiff::DiffAgainst(const FDetailsDiff& Newer, TArray< FSingleObjectDiffEntry > &OutDifferences) const { TSharedPtr< class IDetailsView > OldDetailsView = DetailsView; TSharedPtr< class IDetailsView > NewDetailsView = Newer.DetailsView; const auto& OldSelectedObjects = OldDetailsView->GetSelectedObjects(); const auto& NewSelectedObjects = NewDetailsView->GetSelectedObjects(); check(OldSelectedObjects.Num() == 1); auto OldProperties = OldDetailsView->GetPropertiesInOrderDisplayed(); auto NewProperties = NewDetailsView->GetPropertiesInOrderDisplayed(); TSet<FPropertySoftPath> OldPropertiesSet; TSet<FPropertySoftPath> NewPropertiesSet; auto ToSet = [](const TArray<FPropertyPath>& Array, TSet<FPropertySoftPath>& OutSet) { for (const auto& Entry : Array) { OutSet.Add(FPropertySoftPath(Entry)); } }; ToSet(OldProperties, OldPropertiesSet); ToSet(NewProperties, NewPropertiesSet); // detect removed properties: auto RemovedProperties = OldPropertiesSet.Difference(NewPropertiesSet); for (const auto& RemovedProperty : RemovedProperties) { // @todo: (doc) label these as removed, rather than added to a FSingleObjectDiffEntry Entry(RemovedProperty, EPropertyDiffType::PropertyAddedToA); OutDifferences.Push(Entry); } // detect added properties: auto AddededProperties = NewPropertiesSet.Difference(OldPropertiesSet); for (const auto& AddedProperty : AddededProperties) { FSingleObjectDiffEntry Entry(AddedProperty, EPropertyDiffType::PropertyAddedToB); OutDifferences.Push(Entry); } // check for changed properties auto CommonProperties = NewPropertiesSet.Intersect(OldPropertiesSet); for (const auto& CommonProperty : CommonProperties) { // get value, diff: check(NewSelectedObjects.Num() == 1); auto OldPoperty = CommonProperty.Resolve(OldSelectedObjects[0].Get()); auto NewProperty = CommonProperty.Resolve(NewSelectedObjects[0].Get()); if (!DiffUtils::Identical(OldPoperty, NewProperty)) { OutDifferences.Push(FSingleObjectDiffEntry(CommonProperty, EPropertyDiffType::PropertyValueChanged)); } } }
} } { // make sure that we add any user created classes immediately, generally this will not create anything (because assets have not been discovered yet), but asset discovery // should be allowed to take place at any time: FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); TArray<FName> ClassNames; ClassNames.Add(UActorComponent::StaticClass()->GetFName()); TSet<FName> DerivedClassNames; AssetRegistryModule.Get().GetDerivedClassNames(ClassNames, TSet<FName>(), DerivedClassNames); const bool bIncludeInFilter = true; auto InMemoryClassesSet = TSet<FName>(InMemoryClasses); auto OnDiskClasses = DerivedClassNames.Difference(InMemoryClassesSet); // GetAssetsByClass call is a cludget to get the full asset paths for the blueprints we care about, Bob T. thinks // that the Asset Registry could just keep asset paths: TArray<FAssetData> BlueprintAssetData; AssetRegistryModule.Get().GetAssetsByClass(UBlueprint::StaticClass()->GetFName(), BlueprintAssetData); for (auto OnDiskClass : OnDiskClasses) { FName AssetPath; FString FixedString = OnDiskClass.ToString(); FixedString.RemoveFromEnd(TEXT("_C")); for (auto Blueprint : BlueprintAssetData) { if (Blueprint.AssetName.ToString() == FixedString) {