Exemplo n.º 1
0
        public static TEntity MakeTrackable <TEntity>(TEntity entity) where TEntity : class
        {
            var trackableInterceptor = new DirtyPropertiesTrackerInterceptor();
            var options = new ProxyGenerationOptions(_generationHook);

            options.AddMixinInstance(new DirtyPropertiesTracker());

            var proxy = (TEntity)_generator.CreateClassProxy <TEntity>(
                options,
                trackableInterceptor);

            if (entity == null)
            {
                return(proxy);
            }

            var result = EntityPatcher <TEntity> .Patch(entity, proxy);

            if (result.IsSuccess)
            {
                return(result.Value);
            }
            else
            {
                return(proxy);
            }
        }
Exemplo n.º 2
0
        public void EntityPatcher_ApplyChanges_EntityPatchWithAmbiguousTargetDoesNotThrow()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid0 = CreateEntityGuid();
                var entity0     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity0, entityGuid0);

                var entityGuid1 = CreateEntityGuid();
                var entity1     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity1, entityGuid1);

                PushChanges(differ, DstEntityManager);

                // Create a patch
                SrcEntityManager.AddComponentData(entity1, new EcsTestDataEntity {
                    value1 = entity0
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.IncludeForwardChangeSet, Allocator.TempJob))
                {
                    var forward = changes.ForwardChangeSet;

                    Assert.That(forward.EntityReferenceChanges.Length, Is.EqualTo(1));

                    // Create a new entity in the dst world with the same ID the patch target.
                    var dstEntity0 = DstEntityManager.CreateEntity();
                    DstEntityManager.AddComponentData(dstEntity0, entityGuid1);

                    Assert.DoesNotThrow(() => { EntityPatcher.ApplyChangeSet(DstEntityManager, forward); });
                }
            }
        }
