public static EntityAsset ExtractSceneClone(EntityAsset 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];
            var subTreeHierarchy = new EntityHierarchyData { Entities = { subTreeRoot }, RootEntities = { sourceRootEntity } };
            foreach (var subTreeEntity in subTreeRoot.EnumerateChildren(true))
                subTreeHierarchy.Entities.Add(subTreeEntity);

            // clone the entities of the sub-tree
            var clonedHierarchy = (EntityHierarchyData)AssetCloner.Clone(subTreeHierarchy);
            clonedHierarchy.Entities[sourceRootEntity].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 = (EntityAsset)AssetCloner.Clone(source);
            clonedAsset.Hierarchy = clonedHierarchy;

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

            return clonedAsset;
        }
Beispiel #2
0
        public static EntityAsset ExtractSceneClone(EntityAsset 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];
            var subTreeHierarchy = new EntityHierarchyData {
                Entities = { subTreeRoot }, RootEntities = { sourceRootEntity }
            };

            foreach (var subTreeEntity in subTreeRoot.EnumerateChildren(true))
            {
                subTreeHierarchy.Entities.Add(subTreeEntity);
            }

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

            clonedHierarchy.Entities[sourceRootEntity].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 = (EntityAsset)AssetCloner.Clone(source);

            clonedAsset.Hierarchy = clonedHierarchy;

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

            return(clonedAsset);
        }
Beispiel #3
0
        public static EntityHierarchyData ImportScene(UFile sourceUrl, EntityAsset source, Guid sourceRootEntity, out EntityBase entityBase)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

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

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

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

                // Update mappings
                entityMapping.Add(newEntityId, entity.Id);
                reverseEntityMapping.Add(entity.Id, newEntityId);

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

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

            // Add asset base
            entityBase = new EntityBase {
                Base = new AssetBase(sourceUrl, newAsset), SourceRoot = sourceRootEntity, IdMapping = entityMapping
            };

            return(newAsset.Hierarchy);
        }
Beispiel #4
0
        public void TestEntitySerialization()
        {
            var entityAsset = new EntityAsset();

            var entity1 = new Entity { Id = Guid.NewGuid() };
            var entity2 = new Entity { Id = Guid.NewGuid() };

            entity1.Transform.Children.Add(entity2.Transform);

            entityAsset.Hierarchy.Entities.Add(entity1);
            entityAsset.Hierarchy.Entities.Add(entity2);

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

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

                stream.Position = 0;
                var entityAsset2 = AssetSerializer.Load(stream, "pdxentity");
            }
        }
        private static Entity CreateTrackingEntity(EntityAsset entityAsset, Entity rootEntityAsset, ModelAsset modelAsset, string nodeName)
        {
            var childEntity = new Entity { Name = nodeName };

            // Add TransformComponent
            childEntity.Add(TransformComponent.Key, new TransformComponent());

            // Add ModelNodeLinkComponent
            childEntity.Add(ModelNodeLinkComponent.Key, new ModelNodeLinkComponent
            {
                NodeName = nodeName,
                Target = rootEntityAsset.Get(ModelComponent.Key),
            });

            // Add this asset to the list
            entityAsset.Hierarchy.Entities.Add(childEntity);

            // Get or create transformation component
            var transformationComponent = rootEntityAsset.GetOrCreate(TransformComponent.Key);

            // Mark node as preserved
            modelAsset.PreserveNodes(new List<string> { nodeName });

            // Add as children of model entity
            transformationComponent.Children.Add(childEntity.GetOrCreate(TransformComponent.Key));

            return childEntity;
        }
