public static EntityHierarchyData ImportScene(UFile sourceUrl, EntityGroupAssetBase source, Guid sourceRootEntity)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            // Extract the scene starting from given root
            var newAsset = ExtractSceneClone(source, sourceRootEntity);

            // Generate entity mapping
            var reverseEntityMapping = new Dictionary <Guid, Guid>();

            foreach (var entityDesign in newAsset.Hierarchy.Entities)
            {
                // Generate new Id
                var newEntityId = Guid.NewGuid();

                // Update mappings
                reverseEntityMapping.Add(entityDesign.Entity.Id, newEntityId);

                // Update entity with new id
                entityDesign.Entity.Id = newEntityId;
            }

            // Rewrite entity references
            // Should we nullify invalid references?
            EntityAnalysis.RemapEntitiesId(newAsset.Hierarchy, reverseEntityMapping);

            return(newAsset.Hierarchy);
        }
Example #2
0
        void IDiffResolver.BeforeDiff(Asset baseAsset, Asset asset1, Asset asset2)
        {
            var baseEntityAsset = (EntityAsset)baseAsset;
            var entityAsset1    = (EntityAsset)asset1;
            var entityAsset2    = (EntityAsset)asset2;

            // Let's remap IDs in asset2 (if it comes from a FBX or such, we need to do that)
            var oldBaseTree = new EntityTreeAsset(baseEntityAsset.Hierarchy);
            var newBaseTree = new EntityTreeAsset(entityAsset2.Hierarchy);

            var idRemapping = new Dictionary <Guid, Guid>();

            // Try to transfer ID from old base to new base
            var mergeResult = AssetMerge.Merge(oldBaseTree, newBaseTree, oldBaseTree, node =>
            {
                if (typeof(Guid).IsAssignableFrom(node.InstanceType) && node.BaseNode != null && node.Asset1Node != null)
                {
                    idRemapping.Add((Guid)node.Asset1Node.Instance, (Guid)node.BaseNode.Instance);
                }

                return(AssetMergePolicies.MergePolicyAsset2AsNewBaseOfAsset1(node));
            });

            if (mergeResult.HasErrors)
            {
                //mergeResult.CopyTo();
            }

            EntityAnalysis.RemapEntitiesId(entityAsset2.Hierarchy, idRemapping);
        }
        /// <summary>
        /// Clones a sub-hierarchy of this asset.
        /// </summary>
        /// <param name="sourceRootEntity">The entity that is the root of the sub-hierarchy to clone</param>
        /// <param name="cleanReference">If true, any reference to an entity external to the cloned hierarchy will be set to null.</param>
        /// <param name="entityMapping">A dictionary containing the mapping of ids from the source entites to the new entities.</param>
        /// <returns>A <see cref="EntityHierarchyData"/> corresponding to the cloned entities.</returns>
        public EntityHierarchyData CloneSubHierarchy(Guid sourceRootEntity, bool cleanReference, out Dictionary <Guid, Guid> entityMapping)
        {
            if (!Hierarchy.Entities.ContainsKey(sourceRootEntity))
            {
                throw new ArgumentException(@"The source root entity must be an entity of this asset.", nameof(sourceRootEntity));
            }

            // Note: Instead of copying the whole asset (with its potentially big hierarchy),
            // we first copy the asset only (without the hierarchy), then the sub-hierarchy to extract.
            var subTreeRoot      = Hierarchy.Entities[sourceRootEntity];
            var subTreeHierarchy = new EntityHierarchyData {
                Entities = { subTreeRoot }, RootEntities = { sourceRootEntity }
            };

            foreach (var subTreeEntity in EnumerateChildren(subTreeRoot, true))
            {
                subTreeHierarchy.Entities.Add(Hierarchy.Entities[subTreeEntity.Entity.Id]);
            }

            // clone the entities of the sub-tree
            var clonedHierarchy = (EntityHierarchyData)AssetCloner.Clone(subTreeHierarchy);

            clonedHierarchy.Entities[sourceRootEntity].Entity.Transform.Parent = null;

            if (cleanReference)
            {
                // set to null reference outside of the sub-tree
                EntityAnalysis.FixupEntityReferences(clonedHierarchy);
            }

            // temporary nullify the hierarchy to avoid to clone it
            var sourceHierarchy = Hierarchy;

            Hierarchy = null;

            // revert the source hierarchy
            Hierarchy = sourceHierarchy;

            // Generate entity mapping
            entityMapping = new Dictionary <Guid, Guid>();
            foreach (var entityDesign in clonedHierarchy.Entities)
            {
                // Generate new Id
                var newEntityId = Guid.NewGuid();

                // Update mappings
                entityMapping.Add(entityDesign.Entity.Id, newEntityId);

                // Update entity with new id
                entityDesign.Entity.Id = newEntityId;
            }

            // Rewrite entity references
            // Should we nullify invalid references?
            EntityAnalysis.RemapEntitiesId(clonedHierarchy, entityMapping);

            return(clonedHierarchy);
        }
        public static EntityGroupAssetBase ExtractSceneClone(EntityGroupAssetBase source, Guid sourceRootEntity)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            // Note: Instead of copying the whole asset (with its potentially big hierarchy), we first copy the asset only (without the hierarchy), then the sub-hierarchy to extract.

            // create the hierarchy of the sub-tree
            var subTreeRoot      = source.Hierarchy.Entities[sourceRootEntity].Entity;
            var subTreeHierarchy = new EntityHierarchyData {
                Entities = { subTreeRoot }, RootEntities = { sourceRootEntity }
            };

            foreach (var subTreeEntity in subTreeRoot.EnumerateChildren(true))
            {
                subTreeHierarchy.Entities.Add(source.Hierarchy.Entities[subTreeEntity.Id]);
            }

            // clone the entities of the sub-tree
            var clonedHierarchy = (EntityHierarchyData)AssetCloner.Clone(subTreeHierarchy);

            clonedHierarchy.Entities[sourceRootEntity].Entity.Transform.Parent = null;

            // set to null reference outside of the sub-tree
            EntityAnalysis.FixupEntityReferences(clonedHierarchy);

            // temporary nullify the hierarchy to avoid to clone it
            var sourceHierarchy = source.Hierarchy;

            source.Hierarchy = null;

            // clone asset without hierarchy
            var clonedAsset = (EntityGroupAssetBase)AssetCloner.Clone(source);

            clonedAsset.Hierarchy = clonedHierarchy;

            // revert the source hierarchy
            source.Hierarchy = sourceHierarchy;

            return(clonedAsset);
        }
        public override Asset CreateChildAsset(string location)
        {
            var newAsset = (EntityHierarchyAssetBase)base.CreateChildAsset(location);

            var newIdMaps = Hierarchy.Entities.ToDictionary(x => x.Entity.Id, x => Guid.NewGuid());

            foreach (var entity in newAsset.Hierarchy.Entities)
            {
                // Store the baseid of the new version
                entity.Design.BaseId = entity.Entity.Id;
                // Make sure that we don't replicate the base part InstanceId
                entity.Design.BasePartInstanceId = null;
                // Apply the new Guid
                entity.Entity.Id = newIdMaps[entity.Entity.Id];
            }

            EntityAnalysis.RemapEntitiesId(newAsset.Hierarchy, newIdMaps);

            return(newAsset);
        }