Exemplo n.º 3
0
        public void EntityPatcher_ApplyChanges_EntityPatchWithMissingValueDoesNotThrow()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid0 = CreateEntityGuid();
                var entity0     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity0, entityGuid0);

                var entityGuid1 = CreateEntityGuid();
                var entity1     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity1, entityGuid1);

                PushChanges(differ, DstEntityManager);

                // Create a component with an entity reference
                SrcEntityManager.AddComponentData(entity1, new EcsTestDataEntity {
                    value1 = entity0
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.IncludeForwardChangeSet, Allocator.TempJob))
                {
                    var forward = changes.ForwardChangeSet;

                    Assert.That(forward.EntityReferenceChanges.Length, Is.EqualTo(1));

                    // Destroy the entity the patch references
                    SrcEntityManager.DestroyEntity(entity0);

                    Assert.DoesNotThrow(() => { EntityPatcher.ApplyChangeSet(DstEntityManager, forward); });
                }
            }
        }
    public void CanSerializeAndDeserializeManagedComponents()
    {
        using (var differ = new EntityManagerDiffer(SrcWorld.EntityManager, Allocator.TempJob))
        {
            var entityGuid = CreateEntityGuid();
            var entity     = SrcEntityManager.CreateEntity();

            var srcManagedComponent = new EcsTestManagedDataEntity
            {
                value0    = "Hello",
                value2    = 42,
                nullField = new ClassWithClassFields
                {
                    ClassWithString = new ClassWithString
                    {
                        String = "World"
                    }
                }
            };

            SrcEntityManager.AddComponentData(entity, entityGuid);
            SrcEntityManager.AddComponentData(entity, srcManagedComponent);
            SrcEntityManager.AddComponentData(entity, (EcsTestManagedComponent2)null);

            var options = EntityManagerDifferOptions.IncludeForwardChangeSet | EntityManagerDifferOptions.FastForwardShadowWorld;

            using (var changes = differ.GetChanges(options, Allocator.TempJob))
            {
                var srcChange = new LiveLinkChangeSet
                {
                    Changes   = changes.ForwardChangeSet,
                    SceneName = "Boing",
                    UnloadAllPreviousEntities = true,
                    SceneGUID = new Unity.Entities.Hash128(),
                    FramesToRetainBlobAssets = 1
                };

                var changeSet = SerializeAndDeserialize(srcChange);
                AssertChangeSetsAreEqual(srcChange, changeSet);
                EntityPatcher.ApplyChangeSet(DstEntityManager, changeSet.Changes);
                changeSet.Dispose();
            }

            var dstManagedComponent = GetManagedComponentData <EcsTestManagedDataEntity>(DstEntityManager, entityGuid);

            Assert.That(dstManagedComponent, Is.Not.Null);
            Assert.That(dstManagedComponent, Is.Not.SameAs(srcManagedComponent));
            Assert.That(dstManagedComponent.value0, Is.EqualTo(srcManagedComponent.value0));
            Assert.That(dstManagedComponent.value1, Is.EqualTo(srcManagedComponent.value1));
            Assert.That(dstManagedComponent.value2, Is.EqualTo(srcManagedComponent.value2));
            Assert.That(dstManagedComponent.nullField, Is.Not.SameAs(srcManagedComponent.nullField));
            Assert.That(dstManagedComponent.nullField.ClassWithString, Is.Not.SameAs(srcManagedComponent.nullField.ClassWithString));
            Assert.That(dstManagedComponent.nullField.ClassWithString.String, Is.EqualTo(srcManagedComponent.nullField.ClassWithString.String));

            Assert.That(GetManagedComponentData <EcsTestManagedComponent2>(DstEntityManager, entityGuid), Is.Null);
        }
    }
        public void ApplyPatch(LiveLinkChangeSet changeSet)
        {
            var dstEntities = _DstWorld.EntityManager;
            var sceneSystem = _DstWorld.GetExistingSystem<SceneSystem>();
            Entity sectionEntity;
            var sceneEntity = sceneSystem.GetSceneEntity(changeSet.SceneGUID);

            //@TODO: Check if the scene or section is requested to be loaded
            if (sceneEntity == Entity.Null)
            {
                Debug.LogWarning($"'{changeSet.SceneName}' ({{changeSet.sceneGUID}}) was ignored in live link since it is not loaded.");
                return;
            }

            // Unload scene
            if (changeSet.UnloadAllPreviousEntities)
            {
                //@Todo: Can we try to keep scene & section entities alive? (In case user put custom data on it)
                sceneSystem.UnloadScene(sceneEntity, SceneSystem.UnloadParameters.DestroySectionProxyEntities | SceneSystem.UnloadParameters.DontRemoveRequestSceneLoaded);

                // Create section
                sectionEntity = dstEntities.CreateEntity();
                dstEntities.AddComponentData(sectionEntity, new SceneSectionStreamingSystem.StreamingState { Status = SceneSectionStreamingSystem.StreamingStatus.Loaded});
                dstEntities.AddComponentData(sectionEntity, new DisableSceneResolveAndLoad( ));

                // Configure scene
                dstEntities.AddComponentData(sceneEntity, new DisableSceneResolveAndLoad( ));
                dstEntities.AddComponentData(sceneEntity, new LiveLinkedSceneState { Scene = changeSet.SceneGUID });

                dstEntities.AddBuffer<ResolvedSectionEntity>(sceneEntity).Add(new ResolvedSectionEntity { SectionEntity = sectionEntity} );
                
#if UNITY_EDITOR
                dstEntities.SetName(sectionEntity, "SceneSection (LiveLink): " + changeSet.SceneName);
                dstEntities.SetName(sceneEntity, "Scene (LiveLink): " + changeSet.SceneName);
#endif
            }
            else
            {
                sectionEntity = dstEntities.GetBuffer<ResolvedSectionEntity>(sceneEntity)[0].SectionEntity;
            }
            
            // SceneTag.SceneEntity == Entity.Null is reserved for new entities added via live link.
            if (_AddedScenesQuery.CalculateChunkCount() != 0)
            {
                Debug.LogWarning("SceneTag.SceneEntity must not reference Entity.Null. Destroying Entities.");
                dstEntities.DestroyEntity(_AddedScenesQuery);
            }
            
            EntityPatcher.ApplyChangeSet(_DstWorld.EntityManager, changeSet.Changes);
            
            //liveLink.ConvertedShadowWorld.EntityManager.Debug.CheckInternalConsistency();

            dstEntities.SetSharedComponentData(_AddedScenesQuery, new SceneTag { SceneEntity = sectionEntity });

            EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
        }
        /// <summary>
        /// Pushes forward changes from the tracker to the applier.
        /// </summary>
        protected static void PushChanges(EntityManagerDiffer differ, EntityManager target, bool fastForward = true)
        {
            var options = EntityManagerDifferOptions.IncludeForwardChangeSet;

            if (fastForward)
            {
                options |= EntityManagerDifferOptions.FastForwardShadowWorld;
            }

            using (var changes = differ.GetChanges(options, Allocator.TempJob))
            {
                EntityPatcher.ApplyChangeSet(target, changes.ForwardChangeSet);
            }
        }
