< Summary

Class:DCL.ParcelScenesCleaner
Assembly:DCL.Runtime
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScenesCleaner.cs
Covered lines:61
Uncovered lines:9
Coverable lines:70
Total lines:172
Line coverage:87.1% (61 of 70)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
MarkedEntityInfo(...)0%110100%
MarkedSharedComponentInfo(...)0%110100%
ParcelScenesCleaner()0%110100%
Initialize()0%110100%
OnRendererStateChange(...)0%220100%
MarkForCleanup(...)0%4.024088.89%
MarkRootEntityForCleanup(...)0%110100%
MarkDisposableComponentForCleanup(...)0%110100%
CleanMarkedEntities()0%110100%
CleanMarkedEntitiesAsync()0%27.8921075%
CleanupEntitiesCoroutine()0%550100%
Dispose()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScenesCleaner.cs

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Models;
 3using System.Collections;
 4using System.Collections.Generic;
 5using UnityEngine;
 6using Object = UnityEngine.Object;
 7
 8namespace DCL
 9{
 10    public class ParcelScenesCleaner : IParcelScenesCleaner
 11    {
 12        const float MAX_TIME_BUDGET = 0.01f;
 13
 14        private readonly struct MarkedEntityInfo
 15        {
 16            public readonly ParcelScene scene;
 17            public readonly IDCLEntity entity;
 18
 19            public MarkedEntityInfo(ParcelScene scene, IDCLEntity entity)
 20            {
 921                this.scene = scene;
 922                this.entity = entity;
 923            }
 24        }
 25
 26        private readonly struct MarkedSharedComponentInfo
 27        {
 28            public readonly ParcelScene scene;
 29            public readonly string componentId;
 30
 31            public MarkedSharedComponentInfo(ParcelScene scene, string componentId)
 32            {
 9033                this.scene = scene;
 9034                this.componentId = componentId;
 9035            }
 36        }
 37
 14238        Queue<IDCLEntity> entitiesMarkedForCleanup = new Queue<IDCLEntity>();
 14239        Queue<MarkedEntityInfo> rootEntitiesMarkedForCleanup = new Queue<MarkedEntityInfo>();
 14240        Queue<MarkedSharedComponentInfo> disposableComponentsMarkedForCleanup = new Queue<MarkedSharedComponentInfo>();
 41
 42        Coroutine removeEntitiesCoroutine;
 43
 44        public void Initialize ()
 45        {
 14246            removeEntitiesCoroutine = CoroutineStarter.Start(CleanupEntitiesCoroutine());
 14247            CommonScriptableObjects.rendererState.OnChange += OnRendererStateChange;
 14248        }
 49
 50        private void OnRendererStateChange(bool isEnable, bool prevState)
 51        {
 1552            if (!isEnable)
 53            {
 1454                CleanMarkedEntities();
 1455                Resources.UnloadUnusedAssets();
 56            }
 1557        }
 58
 59        public void MarkForCleanup(IDCLEntity entity)
 60        {
 661            if (entity.markedForCleanup)
 062                return;
 63
 664            entity.markedForCleanup = true;
 65
 666            if (entity.gameObject != null)
 667                entity.gameObject.SetActive(false);
 68
 69#if UNITY_EDITOR
 670            if (entity.gameObject != null)
 671                entity.gameObject.name += "-MARKED-FOR-CLEANUP";
 72#endif
 73
 674            entitiesMarkedForCleanup.Enqueue(entity);
 675        }
 76
 77        // When removing all entities from a scene, we need to separate the root entities, as stated in ParcelScene,
 78        // to avoid traversing a lot of child entities in the same frame and other problems
 1879        public void MarkRootEntityForCleanup(IParcelScene scene, IDCLEntity entity) { rootEntitiesMarkedForCleanup.Enque
 80
 18081        public void MarkDisposableComponentForCleanup(IParcelScene scene, string componentId) { disposableComponentsMark
 82
 83        public void CleanMarkedEntities()
 84        {
 15785            CleanMarkedEntitiesAsync(true).MoveNext();
 15786        }
 87
 88        public IEnumerator CleanMarkedEntitiesAsync(bool immediate = false)
 89        {
 642390            float lastTime = Time.unscaledTime;
 91
 651092            while (disposableComponentsMarkedForCleanup.Count > 0)
 93            {
 8794                MarkedSharedComponentInfo markedSharedComponentInfo = disposableComponentsMarkedForCleanup.Dequeue();
 8795                markedSharedComponentInfo.scene.componentsManagerLegacy.SceneSharedComponentDispose(markedSharedComponen
 96
 8797                if (DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET && !immediate)
 98                {
 099                    yield return null;
 0100                    lastTime = Time.unscaledTime;
 101                }
 102            }
 103
 6423104            HashSet<ParcelScene> scenesToRemove = new HashSet<ParcelScene>();
 105
 106            // If we have root entities queued for removal, we call Parcel Scene's RemoveEntity()
 107            // so that the child entities end up recursively in the entitiesMarkedForCleanup queue
 6429108            while (rootEntitiesMarkedForCleanup.Count > 0)
 109            {
 6110                MarkedEntityInfo markedEntityInfo = rootEntitiesMarkedForCleanup.Dequeue();
 6111                markedEntityInfo.scene.RemoveEntity(markedEntityInfo.entity.entityId, false);
 112
 6113                if (!scenesToRemove.Contains(markedEntityInfo.scene))
 4114                    scenesToRemove.Add(markedEntityInfo.scene);
 115
 6116                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 117                {
 0118                    yield return null;
 0119                    lastTime = Time.unscaledTime;
 120                }
 121            }
 122
 6429123            while (entitiesMarkedForCleanup.Count > 0)
 124            {
 6125                IDCLEntity entity = entitiesMarkedForCleanup.Dequeue();
 6126                entity.SetParent(null);
 6127                entity.Cleanup();
 128
 6129                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 130                {
 0131                    yield return null;
 0132                    lastTime = Time.unscaledTime;
 133                }
 134            }
 135
 12854136            foreach (var scene in scenesToRemove)
 137            {
 4138                if (scene != null && scene.gameObject)
 4139                    Object.Destroy(scene.gameObject);
 140
 4141                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 142                {
 0143                    yield return null;
 0144                    lastTime = Time.unscaledTime;
 145                }
 146            }
 6423147        }
 148
 149        IEnumerator CleanupEntitiesCoroutine()
 150        {
 142151            yield return null;
 140152            Environment.i.platform.memoryManager.OnCriticalMemory += CleanMarkedEntities;
 153
 6126154            while (true)
 155            {
 6266156                yield return CleanMarkedEntitiesAsync();
 6195157                yield return null;
 158            }
 159        }
 160
 161        public void Dispose()
 162        {
 142163            CleanMarkedEntities();
 164
 142165            if (removeEntitiesCoroutine != null)
 142166                CoroutineStarter.Stop(removeEntitiesCoroutine);
 167
 142168            CommonScriptableObjects.rendererState.OnChange -= OnRendererStateChange;
 142169            Environment.i.platform.memoryManager.OnCriticalMemory -= CleanMarkedEntities;
 142170        }
 171    }
 172}