Example #6
0
        public override object ReadYaml(ref ObjectContext objectContext)
        {
            EnterNode(ref objectContext);

            try
            {
                var result = base.ReadYaml(ref objectContext);

                if (typeof(EntityAssetBase).IsAssignableFrom(objectContext.Descriptor.Type))
                {
                    // Let's fixup entity references after serialization
                    EntityAnalysis.FixupEntityReferences((EntityAssetBase)objectContext.Instance);
                }

                return(result);
            }
            finally
            {
                LeaveNode(ref objectContext);
            }
        }
Example #7
0
            public void ApplyChanges()
            {
                // "Garbage collect" entities that are not referenced in hierarchy tree anymore
                var entityHashes = new HashSet <Guid>();

                foreach (var rootEntity in source.RootEntities)
                {
                    CollectEntities(entityHashes, rootEntity);
                }

                source.Entities.Clear();
                foreach (var item in this)
                {
                    if (entityHashes.Contains(item.Key))
                    {
                        source.Entities.Add(item.Value);
                    }
                }

                // Fixup references
                EntityAnalysis.FixupEntityReferences(source);
            }
Example #8
0
        /// <summary>
        /// Clones a sub-hierarchy of this asset.
        /// </summary>
        /// <param name="sourceRootEntities">The entities that are the roots of the sub-hierarchies to clone</param>
        /// <param name="cleanReference">If true, any reference to an entity external to the cloned hierarchy will be set to null.</param>
        /// <param name="entityMapping">A dictionary containing the mapping of ids from the source entites to the new entities.</param>
        /// <returns>A <see cref="AssetCompositeHierarchyData{EntityDesign, Entity}"/> corresponding to the cloned entities.</returns>
        /// <remarks>The entities passed to this methods must be independent in the hierarchy.</remarks>
        public AssetCompositeHierarchyData <EntityDesign, Entity> CloneSubHierarchies(IEnumerable <Guid> sourceRootEntities, bool cleanReference, out Dictionary <Guid, Guid> entityMapping)
        {
            // Note: Instead of copying the whole asset (with its potentially big hierarchy),
            // we first copy the asset only (without the hierarchy), then the sub-hierarchy to extract.
            var subTreeHierarchy = new AssetCompositeHierarchyData <EntityDesign, Entity>();

            foreach (var sourceRootEntity in sourceRootEntities)
            {
                if (!Hierarchy.Parts.ContainsKey(sourceRootEntity))
                {
                    throw new ArgumentException(@"The source root entities must be entities of this asset.", nameof(sourceRootEntities));
                }

                var subTreeRoot = Hierarchy.Parts[sourceRootEntity].Entity;
                subTreeHierarchy.Parts.Add(new EntityDesign(subTreeRoot));
                subTreeHierarchy.RootPartIds.Add(sourceRootEntity);
                foreach (var subTreeEntity in EnumerateChildParts(subTreeRoot, true))
                {
                    subTreeHierarchy.Parts.Add(Hierarchy.Parts[subTreeEntity.Id]);
                }
            }

            // clone the entities of the sub-tree
            var clonedHierarchy = (AssetCompositeHierarchyData <EntityDesign, Entity>)AssetCloner.Clone(subTreeHierarchy);

            foreach (var rootEntity in clonedHierarchy.RootPartIds)
            {
                clonedHierarchy.Parts[rootEntity].Entity.Transform.Parent = null;
            }

            if (cleanReference)
            {
                // set to null reference outside of the sub-tree
                var tempAsset = new PrefabAsset {
                    Hierarchy = clonedHierarchy
                };
                tempAsset.FixupPartReferences();
            }

            // temporary nullify the hierarchy to avoid to clone it
            var sourceHierarchy = Hierarchy;

            Hierarchy = null;

            // revert the source hierarchy
            Hierarchy = sourceHierarchy;

            // Generate entity mapping
            entityMapping = new Dictionary <Guid, Guid>();
            foreach (var entityDesign in clonedHierarchy.Parts)
            {
                // Generate new Id
                var newEntityId = Guid.NewGuid();

                // Update mappings
                entityMapping.Add(entityDesign.Entity.Id, newEntityId);

                // Update entity with new id
                entityDesign.Entity.Id = newEntityId;
            }

            // Rewrite entity references
            // Should we nullify invalid references?
            EntityAnalysis.RemapEntitiesId(clonedHierarchy, entityMapping);

            return(clonedHierarchy);
        }