public void TestCloneSubHierarchyInstanceWithRemoveOverrides() { var baseAsset = AssetHierarchyHelper.BuildAssetContainer(1, 2, 1, null, x => x.Parts[x.RootParts.Single().Id].Part.Name = "BaseName"); var container = baseAsset.Container.NodeContainer; var derivedAsset = AssetHierarchyHelper.BuildAssetContainer(1, 2, 1, baseAsset.Container); var instances = baseAsset.Asset.CreatePartInstances(); var derivedRootId = instances.RootParts.Single().Id; derivedAsset.Graph.AddPartToAsset(instances.Parts, instances.Parts[derivedRootId], derivedAsset.Asset.Hierarchy.RootParts.Single(), 1); derivedAsset.Graph.RefreshBase(); var partToChange = (AssetObjectNode)container.GetNode(instances.Parts.Single(x => x.Value.Part.Name == "BaseName").Value.Part); partToChange[nameof(Types.MyPart.Name)].Update("Overridden"); Debug.Write(AssetHierarchyHelper.PrintHierarchy(derivedAsset.Asset)); var originalRoot = derivedAsset.Asset.Hierarchy.RootParts.Single(); Dictionary <Guid, Guid> remapping; var clone = AssetCompositeHierarchyPropertyGraph <Types.MyPartDesign, Types.MyPart> .CloneSubHierarchies(container, derivedAsset.Asset, originalRoot.Id.Yield(), SubHierarchyCloneFlags.RemoveOverrides, out remapping); var cloneAsset = AssetHierarchyHelper.BuildAssetContainer(0, 0, 0, baseAsset.Container); var cloneRoot = clone.Parts[clone.RootParts.Single().Id]; cloneAsset.Graph.AddPartToAsset(clone.Parts, cloneRoot, null, 0); cloneAsset.Graph.RefreshBase(); Assert.Empty(remapping); Assert.Equal(4, clone.Parts.Count); Assert.Single(clone.RootParts); foreach (var rootPart in clone.RootParts) { Assert.Contains(rootPart, clone.Parts.Values.Select(x => x.Part)); } foreach (var part in clone.Parts.Values) { var matchingPart = derivedAsset.Asset.Hierarchy.Parts[part.Part.Id]; Assert.NotEqual(matchingPart, part); Assert.NotEqual(matchingPart.Part, part.Part); Assert.Equal(matchingPart.Part.Id, part.Part.Id); Assert.Equal(matchingPart.Part.Name, part.Part.Name); } Assert.Equal(originalRoot.Id, cloneRoot.Part.Id); Assert.NotEqual(originalRoot.Children[0], cloneRoot.Part.Children[0]); Assert.NotEqual(originalRoot.Children[1], cloneRoot.Part.Children[1]); Assert.Equal(originalRoot.Children[0].Id, cloneRoot.Part.Children[0].Id); Assert.Equal(originalRoot.Children[1].Id, cloneRoot.Part.Children[1].Id); Assert.NotEqual(originalRoot.Children[0].Parent, cloneRoot.Part.Children[0].Parent); Assert.NotEqual(originalRoot.Children[1].Parent, cloneRoot.Part.Children[1].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[0].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[1].Parent); var clonedChangedPart = (AssetObjectNode)container.GetNode(clone.Parts.Single(x => x.Value.Part.Id == (Guid)partToChange[nameof(IIdentifiable.Id)].Retrieve()).Value.Part); // Note: currently, using RemoveOverrides does not clear the base (it just clears the overrides), so we should expect to still have the base linked. // This behavior could be changed in the future Assert.False(clonedChangedPart[nameof(Types.MyPart.Name)].IsContentOverridden()); Assert.True(clonedChangedPart[nameof(Types.MyPart.Name)].IsContentInherited()); Assert.Equal("Overridden", clonedChangedPart[nameof(Types.MyPart.Name)].Retrieve()); Assert.Equal(partToChange[nameof(Types.MyPart.Name)].BaseNode, clonedChangedPart[nameof(Types.MyPart.Name)].BaseNode); }
public void TestCloneSubHierarchyWithGenerateNewIdsForIdentifiableObjects() { var graph = AssetHierarchyHelper.BuildAssetAndGraph(2, 2, 2); Debug.Write(AssetHierarchyHelper.PrintHierarchy(graph.Asset)); var originalRoot = graph.Asset.Hierarchy.Parts[graph.Asset.Hierarchy.RootParts[1].Id]; Dictionary <Guid, Guid> remapping; var clone = AssetCompositeHierarchyPropertyGraph <Types.MyPartDesign, Types.MyPart> .CloneSubHierarchies(graph.Container.NodeContainer, graph.Asset, originalRoot.Part.Id.Yield(), SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects, out remapping); var cloneRoot = clone.Parts[clone.RootParts.Single().Id]; Assert.NotNull(remapping); Assert.Equal(3, clone.Parts.Count); Assert.Single(clone.RootParts); foreach (var rootPart in clone.RootParts) { Assert.Contains(rootPart, clone.Parts.Values.Select(x => x.Part)); } foreach (var part in clone.Parts.Values) { Assert.Contains(part.Part.Id, remapping.Values); var matchingId = remapping.Single(x => x.Value == part.Part.Id).Key; Assert.NotEqual(part.Part.Id, matchingId); var matchingPart = graph.Asset.Hierarchy.Parts[matchingId]; Assert.NotEqual(matchingPart, part); Assert.NotEqual(matchingPart.Part, part.Part); Assert.NotEqual(matchingPart.Part.Id, part.Part.Id); Assert.Equal(matchingPart.Part.Name, part.Part.Name); } Assert.NotEqual(originalRoot.Part.Id, cloneRoot.Part.Id); Assert.Contains(originalRoot.Part.Id, remapping.Keys); Assert.Equal(remapping[originalRoot.Part.Id], cloneRoot.Part.Id); Assert.NotEqual(originalRoot.Part.Children[0], cloneRoot.Part.Children[0]); Assert.NotEqual(originalRoot.Part.Children[1], cloneRoot.Part.Children[1]); Assert.NotEqual(originalRoot.Part.Children[0].Id, cloneRoot.Part.Children[0].Id); Assert.Contains(originalRoot.Part.Children[0].Id, remapping.Keys); Assert.Equal(remapping[originalRoot.Part.Children[0].Id], cloneRoot.Part.Children[0].Id); Assert.NotEqual(originalRoot.Part.Children[1].Id, cloneRoot.Part.Children[1].Id); Assert.Contains(originalRoot.Part.Children[1].Id, remapping.Keys); Assert.Equal(remapping[originalRoot.Part.Children[1].Id], cloneRoot.Part.Children[1].Id); Assert.NotEqual(originalRoot.Part.Children[0].Parent, cloneRoot.Part.Children[0].Parent); Assert.NotEqual(originalRoot.Part.Children[1].Parent, cloneRoot.Part.Children[1].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[0].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[1].Parent); }
public void TestCloneSubHierarchyWithExternalReferencesWithCleanExternalReferences() { var graph = AssetHierarchyHelper.BuildAssetAndGraph(2, 2, 2, x => x.Parts[GuidGenerator.Get(5)].Part.MyReferences = new List <Types.MyPart> { x.Parts[GuidGenerator.Get(2)].Part }); Debug.Write(AssetHierarchyHelper.PrintHierarchy(graph.Asset)); var originalRoot = graph.Asset.Hierarchy.Parts[graph.Asset.Hierarchy.RootParts[1].Id]; Dictionary <Guid, Guid> remapping; var clone = AssetCompositeHierarchyPropertyGraph <Types.MyPartDesign, Types.MyPart> .CloneSubHierarchies(graph.Container.NodeContainer, graph.Asset, originalRoot.Part.Id.Yield(), SubHierarchyCloneFlags.CleanExternalReferences, out remapping); var cloneRoot = clone.Parts[clone.RootParts.Single().Id]; Assert.Empty(remapping); Assert.Equal(3, clone.Parts.Count); Assert.Single(clone.RootParts); foreach (var rootPart in clone.RootParts) { Assert.Contains(rootPart, clone.Parts.Values.Select(x => x.Part)); } foreach (var part in clone.Parts.Values) { var matchingPart = graph.Asset.Hierarchy.Parts[part.Part.Id]; Assert.NotEqual(matchingPart, part); Assert.NotEqual(matchingPart.Part, part.Part); Assert.Equal(matchingPart.Part.Id, part.Part.Id); Assert.Equal(matchingPart.Part.Name, part.Part.Name); } Assert.Equal(originalRoot.Part.Id, cloneRoot.Part.Id); Assert.NotEqual(originalRoot.Part.Children[0], cloneRoot.Part.Children[0]); Assert.NotEqual(originalRoot.Part.Children[1], cloneRoot.Part.Children[1]); Assert.Equal(originalRoot.Part.Children[0].Id, cloneRoot.Part.Children[0].Id); Assert.Equal(originalRoot.Part.Children[1].Id, cloneRoot.Part.Children[1].Id); Assert.NotEqual(originalRoot.Part.Children[0].Parent, cloneRoot.Part.Children[0].Parent); Assert.NotEqual(originalRoot.Part.Children[1].Parent, cloneRoot.Part.Children[1].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[0].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[1].Parent); Assert.Null(cloneRoot.Part.Children[0].MyReferences[0]); }
protected IEnumerable <TAssetPart> ClonePartsForGameSide([NotNull] AssetCompositeHierarchy <TAssetPartDesign, TAssetPart> asset, [NotNull] IEnumerable <TAssetPart> parts) { var flags = SubHierarchyCloneFlags.RemoveOverrides; var sourceContainer = Asset.PropertyGraph.Container.NodeContainer; var targetContainer = GameSideNodeContainer; var clone = AssetCompositeHierarchyPropertyGraph <TAssetPartDesign, TAssetPart> .CloneSubHierarchies(sourceContainer, targetContainer, asset, parts.Select(p => p.Id), flags, out _); // Collect external references after cloning, we need to fix them up! var rootNode = GameSideNodeContainer.GetOrCreateNode(clone); var definition = AssetQuantumRegistry.GetDefinition(asset.GetType()); var unresolvedReferences = ExternalReferenceCollector.GetExternalReferenceAccessors(definition, rootNode); // Retrieve all available game-side identifiable objects, so we can try to resolve external references with items from this collection. var identifiableObjects = CollectIdentifiableObjects(); foreach (var reference in unresolvedReferences) { if (identifiableObjects.TryGetValue(reference.Key.Id, out var realObject)) { // Target object found, let's update the reference with the real game-side object. foreach (var accessor in reference.Value) { accessor.UpdateValue(realObject); } } else { // Target object not found, let's clear the reference since the currently set object could be asset-side, or a temporary proxy, etc. foreach (var accessor in reference.Value) { accessor.UpdateValue(null); } } } return(clone.RootParts); }
public void TestSimpleCloneSubHierarchy() { var graph = AssetHierarchyHelper.BuildAssetAndGraph(2, 2, 2); Debug.Write(AssetHierarchyHelper.PrintHierarchy(graph.Asset)); var originalRoot = graph.Asset.Hierarchy.Parts[graph.Asset.Hierarchy.RootParts[1].Id]; Dictionary <Guid, Guid> remapping; var clone = AssetCompositeHierarchyPropertyGraph <Types.MyPartDesign, Types.MyPart> .CloneSubHierarchies(graph.Container.NodeContainer, graph.Asset, originalRoot.Part.Id.Yield(), SubHierarchyCloneFlags.None, out remapping); var cloneRoot = clone.Parts[clone.RootParts.Single().Id]; Assert.Empty(remapping); Assert.Equal(3, clone.Parts.Count); Assert.Equal(1, clone.RootParts.Count); foreach (var rootPart in clone.RootParts) { Assert.True(clone.Parts.Values.Select(x => x.Part).Contains(rootPart)); } foreach (var part in clone.Parts.Values) { var matchingPart = graph.Asset.Hierarchy.Parts[part.Part.Id]; Assert.NotEqual(matchingPart, part); Assert.NotEqual(matchingPart.Part, part.Part); Assert.Equal(matchingPart.Part.Id, part.Part.Id); Assert.Equal(matchingPart.Part.Name, part.Part.Name); } Assert.Equal(originalRoot.Part.Id, cloneRoot.Part.Id); Assert.NotEqual(originalRoot.Part.Children[0], cloneRoot.Part.Children[0]); Assert.NotEqual(originalRoot.Part.Children[1], cloneRoot.Part.Children[1]); Assert.Equal(originalRoot.Part.Children[0].Id, cloneRoot.Part.Children[0].Id); Assert.Equal(originalRoot.Part.Children[1].Id, cloneRoot.Part.Children[1].Id); Assert.NotEqual(originalRoot.Part.Children[0].Parent, cloneRoot.Part.Children[0].Parent); Assert.NotEqual(originalRoot.Part.Children[1].Parent, cloneRoot.Part.Children[1].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[0].Parent); Assert.Equal(cloneRoot.Part, cloneRoot.Part.Children[1].Parent); }