Beispiel #6
0
        public static void UpdateScene(EntityAsset source, EntityAsset dest, Guid destRootEntityId)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (dest == null)
            {
                throw new ArgumentNullException("dest");
            }

            EntityBase entityBase;

            if (!dest.AssetBases.TryGetValue(destRootEntityId, out entityBase))
            {
                throw new InvalidOperationException("This entity base was not found with given Id.");
            }

            var entityBaseAsset = (EntityAsset)entityBase.Base.Asset;

            // Extract the scene starting from given root
            var clonedSource = ExtractSceneClone(source, entityBase.SourceRoot);

            // Process entities in mapping
            var entitiesDiff3    = new List <EntityDiff3>();
            var entitiesSourceId = new HashSet <Guid>(entityBase.IdMapping.Values);
            var oppositeMapping  = entityBase.IdMapping.ToDictionary(x => x.Value, x => x.Key);

            foreach (var entityIdEntry in entityBase.IdMapping)
            {
                var entityDiff3 = new EntityDiff3();

                var destEntityId   = entityIdEntry.Key;
                var sourceEntityId = entityIdEntry.Value;

                // Get entity in dest asset (if not there anymore, we can simply skip them, they have been deleted so they can be ignored from future merges)
                if (!dest.Hierarchy.Entities.TryGetValue(destEntityId, out entityDiff3.Asset1))
                {
                    continue;
                }

                // Get entity in updated asset
                clonedSource.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Asset2);

                // Get entity in base (previous import)
                entityBaseAsset.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Base);

                entitiesDiff3.Add(entityDiff3);
            }

            // Merge
            foreach (var entityDiff3 in entitiesDiff3)
            {
                throw new NotImplementedException();
                //entityDiff3.MergeResult = AssetMerge.Merge(entityDiff3.Base, entityDiff3.Asset1, entityDiff3.Asset2, AssetMergePolicies.MergePolicyAsset2AsNewBaseOfAsset1);

                // TODO: Proper logging and error recovery
                if (entityDiff3.MergeResult.HasErrors)
                {
                    throw new InvalidOperationException("Merge error");
                }
            }

            // We gather entities that were added in our source since last import
            // Note: We only cares about the ones that are in source but not in base -- everything else should be in entityBase.IdMapping
            //       (otherwise it means entity has been deleted already in dest and/or source, so merge is deleted)
            var sourceExtraIds = new HashSet <Guid>(clonedSource.Hierarchy.Entities.Select(x => x.Id)); // Everything in source,

            sourceExtraIds.ExceptWith(entityBaseAsset.Hierarchy.Entities.Select(x => x.Id));            // but not in base,
            sourceExtraIds.ExceptWith(entitiesSourceId);                                                // and not in entityBase.IdMapping...

            foreach (var sourceEntityId in sourceExtraIds)
            {
                var entityDiff3 = new EntityDiff3();

                // Get entity in updated asset
                clonedSource.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Asset2);

                // Add it in our new entity, if possible at the same location
                var  asset = entityDiff3.Asset2;
                var  parentSourceEntity = FindParent(clonedSource.Hierarchy, entityDiff3.Asset2);
                Guid parentDestEntityId;
                if (!oppositeMapping.TryGetValue(parentSourceEntity.Id, out parentDestEntityId))
                {
                    continue;
                }
            }

            // Rebuild tree
            foreach (var entityDiff3 in entitiesDiff3)
            {
                // TODO: Try to propagate tree changes (it's not a big deal if we fail, but try to do it as good as possible)
            }
        }
        public static void UpdateScene(EntityAsset source, EntityAsset dest, Guid destRootEntityId)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (dest == null) throw new ArgumentNullException("dest");

            EntityBase entityBase;
            if (!dest.AssetBases.TryGetValue(destRootEntityId, out entityBase))
                throw new InvalidOperationException("This entity base was not found with given Id.");

            var entityBaseAsset = (EntityAsset)entityBase.Base.Asset;

            // Extract the scene starting from given root
            var clonedSource = ExtractSceneClone(source, entityBase.SourceRoot);

            // Process entities in mapping
            var entitiesDiff3 = new List<EntityDiff3>();
            var entitiesSourceId = new HashSet<Guid>(entityBase.IdMapping.Values);
            var oppositeMapping = entityBase.IdMapping.ToDictionary(x => x.Value, x => x.Key);
            foreach (var entityIdEntry in entityBase.IdMapping)
            {
                var entityDiff3 = new EntityDiff3();

                var destEntityId = entityIdEntry.Key;
                var sourceEntityId = entityIdEntry.Value;

                // Get entity in dest asset (if not there anymore, we can simply skip them, they have been deleted so they can be ignored from future merges)
                if (!dest.Hierarchy.Entities.TryGetValue(destEntityId, out entityDiff3.Asset1))
                    continue;

                // Get entity in updated asset
                clonedSource.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Asset2);
                
                // Get entity in base (previous import)
                entityBaseAsset.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Base);

                entitiesDiff3.Add(entityDiff3);
            }

            // Merge
            foreach (var entityDiff3 in entitiesDiff3)
            {
                throw new NotImplementedException();
                //entityDiff3.MergeResult = AssetMerge.Merge(entityDiff3.Base, entityDiff3.Asset1, entityDiff3.Asset2, AssetMergePolicies.MergePolicyAsset2AsNewBaseOfAsset1);

                // TODO: Proper logging and error recovery
                if (entityDiff3.MergeResult.HasErrors)
                    throw new InvalidOperationException("Merge error");
            }

            // We gather entities that were added in our source since last import
            // Note: We only cares about the ones that are in source but not in base -- everything else should be in entityBase.IdMapping
            //       (otherwise it means entity has been deleted already in dest and/or source, so merge is deleted)
            var sourceExtraIds = new HashSet<Guid>(clonedSource.Hierarchy.Entities.Select(x => x.Id));  // Everything in source,
            sourceExtraIds.ExceptWith(entityBaseAsset.Hierarchy.Entities.Select(x => x.Id));            // but not in base,
            sourceExtraIds.ExceptWith(entitiesSourceId);                                                // and not in entityBase.IdMapping...

            foreach (var sourceEntityId in sourceExtraIds)
            {
                var entityDiff3 = new EntityDiff3();

                // Get entity in updated asset
                clonedSource.Hierarchy.Entities.TryGetValue(sourceEntityId, out entityDiff3.Asset2);

                // Add it in our new entity, if possible at the same location
                var asset = entityDiff3.Asset2;
                var parentSourceEntity = FindParent(clonedSource.Hierarchy, entityDiff3.Asset2);
                Guid parentDestEntityId;
                if (!oppositeMapping.TryGetValue(parentSourceEntity.Id, out parentDestEntityId))
                    continue;

                
            }

            // Rebuild tree
            foreach (var entityDiff3 in entitiesDiff3)
            {
                // TODO: Try to propagate tree changes (it's not a big deal if we fail, but try to do it as good as possible)
            }
        }
        public static EntityHierarchyData ImportScene(UFile sourceUrl, EntityAsset source, Guid sourceRootEntity, out EntityBase entityBase)
        {
            if (source == null) throw new ArgumentNullException("source");

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

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

                // Update mappings
                entityMapping.Add(newEntityId, entity.Id);
                reverseEntityMapping.Add(entity.Id, newEntityId);

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

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

            // Add asset base
            entityBase = new EntityBase { Base = new AssetBase(sourceUrl, newAsset), SourceRoot = sourceRootEntity, IdMapping = entityMapping };

            return newAsset.Hierarchy;
        }
