/// <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 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); } }
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); }