Exemplo n.º 7
0
        public void Validate()
        {
            var srcEm = SourceWorld.EntityManager;
            var dstEm = DestinationWorld.EntityManager;

            using (var changes = EntityDiffer.GetChanges(srcEm, dstEm, _differOptions, Query, _srcBlobAssets, Allocator.TempJob))
            {
                EntityPatcher.ApplyChangeSet(dstEm, changes.ForwardChangeSet);
            }

            using (var changes = EntityDiffer.GetChanges(dstEm, srcEm, _differOptions, Query, _dstBlobAssets, Allocator.TempJob))
            {
                if (!changes.ForwardChangeSet.HasChanges)
                {
                    return;
                }
                // TODO: Format the entity changeset nicely and print it out
                throw new Exception("Diff is not zero!");
            }
        }
    public void PatchWithObjectReferenceResolving()
    {
        var material = AssetDatabase.LoadAssetAtPath <Material>("Packages/com.unity.entities/Unity.Scenes.Hybrid.Tests/Test.mat");

        using (var differ = new EntityManagerDiffer(SrcWorld.EntityManager, Allocator.TempJob))
        {
            var entityGuid = CreateEntityGuid();

            var entity = SrcEntityManager.CreateEntity();
            SrcEntityManager.AddComponentData(entity, entityGuid);
            SrcEntityManager.AddSharedComponentData(entity, new ComponentWithObjectRef {
                Material = material
            });
            SrcEntityManager.AddComponentData(entity, new EcsTestData(5));

            var options = EntityManagerDifferOptions.IncludeForwardChangeSet | EntityManagerDifferOptions.FastForwardShadowWorld;

            using (var changes = differ.GetChanges(options, Allocator.TempJob))
            {
                var srcChange = new LiveLinkChangeSet
                {
                    Changes   = changes.ForwardChangeSet,
                    SceneName = "Boing",
                    UnloadAllPreviousEntities = true,
                    SceneGUID = new Unity.Entities.Hash128(),
                    FramesToRetainBlobAssets = 1
                };

                var changeSet = SerializeAndDeserialize(srcChange);
                AssertChangeSetsAreEqual(srcChange, changeSet);

                EntityPatcher.ApplyChangeSet(DstEntityManager, changeSet.Changes);

                changeSet.Dispose();
            }

            var dstMaterial = GetSharedComponentData <ComponentWithObjectRef>(DstEntityManager, entityGuid).Material;
            Assert.AreEqual(material, dstMaterial);
            Assert.AreEqual(5, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
        }
    }
Exemplo n.º 9
0
        public async Task <ResponseContext <T> > UpdateAsync(T entity, params Expression <Func <T, bool> >[] keySelectors)
        {
            try
            {
                if (entity == null)
                {
                    return(ResponseContext.Fail <T>(string.Format(ExceptionMessages.ArgumentException_ProvideValue, ResourceName), ErrorType.Argument));
                }

                return((await this.Async(async r => (await ValidateUpdateEntity(entity))
                                         .Then(() => OnUpdateSecurityClearance()))
                        .ThenAsync(() => GetByIdBasicAsync(keySelectors))
                        .ThenAsync(result => EntityPatcher <T> .PatchAsync(entity, result.Value))
                        .ThenAsync(result => OnBeforeUpdate(result.Value))
                        .ThenAsync(result => OnUpdateAsync(result.Value))
                        .ThenAsync(result => IncludeInUpdateTransaction(result.Value))
                        .ThenIfAsync(CommitInmediately, async result =>
                {
                    Result <int> commitResult;
                    if (_wrapUpdateInTrasaction)
                    {
                        commitResult = await AggregateParams.UOW.CommitWithinTransactionAsync();
                    }
                    else
                    {
                        commitResult = await AggregateParams.UOW.CommitAsync();
                    }

                    return commitResult.Ensure(r => r.Value > 0, ErrorType.CommitFailure, string.Format(ExceptionMessages.Exception_UpdateEntityError, ResourceName))
                    .Return(() => result);
                })
                        .ThenAsync(result => AfterUpdate(result)))
                       .ToResponseContext()
                       .withRecordCount(1)
                       .ThenIf(AggregateParams.Context.IsHATEOASRequest, response => UpdateHATEOAS(response)));
            }
            catch (Exception e)
            {
                throw new Exception(string.Format(ExceptionMessages.Exception_UpdateEntityError, ResourceName), e);
            }
        }
        public void UndoRedoPrefabInstancesWithRelationship()
        {
            const int instanceCount       = 10;
            var       srcPrefabRootGuid   = CreateEntityGuid();
            var       srcPrefabLevel0Guid = CreateEntityGuid();
            var       prefabLevel1Guid    = CreateEntityGuid();

            const EntityManagerDifferOptions options = EntityManagerDifferOptions.IncludeForwardChangeSet |
                                                       EntityManagerDifferOptions.FastForwardShadowWorld;

            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                // Create Root Prefab entity with a Guid component
                var srcPrefabRoot = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab), typeof(LinkedEntityGroup));
                SrcEntityManager.AddComponentData(srcPrefabRoot, srcPrefabRootGuid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcPrefabRoot);

                PushChanges(differ, DstEntityManager);

                using (var changes = differ.GetChanges(options, Allocator.TempJob))
                {
                    EntityPatcher.ApplyChangeSet(DstEntityManager, changes.ForwardChangeSet);
                }

                // Instantiate root prefab in dst world 10 times
                var dstPrefabRoot    = GetEntity(DstEntityManager, srcPrefabRootGuid);
                var dstInstanceRoots = new Entity[instanceCount];
                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstInstanceRoot = DstEntityManager.Instantiate(dstPrefabRoot);
                    dstInstanceRoots[i] = dstInstanceRoot;
                    Assert.AreEqual(1, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot).Length);
                    Assert.AreEqual(dstInstanceRoot, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot)[0].Value);
                }

                // Add level 0 entity to the prefab
                var srcLevel0Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel0Prefab, srcPrefabLevel0Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel0Prefab);

                SrcEntityManager.SetComponentData(srcPrefabRoot, new HierarchyComponent {
                    Parent = Entity.Null, Child = srcLevel0Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = Entity.Null
                });

                // Synchronize worlds, we now should have 10 instances in the world along with a level0 for each
                // and hierarchy matching the relationships create
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstInstanceRoot   = dstInstanceRoots[i];
                    var dstInstanceGroup  = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;

                    Assert.AreEqual(2, dstInstanceGroup.Length);
                    Assert.AreEqual(dstInstanceRoot, dstInstanceGroup[0].Value);
                    Assert.AreEqual(dstInstanceLevel0, dstInstanceGroup[1].Value);

                    var hierarchyLevel0 = DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0);
                    var hierarchyRoot   = DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceRoot);

                    Assert.AreEqual(dstInstanceRoot, hierarchyLevel0.Parent);
                    Assert.AreEqual(dstInstanceLevel0, hierarchyRoot.Child);
                }

                // Add level 1 entity to the prefab
                var srcLevel1Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel1Prefab, prefabLevel1Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel1Prefab);

                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = srcLevel1Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel1Prefab, new HierarchyComponent {
                    Parent = srcLevel0Prefab, Child = Entity.Null
                });

                // Synchronize worlds, we now should have 10 instances of level 1 linked to their matching level 0
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(3, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;
                    var dstInstanceLevel1 = dstInstanceGroup[2].Value;

                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Parent);
                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Child);
                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                }

                // Remove level 1 entity from the prefab
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).RemoveAt(2);
                SrcEntityManager.DestroyEntity(srcLevel1Prefab);

                // Fix the hierarchy of level 0 to remove the link to level 1
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = Entity.Null
                });

                // Synchronize worlds, destination world should no longer have instances of level 1
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(2, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel1 = dstInstanceGroup[1].Value;

                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                    Assert.AreEqual(Entity.Null, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Child);
                }

                // Add again level 1 as a Child of level 0
                srcLevel1Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel1Prefab, prefabLevel1Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel1Prefab);
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = srcLevel1Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel1Prefab, new HierarchyComponent {
                    Parent = srcLevel0Prefab, Child = Entity.Null
                });

                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(3, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;
                    var dstInstanceLevel1 = dstInstanceGroup[2].Value;

                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Parent);
                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Child);
                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                }
            }
        }