< Summary

Class:ECSSystems.ScenesUiSystem.ECSScenesUiSystem
Assembly:ECS7Plugin.Systems.ScenesUiSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/Systems/ScenesUiSystem/ECSScenesUiSystem.cs
Covered lines:63
Uncovered lines:3
Coverable lines:66
Total lines:196
Line coverage:95.4% (63 of 66)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ECSScenesUiSystem(...)0%110100%
Dispose()0%110100%
Update()0%10100100%
LoadedScenesOnOnRemoved(...)0%6200%
ApplyParenting(...)0%770100%
ClearCurrentSceneUI(...)0%220100%
GetCurrentScene(...)0%440100%
ApplySceneUI(...)0%220100%
GetParentContainerModel(...)0%550100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/Systems/ScenesUiSystem/ECSScenesUiSystem.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using DCL;
 4using DCL.Controllers;
 5using DCL.ECS7.InternalComponents;
 6using DCL.ECSRuntime;
 7using DCL.Models;
 8using UnityEngine.UIElements;
 9
 10namespace ECSSystems.ScenesUiSystem
 11{
 12    public class ECSScenesUiSystem : IDisposable
 13    {
 14        private class State
 15        {
 16            public UIDocument uiDocument;
 17            public IInternalECSComponent<InternalUiContainer> internalUiContainerComponent;
 18            public IWorldState worldState;
 19            public BaseList<IParcelScene> loadedScenes;
 20            public string lastSceneId;
 21            public bool isPendingSceneUI;
 22            public IParcelScene currentScene;
 23        }
 24
 25        private readonly State state;
 26
 627        public ECSScenesUiSystem(UIDocument uiDocument,
 28            IInternalECSComponent<InternalUiContainer> internalUiContainerComponent,
 29            BaseList<IParcelScene> loadedScenes,
 30            IWorldState worldState)
 31        {
 632            state = new State()
 33            {
 34                uiDocument = uiDocument,
 35                internalUiContainerComponent = internalUiContainerComponent,
 36                worldState = worldState,
 37                loadedScenes = loadedScenes,
 38                lastSceneId = null,
 39                isPendingSceneUI = true,
 40                currentScene = null
 41            };
 42
 643            state.loadedScenes.OnRemoved += LoadedScenesOnOnRemoved;
 644        }
 45
 46        public void Dispose()
 47        {
 148            state.loadedScenes.OnRemoved -= LoadedScenesOnOnRemoved;
 149        }
 50
 51        public void Update()
 52        {
 1253            string currentSceneId = state.worldState.GetCurrentSceneId();
 1254            bool sceneChanged = state.lastSceneId != currentSceneId;
 1255            state.lastSceneId = currentSceneId;
 56
 1257            ApplyParenting(state.uiDocument, state.internalUiContainerComponent);
 58
 59            // clear UI if scene changed
 1260            if (sceneChanged && !state.isPendingSceneUI)
 61            {
 362                ClearCurrentSceneUI(state.uiDocument);
 363                state.isPendingSceneUI = !string.IsNullOrEmpty(currentSceneId);
 64            }
 1265            if (sceneChanged && state.currentScene != null && currentSceneId != state.currentScene.sceneData.id)
 66            {
 467                state.currentScene = null;
 68            }
 69
 70            // UI not set for current scene yet
 1271            if (state.isPendingSceneUI)
 72            {
 73                // we get current scene reference
 1274                state.currentScene ??= GetCurrentScene(currentSceneId, state.loadedScenes);
 75
 76                // we apply current scene UI
 1277                if (state.currentScene != null)
 78                {
 879                    if (ApplySceneUI(state.internalUiContainerComponent, state.uiDocument, state.currentScene))
 80                    {
 681                        state.isPendingSceneUI = false;
 82                    }
 83                }
 84            }
 1285        }
 86
 87        private void LoadedScenesOnOnRemoved(IParcelScene scene)
 88        {
 089            if (scene.sceneData.id == state.lastSceneId)
 90            {
 091                state.lastSceneId = null;
 92            }
 093        }
 94
 95        internal static void ApplyParenting(UIDocument uiDocument, IInternalECSComponent<InternalUiContainer> internalUi
 96        {
 97            // check for orphan ui containers
 1598            var allContainers = internalUiContainerComponent.GetForAll();
 8099            for (int i = 0; i < allContainers.Count; i++)
 100            {
 25101                var uiContainerData = allContainers[i].value;
 102
 103                // add global scenes ui but
 104                // skip non-global scenes ui containers on root entity since no parenting is needed
 25105                if (uiContainerData.entity.entityId == SpecialEntityId.SCENE_ROOT_ENTITY)
 106                {
 21107                    var model = uiContainerData.model;
 21108                    if (uiContainerData.scene.isPersistent && model.parentElement == null)
 109                    {
 2110                        uiDocument.rootVisualElement.Add(model.rootElement);
 2111                        model.parentElement = uiDocument.rootVisualElement;
 2112                        internalUiContainerComponent.PutFor(uiContainerData.scene, uiContainerData.entity, model);
 113                    }
 2114                    continue;
 115                }
 116
 117                // skip containers with parent already set
 4118                if (uiContainerData.model.parentElement != null)
 119                    continue;
 120
 4121                InternalUiContainer parentDataModel = GetParentContainerModel(
 122                    internalUiContainerComponent,
 123                    uiContainerData.scene,
 124                    uiContainerData.model.parentId);
 125
 126                // apply parenting
 4127                if (parentDataModel != null)
 128                {
 3129                    var currentContainerModel = uiContainerData.model;
 3130                    parentDataModel.rootElement.Add(uiContainerData.model.rootElement);
 3131                    currentContainerModel.parentElement = parentDataModel.rootElement;
 132
 3133                    internalUiContainerComponent.PutFor(uiContainerData.scene, uiContainerData.model.parentId, parentDat
 3134                    internalUiContainerComponent.PutFor(uiContainerData.scene, uiContainerData.entity, currentContainerM
 135                }
 136            }
 15137        }
 138
 139        internal static void ClearCurrentSceneUI(UIDocument uiDocument)
 140        {
 4141            if (uiDocument.rootVisualElement.childCount > 0)
 142            {
 4143                uiDocument.rootVisualElement.RemoveAt(0);
 144            }
 4145        }
 146
 147        internal static IParcelScene GetCurrentScene(string sceneId, IList<IParcelScene> loadedScenes)
 148        {
 14149            if (string.IsNullOrEmpty(sceneId))
 1150                return null;
 151
 13152            IParcelScene currentScene = null;
 44153            for (int i = 0; i < loadedScenes.Count; i++)
 154            {
 17155                if (loadedScenes[i].sceneData.id == sceneId)
 156                {
 8157                    currentScene = loadedScenes[i];
 8158                    break;
 159                }
 160            }
 161
 13162            return currentScene;
 163        }
 164
 165        internal static bool ApplySceneUI(IInternalECSComponent<InternalUiContainer> internalUiContainerComponent,
 166            UIDocument uiDocument, IParcelScene currentScene)
 167        {
 10168            IECSReadOnlyComponentData<InternalUiContainer> sceneRootUiContainer =
 169                internalUiContainerComponent.GetFor(currentScene, SpecialEntityId.SCENE_ROOT_ENTITY);
 170
 10171            if (sceneRootUiContainer != null)
 172            {
 7173                var model = sceneRootUiContainer.model;
 7174                uiDocument.rootVisualElement.Insert(0, model.rootElement);
 7175                model.parentElement = uiDocument.rootVisualElement;
 7176                internalUiContainerComponent.PutFor(currentScene, SpecialEntityId.SCENE_ROOT_ENTITY, model);
 7177                return true;
 178            }
 3179            return false;
 180        }
 181
 182        private static InternalUiContainer GetParentContainerModel(IInternalECSComponent<InternalUiContainer> internalUi
 183            IParcelScene scene, long parentId)
 184        {
 4185            InternalUiContainer parentDataModel =
 186                internalUiContainerComponent.GetFor(scene, parentId)?.model;
 187
 188            // create root entity ui container if needed
 4189            if (parentDataModel == null && parentId == SpecialEntityId.SCENE_ROOT_ENTITY)
 190            {
 2191                parentDataModel = new InternalUiContainer();
 192            }
 4193            return parentDataModel;
 194        }
 195    }
 196}