Beispiel #9
0
        private static AssetItem ImportEntity(List<AssetItem> assetReferences, UFile localPath, AssetItem modelItem)
        {
            var entityUrl = new UFile(localPath.GetFileName(), null);

            // TODO: Entities do not have source anymore, if this is needed again we should make scene assets that do not inherits from entity assets.
            var asset = new EntityAsset(); // { Source = localPath };
            var rootEntityData = new Entity();
            asset.Hierarchy.Entities.Add(rootEntityData);
            asset.Hierarchy.RootEntity = rootEntityData.Id;

            rootEntityData.Name = entityUrl;
            // Use modelUrl.Path to get the url without the extension
            rootEntityData.Add(ModelComponent.Key, new ModelComponent { Model = AttachedReferenceManager.CreateSerializableVersion<Rendering.Model>(modelItem.Id, modelItem.Location) });

            var assetReference = new AssetItem(entityUrl, asset);
            assetReferences.Add(assetReference);

            return assetReference;
        }
        private static AssetItem ImportEntity(List<AssetItem> assetReferences, UFile localPath, AssetItem modelItem)
        {
            var entityUrl = new UFile(localPath.GetFileName(), null);

            var asset = new EntityAsset { Source = localPath };
            var rootEntityData = new Entity();
            asset.Hierarchy.Entities.Add(rootEntityData);
            asset.Hierarchy.RootEntity = rootEntityData.Id;

            rootEntityData.Name = entityUrl;
            // Use modelUrl.Path to get the url without the extension
            rootEntityData.Add(ModelComponent.Key, new ModelComponent { Model = AttachedReferenceManager.CreateSerializableVersion<Rendering.Model>(modelItem.Id, modelItem.Location) });

            var assetReference = new AssetItem(entityUrl, asset);
            assetReferences.Add(assetReference);

            return assetReference;
        }