< Summary

Class:DCL.LoadingScreen.LoadingScreenController
Assembly:DCL.LoadingScreen
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/LoadingScreen/Scripts/LoadingScreenController.cs
Covered lines:0
Uncovered lines:93
Coverable lines:93
Total lines:236
Line coverage:0% (0 of 93)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:16
Method coverage:0% (0 of 16)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
LoadingScreenController(...)0%2100%
Dispose()0%2100%
FadeInFinished(...)0%2100%
ReadyScene(...)0%6200%
PlayerLoaded(...)0%6200%
OnSignupFlow(...)0%12300%
TeleportRequested(...)0%30500%
IsNewRealm()0%20400%
IsNewScene(...)0%2100%
IsSceneLoaded(...)0%6200%
HandlePlayerLoading()0%12300%
FadeOutView()0%6200%
FadeOutViewAsync()0%20400%
OnShaderPrewarmProgress(...)0%2100%
ShowRandomPositionNotification()0%2100%
RandomPositionRequested()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/LoadingScreen/Scripts/LoadingScreenController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Helpers;
 3using DCL.Interface;
 4using DCL.NotificationModel;
 5using MainScripts.DCL.Controllers.ShaderPrewarm;
 6using System;
 7using System.Threading;
 8using UnityEngine;
 9
 10namespace DCL.LoadingScreen
 11{
 12    /// <summary>
 13    /// Controls the state of the loading screen. It's responsibility is to update the view depending on the SceneContro
 14    /// Creates and provides the controllers associated to the LoadingScreen: TipsController and PercentageController
 15    /// </summary>
 16    public class LoadingScreenController : IDisposable
 17    {
 18        private readonly ILoadingScreenView view;
 19        private readonly ISceneController sceneController;
 20        private readonly DataStore_Player playerDataStore;
 21        private readonly DataStore_Common commonDataStore;
 22        private readonly DataStore_LoadingScreen loadingScreenDataStore;
 23        private readonly DataStore_Realm realmDataStore;
 24        private readonly IWorldState worldState;
 25
 26        private Vector2Int currentDestination;
 27        private string currentRealm;
 28        private bool currentRealmIsWorld;
 29        private readonly LoadingScreenTipsController tipsController;
 30        private readonly LoadingScreenPercentageController percentageController;
 31        internal readonly LoadingScreenTimeoutController timeoutController;
 32        private readonly NotificationsController notificationsController;
 33        private bool onSignUpFlow;
 34        internal bool showRandomPositionNotification;
 35        private bool isFadingOut;
 36        private readonly IShaderPrewarm shaderPrewarm;
 37        private readonly CancellationTokenSource cancellationTokenSource;
 38
 039        public LoadingScreenController(ILoadingScreenView view, ISceneController sceneController, IWorldState worldState
 40            DataStore_Player playerDataStore, DataStore_Common commonDataStore, DataStore_LoadingScreen loadingScreenDat
 41        {
 042            cancellationTokenSource = new CancellationTokenSource();
 43
 044            this.shaderPrewarm = shaderPrewarm;
 045            this.view = view;
 046            this.sceneController = sceneController;
 047            this.playerDataStore = playerDataStore;
 048            this.commonDataStore = commonDataStore;
 049            this.worldState = worldState;
 050            this.loadingScreenDataStore = loadingScreenDataStore;
 051            this.realmDataStore = realmDataStore;
 052            this.notificationsController = notificationsController;
 53
 054            tipsController = new LoadingScreenTipsController(view.GetTipsView());
 055            percentageController = new LoadingScreenPercentageController(sceneController, view.GetPercentageView(), comm
 056            timeoutController = new LoadingScreenTimeoutController(view.GetTimeoutView(), worldState, this);
 57
 058            this.playerDataStore.lastTeleportPosition.OnChange += TeleportRequested;
 059            this.commonDataStore.isSignUpFlow.OnChange += OnSignupFlow;
 060            this.sceneController.OnReadyScene += ReadyScene;
 061            view.OnFadeInFinish += FadeInFinished;
 62
 63            // The initial loading has still a destination to set. We are starting the timeout for the
 64            // websocket initialization
 065            timeoutController.StartTimeout(new Vector2Int(-1, -1));
 066        }
 67
 68        public void Dispose()
 69        {
 070            view.Dispose();
 071            percentageController.Dispose();
 072            timeoutController.Dispose();
 73
 074            playerDataStore.lastTeleportPosition.OnChange -= TeleportRequested;
 075            commonDataStore.isSignUpFlow.OnChange -= OnSignupFlow;
 076            sceneController.OnReadyScene -= ReadyScene;
 077            view.OnFadeInFinish -= FadeInFinished;
 78
 079            cancellationTokenSource.Cancel();
 080            cancellationTokenSource.Dispose();
 081        }
 82
 83        private void FadeInFinished(ShowHideAnimator obj)
 84        {
 085            loadingScreenDataStore.decoupledLoadingHUD.visible.Set(true);
 086        }
 87
 88        private void ReadyScene(int obj)
 89        {
 90            //We have to check that the latest scene loaded is the one from our current destination
 091            if (worldState.GetSceneNumberByCoords(currentDestination).Equals(obj))
 092                HandlePlayerLoading();
 093        }
 94
 95        //We have to add one more check not to show the loadingScreen unless the player is loaded
 96        private void PlayerLoaded(bool loaded, bool _)
 97        {
 098            if (loaded)
 099                FadeOutView();
 100
 0101            commonDataStore.isPlayerRendererLoaded.OnChange -= PlayerLoaded;
 0102        }
 103
 104        private void OnSignupFlow(bool current, bool previous)
 105        {
 0106            onSignUpFlow = current;
 107
 0108            if (realmDataStore.playerRealmAboutConfiguration.Get() != null)
 109            {
 0110                currentRealm = realmDataStore.playerRealmAboutConfiguration.Get().RealmName;
 0111                currentRealmIsWorld = commonDataStore.isWorld.Get();
 112            }
 113
 0114            if (current)
 0115                FadeOutView();
 116            else
 0117                view.FadeIn(false, false);
 0118        }
 119
 120        private void TeleportRequested(Vector3 current, Vector3 previous)
 121        {
 0122            if (onSignUpFlow) return;
 123
 0124            Vector2Int currentDestinationCandidate = Utils.WorldToGridPosition(current);
 125
 0126            if (IsNewRealm() || IsNewScene(currentDestinationCandidate))
 127            {
 0128                currentDestination = currentDestinationCandidate;
 129
 130                //On a teleport, to copy previos behaviour, we disable tips entirely and show the teleporting screen
 131                //This is probably going to change with the integration of WORLDS loading screen
 132                //Temporarily removing tips until V2
 133                //tipsController.StopTips();
 0134                percentageController.StartLoading(currentDestination);
 0135                timeoutController.StartTimeout(currentDestination);
 0136                view.FadeIn(false, true);
 137            }
 0138            else if (IsSceneLoaded(currentDestinationCandidate))
 0139                HandlePlayerLoading();
 0140        }
 141
 142        //The realm gets changed before the scenes starts to unload. So, if we try to teleport to a world scene in which
 143        //we wont see the loading screen. Same happens when leaving a world. Thats why we need to keep track of the late
 144        private bool IsNewRealm()
 145        {
 146            //Realm has not been set yet, so we are not in a new realm
 0147            if (realmDataStore.playerRealmAboutConfiguration.Get() == null)
 0148                return false;
 149
 150            bool realmChangeRequiresLoadingScreen;
 151
 0152            if (commonDataStore.isWorld.Get())
 0153                realmChangeRequiresLoadingScreen = string.IsNullOrEmpty(currentRealm) || !currentRealm.Equals(realmDataS
 154            else
 0155                realmChangeRequiresLoadingScreen = currentRealmIsWorld;
 156
 0157            currentRealm = realmDataStore.playerRealmAboutConfiguration.Get().RealmName;
 0158            currentRealmIsWorld = commonDataStore.isWorld.Get();
 0159            return realmChangeRequiresLoadingScreen;
 160        }
 161
 162        //If the destination scene is not loaded, we show the teleport screen. THis is called in the POSITION_UNSETTLED
 163        //On the other hand, the POSITION_SETTLED event is called; but since the scene will already be loaded, the loadi
 164        private bool IsNewScene(Vector2Int currentDestinationCandidate) =>
 0165            worldState.GetSceneNumberByCoords(currentDestinationCandidate).Equals(-1);
 166
 167        private bool IsSceneLoaded(Vector2Int candidate) =>
 0168            worldState.GetScene(worldState.GetSceneNumberByCoords(candidate))?.loadingProgress >= 100;
 169
 170        private void HandlePlayerLoading()
 171        {
 172            //We have to check if the player is loaded
 0173            if (commonDataStore.isPlayerRendererLoaded.Get())
 0174                FadeOutView();
 175            else
 176            {
 0177                if (!isFadingOut)
 0178                    percentageController.SetAvatarLoadingMessage();
 179
 0180                commonDataStore.isPlayerRendererLoaded.OnChange += PlayerLoaded;
 181            }
 0182        }
 183
 184        private void FadeOutView()
 185        {
 0186            if (isFadingOut) return;
 0187            isFadingOut = true;
 0188            FadeOutViewAsync(cancellationTokenSource.Token).Forget();
 0189        }
 190
 191        private async UniTask FadeOutViewAsync(CancellationToken cancellationToken)
 192        {
 0193            timeoutController.StopTimeout();
 194
 0195            await shaderPrewarm.PrewarmAsync(OnShaderPrewarmProgress, cancellationToken);
 196
 0197            view.FadeOut();
 0198            loadingScreenDataStore.decoupledLoadingHUD.visible.Set(false);
 199
 0200            if (showRandomPositionNotification)
 0201                ShowRandomPositionNotification();
 202
 0203            isFadingOut = false;
 0204        }
 205
 206        private void OnShaderPrewarmProgress(float progress)
 207        {
 0208            percentageController.SetShaderCompilingMessage(progress);
 0209        }
 210
 211        private void ShowRandomPositionNotification()
 212        {
 0213            notificationsController.ShowNotification(new Model
 214            {
 215                message = "There was an error while trying to load your home scene. If the problem persists contact supp
 216                type = NotificationModel.Type.ERROR,
 217                timer = 10f,
 218                destroyOnFinish = true
 219            });
 220
 0221            showRandomPositionNotification = false;
 0222        }
 223
 224        public void RandomPositionRequested()
 225        {
 0226            WebInterface.SendChatMessage(new ChatMessage
 227            {
 228                messageType = ChatMessage.Type.NONE,
 229                recipient = string.Empty,
 230                body = "/goto random",
 231            });
 232
 0233            showRandomPositionNotification = true;
 0234        }
 235    }
 236}