public void TestMergeSimpleWithBasePartsAndLinksForChildren() { // Similar to TestMergeSimpleWithBasePartsAndLinks, but perform merge on Entity.Transform.Children instead // Also Check that an asset that was removed is not added and links are actually removed as well // part1: part2: newAsset (BaseParts: part1): newAssetMerged (BaseParts: part2): // ERoot ERoot ERoot1 ERoot1 // EA EA EA1 (base: EA) EA1' (base: EA) // EB EB EB1 (base: EB) EB1' (base: EB) // EC + link: EA EC + link: EA EC1 (base: EC) + link: EA1 EC1' (base: EC) + link: EA1' // ED + link: EB ED1' (base: ED) + link: EB1' // ERoot2 ERoot2 // EA2 (base: EA) EA2' (base: EA) // // EC2 (base: EC) + link: EA2 EC2' (base: EC) + link: EA2' // ED2' (base: ED) + noLink var eRoot = new Entity("Root"); var entityA = new Entity() { Name = "A" }; var entityB = new Entity() { Name = "B" }; var entityC = new Entity() { Name = "C" }; // EC + link: EA entityC.Add(new TestEntityComponent() { EntityLink = entityA }); eRoot.Transform.Children.Add(entityA.Transform); eRoot.Transform.Children.Add(entityB.Transform); eRoot.Transform.Children.Add(entityC.Transform); // part1 Asset var part1 = new EntityGroupAsset(); part1.Hierarchy.Entities.Add(new EntityDesign(eRoot, new EntityDesignData())); part1.Hierarchy.Entities.Add(new EntityDesign(entityA, new EntityDesignData())); part1.Hierarchy.Entities.Add(new EntityDesign(entityB, new EntityDesignData())); part1.Hierarchy.Entities.Add(new EntityDesign(entityC, new EntityDesignData())); part1.Hierarchy.RootEntities.Add(eRoot.Id); // part2 Asset var part2 = (EntityGroupAsset)AssetCloner.Clone(part1); var eRootPart2 = part2.Hierarchy.Entities.Where(it => it.Entity.Name == "Root").Select(it => it.Entity).First(); var entityD = new Entity() { Name = "D" }; eRootPart2.Transform.Children.Add(entityD.Transform); // ED + link: EB var entityBFrom2 = part2.Hierarchy.Entities.Where(it => it.Entity.Name == "B").Select(it => it.Entity).First(); entityD.Add(new TestEntityComponent() { EntityLink = entityBFrom2 }); part2.Hierarchy.Entities.Add(new EntityDesign(entityD, new EntityDesignData())); // originalAsset: Add a new instanceId for this part var asset = new EntityGroupAsset { BaseParts = new List<AssetBasePart>() }; var assetBasePart = new AssetBasePart(new AssetBase("part", part1)); asset.BaseParts.Add(assetBasePart); // Create derived parts var eRoot1Asset = (EntityGroupAsset)part1.CreateChildAsset("part"); var eRoot2Asset = (EntityGroupAsset)part1.CreateChildAsset("part"); asset.AddPart(eRoot1Asset); asset.AddPart(eRoot2Asset); var eRoot2 = asset.Hierarchy.Entities[eRoot2Asset.Hierarchy.RootEntities[0]]; var entityToRemove = eRoot2.Entity.Transform.Children.First(it => it.Entity.Name == "B"); eRoot2.Entity.Transform.Children.Remove(entityToRemove); asset.Hierarchy.Entities.Remove(entityToRemove.Entity.Id); // Merge entities (NOTE: it is important to clone baseAsset/newBaseAsset) var entityMerge = asset.Merge(null, null, new List<AssetBasePart>() { new AssetBasePart(new AssetBase("part", part2)) { InstanceIds = { eRoot1Asset.Id, eRoot2Asset.Id } } }); Assert.False(entityMerge.HasErrors); // EntityD must be now part of the new asset Assert.AreEqual(2, asset.Hierarchy.RootEntities.Count); Assert.AreEqual(9, asset.Hierarchy.Entities.Count); Assert.AreEqual(2, asset.Hierarchy.Entities.Count(it => it.Entity.Name == "D")); foreach (var entity in asset.Hierarchy.Entities.Where(it => it.Entity.Name == "D")) { // Check that we have the correct baesId and basePartInstanceId Assert.True(entity.Design.BasePartInstanceId.HasValue); Assert.True(entity.Design.BaseId.HasValue); Assert.AreEqual(entityD.Id, entity.Design.BaseId.Value); } var entityDesignD1 = asset.Hierarchy.Entities[asset.Hierarchy.Entities[asset.Hierarchy.RootEntities[0]].Entity.Transform.Children.Where(it => it.Entity.Name == "D").Select(it => it.Entity.Id).FirstOrDefault()]; Assert.NotNull(entityDesignD1); Assert.AreEqual(eRoot1Asset.Id, entityDesignD1.Design.BasePartInstanceId); var testComponentD1 = entityDesignD1.Entity.Get<TestEntityComponent>(); Assert.NotNull(testComponentD1); var entityB1 = asset.Hierarchy.Entities[asset.Hierarchy.RootEntities[0]].Entity.Transform.Children.Where(it => it.Entity.Name == "B").Select(it => it.Entity).First(); Assert.AreEqual(entityB1, testComponentD1.EntityLink); var entityDesignD2 = asset.Hierarchy.Entities[asset.Hierarchy.Entities[asset.Hierarchy.RootEntities[1]].Entity.Transform.Children.Where(it => it.Entity.Name == "D").Select(it => it.Entity.Id).FirstOrDefault()]; Assert.NotNull(entityDesignD2); Assert.AreEqual(eRoot2Asset.Id, entityDesignD2.Design.BasePartInstanceId); var testComponentD2 = entityDesignD2.Entity.Get<TestEntityComponent>(); Assert.NotNull(testComponentD2); Assert.AreEqual(null, testComponentD2.EntityLink); }
/// <summary> /// Adds an entity as a part asset. /// </summary> /// <param name="assetPartBase">The entity asset to be used as a part (must be created directly from <see cref="CreateChildAsset"/>)</param> /// <param name="rootEntityId">An optional entity id to attach the part to it. If null, the part will be attached to the root entities of this instance</param> public void AddPart(EntityGroupAssetBase assetPartBase, Guid? rootEntityId = null) { if (assetPartBase == null) throw new ArgumentNullException(nameof(assetPartBase)); // The assetPartBase must be a plain child asset if (assetPartBase.Base == null) throw new InvalidOperationException($"Expecting a Base for {nameof(assetPartBase)}"); if (assetPartBase.BaseParts != null) throw new InvalidOperationException($"Expecting a null BaseParts for {nameof(assetPartBase)}"); // Check that the assetPartBase contains only entities from its base (no new entity, must be a plain ChildAsset) if (assetPartBase.Hierarchy.Entities.Any(entity => !entity.Design.BaseId.HasValue)) { throw new InvalidOperationException("An asset part base must contain only base assets"); } // The instance id will be the id of the assetPartBase var instanceId = assetPartBase.Id; if (this.BaseParts == null) { this.BaseParts = new List<AssetBasePart>(); } var basePart = this.BaseParts.FirstOrDefault(basePartIt => basePartIt.Base.Id == this.Id); if (basePart == null) { basePart = new AssetBasePart(assetPartBase.Base); this.BaseParts.Add(basePart); } basePart.InstanceIds.Add(instanceId); // If a RootEntityId is given and found in this instance, add them as children of entity if (rootEntityId.HasValue && this.Hierarchy.Entities.ContainsKey(rootEntityId.Value)) { var rootEntity = Hierarchy.Entities[rootEntityId.Value]; foreach (var entityId in assetPartBase.Hierarchy.RootEntities) { var entity = assetPartBase.Hierarchy.Entities[entityId]; rootEntity.Entity.Transform.Children.Add(entity.Entity.Transform); } } else { // Else add them as root this.Hierarchy.RootEntities.AddRange(assetPartBase.Hierarchy.RootEntities); } // Add all entities with the correct instance id foreach (var entityEntry in assetPartBase.Hierarchy.Entities) { entityEntry.Design.BasePartInstanceId = instanceId; this.Hierarchy.Entities.Add(entityEntry); } }