< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
MarkedEntityInfo(...)0%2100%
MarkedSharedComponentInfo(...)0%2100%
ParcelScenesCleaner()0%110100%
Initialize()0%110100%
OnRendererStateChange(...)0%6200%
MarkForCleanup(...)0%4.024088.89%
MarkRootEntityForCleanup(...)0%110100%
MarkDisposableComponentForCleanup(...)0%110100%
CleanMarkedEntities()0%110100%
CleanMarkedEntitiesAsync()0%21.0121096.88%
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 struct MarkedEntityInfo
 15        {
 16            public ParcelScene scene;
 17            public IDCLEntity entity;
 18
 19            public MarkedEntityInfo(ParcelScene scene, IDCLEntity entity)
 20            {
 021                this.scene = scene;
 022                this.entity = entity;
 023            }
 24        }
 25
 26        private struct MarkedSharedComponentInfo
 27        {
 28            public ParcelScene scene;
 29            public string componentId;
 30
 31            public MarkedSharedComponentInfo(ParcelScene scene, string componentId)
 32            {
 033                this.scene = scene;
 034                this.componentId = componentId;
 035            }
 36        }
 37
 8538        Queue<IDCLEntity> entitiesMarkedForCleanup = new Queue<IDCLEntity>();
 8539        Queue<MarkedEntityInfo> rootEntitiesMarkedForCleanup = new Queue<MarkedEntityInfo>();
 8540        Queue<MarkedSharedComponentInfo> disposableComponentsMarkedForCleanup = new Queue<MarkedSharedComponentInfo>();
 41
 42        Coroutine removeEntitiesCoroutine;
 43
 44        public void Initialize ()
 45        {
 8546            removeEntitiesCoroutine = CoroutineStarter.Start(CleanupEntitiesCoroutine());
 8547            CommonScriptableObjects.rendererState.OnChange += OnRendererStateChange;
 8548        }
 49
 50        private void OnRendererStateChange(bool isEnable, bool prevState)
 51        {
 052            if (!isEnable)
 53            {
 054                CleanMarkedEntities();
 055                Resources.UnloadUnusedAssets();
 56            }
 057        }
 58
 59        public void MarkForCleanup(IDCLEntity entity)
 60        {
 161            if (entity.markedForCleanup)
 062                return;
 63
 164            entity.markedForCleanup = true;
 65
 166            if (entity.gameObject != null)
 167                entity.gameObject.SetActive(false);
 68
 69#if UNITY_EDITOR
 170            if (entity.gameObject != null)
 171                entity.gameObject.name += "-MARKED-FOR-CLEANUP";
 72#endif
 73
 174            entitiesMarkedForCleanup.Enqueue(entity);
 175        }
 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
 1079        public void MarkRootEntityForCleanup(IParcelScene scene, IDCLEntity entity) { rootEntitiesMarkedForCleanup.Enque
 80
 17681        public void MarkDisposableComponentForCleanup(IParcelScene scene, string componentId) { disposableComponentsMark
 82
 83        public void CleanMarkedEntities()
 84        {
 8585            CleanMarkedEntitiesAsync(true).MoveNext();
 8586        }
 87
 88        public IEnumerator CleanMarkedEntitiesAsync(bool immediate = false)
 89        {
 66590            float lastTime = Time.unscaledTime;
 91
 73592            while (disposableComponentsMarkedForCleanup.Count > 0)
 93            {
 8594                MarkedSharedComponentInfo markedSharedComponentInfo = disposableComponentsMarkedForCleanup.Dequeue();
 8595                markedSharedComponentInfo.scene.SharedComponentDispose(markedSharedComponentInfo.componentId);
 96
 8597                if (DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET && !immediate)
 98                {
 1599                    yield return null;
 0100                    lastTime = Time.unscaledTime;
 101                }
 102            }
 103
 650104            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
 651108            while (rootEntitiesMarkedForCleanup.Count > 0)
 109            {
 1110                MarkedEntityInfo markedEntityInfo = rootEntitiesMarkedForCleanup.Dequeue();
 1111                markedEntityInfo.scene.RemoveEntity(markedEntityInfo.entity.entityId, false);
 112
 1113                if (!scenesToRemove.Contains(markedEntityInfo.scene))
 1114                    scenesToRemove.Add(markedEntityInfo.scene);
 115
 1116                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 117                {
 1118                    yield return null;
 1119                    lastTime = Time.unscaledTime;
 120                }
 121            }
 122
 651123            while (entitiesMarkedForCleanup.Count > 0)
 124            {
 1125                IDCLEntity entity = entitiesMarkedForCleanup.Dequeue();
 1126                entity.SetParent(null);
 1127                entity.Cleanup();
 128
 1129                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 130                {
 1131                    yield return null;
 1132                    lastTime = Time.unscaledTime;
 133                }
 134            }
 135
 1302136            foreach (var scene in scenesToRemove)
 137            {
 1138                if (scene != null && !Environment.i.world.state.loadedScenes.ContainsKey(scene.sceneData.id))
 1139                    Object.Destroy(scene.gameObject);
 140
 1141                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 142                {
 1143                    yield return null;
 1144                    lastTime = Time.unscaledTime;
 145                }
 146            }
 650147        }
 148
 149        IEnumerator CleanupEntitiesCoroutine()
 150        {
 85151            yield return null;
 85152            Environment.i.platform.memoryManager.OnCriticalMemory += CleanMarkedEntities;
 153
 495154            while (true)
 155            {
 580156                yield return CleanMarkedEntitiesAsync();
 527157                yield return null;
 158            }
 159        }
 160
 161        public void Dispose()
 162        {
 85163            CleanMarkedEntities();
 164
 85165            if (removeEntitiesCoroutine != null)
 85166                CoroutineStarter.Stop(removeEntitiesCoroutine);
 167
 85168            CommonScriptableObjects.rendererState.OnChange -= OnRendererStateChange;
 85169            Environment.i.platform.memoryManager.OnCriticalMemory -= CleanMarkedEntities;
 85170        }
 171    }
 172}