Esempio n. 1
0
        public void TestSerializationWithBaseAndParts()
        {
            // Create an entity as in TestSerialization
            // Then create a derivedAsset from it 
            // Then create a partAsset and add this partAsset as a composition to derivedAsset
            // Serialize and deserialize derivedAsset
            // Check that deserialized derivedAsset has all base/baseParts correctly serialized

            var originAsset = CreateOriginAsset();

            var derivedAsset = (PrefabAsset)originAsset.CreateChildAsset("base");

            var basePartAsset = new PrefabAsset();
            var entityPart1 = new Entity() { Name = "EPart1" };
            var entityPart2 = new Entity() { Name = "EPart2" };
            basePartAsset.Hierarchy.Entities.Add(entityPart1);
            basePartAsset.Hierarchy.Entities.Add(entityPart2);
            basePartAsset.Hierarchy.RootEntities.Add(entityPart1.Id);
            basePartAsset.Hierarchy.RootEntities.Add(entityPart2.Id);

            // Add 2 asset parts from the same base
            var instance = basePartAsset.CreatePrefabInstance(derivedAsset, "part");
            derivedAsset.Hierarchy.Entities.AddRange(instance.Entities);
            derivedAsset.Hierarchy.RootEntities.AddRange(instance.RootEntities);

            var instance2 = basePartAsset.CreatePrefabInstance(derivedAsset, "part");
            derivedAsset.Hierarchy.Entities.AddRange(instance2.Entities);
            derivedAsset.Hierarchy.RootEntities.AddRange(instance2.RootEntities);

            using (var stream = new MemoryStream())
            {
                AssetSerializer.Save(stream, derivedAsset);

                stream.Position = 0;
                var serializedVersion = Encoding.UTF8.GetString(stream.ToArray());
                Console.WriteLine(serializedVersion);

                stream.Position = 0;
                var newAsset = (PrefabAsset)AssetSerializer.Load(stream, "xkentity");

                Assert.NotNull(newAsset.Base);
                Assert.NotNull(newAsset.BaseParts);

                // We should have only 1 base part, as we created parts from the same base
                Assert.AreEqual(1, newAsset.BaseParts.Count);

                CheckAsset(derivedAsset, newAsset);

                CheckAsset(originAsset, (PrefabAsset)newAsset.Base.Asset);

                CheckGenericAsset(basePartAsset, (PrefabAsset)newAsset.BaseParts[0].Asset);
            }
        }
        public void TestMultiplePrefabsInheritanceAndChildren()
        {
            // The purpose of this test is to check that modifying a prefab base is correctly propagated through all 
            // derived prefabs. We use the following scenario:
            //
            // a1: base asset
            // a2: inherit from a1 by composition with 2 instances (baseParts: a1 => 2 instances)
            // a3: inherit from a1 by composition with 1 instances (baseParts: a1 => 1 instances)
            // a4: inherit from a2 and a3 by composition with 1 instances for each (baseParts: a1 => 1 instance, a2 => 1 instance)
            //
            // Unlike TestMultiplePrefabsMixedInheritance, we use only inheritance by composition for this scenario to match current use cases

            var package = new Package();

            var assetItems = package.Assets;


            // First we create assets with the following configuration:
            // a1:                  a2: (baseParts: a1, 2 instances)     a3: (baseParts: a1)               a4: (baseParts: a2 x 1, a3 x 1)
            //  | er                 | er1 (base: er)                     | er1' (base: er)                 | eRoot
            //    | ea                 | ea1 (base: ea)                     | ea1' (base: ea)                 | er1* (base: er)  
            //    | eb                 | eb1 (base: eb)                     | eb1' (base: eb)                   | ea1* (base: ea)
            //    | ec                 | ec1 (base: ec)                     | ec1' (base: ec)                   | eb1* (base: eb)
            //                       | er2 (base: er)                                                           | ec1* (base: ec)
            //                         | ea2 (base: ea)                                                       | er2* (base: er)  
            //                         | eb2 (base: eb)                                                         | ea2* (base: ea)
            //                         | ec2 (base: ec)                                                         | eb2* (base: eb)
            //                                                                                                  | ec2* (base: ec)  
            //                                                                                              | er1'* (base: er)     
            //                                                                                                | ea1'* (base: ea)    
            //                                                                                                | eb1'* (base: eb)  
            //                                                                                                | ec1'* (base: ec)
            var a1 = new PrefabAsset();
            var er = new Entity("er");
            var ea = new Entity("ea");
            var eb = new Entity("eb");
            var ec = new Entity("ec");
            a1.Hierarchy.Parts.Add(new EntityDesign(er));
            a1.Hierarchy.Parts.Add(new EntityDesign(ea));
            a1.Hierarchy.Parts.Add(new EntityDesign(eb));
            a1.Hierarchy.Parts.Add(new EntityDesign(ec));
            a1.Hierarchy.RootPartIds.Add(er.Id);
            er.AddChild(ea);
            er.AddChild(eb);
            er.AddChild(ec);

            assetItems.Add(new AssetItem("a1", a1));

            var member = (IMemberDescriptor)TypeDescriptorFactory.Default.Find(typeof(Entity))[nameof(Entity.Name)];
            
            var a2 = new PrefabAsset();
            var a2PartInstance1 = a1.CreatePrefabInstance(a2, "a1");
            foreach (var entity in a2PartInstance1.Parts)
            {
                entity.Entity.Name += "1";
            }

            var a2PartInstance2 = a1.CreatePrefabInstance(a2, "a1");
            foreach (var entity in a2PartInstance2.Parts)
            {
                entity.Entity.Name += "2";
            }

            a2.Hierarchy.Parts.AddRange(a2PartInstance1.Parts);
            a2.Hierarchy.Parts.AddRange(a2PartInstance2.Parts);
            a2.Hierarchy.RootPartIds.AddRange(a2PartInstance1.RootPartIds);
            a2.Hierarchy.RootPartIds.AddRange(a2PartInstance2.RootPartIds);
            Assert.AreEqual(8, a2.Hierarchy.Parts.Count);
            Assert.AreEqual(2, a2.Hierarchy.RootPartIds.Count);
            assetItems.Add(new AssetItem("a2", a2));

            var a3 = new PrefabAsset();
            var a3PartInstance1 = a1.CreatePrefabInstance(a3, "a1");
            foreach (var entity in a3PartInstance1.Parts)
            {
                entity.Entity.Name += "1'";
            }
            a3.Hierarchy.Parts.AddRange(a3PartInstance1.Parts);
            a3.Hierarchy.RootPartIds.AddRange(a3PartInstance1.RootPartIds);
            Assert.AreEqual(4, a3.Hierarchy.Parts.Count);
            Assert.AreEqual(1, a3.Hierarchy.RootPartIds.Count);
            assetItems.Add(new AssetItem("a3", a3));

            var a4 = new PrefabAsset();
            var eRoot = new Entity("eRoot");
            var a2PartInstance3 = a2.CreatePrefabInstance(a4, "a2");

            foreach (var entity in a2PartInstance3.Parts)
            {
                entity.Entity.Name += "*";
            }
            foreach (var entity in a2PartInstance3.Parts.Where(t => a2PartInstance3.RootPartIds.Contains(t.Entity.Id)))
            {
                eRoot.AddChild(entity.Entity);
            }
            var a3PartInstance2 = a3.CreatePrefabInstance(a4, "a3");
            foreach (var entity in a3PartInstance2.Parts)
            {
                entity.Entity.Name += "*";
            }

            a4.Hierarchy.Parts.Add(new EntityDesign(eRoot));
            a4.Hierarchy.Parts.AddRange(a2PartInstance3.Parts);
            a4.Hierarchy.Parts.AddRange(a3PartInstance2.Parts);
            a4.Hierarchy.RootPartIds.Add(eRoot.Id);
            a4.Hierarchy.RootPartIds.AddRange(a3PartInstance2.RootPartIds);

            Assert.AreEqual(13, a4.Hierarchy.Parts.Count);
            Assert.AreEqual(2, a4.Hierarchy.RootPartIds.Count);

            assetItems.Add(new AssetItem("a4", a4));

            Assert.True(a1.DumpTo(Console.Out, "a1 BEFORE PrefabMergeAsset"));
            Assert.True(a2.DumpTo(Console.Out, "a2 BEFORE PrefabMergeAsset"));
            Assert.True(a3.DumpTo(Console.Out, "a3 BEFORE PrefabMergeAsset"));
            Assert.True(a4.DumpTo(Console.Out, "a4 BEFORE PrefabMergeAsset"));


            // Then we simulate a concurrent change to a1 by someone that didn't have a2/a3/a4
            // - Add one component to a1, linking to an existing entity ea
            // - Add a root entity to a1 with a link to an existing entity eb
            //
            // a1:                  a2: (baseParts: a1, 2 instances)     a3: (baseParts: a1)                a4: (baseParts: a2 x 1, a3 x 1)
            //  | er                 | er1 (base: er)                     | er1' (base: er)                  | eRoot
            //    | ea                 | ea1 (base: ea)                     | ea1' (base: ea)                  | er1* (base: er)  
            //    | eb                 | eb1 (base: eb)                     | eb1' (base: eb)                    | ea1* (base: ea)
            //    | ec + link ea       | ec1 + link ea1 (base: ec)          | ec1' + link ea1' (base: ec)        | eb1* (base: eb)
            //  | ex                 | er2 (base: er)                     | ex(1') (base: ex)                    | ec1* + link ea1* (base: ec)
            //    | ey + link eb       | ea2 (base: ea)                     | ey(1') + link eb1'               | er2* (base: er)  
            //                         | eb2 (base: eb)                                                          | ea2* (base: ea)
            //                         | ec2 + link ea2 (base: ec)                                               | eb2* (base: eb)
            //                       | ex(1)                                                                     | ec2* + link ea2* (base: ec)  
            //                         | ey(1) + link eb1                                                    | er1'* (base: er)     
            //                       | ex(2)                                                                   | ea1'* (base: ea)
            //                         | ey(2) + link eb2                                                      | eb1'* (base: eb)  
            //                                                                                                 | ec1'* + link ea1'* (base: ec)  
            //                                                                                               | ex(1*)
            //                                                                                                 | ey(1*) + link eb1*
            //                                                                                               | ex(2*)
            //                                                                                                 | ey(2*) + link eb2*
            //                                                                                               | ex(1') (base: ex)   
            //                                                                                                 | ey(1') + link eb1'*
            ec.Components.Add(new TestEntityComponent() { EntityLink = ea });

            var ex = new Entity("ex");
            var ey = new Entity("ey");
            ey.Components.Add(new TestEntityComponent() { EntityLink = eb });
            ex.AddChild(ey);
            a1.Hierarchy.Parts.Add(new EntityDesign(ex));
            a1.Hierarchy.Parts.Add(new EntityDesign(ey));
            a1.Hierarchy.RootPartIds.Add(ex.Id);
            Assert.AreEqual(6, a1.Hierarchy.Parts.Count);
            Assert.AreEqual(2, a1.Hierarchy.RootPartIds.Count);

            // Simulates the loading of this package
            using (var session = new PackageSession())
            {
                var logger = new LoggerResult();
                session.AddExistingPackage(package, logger);

                Assert.False(logger.HasErrors);

                Assert.True(a1.DumpTo(Console.Out, "a1 AFTER PrefabMergeAsset"));

                // ------------------------------------------------
                // Check for a2
                // ------------------------------------------------
                // a2: (baseParts: a1, 2 instances)
                //  | er1 (base: er)               
                //    | ea1 (base: ea)             
                //    | eb1 (base: eb)             
                //    | ec1 + link ea1 (base: ec)  
                //  | er2 (base: er)               
                //    | ea2 (base: ea)             
                //    | eb2 (base: eb)             
                //    | ec2 + link ea2 (base: ec)  
                //  | ex(1)                          
                //    | ey(1) + link eb1             
                //  | ex(2)                          
                //    | ey(2) + link eb2             
                {
                    Assert.True(a2.DumpTo(Console.Out, "a2 AFTER PrefabMergeAsset"));
                    Assert.AreEqual(4, a2.Hierarchy.RootPartIds.Count);
                    Assert.True(a2.Hierarchy.Parts.All(it => it.Base != null));

                    // Check that we have all expected entities
                    Assert.AreEqual(12, a2.Hierarchy.Parts.Count);

                    var eb1 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb1")?.Entity;
                    var eb2 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb2")?.Entity;
                    Assert.NotNull(eb1);
                    Assert.NotNull(eb2);

                    // Check that we have ex and ey
                    var exList = a2.Hierarchy.Parts.Where(it => it.Entity.Name == ex.Name).ToList();
                    Assert.AreEqual(2, exList.Count);

                    // Check that both [ex] have both 1 element [ey] and the links to eb1/eb2 are correct
                    {
                        var expecting = new List<Entity>() { eb1, eb2 };
                        for (int i = 0; i < exList.Count; i++)
                        {
                            var ex1 = exList[i].Entity;
                            Assert.AreEqual(1, ex1.Transform.Children.Count);
                            var ey1 = ex1.Transform.Children[0].Entity;
                            Assert.AreEqual(ey.Name, ey1.Name);
                            Assert.NotNull(ey1.Get<TestEntityComponent>());

                            var entityLink = ey1.Get<TestEntityComponent>().EntityLink;
                            Assert.True(expecting.Contains(entityLink));
                            expecting.Remove(entityLink);
                        }
                    }

                    // Check link from ec1 to ea1
                    {
                        var ec1 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ec1")?.Entity;
                        Assert.NotNull(ec1);

                        var ea1 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ea1")?.Entity;
                        Assert.NotNull(ea1);

                        Assert.NotNull(ec1.Get<TestEntityComponent>());
                        Assert.AreEqual(ea1, ec1.Get<TestEntityComponent>().EntityLink);
                    }

                    // Check link from ec2 to ea2
                    {
                        var ec2 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ec2")?.Entity;
                        Assert.NotNull(ec2);

                        var ea2 = a2.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ea2")?.Entity;
                        Assert.NotNull(ea2);

                        Assert.NotNull(ec2.Get<TestEntityComponent>());
                        Assert.AreEqual(ea2, ec2.Get<TestEntityComponent>().EntityLink);
                    }
                }

                // ------------------------------------------------
                // Check for a3
                // ------------------------------------------------
                // a3: (baseParts: a1)             
                //  | er1' (base: er)              
                //    | ea1' (base: ea)            
                //    | eb1' (base: eb)            
                //    | ec1' + link ea1' (base: ec)
                //  | ex1' (base: ex)              
                //    | ey1' + link eb1'           
                {
                    Assert.True(a3.DumpTo(Console.Out, "a3 AFTER PrefabMergeAsset"));

                    Assert.AreEqual(2, a3.Hierarchy.RootPartIds.Count);
                    Assert.True(a3.Hierarchy.Parts.All(it => it.Base != null));

                    // Check that we have all expected entities
                    Assert.AreEqual(6, a3.Hierarchy.Parts.Count);

                    var eb1 = a3.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb1'")?.Entity;
                    Assert.NotNull(eb1);

                    // Check that we have ex and ey
                    var exList = a3.Hierarchy.Parts.Where(it => it.Entity.Name == ex.Name).ToList();
                    Assert.AreEqual(1, exList.Count);

                    // Check that [ex] have 1 element [ey] and the link to eb1 is correct
                    {
                        var ex1 = exList[0].Entity;
                        Assert.AreEqual(1, ex1.Transform.Children.Count);
                        var ey1 = ex1.Transform.Children[0].Entity;
                        Assert.AreEqual(ey.Name, ey1.Name);
                        Assert.NotNull(ey1.Get<TestEntityComponent>());

                        Assert.AreEqual(eb1, ey1.Get<TestEntityComponent>().EntityLink);
                    }

                    {
                        var ec1 = a3.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ec1'")?.Entity;
                        Assert.NotNull(ec1);

                        var ea1 = a3.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "ea1'")?.Entity;
                        Assert.NotNull(ea1);

                        Assert.NotNull(ec1.Get<TestEntityComponent>());
                        Assert.AreEqual(ea1, ec1.Get<TestEntityComponent>().EntityLink);
                    }
                }

                // ------------------------------------------------
                // Check for a4
                // ------------------------------------------------
                // a4: (baseParts: a2 x 1, a3 x 1)
                //  | eNewRoot
                //    | er1* (base: er)  
                //      | ea1* (base: ea)
                //      | eb1* (base: eb)
                //      | ec1* + link ea1* (base: ec)
                //    | er2* (base: er)  
                //      | ea2* (base: ea)
                //      | eb2* (base: eb)
                //      | ec2* + link ea2* (base: ec)
                //  | er1'* (base: er)     
                //    | ea1'* (base: ea)
                //    | eb1'* (base: eb)  
                //    | ec1'* + link ea1'* (base: ec)
                //  | ex(1*)
                //    | ey(1*) + link eb1*
                //  | ex(2*)
                //    | ey(2*) + link eb2*
                //  | ex(1') (base: ex)   
                //    | ey(1') + link eb1'*
                {
                    Assert.True(a4.DumpTo(Console.Out, "a4 AFTER PrefabMergeAsset"));

                    Assert.AreEqual(5, a4.Hierarchy.RootPartIds.Count);
                    Assert.True(a4.Hierarchy.Parts.Where(it => it.Entity.Name != "eRoot").All(it => it.Entity.Name != "eRoot" && it.Base != null));

                    // Check that we have all expected entities
                    Assert.AreEqual(19, a4.Hierarchy.Parts.Count);

                    var eb1 = a4.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb1*")?.Entity;
                    var eb1_2 = a4.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb1'*")?.Entity;
                    var eb2 = a4.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "eb2*")?.Entity;
                    Assert.NotNull(eb1);
                    Assert.NotNull(eb1_2);
                    Assert.NotNull(eb2);

                    // Check that we have ex and ey
                    var exList = a4.Hierarchy.Parts.Where(it => it.Entity.Name == ex.Name).ToList();
                    Assert.AreEqual(3, exList.Count);

                    // Check that both [ex] have both 1 element [ey] and the links to eb1/eb2 are correct
                    {
                        var expecting = new List<Entity>() { eb1, eb1_2, eb2 };

                        for (int i = 0; i < exList.Count; i++)
                        {
                            var ex1 = exList[i].Entity;
                            Assert.AreEqual(1, ex1.Transform.Children.Count);
                            var ey1 = ex1.Transform.Children[0].Entity;
                            Assert.AreEqual(ey.Name, ey1.Name);
                            Assert.NotNull(ey1.Get<TestEntityComponent>());

                            var entityLink = ey1.Get<TestEntityComponent>().EntityLink;
                            Assert.True(expecting.Contains(entityLink));
                            expecting.Remove(entityLink);
                        }
                    }

                    // Check all [er] entities
                    Action<string> checkErX = (erName) =>
                    {
                        var er1 = a4.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == erName)?.Entity;
                        Assert.NotNull(er1);
                        Assert.AreEqual(3, er1.Transform.Children.Count);

                        var ec1 = er1.Transform.Children.FirstOrDefault(it => it.Entity.Name.StartsWith("ec"))?.Entity;
                        Assert.NotNull(ec1);
                        var ea1 = er1.Transform.Children.FirstOrDefault(it => it.Entity.Name.StartsWith("ea"))?.Entity;
                        Assert.NotNull(ea1);

                        Assert.NotNull(ec1.Get<TestEntityComponent>());

                        Assert.AreEqual(ea1, ec1.Get<TestEntityComponent>().EntityLink);
                    };

                    checkErX("er1*");
                    checkErX("er2*");
                    checkErX("er1'*");
                }
            }
        }
        public void TestMultiplePrefabsMixedInheritance()
        {
            // The purpose of this test is to check that modifying a prefab base is correctly propagated through all 
            // derived prefabs. We use the following scenario:
            // a1: base asset)
            // a2: inherit from a1 by composition with 2 instances (baseParts: a1, 2 instances)
            // a3: direct inheritance from a2 (base: a2)
            // This scenario doesn't happen in practice, as we have restricted only to inheritance by composition for prefabs
            // but we verify that the code is actually working for this scenario

            var package = new Package();

            var assetItems = package.Assets;

            // Before Adding Package
            // a1:      a2: (baseParts: a1, 2 instances)     a3: (base: a2)
            //  | ea     | ea1 (base: ea)                     | ea1' (base: ea1)
            //  | eb     | eb1 (base: eb)                     | eb1' (base: eb1)
            //           | ea2 (base: ea)                     | ea2' (base: ea2)
            //           | eb2 (base: eb)                     | eb2' (base: eb2)


            // After adding the package to the session 
            // We add one entity to the base a1 
            // a1:      a2: (baseParts: a1, 2 instances)     a3: (base: a2)
            //  | ea     | ea1 (base: ea)                     | ea1' (base: ea1)
            //  | eb     | eb1 (base: eb)                     | eb1' (base: eb1)
            //  | ec     | ec1 (base: ec)                     | ec1' (base: ec1)
            //           | ea2 (base: ea)                     | ea2' (base: ea2)
            //           | eb2 (base: eb)                     | eb2' (base: eb2)
            //           | ec2 (base: ec)                     | ec2' (base: ec2)

            var a1 = new PrefabAsset();
            var ea = new Entity("ea");
            var eb = new Entity("eb");
            a1.Hierarchy.Parts.Add(new EntityDesign(ea));
            a1.Hierarchy.Parts.Add(new EntityDesign(eb));
            a1.Hierarchy.RootPartIds.Add(ea.Id);
            a1.Hierarchy.RootPartIds.Add(eb.Id);

            assetItems.Add(new AssetItem("a1", a1));

            var a2 = new PrefabAsset();
            var aPartInstance1 = a1.CreatePrefabInstance(a2, "a1");
            var aPartInstance2 = a1.CreatePrefabInstance(a2, "a1");
            a2.Hierarchy.Parts.AddRange(aPartInstance1.Parts);
            a2.Hierarchy.Parts.AddRange(aPartInstance2.Parts);
            a2.Hierarchy.RootPartIds.AddRange(aPartInstance1.RootPartIds);
            a2.Hierarchy.RootPartIds.AddRange(aPartInstance2.RootPartIds);
            assetItems.Add(new AssetItem("a2", a2));

            // Modify a1 to add entity ec
            var ec = new Entity("ec");
            a1.Hierarchy.Parts.Add(new EntityDesign(ec));
            a1.Hierarchy.RootPartIds.Add(ec.Id);

            var a3 = (PrefabAsset)a2.CreateDerivedAsset("a2");

            assetItems.Add(new AssetItem("a3", a3));

            // Create a session with this project
            using (var session = new PackageSession())
            {
                var logger = new LoggerResult();
                session.AddExistingPackage(package, logger);

                Assert.False(logger.HasErrors);

                Assert.AreEqual(6, a2.Hierarchy.RootPartIds.Count);
                Assert.True(a2.Hierarchy.Parts.All(it => it.Base != null));

                Assert.AreEqual(6, a3.Hierarchy.RootPartIds.Count);
                Assert.True(a3.Hierarchy.Parts.All(it => it.Base != null && a2.Hierarchy.Parts.ContainsKey(it.Base.BasePartId)));
            }
        }
        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 PrefabAsset();
            part1.Hierarchy.Parts.Add(new EntityDesign(eRoot));
            part1.Hierarchy.Parts.Add(new EntityDesign(entityA));
            part1.Hierarchy.Parts.Add(new EntityDesign(entityB));
            part1.Hierarchy.Parts.Add(new EntityDesign(entityC));
            part1.Hierarchy.RootPartIds.Add(eRoot.Id);

            // part2 Asset
            var part2 = AssetCloner.Clone(part1);
            var eRootPart2 = part2.Hierarchy.Parts.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.Parts.Where(it => it.Entity.Name == "B").Select(it => it.Entity).First();
            entityD.Add(new TestEntityComponent() { EntityLink = entityBFrom2 });
            part2.Hierarchy.Parts.Add(new EntityDesign(entityD));

            // originalAsset: Add a new instanceId for this part
            var asset = new PrefabAsset();

            // Create derived parts
            //var eRoot1Asset = (PrefabAsset)part1.CreateDerivedAsset("part");
            //var eRoot2Asset = (PrefabAsset)part1.CreateDerivedAsset("part");
            //asset.AddPart(eRoot1Asset);
            //asset.AddPart(eRoot2Asset);
            Guid eRoot1Id;
            Guid eRoot2Id;
            var eRoot1Asset = part1.CreatePrefabInstance(asset, "part", out eRoot1Id);
            var eRoot2Asset = part1.CreatePrefabInstance(asset, "part", out eRoot2Id);
            asset.Hierarchy.Parts.AddRange(eRoot1Asset.Parts);
            asset.Hierarchy.Parts.AddRange(eRoot2Asset.Parts);
            asset.Hierarchy.RootPartIds.AddRange(eRoot1Asset.RootPartIds);
            asset.Hierarchy.RootPartIds.AddRange(eRoot2Asset.RootPartIds);

            //var eRoot2 = asset.Hierarchy.Entities[eRoot2Asset.Hierarchy.RootEntities[0]];
            var eRoot2 = asset.Hierarchy.Parts[eRoot2Asset.RootPartIds[0]];

            var entityToRemove = eRoot2.Entity.Transform.Children.First(it => it.Entity.Name == "B");
            eRoot2.Entity.Transform.Children.Remove(entityToRemove);
            asset.Hierarchy.Parts.Remove(entityToRemove.Entity.Id);

            // EntityD must be now part of the new asset
            Assert.AreEqual(2, asset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(9, asset.Hierarchy.Parts.Count);
            Assert.AreEqual(2, asset.Hierarchy.Parts.Count(it => it.Entity.Name == "D"));

            foreach (var entity in asset.Hierarchy.Parts.Where(it => it.Entity.Name == "D"))
            {
                // Check that we have the correct baesId and basePartInstanceId
                Assert.True(entity.Base != null);
                Assert.AreEqual(entityD.Id, entity.Base.BasePartId);
            }

            var entityDesignD1 = asset.Hierarchy.Parts[asset.Hierarchy.Parts[asset.Hierarchy.RootPartIds[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);
            Assert.AreEqual(eRoot1Id, entityDesignD1.Base.InstanceId);
            var testComponentD1 = entityDesignD1.Entity.Get<TestEntityComponent>();
            Assert.NotNull(testComponentD1);
            var entityB1 = asset.Hierarchy.Parts[asset.Hierarchy.RootPartIds[0]].Entity.Transform.Children.Where(it => it.Entity.Name == "B").Select(it => it.Entity).First();
            Assert.AreEqual(entityB1, testComponentD1.EntityLink);

            var entityDesignD2 = asset.Hierarchy.Parts[asset.Hierarchy.Parts[asset.Hierarchy.RootPartIds[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);
            Assert.AreEqual(eRoot2Id, entityDesignD2.Base.InstanceId);
            var testComponentD2 = entityDesignD2.Entity.Get<TestEntityComponent>();
            Assert.NotNull(testComponentD2);
            Assert.AreEqual(null, testComponentD2.EntityLink);
        }
        public void TestMergeSimpleWithBasePartsAndLinks()
        {
            // part1:                part2:                  newAsset (BaseParts: part1):       newAssetMerged (BaseParts: part2):
            //   EA                    EA                      EA1 (base: EA)                     [0] EA1' (base: EA) 
            //   EB                    EB                      EB1 (base: EB)                     [1] EB1' (base: EB)
            //   EC + link: EA         EC + link: EA           EC1 (base: EC) + link: EA1         [2] EC1' (base: EC) + link: EA1'
            //                         ED + link: EB           EA2 (base: EA)                     [3] EA2' (base: EA)
            //                                                 EB2 (base: EB)                     [4] EB2' (base: EB)
            //                                                 EC2 (base: EC) + link: EA2         [5] EC2' (base: EC) + link: EA2'
            //                                                                                    [6] ED1' (base: ED) + link: EB1'
            //                                                                                    [7] ED2' (base: ED) + link: EB2'
            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 });

            // part1 Asset
            var basePart = new PrefabAsset();
            basePart.Hierarchy.Parts.Add(new EntityDesign(entityA));
            basePart.Hierarchy.Parts.Add(new EntityDesign(entityB));
            basePart.Hierarchy.Parts.Add(new EntityDesign(entityC));
            basePart.Hierarchy.RootPartIds.Add(entityA.Id);
            basePart.Hierarchy.RootPartIds.Add(entityB.Id);
            basePart.Hierarchy.RootPartIds.Add(entityC.Id);

            // originalAsset: Add a new instanceId for this part
            var asset = new PrefabAsset();

            // Create part1 asset
            Guid part1InstanceId;
            Guid part12InstanceId;
            var part1 = basePart.CreatePrefabInstance(asset, "part", out part1InstanceId);
            var entityB1 = part1.Parts.First(it => it.Entity.Name == "B").Entity;
            var part12 = basePart.CreatePrefabInstance(asset, "part", out part12InstanceId);
            var entityB2 = part12.Parts.First(it => it.Entity.Name == "B").Entity;

            // create part2 assset
            var entityD = new Entity() { Name = "D" };
            basePart.Hierarchy.Parts.Add(new EntityDesign(entityD));
            basePart.Hierarchy.RootPartIds.Add(entityD.Id);
            // ED + link: EB
            var entityBFrom2 = basePart.Hierarchy.Parts.Where(it => it.Entity.Name == "B").Select(it => it.Entity).First();
            entityD.Add(new TestEntityComponent() { EntityLink = entityBFrom2 });

            asset.Hierarchy.Parts.AddRange(part1.Parts);
            asset.Hierarchy.Parts.AddRange(part12.Parts);
            asset.Hierarchy.RootPartIds.AddRange(part1.RootPartIds);
            asset.Hierarchy.RootPartIds.AddRange(part12.RootPartIds);

            // EntityD must be now part of the new asset
            Assert.AreEqual(8, asset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(8, asset.Hierarchy.Parts.Count);
            Assert.AreEqual(2, asset.Hierarchy.Parts.Count(it => it.Entity.Name == "D"));

            foreach (var entity in asset.Hierarchy.Parts.Where(it => it.Entity.Name == "D"))
            {
                // Check that we have the correct baesId and basePartInstanceId
                Assert.True(entity.Base != null);
                Assert.AreEqual(entityD.Id, entity.Base.BasePartId);

                // Make sure that the entity is in the RootEntities
                Assert.True(asset.Hierarchy.RootPartIds.Contains(entity.Entity.Id));
            }

            var entityDesignD1 = asset.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "D" && it.Base.InstanceId == part1InstanceId);
            Assert.NotNull(entityDesignD1);

            var entityDesignD2 = asset.Hierarchy.Parts.FirstOrDefault(it => it.Entity.Name == "D" && it.Base.InstanceId == part12InstanceId);
            Assert.NotNull(entityDesignD2);

            // Check components
            var testComponentD1 = entityDesignD1.Entity.Get<TestEntityComponent>();
            Assert.NotNull(testComponentD1);
            Assert.AreEqual(entityB1, testComponentD1.EntityLink);

            var testComponentD2 = entityDesignD2.Entity.Get<TestEntityComponent>();
            Assert.NotNull(testComponentD2);
            Assert.AreEqual(entityB2, testComponentD2.EntityLink);
        }
Esempio n. 6
0
        public void TestCascadedInheritance()
        {
            // Test with:
            // a1: an asset with 2 entities
            // a2: an asset using a1 by composition with 2 instances
            // a3: an asset based on a2
            //
            // Add one entity to a1. Check that a2 and a3 will get correctly the entities replicated

            // Before Merge
            // a1:      a2: (baseParts: a1, 2 instances)     a3: (base: a2)
            //  | ea     | ea1 (base: ea)                     | ea1' (base: ea1)
            //  | eb     | eb1 (base: eb)                     | eb1' (base: eb1)
            //           | ea2 (base: ea)                     | ea2' (base: ea2)
            //           | eb2 (base: eb)                     | eb2' (base: eb2)


            // After Merge
            // We add one entity to the base a1 
            // a1:      a2: (baseParts: a1, 2 instances)     a3: (base: a2)
            //  | ea     | ea1 (base: ea)                     | ea1' (base: ea1)
            //  | eb     | eb1 (base: eb)                     | eb1' (base: eb1)
            //  | ec     | ec1 (base: ec)                     | ec1' (base: ec1)
            //           | ea2 (base: ea)                     | ea2' (base: ea2)
            //           | eb2 (base: eb)                     | eb2' (base: eb2)
            //           | ec2 (base: ec)                     | ec2' (base: ec2)

            var a1 = new PrefabAsset();
            var ea = new Entity("ea");
            var eb = new Entity("eb");
            a1.Hierarchy.Entities.Add(ea);
            a1.Hierarchy.Entities.Add(eb);
            a1.Hierarchy.RootEntities.Add(ea.Id);
            a1.Hierarchy.RootEntities.Add(eb.Id);

            var a2 = new PrefabAsset();
            var aPartInstance1 = a1.CreatePrefabInstance(a2, "a1");
            var aPartInstance2 = a1.CreatePrefabInstance(a2, "a1");
            a2.Hierarchy.Entities.AddRange(aPartInstance1.Entities);
            a2.Hierarchy.Entities.AddRange(aPartInstance2.Entities);
            a2.Hierarchy.RootEntities.AddRange(aPartInstance1.RootEntities);
            a2.Hierarchy.RootEntities.AddRange(aPartInstance2.RootEntities);

            // Modify a1 to add entity ec
            var ec = new Entity("ec");
            a1.Hierarchy.Entities.Add(ec);
            a1.Hierarchy.RootEntities.Add(ec.Id);

            var a3 = (PrefabAsset)a2.CreateChildAsset("a2");

            // Merge a2
            var result2 = a2.Merge(null, null, new List<AssetBase>()
            {
                new AssetBase("a1", (Asset)AssetCloner.Clone(a1))
            });

            Assert.False(result2.HasErrors);
            Assert.AreEqual(6, a2.Hierarchy.RootEntities.Count);
            Assert.True(a2.Hierarchy.Entities.All(it => it.Design.BaseId.HasValue && it.Design.BasePartInstanceId.HasValue));

            // Merge a3
            var result3 = a3.Merge((Asset)AssetCloner.Clone(a3.Base.Asset), (Asset)AssetCloner.Clone(a2), null);

            Assert.False(result3.HasErrors);
            Assert.AreEqual(6, a3.Hierarchy.RootEntities.Count);
            Assert.True(a3.Hierarchy.Entities.All(it => !it.Design.BasePartInstanceId.HasValue));
            Assert.True(a3.Hierarchy.Entities.All(it => it.Design.BaseId.HasValue && a2.Hierarchy.Entities.ContainsKey(it.Design.BaseId.Value)));
        }