< Summary

Class:DCL.ParcelScenesCleaner
Assembly:DCL.Runtime
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScenesCleaner.cs
Covered lines:55
Uncovered lines:15
Coverable lines:70
Total lines:172
Line coverage:78.5% (55 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%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            {
 021                this.scene = scene;
 022                this.entity = entity;
 023            }
 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            {
 033                this.scene = scene;
 034                this.componentId = componentId;
 035            }
 36        }
 37
 12938        Queue<IDCLEntity> entitiesMarkedForCleanup = new Queue<IDCLEntity>();
 12939        Queue<MarkedEntityInfo> rootEntitiesMarkedForCleanup = new Queue<MarkedEntityInfo>();
 12940        Queue<MarkedSharedComponentInfo> disposableComponentsMarkedForCleanup = new Queue<MarkedSharedComponentInfo>();
 41
 42        Coroutine removeEntitiesCoroutine;
 43
 44        public void Initialize ()
 45        {
 12946            removeEntitiesCoroutine = CoroutineStarter.Start(CleanupEntitiesCoroutine());
 12947            CommonScriptableObjects.rendererState.OnChange += OnRendererStateChange;
 12948        }
 49
 50        private void OnRendererStateChange(bool isEnable, bool prevState)
 51        {
 1352            if (!isEnable)
 53            {
 1354                CleanMarkedEntities();
 1355                Resources.UnloadUnusedAssets();
 56            }
 1357        }
 58
 59        public void MarkForCleanup(IDCLEntity entity)
 60        {
 261            if (entity.markedForCleanup)
 062                return;
 63
 264            entity.markedForCleanup = true;
 65
 266            if (entity.gameObject != null)
 267                entity.gameObject.SetActive(false);
 68
 69#if UNITY_EDITOR
 270            if (entity.gameObject != null)
 271                entity.gameObject.name += "-MARKED-FOR-CLEANUP";
 72#endif
 73
 274            entitiesMarkedForCleanup.Enqueue(entity);
 275        }
 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
 479        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        {
 14385            CleanMarkedEntitiesAsync(true).MoveNext();
 14386        }
 87
 88        public IEnumerator CleanMarkedEntitiesAsync(bool immediate = false)
 89        {
 95890            float lastTime = Time.unscaledTime;
 91
 104592            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
 958104            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
 960108            while (rootEntitiesMarkedForCleanup.Count > 0)
 109            {
 2110                MarkedEntityInfo markedEntityInfo = rootEntitiesMarkedForCleanup.Dequeue();
 2111                markedEntityInfo.scene.RemoveEntity(markedEntityInfo.entity.entityId, false);
 112
 2113                if (!scenesToRemove.Contains(markedEntityInfo.scene))
 2114                    scenesToRemove.Add(markedEntityInfo.scene);
 115
 2116                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 117                {
 0118                    yield return null;
 0119                    lastTime = Time.unscaledTime;
 120                }
 121            }
 122
 960123            while (entitiesMarkedForCleanup.Count > 0)
 124            {
 2125                IDCLEntity entity = entitiesMarkedForCleanup.Dequeue();
 2126                entity.SetParent(null);
 2127                entity.Cleanup();
 128
 2129                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 130                {
 0131                    yield return null;
 0132                    lastTime = Time.unscaledTime;
 133                }
 134            }
 135
 1920136            foreach (var scene in scenesToRemove)
 137            {
 2138                if (scene != null && scene.gameObject)
 2139                    Object.Destroy(scene.gameObject);
 140
 2141                if (!immediate && DCLTime.realtimeSinceStartup - lastTime >= MAX_TIME_BUDGET)
 142                {
 0143                    yield return null;
 0144                    lastTime = Time.unscaledTime;
 145                }
 146            }
 958147        }
 148
 149        IEnumerator CleanupEntitiesCoroutine()
 150        {
 129151            yield return null;
 128152            Environment.i.platform.memoryManager.OnCriticalMemory += CleanMarkedEntities;
 153
 687154            while (true)
 155            {
 815156                yield return CleanMarkedEntitiesAsync();
 740157                yield return null;
 158            }
 159        }
 160
 161        public void Dispose()
 162        {
 129163            CleanMarkedEntities();
 164
 129165            if (removeEntitiesCoroutine != null)
 129166                CoroutineStarter.Stop(removeEntitiesCoroutine);
 167
 129168            CommonScriptableObjects.rendererState.OnChange -= OnRendererStateChange;
 129169            Environment.i.platform.memoryManager.OnCriticalMemory -= CleanMarkedEntities;
 129170        }
 171    }
 172}