void DiffUtils::CompareUnrelatedSCS(const UBlueprint* Old, const TArray< FSCSResolvedIdentifier >& OldHierarchy, const UBlueprint* New, const TArray< FSCSResolvedIdentifier >& NewHierarchy, FSCSDiffRoot& OutDifferingEntries ) { const auto FindEntry = [](TArray< FSCSResolvedIdentifier > const& InArray, const FSCSIdentifier* Value) -> const FSCSResolvedIdentifier* { for (const auto& Node : InArray) { if (Node.Identifier.Name == Value->Name ) { return &Node; } } return nullptr; }; for (const auto& OldNode : OldHierarchy) { const FSCSResolvedIdentifier* NewEntry = FindEntry(NewHierarchy, &OldNode.Identifier); if (NewEntry != nullptr) { // did a property change? TArray<FSingleObjectDiffEntry> DifferingProperties; DiffUtils::CompareUnrelatedObjects(OldNode.Object, NewEntry->Object, DifferingProperties); for (const auto& Property : DifferingProperties) { FSCSDiffEntry Diff = { OldNode.Identifier, ETreeDiffType::NODE_PROPERTY_CHANGED, Property }; OutDifferingEntries.Entries.Push(Diff); } // did it move? if( NewEntry->Identifier.TreeLocation != OldNode.Identifier.TreeLocation ) { FSCSDiffEntry Diff = { OldNode.Identifier, ETreeDiffType::NODE_MOVED, FSingleObjectDiffEntry() }; OutDifferingEntries.Entries.Push(Diff); } // no change! Do nothing. } else { // not found in the new data, must have been deleted: FSCSDiffEntry Entry = { OldNode.Identifier, ETreeDiffType::NODE_REMOVED, FSingleObjectDiffEntry() }; OutDifferingEntries.Entries.Push( Entry ); } } for (const auto& NewNode : NewHierarchy) { const FSCSResolvedIdentifier* OldEntry = FindEntry(OldHierarchy, &NewNode.Identifier); if (OldEntry == nullptr) { FSCSDiffEntry Entry = { NewNode.Identifier, ETreeDiffType::NODE_ADDED, FSingleObjectDiffEntry() }; OutDifferingEntries.Entries.Push( Entry ); } } }
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)); } } }
void DiffUtils::CompareUnrelatedObjects(const UObject* A, const UObject* B, TArray<FSingleObjectDiffEntry>& OutDifferingProperties) { FPropertySoftPathSet PropertiesInA = GetPropertyNameSet(A); FPropertySoftPathSet PropertiesInB = GetPropertyNameSet(B); // any properties in A that aren't in B are differing: auto AddedToA = PropertiesInA.Difference(PropertiesInB).Array(); for( const auto& Entry : AddedToA ) { OutDifferingProperties.Push(FSingleObjectDiffEntry( Entry, EPropertyDiffType::PropertyAddedToA )); } // and the converse: auto AddedToB = PropertiesInB.Difference(PropertiesInA).Array(); for (const auto& Entry : AddedToB) { OutDifferingProperties.Push(FSingleObjectDiffEntry( Entry, EPropertyDiffType::PropertyAddedToB )); } // for properties in common, dig out the uproperties and determine if they're identical: if (A && B) { FPropertySoftPathSet Common = PropertiesInA.Intersect(PropertiesInB); for (const auto& PropertyName : Common) { FResolvedProperty AProp = PropertyName.Resolve(A); FResolvedProperty BProp = PropertyName.Resolve(B); check(AProp != FResolvedProperty() && BProp != FResolvedProperty()); if (!DiffUtils::Identical(AProp, BProp)) { OutDifferingProperties.Push(FSingleObjectDiffEntry( PropertyName, EPropertyDiffType::PropertyValueChanged )); } } } }