< Summary

Class:DCL.Tutorial.TutorialController
Assembly:Onboarding
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Tutorial/Scripts/TutorialController.cs
Covered lines:203
Uncovered lines:47
Coverable lines:250
Total lines:641
Line coverage:81.2% (203 of 250)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Initialize()0%2100%
CreateTutorialView()0%110100%
SetConfiguration(...)0%3.13077.78%
Dispose()0%4.024088.89%
SetTutorialEnabled(...)0%110100%
SetTutorialEnabledForUsersThatAlreadyDidTheTutorial(...)0%6200%
SetBuilderInWorldTutorialEnabled()0%2100%
SetupTutorial(...)0%9.019095.45%
SetTutorialDisabled()0%880100%
StartTutorialFromStep()0%16.1716091.3%
ShowTeacher3DModel(...)0%330100%
SetTeacherPosition(...)0%4.374071.43%
PlayTeacherAnimation(...)0%220100%
SetTeacherCanvasSortingOrder(...)0%2.062075%
SkipTutorial()0%8.147071.43%
SetEagleEyeCameraActive(...)0%440100%
OnRenderingStateChanged(...)0%5.025090%
ExecuteSteps()0%27.5127091.11%
SetUserTutorialStepAsCompleted(...)0%110100%
MoveTeacher()0%6.976070%
IsTaskbarHUDInitialized_OnChange(...)0%64050%
MoreMenu_OnRestartTutorial()0%110100%
IsPlayerInsideGenesisPlaza()0%8.817066.67%
SendStepStartedSegmentStats(...)0%2100%
SendStepCompletedSegmentStats(...)0%2100%
SendSkipTutorialSegmentStats(...)0%2100%
EagleEyeCameraRotation()0%330100%
BlockPlayerCameraUntilBlendingIsFinished()0%15150100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Tutorial/Scripts/TutorialController.cs

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Interface;
 3using System;
 4using System.Collections;
 5using System.Collections.Generic;
 6using UnityEngine;
 7using DCL.Helpers;
 8
 9namespace DCL.Tutorial
 10{
 11    /// <summary>
 12    /// Controller that handles all the flow related to the onboarding tutorial.
 13    /// </summary>
 14    public class TutorialController : PluginFeature
 15    {
 16        [Serializable]
 17        public class TutorialInitializationMessage
 18        {
 19            public string fromDeepLink;
 20            public string enableNewTutorialCamera;
 21        }
 22
 23        [Flags]
 24        public enum TutorialFinishStep
 25        {
 26            None = 0,
 27            OldTutorialValue = 99, // NOTE: old tutorial set tutorialStep to 99 when finished
 28            EmailRequested = 128, // NOTE: old email prompt set tutorialStep to 128 when finished
 29            NewTutorialFinished = 256
 30        }
 31
 32        public enum TutorialType
 33        {
 34            Initial,
 35            BuilderInWorld
 36        }
 37
 38        internal enum TutorialPath
 39        {
 40            FromGenesisPlaza,
 41            FromDeepLink,
 42            FromResetTutorial,
 43            FromBuilderInWorld,
 44            FromUserThatAlreadyDidTheTutorial
 45        }
 46
 2747        public static TutorialController i { get; private set; }
 48
 049        public HUDController hudController { get => HUDController.i; }
 50
 051        public int currentStepIndex { get; internal set; }
 52        public event Action OnTutorialEnabled;
 53        public event Action OnTutorialDisabled;
 54
 55        private const string PLAYER_PREFS_VOICE_CHAT_FEATURE_SHOWED = "VoiceChatFeatureShowed";
 56
 57        internal TutorialSettings configuration;
 58        internal TutorialView tutorialView;
 59
 60        internal bool isRunning = false;
 61        internal bool openedFromDeepLink = false;
 62        internal bool playerIsInGenesisPlaza = false;
 63        internal TutorialStep runningStep = null;
 64        internal bool tutorialReset = false;
 65        internal float elapsedTimeInCurrentStep = 0f;
 66        internal TutorialPath currentPath;
 67        internal int currentStepNumber;
 68        internal TutorialType tutorialType = TutorialType.Initial;
 69
 70        private Coroutine executeStepsCoroutine;
 71        private Coroutine teacherMovementCoroutine;
 72        private Coroutine eagleEyeRotationCoroutine;
 73
 074        internal bool userAlreadyDidTheTutorial { get; set; }
 75
 76        public override void Initialize()
 77        {
 078            base.Initialize();
 79
 080            tutorialView = CreateTutorialView();
 081            SetConfiguration(tutorialView.configuration);
 082        }
 83
 84        internal TutorialView CreateTutorialView()
 85        {
 4486            GameObject tutorialGO = GameObject.Instantiate(Resources.Load<GameObject>("TutorialView"));
 4487            tutorialGO.name = "TutorialController";
 4488            TutorialView tutorialView = tutorialGO.GetComponent<TutorialView>();
 4489            tutorialView.ConfigureView(this);
 90
 4491            return tutorialView;
 92        }
 93
 94        public void SetConfiguration(TutorialSettings configuration)
 95        {
 4496            this.configuration = configuration;
 97
 4498            i = this;
 4499            ShowTeacher3DModel(false);
 100
 44101            if (CommonScriptableObjects.isTaskbarHUDInitialized.Get())
 44102                IsTaskbarHUDInitialized_OnChange(true, false);
 103            else
 0104                CommonScriptableObjects.isTaskbarHUDInitialized.OnChange += IsTaskbarHUDInitialized_OnChange;
 105
 44106            if (configuration.debugRunTutorial)
 107            {
 0108                SetTutorialEnabled(JsonUtility.ToJson(new TutorialInitializationMessage
 109                {
 110                    fromDeepLink = configuration.debugOpenedFromDeepLink.ToString(),
 111                    enableNewTutorialCamera = false.ToString()
 112                }));
 113            }
 44114        }
 115
 116        public override void Dispose()
 117        {
 44118            base.Dispose();
 119
 44120            SetTutorialDisabled();
 121
 44122            CommonScriptableObjects.isTaskbarHUDInitialized.OnChange -= IsTaskbarHUDInitialized_OnChange;
 123
 44124            if (hudController != null &&
 125                hudController.taskbarHud != null)
 126            {
 0127                hudController.taskbarHud.moreMenu.OnRestartTutorial -= MoreMenu_OnRestartTutorial;
 128            }
 129
 44130            NotificationsController.disableWelcomeNotification = false;
 131
 44132            if (tutorialView != null)
 44133                GameObject.Destroy(tutorialView.gameObject);
 44134        }
 135
 136        public void SetTutorialEnabled(string json)
 137        {
 1138            TutorialInitializationMessage msg = JsonUtility.FromJson<TutorialInitializationMessage>(json);
 1139            SetupTutorial(msg.fromDeepLink, msg.enableNewTutorialCamera, TutorialType.Initial);
 1140        }
 141
 142        public void SetTutorialEnabledForUsersThatAlreadyDidTheTutorial(string json)
 143        {
 0144            TutorialInitializationMessage msg = JsonUtility.FromJson<TutorialInitializationMessage>(json);
 145
 146            // TODO (Santi): This a TEMPORAL fix. It will be removed when we refactorize the tutorial system in order to
 0147            if (PlayerPrefsUtils.GetInt(PLAYER_PREFS_VOICE_CHAT_FEATURE_SHOWED) == 1)
 0148                return;
 149
 0150            SetupTutorial(false.ToString(), msg.enableNewTutorialCamera, TutorialType.Initial, true);
 0151        }
 152
 0153        public void SetBuilderInWorldTutorialEnabled() { SetupTutorial(false.ToString(), false.ToString(), TutorialType.
 154
 155        /// <summary>
 156        /// Enables the tutorial controller and waits for the RenderingState is enabled to start to execute the correspo
 157        /// </summary>
 158        internal void SetupTutorial(string fromDeepLink, string enableNewTutorialCamera, TutorialType tutorialType, bool
 159        {
 2160            if (isRunning)
 0161                return;
 162
 2163            if (Convert.ToBoolean(enableNewTutorialCamera))
 164            {
 1165                configuration.eagleCamInitPosition = new Vector3(15, 115, -30);
 1166                configuration.eagleCamInitLookAtPoint = new Vector3(16, 105, 6);
 1167                configuration.eagleCamRotationActived = false;
 168            }
 169
 2170            isRunning = true;
 2171            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(0f);
 2172            this.userAlreadyDidTheTutorial = userAlreadyDidTheTutorial;
 2173            CommonScriptableObjects.allUIHidden.Set(false);
 2174            CommonScriptableObjects.tutorialActive.Set(true);
 2175            openedFromDeepLink = Convert.ToBoolean(fromDeepLink);
 2176            this.tutorialType = tutorialType;
 177
 2178            hudController?.taskbarHud?.ShowTutorialOption(false);
 2179            hudController?.profileHud?.HideProfileMenu();
 180
 2181            NotificationsController.disableWelcomeNotification = true;
 182
 2183            WebInterface.SetDelightedSurveyEnabled(false);
 184
 2185            if (!CommonScriptableObjects.rendererState.Get())
 1186                CommonScriptableObjects.rendererState.OnChange += OnRenderingStateChanged;
 187            else
 1188                OnRenderingStateChanged(true, false);
 189
 2190            OnTutorialEnabled?.Invoke();
 1191        }
 192
 193        /// <summary>
 194        /// Stop and disables the tutorial controller.
 195        /// </summary>
 196        public void SetTutorialDisabled()
 197        {
 76198            CommonScriptableObjects.featureKeyTriggersBlocked.Set(false);
 199
 76200            if (executeStepsCoroutine != null)
 201            {
 1202                CoroutineStarter.Stop(executeStepsCoroutine);
 1203                executeStepsCoroutine = null;
 204            }
 205
 76206            if (runningStep != null)
 207            {
 1208                GameObject.Destroy(runningStep.gameObject);
 1209                runningStep = null;
 210            }
 211
 76212            tutorialReset = false;
 76213            isRunning = false;
 76214            DataStore.i.virtualAudioMixer.sceneSFXVolume.Set(1f);
 76215            ShowTeacher3DModel(false);
 76216            WebInterface.SetDelightedSurveyEnabled(true);
 217
 76218            if (Environment.i != null && Environment.i.world != null)
 219            {
 76220                WebInterface.SendSceneExternalActionEvent(Environment.i.world.state.currentSceneId, "tutorial", "end");
 221            }
 222
 76223            NotificationsController.disableWelcomeNotification = false;
 224
 76225            hudController?.taskbarHud?.ShowTutorialOption(true);
 226
 76227            CommonScriptableObjects.tutorialActive.Set(false);
 228
 76229            CommonScriptableObjects.rendererState.OnChange -= OnRenderingStateChanged;
 230
 76231            OnTutorialDisabled?.Invoke();
 2232        }
 233
 234        /// <summary>
 235        /// Starts to execute the tutorial from a specific step (It is needed to call SetTutorialEnabled() before).
 236        /// </summary>
 237        /// <param name="stepIndex">First step to be executed.</param>
 238        public IEnumerator StartTutorialFromStep(int stepIndex)
 239        {
 32240            if (!isRunning)
 2241                yield break;
 242
 30243            if (runningStep != null)
 244            {
 10245                runningStep.OnStepFinished();
 10246                GameObject.Destroy(runningStep.gameObject);
 10247                runningStep = null;
 248            }
 249
 30250            switch (tutorialType)
 251            {
 252                case TutorialType.Initial:
 28253                    if (userAlreadyDidTheTutorial)
 254                    {
 2255                        yield return ExecuteSteps(TutorialPath.FromUserThatAlreadyDidTheTutorial, stepIndex);
 2256                    }
 26257                    else if (playerIsInGenesisPlaza || tutorialReset)
 258                    {
 24259                        if (tutorialReset)
 260                        {
 3261                            yield return ExecuteSteps(TutorialPath.FromResetTutorial, stepIndex);
 2262                        }
 263                        else
 264                        {
 21265                            yield return ExecuteSteps(TutorialPath.FromGenesisPlaza, stepIndex);
 266                        }
 21267                    }
 2268                    else if (openedFromDeepLink)
 269                    {
 2270                        yield return ExecuteSteps(TutorialPath.FromDeepLink, stepIndex);
 2271                    }
 272                    else
 273                    {
 0274                        SetTutorialDisabled();
 0275                        yield break;
 276                    }
 277
 278                    break;
 279                case TutorialType.BuilderInWorld:
 2280                    yield return ExecuteSteps(TutorialPath.FromBuilderInWorld, stepIndex);
 281                    break;
 282            }
 29283        }
 284
 285        /// <summary>
 286        /// Shows the teacher that will be guiding along the tutorial.
 287        /// </summary>
 288        /// <param name="active">True for show the teacher.</param>
 289        public void ShowTeacher3DModel(bool active)
 290        {
 141291            if (configuration.teacherCamera != null)
 141292                configuration.teacherCamera.enabled = active;
 293
 141294            if (configuration.teacherRawImage != null)
 84295                configuration.teacherRawImage.gameObject.SetActive(active);
 141296        }
 297
 298        /// <summary>
 299        /// Move the tutorial teacher to a specific position.
 300        /// </summary>
 301        /// <param name="position">Target position.</param>
 302        /// <param name="animated">True for apply a smooth movement.</param>
 303        public void SetTeacherPosition(Vector2 position, bool animated = true)
 304        {
 29305            if (teacherMovementCoroutine != null)
 0306                CoroutineStarter.Stop(teacherMovementCoroutine);
 307
 29308            if (configuration.teacherRawImage != null)
 309            {
 2310                if (animated)
 0311                    teacherMovementCoroutine = CoroutineStarter.Start(MoveTeacher(configuration.teacherRawImage.rectTran
 312                else
 2313                    configuration.teacherRawImage.rectTransform.position = position;
 314            }
 29315        }
 316
 317        /// <summary>
 318        /// Plays a specific animation on the tutorial teacher.
 319        /// </summary>
 320        /// <param name="animation">Animation to apply.</param>
 321        public void PlayTeacherAnimation(TutorialTeacher.TeacherAnimation animation)
 322        {
 55323            if (configuration.teacher == null)
 27324                return;
 325
 28326            configuration.teacher.PlayAnimation(animation);
 28327        }
 328
 329        /// <summary>
 330        /// Set sort order for canvas containing teacher RawImage
 331        /// </summary>
 332        /// <param name="sortOrder"></param>
 333        public void SetTeacherCanvasSortingOrder(int sortOrder)
 334        {
 13335            if (configuration.teacherCanvas == null)
 0336                return;
 337
 13338            configuration.teacherCanvas.sortingOrder = sortOrder;
 13339        }
 340
 341        /// <summary>
 342        /// Finishes the current running step, skips all the next ones and completes the tutorial.
 343        /// </summary>
 344        public void SkipTutorial()
 345        {
 5346            if (!configuration.debugRunTutorial && configuration.sendStats)
 347            {
 0348                SendSkipTutorialSegmentStats(
 349                    configuration.tutorialVersion,
 350                    runningStep.name.Replace("(Clone)", "").Replace("TutorialStep_", ""));
 351            }
 352
 5353            int skipIndex = configuration.stepsOnGenesisPlaza.Count +
 354                            configuration.stepsFromDeepLink.Count +
 355                            configuration.stepsFromReset.Count +
 356                            configuration.stepsFromBuilderInWorld.Count +
 357                            configuration.stepsFromUserThatAlreadyDidTheTutorial.Count;
 358
 5359            CoroutineStarter.Start(StartTutorialFromStep(skipIndex));
 360
 5361            hudController?.taskbarHud?.SetVisibility(true);
 5362            hudController?.profileHud?.SetBackpackButtonVisibility(true);
 0363        }
 364
 365        /// <summary>
 366        /// Activate/deactivate the eagle eye camera.
 367        /// </summary>
 368        /// <param name="isActive">True for activate the eagle eye camera.</param>
 369        public void SetEagleEyeCameraActive(bool isActive)
 370        {
 6371            configuration.eagleEyeCamera.gameObject.SetActive(isActive);
 6372            CoroutineStarter.Start(BlockPlayerCameraUntilBlendingIsFinished(isActive));
 373
 6374            if (isActive)
 375            {
 3376                configuration.eagleEyeCamera.transform.position = configuration.eagleCamInitPosition;
 3377                configuration.eagleEyeCamera.transform.LookAt(configuration.eagleCamInitLookAtPoint);
 378
 3379                if (configuration.eagleCamRotationActived)
 2380                    eagleEyeRotationCoroutine = CoroutineStarter.Start(EagleEyeCameraRotation(configuration.eagleCamRota
 2381            }
 3382            else if (eagleEyeRotationCoroutine != null)
 383            {
 2384                CoroutineStarter.Stop(eagleEyeRotationCoroutine);
 385            }
 4386        }
 387
 388        internal void OnRenderingStateChanged(bool renderingEnabled, bool prevState)
 389        {
 3390            if (!renderingEnabled)
 0391                return;
 392
 3393            CommonScriptableObjects.rendererState.OnChange -= OnRenderingStateChanged;
 394
 3395            playerIsInGenesisPlaza = IsPlayerInsideGenesisPlaza();
 396
 3397            if (configuration.debugRunTutorial)
 1398                currentStepIndex = configuration.debugStartingStepIndex >= 0 ? configuration.debugStartingStepIndex : 0;
 399            else
 2400                currentStepIndex = 0;
 401
 3402            PlayTeacherAnimation(TutorialTeacher.TeacherAnimation.Reset);
 3403            executeStepsCoroutine = CoroutineStarter.Start(StartTutorialFromStep(currentStepIndex));
 3404        }
 405
 406        private IEnumerator ExecuteSteps(TutorialPath tutorialPath, int startingStepIndex)
 407        {
 30408            List<TutorialStep> steps = new List<TutorialStep>();
 409
 410            switch (tutorialPath)
 411            {
 412                case TutorialPath.FromGenesisPlaza:
 21413                    steps = configuration.stepsOnGenesisPlaza;
 21414                    break;
 415                case TutorialPath.FromDeepLink:
 2416                    steps = configuration.stepsFromDeepLink;
 2417                    break;
 418                case TutorialPath.FromResetTutorial:
 3419                    steps = configuration.stepsFromReset;
 3420                    break;
 421                case TutorialPath.FromBuilderInWorld:
 2422                    steps = configuration.stepsFromBuilderInWorld;
 2423                    break;
 424                case TutorialPath.FromUserThatAlreadyDidTheTutorial:
 2425                    steps = configuration.stepsFromUserThatAlreadyDidTheTutorial;
 426                    break;
 427            }
 428
 30429            currentPath = tutorialPath;
 430
 30431            elapsedTimeInCurrentStep = 0f;
 148432            for (int i = startingStepIndex; i < steps.Count; i++)
 433            {
 44434                var stepPrefab = steps[i];
 435
 436                // TODO (Santi): This a TEMPORAL fix. It will be removed when we refactorize the tutorial system in orde
 44437                if (stepPrefab is TutorialStep_Tooltip_UsersAround &&
 438                    CommonScriptableObjects.voiceChatDisabled.Get())
 439                    continue;
 440
 44441                if (stepPrefab.letInstantiation)
 19442                    runningStep = GameObject.Instantiate(stepPrefab, tutorialView.transform).GetComponent<TutorialStep>(
 443                else
 25444                    runningStep = steps[i];
 445
 44446                currentStepIndex = i;
 447
 44448                elapsedTimeInCurrentStep = Time.realtimeSinceStartup;
 44449                currentStepNumber = i + 1;
 450
 44451                if (!configuration.debugRunTutorial && configuration.sendStats)
 452                {
 0453                    SendStepStartedSegmentStats(
 454                        configuration.tutorialVersion,
 455                        tutorialPath,
 456                        i + 1,
 457                        runningStep.name.Replace("(Clone)", "").Replace("TutorialStep_", ""));
 458                }
 459
 44460                if (tutorialPath == TutorialPath.FromUserThatAlreadyDidTheTutorial &&
 461                    runningStep is TutorialStep_Tooltip)
 462                {
 0463                    ((TutorialStep_Tooltip) runningStep).OverrideSetMaxTimeToHide(true);
 464                }
 465
 44466                runningStep.OnStepStart();
 44467                yield return runningStep.OnStepExecute();
 44468                if (i < steps.Count - 1)
 20469                    PlayTeacherAnimation(TutorialTeacher.TeacherAnimation.StepCompleted);
 470                else
 24471                    PlayTeacherAnimation(TutorialTeacher.TeacherAnimation.QuickGoodbye);
 472
 44473                yield return runningStep.OnStepPlayHideAnimation();
 44474                runningStep.OnStepFinished();
 44475                elapsedTimeInCurrentStep = Time.realtimeSinceStartup - elapsedTimeInCurrentStep;
 476
 44477                if (!configuration.debugRunTutorial &&
 478                    configuration.sendStats &&
 479                    tutorialPath != TutorialPath.FromUserThatAlreadyDidTheTutorial)
 480                {
 0481                    SendStepCompletedSegmentStats(
 482                        configuration.tutorialVersion,
 483                        tutorialPath,
 484                        i + 1,
 485                        runningStep.name.Replace("(Clone)", "").Replace("TutorialStep_", ""),
 486                        elapsedTimeInCurrentStep);
 487                }
 488
 44489                GameObject.Destroy(runningStep.gameObject);
 490
 44491                if (i < steps.Count - 1 && configuration.timeBetweenSteps > 0)
 0492                    yield return new WaitForSeconds(configuration.timeBetweenSteps);
 493            }
 494
 30495            if (!configuration.debugRunTutorial &&
 496                tutorialPath != TutorialPath.FromBuilderInWorld &&
 497                tutorialPath != TutorialPath.FromUserThatAlreadyDidTheTutorial)
 498            {
 26499                SetUserTutorialStepAsCompleted(TutorialFinishStep.NewTutorialFinished);
 500            }
 501
 30502            runningStep = null;
 503
 30504            SetTutorialDisabled();
 30505        }
 506
 52507        private void SetUserTutorialStepAsCompleted(TutorialFinishStep finishStepType) { WebInterface.SaveUserTutorialSt
 508
 509        internal IEnumerator MoveTeacher(Vector2 fromPosition, Vector2 toPosition)
 510        {
 1511            if (configuration.teacherRawImage == null)
 0512                yield break;
 513
 1514            float t = 0f;
 515
 2516            while (Vector2.Distance(configuration.teacherRawImage.rectTransform.position, toPosition) > 0)
 517            {
 2518                t += configuration.teacherMovementSpeed * Time.deltaTime;
 2519                if (t <= 1.0f)
 2520                    configuration.teacherRawImage.rectTransform.position = Vector2.Lerp(fromPosition, toPosition, config
 521                else
 0522                    configuration.teacherRawImage.rectTransform.position = toPosition;
 523
 2524                yield return null;
 525            }
 0526        }
 527
 528        private void IsTaskbarHUDInitialized_OnChange(bool current, bool previous)
 529        {
 44530            if (current &&
 531                hudController != null &&
 532                hudController.taskbarHud != null)
 533            {
 0534                hudController.taskbarHud.moreMenu.OnRestartTutorial -= MoreMenu_OnRestartTutorial;
 0535                hudController.taskbarHud.moreMenu.OnRestartTutorial += MoreMenu_OnRestartTutorial;
 536            }
 44537        }
 538
 539        internal void MoreMenu_OnRestartTutorial()
 540        {
 1541            SetTutorialDisabled();
 1542            tutorialReset = true;
 1543            SetTutorialEnabled(JsonUtility.ToJson(new TutorialInitializationMessage
 544            {
 545                fromDeepLink = false.ToString(),
 546                enableNewTutorialCamera = false.ToString()
 547            }));
 1548        }
 549
 550        internal static bool IsPlayerInsideGenesisPlaza()
 551        {
 3552            if (Environment.i.world == null)
 0553                return false;
 554
 3555            IWorldState worldState = Environment.i.world.state;
 556
 3557            if (worldState == null || worldState.currentSceneId == null)
 0558                return false;
 559
 3560            Vector2Int genesisPlazaBaseCoords = new Vector2Int(-9, -9);
 561
 3562            IParcelScene currentScene = null;
 3563            if (worldState.loadedScenes != null)
 0564                currentScene = worldState.loadedScenes[worldState.currentSceneId];
 565
 3566            if (currentScene != null && currentScene.IsInsideSceneBoundaries(genesisPlazaBaseCoords))
 0567                return true;
 568
 3569            return false;
 570        }
 571
 572        private void SendStepStartedSegmentStats(int version, TutorialPath tutorialPath, int stepNumber, string stepName
 573        {
 0574            WebInterface.AnalyticsPayload.Property[] properties = new WebInterface.AnalyticsPayload.Property[]
 575            {
 576                new WebInterface.AnalyticsPayload.Property("version", version.ToString()),
 577                new WebInterface.AnalyticsPayload.Property("path", tutorialPath.ToString()),
 578                new WebInterface.AnalyticsPayload.Property("step number", stepNumber.ToString()),
 579                new WebInterface.AnalyticsPayload.Property("step name", stepName)
 580            };
 0581            WebInterface.ReportAnalyticsEvent("tutorial step started", properties);
 0582        }
 583
 584        private void SendStepCompletedSegmentStats(int version, TutorialPath tutorialPath, int stepNumber, string stepNa
 585        {
 0586            WebInterface.AnalyticsPayload.Property[] properties = new WebInterface.AnalyticsPayload.Property[]
 587            {
 588                new WebInterface.AnalyticsPayload.Property("version", version.ToString()),
 589                new WebInterface.AnalyticsPayload.Property("path", tutorialPath.ToString()),
 590                new WebInterface.AnalyticsPayload.Property("step number", stepNumber.ToString()),
 591                new WebInterface.AnalyticsPayload.Property("step name", stepName),
 592                new WebInterface.AnalyticsPayload.Property("elapsed time", elapsedTime.ToString("0.00"))
 593            };
 0594            WebInterface.ReportAnalyticsEvent("tutorial step completed", properties);
 0595        }
 596
 597        private void SendSkipTutorialSegmentStats(int version, string stepName)
 598        {
 0599            WebInterface.AnalyticsPayload.Property[] properties = new WebInterface.AnalyticsPayload.Property[]
 600            {
 601                new WebInterface.AnalyticsPayload.Property("version", version.ToString()),
 602                new WebInterface.AnalyticsPayload.Property("path", currentPath.ToString()),
 603                new WebInterface.AnalyticsPayload.Property("step number", currentStepNumber.ToString()),
 604                new WebInterface.AnalyticsPayload.Property("step name", stepName),
 605                new WebInterface.AnalyticsPayload.Property("elapsed time", (Time.realtimeSinceStartup - elapsedTimeInCur
 606            };
 0607            WebInterface.ReportAnalyticsEvent("tutorial skipped", properties);
 0608        }
 609
 610        internal IEnumerator EagleEyeCameraRotation(float rotationSpeed)
 611        {
 4612            while (true)
 613            {
 6614                configuration.eagleEyeCamera.transform.Rotate(Vector3.up * Time.deltaTime * rotationSpeed, Space.World);
 6615                yield return null;
 616            }
 617        }
 618
 619        private IEnumerator BlockPlayerCameraUntilBlendingIsFinished(bool hideUIs)
 620        {
 6621            if (hideUIs)
 622            {
 3623                hudController?.minimapHud?.SetVisibility(false);
 3624                hudController?.profileHud?.SetVisibility(false);
 625            }
 626
 6627            CommonScriptableObjects.cameraBlocked.Set(true);
 628
 6629            yield return null;
 864630            yield return new WaitUntil(() => !CommonScriptableObjects.cameraIsBlending.Get());
 631
 6632            CommonScriptableObjects.cameraBlocked.Set(false);
 633
 6634            if (!hideUIs)
 635            {
 3636                hudController?.minimapHud?.SetVisibility(true);
 3637                hudController?.profileHud?.SetVisibility(true);
 638            }
 6639        }
 640    }
 641}