public void TestInheritance()
        {
            // -----------------------------------------------------------
            // Tests inheritance
            // -----------------------------------------------------------
            // 4 assets
            // [asset1] is referencing [asset2]
            // [asset2]
            // [asset3] is inheriting  [asset1]
            // We create a [project1] with [asset1, asset2, asset3]
            // Check direct inherit dependencies for [asset3]: [asset1]
            // -----------------------------------------------------------

            var asset1 = new AssetObjectTest();
            var asset2 = new AssetObjectTest();
            var assetItem1 = new AssetItem("asset-1", asset1);
            var assetItem2 = new AssetItem("asset-2", asset2);

            var asset3 = assetItem1.CreateDerivedAsset();
            var assetItem3 = new AssetItem("asset-3", asset3);

            asset1.Reference = new AssetReference(assetItem2.Id, assetItem2.Location);

            var project = new Package();
            project.Assets.Add(assetItem1);
            project.Assets.Add(assetItem2);
            project.Assets.Add(assetItem3);

            // Create a session with this project
            using (var session = new PackageSession(project))
            {
                var dependencyManager = session.DependencyManager;

                // Verify inheritance
                {
                    var assets = dependencyManager.FindAssetsInheritingFrom(asset1.Id);
                    Assert.AreEqual(1, assets.Count);
                    Assert.AreEqual(asset3.Id, assets[0].Id);
                }

                // Remove the inheritance
                var copyBase = asset3.Archetype;
                asset3.Archetype = null;
                assetItem3.IsDirty = true;
                {
                    var assets = dependencyManager.FindAssetsInheritingFrom(asset1.Id);
                    Assert.AreEqual(0, assets.Count);
                }

                // Add back the inheritance
                asset3.Archetype = copyBase;
                assetItem3.IsDirty = true;
                {
                    var assets = dependencyManager.FindAssetsInheritingFrom(asset1.Id);
                    Assert.AreEqual(1, assets.Count);
                    Assert.AreEqual(asset3.Id, assets[0].Id);
                }
            }
        }
        public void TestCreateChildAsset()
        {
            // Create an Entity child asset

            // base: EA, EB, EC
            // newAsset: EA'(base: EA), EB'(base: EB), EC'(base: EC)

            var entityA = new Entity() { Name = "A" };
            var entityB = new Entity() { Name = "B" };
            var entityC = new Entity() { Name = "C" };

            // Create Base Asset
            var baseAsset = new PrefabAsset();
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityA));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityB));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityC));
            baseAsset.Hierarchy.RootPartIds.Add(entityA.Id);
            baseAsset.Hierarchy.RootPartIds.Add(entityB.Id);
            baseAsset.Hierarchy.RootPartIds.Add(entityC.Id);

            var baseAssetItem = new AssetItem("base", baseAsset);

            // Create new Asset (from base)
            var newAsset = (PrefabAsset)baseAssetItem.CreateDerivedAsset();

            // On a derive asset all entities must have a base value and base must come from baseAsset
            Assert.True(newAsset.Hierarchy.Parts.All(item => item.Base != null && baseAsset.Hierarchy.Parts.ContainsKey(item.Base.BasePartId)));

            // Verify that we have exactly the same number of entities
            Assert.AreEqual(baseAsset.Hierarchy.RootPartIds.Count, newAsset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(baseAsset.Hierarchy.Parts.Count, newAsset.Hierarchy.Parts.Count);

            // Verify that baseId and newId is correctly setup
            var entityAInNew = newAsset.Hierarchy.Parts.FirstOrDefault(item => item.Base.BasePartId == entityA.Id && item.Entity.Id != item.Base.BasePartId);
            Assert.NotNull(entityAInNew);

            var entityBInNew = newAsset.Hierarchy.Parts.FirstOrDefault(item => item.Base.BasePartId == entityB.Id && item.Entity.Id != item.Base.BasePartId);
            Assert.NotNull(entityBInNew);

            var entityCInNew = newAsset.Hierarchy.Parts.FirstOrDefault(item => item.Base.BasePartId == entityC.Id && item.Entity.Id != item.Base.BasePartId);
            Assert.NotNull(entityCInNew);

            // Verify that RootEntities are also correctly mapped
            Assert.AreEqual(entityAInNew.Entity.Id, newAsset.Hierarchy.RootPartIds[0]);
            Assert.AreEqual(entityBInNew.Entity.Id, newAsset.Hierarchy.RootPartIds[1]);
            Assert.AreEqual(entityCInNew.Entity.Id, newAsset.Hierarchy.RootPartIds[2]);
        }
        public void TestMergeSimpleHierarchy()
        {
            // Test merging a simple Entity Asset that has 3 entities
            //
            // base: EA, EB, EC
            // newBase: EA, EB, EC, ED
            // newAsset: EA, EB, EC
            //
            // Result Merge: EA, EB, EC, ED

            var entityA = new Entity() { Name = "A" };
            var entityB = new Entity() { Name = "B" };
            var entityC = new Entity() { Name = "C" };

            // Create Base Asset
            var baseAsset = new PrefabAsset();
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityA));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityB));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(entityC));
            baseAsset.Hierarchy.RootPartIds.Add(entityA.Id);
            baseAsset.Hierarchy.RootPartIds.Add(entityB.Id);
            baseAsset.Hierarchy.RootPartIds.Add(entityC.Id);

            var baseAssetItem = new AssetItem("base", baseAsset);

            // Create new Base Asset
            var entityD = new Entity() { Name = "D" };
            var newBaseAsset = AssetCloner.Clone(baseAsset);
            newBaseAsset.Hierarchy.Parts.Add(new EntityDesign(entityD));
            newBaseAsset.Hierarchy.RootPartIds.Add(entityD.Id);

            // Create new Asset (from base)
            var newAsset = (PrefabAsset)baseAssetItem.CreateDerivedAsset();

            // Both root and entities must be the same
            Assert.AreEqual(4, newAsset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(4, newAsset.Hierarchy.Parts.Count);

            // All entities must have a base value
            Assert.True(newAsset.Hierarchy.Parts.All(item => item.Base != null));

            var entityAInNewAsset = newAsset.Hierarchy.Parts.Where(item => item.Base.BasePartId == entityA.Id).Select(item => item.Entity).FirstOrDefault();
            Assert.NotNull(entityAInNewAsset);
            var entityBInNewAsset = newAsset.Hierarchy.Parts.Where(item => item.Base.BasePartId == entityB.Id).Select(item => item.Entity).FirstOrDefault();
            Assert.NotNull(entityBInNewAsset);
            var entityCInNewAsset = newAsset.Hierarchy.Parts.Where(item => item.Base.BasePartId == entityC.Id).Select(item => item.Entity).FirstOrDefault();
            Assert.NotNull(entityCInNewAsset);

            var entityDInNewAsset = newAsset.Hierarchy.Parts.Where(item => item.Base.BasePartId == entityD.Id).Select(item => item.Entity).FirstOrDefault();
            Assert.NotNull(entityDInNewAsset);

            // Hierarchy must be: EA, EB, EC, ED
            Assert.AreEqual(entityAInNewAsset.Id, newAsset.Hierarchy.RootPartIds[0]);
            Assert.AreEqual(entityBInNewAsset.Id, newAsset.Hierarchy.RootPartIds[1]);
            Assert.AreEqual(entityCInNewAsset.Id, newAsset.Hierarchy.RootPartIds[2]);
            Assert.AreEqual(entityDInNewAsset.Id, newAsset.Hierarchy.RootPartIds[3]);
        }
        public void TestMergeAddEntityWithLinks2()
        {
            // Test merging an PrefabAsset with a root entity EA, and 3 child entities
            // - Add a child entity to NewBase that has a link to an another entity + a link to the component of another entity
            //
            //       Base         NewBase                      NewAsset                  NewAsset (Merged)
            //                                                 
            //       EA           EA                           EA'(base: EA)             EA'(base: EA)
            //        |-EA1       |-EA1                        |-EA1'(base: EA1)         |-EA1'(base: EA1)
            //        |-EA2       |-EA2 + link EA4             |-EA2'(base: EA2)         |-EA2'(base: EA2) + link EA4'
            //        |-EA3       |-EA3                        |-EA3'(base: EA3)         |-EA3'(base: EA3)
            //                    |-EA4                                                  |-EA4'(base: EA4)
            //
            var eA = new Entity() { Name = "A" };
            var eA1 = new Entity() { Name = "A1" };
            var eA2 = new Entity() { Name = "A2" };
            var eA3 = new Entity() { Name = "A3" };
            eA.Transform.Children.Add(eA1.Transform);
            eA.Transform.Children.Add(eA2.Transform);
            eA.Transform.Children.Add(eA3.Transform);

            // Create Base Asset
            var baseAsset = new PrefabAsset();
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA1));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA2));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA3));
            baseAsset.Hierarchy.RootPartIds.Add(eA.Id);

            var baseAssetItem = new AssetItem("base", baseAsset);

            // Create new Base Asset
            var newBaseAsset = AssetCloner.Clone(baseAsset);
            var eA4 = new Entity() { Name = "A4" };
            var rootInNewBase = newBaseAsset.Hierarchy.Parts[newBaseAsset.Hierarchy.RootPartIds.First()];

            var eA2InNewBaseTransform = rootInNewBase.Entity.Transform.Children.FirstOrDefault(item => item.Entity.Id == eA2.Id);
            Assert.NotNull(eA2InNewBaseTransform);

            // Add EA4 with link to EA1 entity and EA2 component
            var testComponent = new TestEntityComponent
            {
                EntityLink = eA4,
            };

            eA2InNewBaseTransform.Entity.Add(testComponent);
            newBaseAsset.Hierarchy.Parts.Add(new EntityDesign(eA4));
            rootInNewBase.Entity.Transform.Children.Add(eA4.Transform);

            // Create new Asset (from base)
            var newAsset = (PrefabAsset)baseAssetItem.CreateDerivedAsset();

            Assert.AreEqual(1, newAsset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(5, newAsset.Hierarchy.Parts.Count); // EA, EA1', EA2', EA3', EA4'

            var rootEntity = newAsset.Hierarchy.Parts[newAsset.Hierarchy.RootPartIds.First()];

            Assert.AreEqual(4, rootEntity.Entity.Transform.Children.Count);

            var eA1Merged = rootEntity.Entity.Transform.Children[0].Entity;
            var eA2Merged = rootEntity.Entity.Transform.Children[1].Entity;
            var eA4Merged = rootEntity.Entity.Transform.Children[3].Entity;
            Assert.AreEqual("A1", eA1Merged.Name);
            Assert.AreEqual("A2", eA2Merged.Name);
            Assert.AreEqual("A3", rootEntity.Entity.Transform.Children[2].Entity.Name);
            Assert.AreEqual("A4", eA4Merged.Name);

            var testComponentMerged = eA2Merged.Get<TestEntityComponent>();
            Assert.NotNull(testComponentMerged);

            Assert.AreEqual(eA4Merged, testComponentMerged.EntityLink);
        }
        public void TestMergeEntityWithChildren()
        {
            // Test merging an PrefabAsset with a root entity EA, and 3 child entities
            // - Add a child entity to NewBase
            // - Remove a child entity from NewAsset
            //
            //       Base         NewBase       NewAsset                  NewAsset (Merged)
            // 
            //       EA           EA            EA'(base: EA)             EA'(base: EA)
            //        |-EA1       |-EA1         |-EA1'(base: EA1)         |-EA1'(base: EA1)
            //        |-EA2       |-EA2         |                         |
            //        |-EA3       |-EA3         |-EA3'(base: EA3)         |-EA3'(base: EA3)
            //                    |-EA4                                   |-EA4'(base: EA4)
            //

            var eA = new Entity() { Name = "A" };
            var eA1 = new Entity() { Name = "A1" };
            var eA2 = new Entity() { Name = "A2" };
            var eA3 = new Entity() { Name = "A3" };
            eA.Transform.Children.Add(eA1.Transform);
            eA.Transform.Children.Add(eA2.Transform);
            eA.Transform.Children.Add(eA3.Transform);

            // Create Base Asset
            var baseAsset = new PrefabAsset();
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA1));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA2));
            baseAsset.Hierarchy.Parts.Add(new EntityDesign(eA3));
            baseAsset.Hierarchy.RootPartIds.Add(eA.Id);

            var baseAssetItem = new AssetItem("base", baseAsset);

            // Create new Base Asset
            var newBaseAsset = AssetCloner.Clone(baseAsset);
            var eA2FromNewBase = newBaseAsset.Hierarchy.Parts.First(item => item.Entity.Id == eA2.Id);
            newBaseAsset.Hierarchy.Parts[eA.Id].Entity.Transform.Children.Remove(eA2FromNewBase.Entity.Transform);

            // Create new Asset (from base)
            var newAsset = (PrefabAsset)baseAssetItem.CreateDerivedAsset();
            var eA4 = new Entity() { Name = "A4" };
            newAsset.Hierarchy.Parts.Add(new EntityDesign(eA4));
            newAsset.Hierarchy.Parts[newAsset.Hierarchy.RootPartIds.First()].Entity.Transform.Children.Add(eA4.Transform);

            Assert.AreEqual(1, newAsset.Hierarchy.RootPartIds.Count);
            Assert.AreEqual(4, newAsset.Hierarchy.Parts.Count); // EA, EA1', EA3', EA4'

            var rootEntity = newAsset.Hierarchy.Parts[newAsset.Hierarchy.RootPartIds.First()];

            Assert.AreEqual(3, rootEntity.Entity.Transform.Children.Count);

            Assert.AreEqual("A1", rootEntity.Entity.Transform.Children[0].Entity.Name);
            Assert.AreEqual("A3", rootEntity.Entity.Transform.Children[1].Entity.Name);
            Assert.AreEqual("A4", rootEntity.Entity.Transform.Children[2].Entity.Name);
        }