< Summary

Class:DCL.Skybox.SkyboxController
Assembly:ProceduralSkybox
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/ProceduralSkybox/ToolProceduralSkybox/Scripts/SkyboxController.cs
Covered lines:0
Uncovered lines:273
Coverable lines:273
Total lines:652
Line coverage:0% (0 of 273)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:37
Method coverage:0% (0 of 37)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SkyboxController(...)0%30500%
DoAsyncInitializations()0%90900%
LoadConfigurations()0%42600%
AssignMainOverlayCamera(...)0%2100%
AssignCameraReferences(...)0%2100%
OnFullscreenUIVisibilityChange(...)0%20400%
FixedTime_OnChange(...)0%12300%
UseDynamicSkybox_OnChange(...)0%12300%
GetOrCreateEnvironmentProbe()0%72800%
ReflectionResolution_OnChange(...)0%2100%
AssignCameraInstancetoProbe()0%12300%
KernelConfig_OnChange(...)0%6200%
UpdateConfig(...)0%90900%
ApplyConfig()0%30500%
GetTimeFromTheServer(...)0%2100%
SelectSkyboxConfiguration()0%56700%
Configuration_OnTimelineEvent(...)0%6200%
Update()0%90900%
Dispose()0%6200%
PauseTime(...)0%6200%
ResumeTime(...)0%6200%
IsPaused()0%2100%
GetCurrentConfiguration()0%2100%
GetCurrentTimeOfTheDay()0%2100%
SetOverrideController(...)0%2100%
GetControlBackFromEditor(...)0%6200%
UpdateConfigurationTimelineEvent(...)0%2100%
ApplyAvatarColor(...)0%12300%
OnAvatarMatProfileOnChange(...)0%2100%
GetSkyboxElements()0%2100%
DisposeCT()0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/ProceduralSkybox/ToolProceduralSkybox/Scripts/SkyboxController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Providers;
 3using System;
 4using System.Linq;
 5using UnityEngine;
 6using System.Collections.Generic;
 7using System.Threading;
 8
 9namespace DCL.Skybox
 10{
 11    /// <summary>
 12    /// This class will handle runtime execution of skybox cycle.
 13    /// Load and assign material to the Skybox.
 14    /// This will mostly increment the time cycle and apply values from configuration to the material.
 15    /// </summary>
 16    public class SkyboxController : IPlugin
 17    {
 18        public event SkyboxConfiguration.TimelineEvents OnTimelineEvent;
 19
 020        public static SkyboxController i { get; private set; }
 21
 22        public const string DEFAULT_SKYBOX_ID = "Generic_Skybox";
 23
 24        public string loadedConfig;
 025        public float lifecycleDuration = 2;
 26
 27        private float timeOfTheDay;                            // (Nishant.K) Time will be provided from outside, So rem
 28        private Light directionalLight;
 29        private SkyboxConfiguration configuration;
 30        private Material selectedMat;
 31        private bool overrideDefaultSkybox;
 32        private string overrideSkyboxID;
 33        private bool isPaused;
 34        private float timeNormalizationFactor;
 35        private int slotCount;
 36        private bool overrideByEditor = false;
 37        private SkyboxElements skyboxElements;
 38
 39        // Reflection probe//
 40        private ReflectionProbe skyboxProbe;
 41        private bool probeParented = false;
 042        private float reflectionUpdateTime = 1;                                 // In Mins
 43        private ReflectionProbeRuntime runtimeReflectionObj;
 44
 45        // Timer sync
 46        private int syncCounter = 0;
 047        private int syncAfterCount = 10;
 48
 49        // Report to kernel
 050        private ITimeReporter timeReporter { get; set; } = new TimeReporter();
 51
 52        private readonly DataStore dataStore;
 53        private Service<IAddressableResourceProvider> addresableResolver;
 54        private Dictionary<string, SkyboxConfiguration> skyboxConfigurationsDictionary;
 55        private MaterialReferenceContainer materialReferenceContainer;
 56        private CancellationTokenSource addressableCTS;
 57
 058        public SkyboxCamera SkyboxCamera { get; private set; }
 59
 060        public SkyboxController(DataStore dataStore)
 61        {
 062            i = this;
 63
 064            this.dataStore = dataStore;
 65
 66            // Find and delete test directional light obj if any
 067            Light[] testDirectionalLight = GameObject.FindObjectsOfType<Light>().Where(s => s.name == "The Sun_Temp").To
 068            for (int i = 0; i < testDirectionalLight.Length; i++)
 69            {
 070                GameObject.DestroyImmediate(testDirectionalLight[i].gameObject);
 71            }
 72
 73            // Get or Create new Directional Light Object
 074            directionalLight = GameObject.FindObjectsOfType<Light>().Where(s => s.type == LightType.Directional).FirstOr
 75
 076            if (directionalLight == null)
 77            {
 078                GameObject temp = new GameObject("The Sun");
 79                // Add the light component
 080                directionalLight = temp.AddComponent<Light>();
 081                directionalLight.type = LightType.Directional;
 82            }
 83
 084            CommonScriptableObjects.isFullscreenHUDOpen.OnChange += OnFullscreenUIVisibilityChange;
 085            CommonScriptableObjects.isLoadingHUDOpen.OnChange += OnFullscreenUIVisibilityChange;
 086            dataStore.skyboxConfig.avatarMatProfile.OnChange += OnAvatarMatProfileOnChange;
 87
 088            DoAsyncInitializations();
 089        }
 90
 91        private async UniTaskVoid DoAsyncInitializations()
 92        {
 93            try
 94            {
 095                addressableCTS = new CancellationTokenSource();
 096                materialReferenceContainer = await addresableResolver.Ref.GetAddressable<MaterialReferenceContainer>("Sk
 097                await GetOrCreateEnvironmentProbe(addressableCTS.Token);
 098                await LoadConfigurations(addressableCTS.Token);
 099                skyboxElements = new SkyboxElements();
 0100                await skyboxElements.Initialize(addresableResolver.Ref, materialReferenceContainer, addressableCTS.Token
 0101            }
 0102            catch (Exception e)
 103            {
 0104                Debug.LogWarning("Retrying skybox addressables async request...");
 0105                DisposeCT();
 0106                DoAsyncInitializations().Forget();
 0107                return;
 108            }
 109
 110            // Create skybox Camera
 0111            SkyboxCamera = new SkyboxCamera();
 112
 113            // Get current time from the server
 0114            GetTimeFromTheServer(dataStore.worldTimer.GetCurrentTime());
 0115            dataStore.worldTimer.OnTimeChanged += GetTimeFromTheServer;
 116
 117            // Update config whenever skybox config changed in data store. Can be used for both testing and runtime
 0118            dataStore.skyboxConfig.objectUpdated.OnChange += UpdateConfig;
 119
 120            // Change as Kernel config is initialized or updated
 0121            KernelConfig.i.EnsureConfigInitialized()
 122                        .Then(config =>
 123                         {
 0124                             KernelConfig_OnChange(config, null);
 0125                         });
 126
 0127            KernelConfig.i.OnChange += KernelConfig_OnChange;
 128
 0129            Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 130
 0131            dataStore.skyboxConfig.reflectionResolution.OnChange += ReflectionResolution_OnChange;
 132
 133            // Register for camera references
 0134            dataStore.camera.transform.OnChange += AssignCameraReferences;
 0135            AssignCameraReferences(dataStore.camera.transform.Get(), null);
 136
 137            // Register UI related events
 0138            dataStore.skyboxConfig.mode.OnChange += UseDynamicSkybox_OnChange;
 0139            dataStore.skyboxConfig.fixedTime.OnChange += FixedTime_OnChange;
 140            //Ensure current settings
 0141            UseDynamicSkybox_OnChange(dataStore.skyboxConfig.mode.Get());
 0142            FixedTime_OnChange(dataStore.skyboxConfig.fixedTime.Get());
 0143        }
 144
 145        private async UniTask LoadConfigurations(CancellationToken ct)
 146        {
 0147            IList<SkyboxConfiguration> skyboxConfigurations = await addresableResolver.Ref.GetAddressablesList<SkyboxCon
 0148            skyboxConfigurationsDictionary = new Dictionary<string, SkyboxConfiguration>();
 0149            foreach (SkyboxConfiguration skyboxConfiguration in skyboxConfigurations)
 150            {
 0151                skyboxConfigurationsDictionary.Add(skyboxConfiguration.name, skyboxConfiguration);
 152            }
 0153        }
 154
 155        public void AssignMainOverlayCamera(Transform currentTransform)
 156        {
 0157            SkyboxCamera.AssignTargetCamera(currentTransform);
 0158        }
 159
 160        private void AssignCameraReferences(Transform currentTransform, Transform prevTransform)
 161        {
 0162            SkyboxCamera.AssignTargetCamera(currentTransform);
 0163            skyboxElements.AssignCameraInstance(currentTransform);
 0164        }
 165
 166        private void OnFullscreenUIVisibilityChange(bool visibleState, bool prevVisibleState)
 167        {
 0168            if (visibleState == prevVisibleState)
 0169                return;
 170
 0171            if(SkyboxCamera == null) return;
 172
 0173            SkyboxCamera.SetCameraEnabledState(!visibleState && CommonScriptableObjects.rendererState.Get());
 0174        }
 175
 176        private void FixedTime_OnChange(float current, float _ = 0)
 177        {
 0178            if (dataStore.skyboxConfig.mode.Get() != SkyboxMode.Dynamic)
 179            {
 0180                PauseTime(true, current);
 181            }
 182
 0183            if (runtimeReflectionObj != null)
 184            {
 0185                runtimeReflectionObj.FixedSkyboxTimeChanged();
 186            }
 0187        }
 188
 189        private void UseDynamicSkybox_OnChange(SkyboxMode current, SkyboxMode _ = SkyboxMode.Dynamic)
 190        {
 0191            if (current == SkyboxMode.Dynamic)
 192            {
 193                // Get latest time from server
 0194                UpdateConfig();
 195            }
 196            else
 197            {
 0198                PauseTime(true, dataStore.skyboxConfig.fixedTime.Get());
 199            }
 200
 0201            if (runtimeReflectionObj != null)
 202            {
 0203                runtimeReflectionObj.SkyboxModeChanged(current == SkyboxMode.Dynamic);
 204            }
 0205        }
 206
 207        private async UniTask GetOrCreateEnvironmentProbe(CancellationToken cts)
 208        {
 209            // Get Reflection Probe Object
 0210            skyboxProbe = GameObject.FindObjectsOfType<ReflectionProbe>().Where(s => s.name == "SkyboxProbe").FirstOrDef
 211
 0212            if (dataStore.skyboxConfig.disableReflection.Get())
 213            {
 0214                if (skyboxProbe != null)
 215                {
 0216                    skyboxProbe.gameObject.SetActive(false);
 217                }
 218
 0219                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;
 0220                RenderSettings.customReflection = null;
 0221                return;
 222            }
 223
 0224            if (skyboxProbe == null)
 225            {
 226                // Instantiate new probe from the resources
 0227                GameObject temp = await addresableResolver.Ref.GetAddressable<GameObject>("SkyboxProbe.prefab", cts);
 0228                GameObject probe = GameObject.Instantiate<GameObject>(temp);
 0229                probe.name = "SkyboxProbe";
 0230                skyboxProbe = probe.GetComponent<ReflectionProbe>();
 231
 232                // make probe a child of main camera
 0233                AssignCameraInstancetoProbe();
 234            }
 235
 236            // Update time in Reflection Probe
 0237            runtimeReflectionObj = skyboxProbe.GetComponent<ReflectionProbeRuntime>();
 0238            if (runtimeReflectionObj == null)
 239            {
 0240                runtimeReflectionObj = skyboxProbe.gameObject.AddComponent<ReflectionProbeRuntime>();
 241            }
 242
 243            // Update resolution
 0244            runtimeReflectionObj.UpdateResolution(dataStore.skyboxConfig.reflectionResolution.Get());
 245
 246            // Assign as seconds
 0247            runtimeReflectionObj.updateAfter = reflectionUpdateTime * 60;
 248
 0249            RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;
 0250            RenderSettings.customReflection = null;
 0251        }
 252
 0253        private void ReflectionResolution_OnChange(int current, int previous) { runtimeReflectionObj.UpdateResolution(cu
 254
 255        private void AssignCameraInstancetoProbe()
 256        {
 0257            if (skyboxProbe == null)
 258            {
 259#if UNITY_EDITOR
 0260                Debug.LogError("Cannot parent the probe as probe is not instantiated");
 261#endif
 0262                return;
 263            }
 264
 265            // make probe a child of main camera
 0266            if (Camera.main != null)
 267            {
 0268                GameObject mainCam = Camera.main.gameObject;
 0269                runtimeReflectionObj.followTransform = mainCam.transform;
 0270                probeParented = true;
 271            }
 0272        }
 273
 274        private void KernelConfig_OnChange(KernelConfigModel current, KernelConfigModel previous)
 275        {
 0276            if (overrideByEditor)
 277            {
 0278                return;
 279            }
 280            // set skyboxConfig to true
 0281            dataStore.skyboxConfig.configToLoad.Set(current.proceduralSkyboxConfig.configToLoad);
 0282            dataStore.skyboxConfig.lifecycleDuration.Set(current.proceduralSkyboxConfig.lifecycleDuration);
 0283            dataStore.skyboxConfig.jumpToTime.Set(current.proceduralSkyboxConfig.fixedTime);
 0284            dataStore.skyboxConfig.updateReflectionTime.Set(current.proceduralSkyboxConfig.updateReflectionTime);
 0285            dataStore.skyboxConfig.disableReflection.Set(current.proceduralSkyboxConfig.disableReflection);
 286
 287            // Call update on skybox config which will call Update config in this class.
 0288            dataStore.skyboxConfig.objectUpdated.Set(true, true);
 0289        }
 290
 291
 292        /// <summary>
 293        /// Called whenever any change in skyboxConfig is observed
 294        /// </summary>
 295        /// <param name="current"></param>
 296        /// <param name="previous"></param>
 297        public void UpdateConfig(bool current = true, bool previous = false)
 298        {
 0299            if (overrideByEditor)
 300            {
 0301                return;
 302            }
 303
 304            // Reset Object Update value without notifying
 0305            dataStore.skyboxConfig.objectUpdated.Set(false, false);
 306
 307            //Ensure default configuration
 0308            SelectSkyboxConfiguration();
 309
 0310            if (dataStore.skyboxConfig.mode.Get() != SkyboxMode.Dynamic)
 311            {
 0312                return;
 313            }
 314
 0315            if (loadedConfig != dataStore.skyboxConfig.configToLoad.Get())
 316            {
 317                // Apply configuration
 0318                overrideDefaultSkybox = true;
 0319                overrideSkyboxID = dataStore.skyboxConfig.configToLoad.Get();
 320            }
 321
 322            // Apply time
 0323            lifecycleDuration = dataStore.skyboxConfig.lifecycleDuration.Get();
 324
 0325            ApplyConfig();
 326
 327            // if Paused
 0328            if (dataStore.skyboxConfig.jumpToTime.Get() >= 0)
 329            {
 0330                PauseTime(true, dataStore.skyboxConfig.jumpToTime.Get());
 331            }
 332            else
 333            {
 0334                ResumeTime();
 335            }
 336
 337            // Update reflection time
 0338            if (dataStore.skyboxConfig.disableReflection.Get())
 339            {
 0340                if (skyboxProbe != null)
 341                {
 0342                    skyboxProbe.gameObject.SetActive(false);
 343                }
 344
 0345                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;
 0346                RenderSettings.customReflection = null;
 347            }
 0348            else if (runtimeReflectionObj != null)
 349            {
 350                // If reflection update time is -1 then calculate time based on the cycle time, else assign same
 0351                if (dataStore.skyboxConfig.updateReflectionTime.Get() >= 0)
 352                {
 0353                    reflectionUpdateTime = dataStore.skyboxConfig.updateReflectionTime.Get();
 354                }
 355                else
 356                {
 357                    // Evaluate with the cycle time
 0358                    reflectionUpdateTime = 1;               // Default for an hour is 1 min
 359                    // get cycle time in hours
 0360                    reflectionUpdateTime = (dataStore.skyboxConfig.lifecycleDuration.Get() / 60);
 361                }
 0362                runtimeReflectionObj.updateAfter = Mathf.Clamp(reflectionUpdateTime * 60, 5, 86400);
 363            }
 0364        }
 365
 366        /// <summary>
 367        /// Apply changed configuration
 368        /// </summary>
 369        private bool ApplyConfig()
 370        {
 0371            if (overrideByEditor)
 372            {
 0373                return false;
 374            }
 375
 0376            bool gotConfiguration = SelectSkyboxConfiguration();
 0377            if (!gotConfiguration)
 378            {
 0379                return false;
 380            }
 381
 0382            if (!configuration.useDirectionalLight)
 383            {
 0384                directionalLight.gameObject.SetActive(false);
 385            }
 386
 387            // Calculate time factor
 0388            if (lifecycleDuration <= 0)
 389            {
 0390                lifecycleDuration = 0.01f;
 391            }
 392
 393            // Convert minutes in seconds and then normalize with cycle time
 0394            timeNormalizationFactor = lifecycleDuration * 60 / SkyboxUtils.CYCLE_TIME;
 0395            timeReporter.Configure(timeNormalizationFactor, SkyboxUtils.CYCLE_TIME);
 396
 0397            GetTimeFromTheServer(dataStore.worldTimer.GetCurrentTime());
 398
 0399            return true;
 400        }
 401
 402        void GetTimeFromTheServer(DateTime serverTime)
 403        {
 0404            DateTime serverTimeNoTicks = new DateTime(serverTime.Year, serverTime.Month, serverTime.Day, serverTime.Hour
 0405            long elapsedTicks = serverTime.Ticks - serverTimeNoTicks.Ticks;
 406
 0407            float miliseconds = serverTime.Millisecond + (elapsedTicks / 10000);
 408
 409            // Convert miliseconds to seconds
 0410            float seconds = serverTime.Second + (miliseconds / 1000);
 411
 412            // Convert seconds to minutes
 0413            float minutes = serverTime.Minute + (seconds / 60);
 414
 415            // Convert minutes to hour (in float format)
 0416            float totalTimeInMins = serverTime.Hour * 60 + minutes;
 417
 0418            float timeInCycle = (totalTimeInMins / lifecycleDuration) + 1;
 0419            float percentageSkyboxtime = timeInCycle - (int)timeInCycle;
 420
 0421            timeOfTheDay = percentageSkyboxtime * SkyboxUtils.CYCLE_TIME;
 0422        }
 423
 424        /// <summary>
 425        /// Select Configuration to load.
 426        /// </summary>
 427        private bool SelectSkyboxConfiguration()
 428        {
 0429            bool tempConfigLoaded = true;
 430
 0431            string configToLoad = loadedConfig;
 0432            if (string.IsNullOrEmpty(loadedConfig))
 433            {
 0434                configToLoad = DEFAULT_SKYBOX_ID;
 435            }
 436
 437
 0438            if (overrideDefaultSkybox)
 439            {
 0440                configToLoad = overrideSkyboxID;
 0441                overrideDefaultSkybox = false;
 442            }
 443
 444            // config already loaded, return
 0445            if (configToLoad.Equals(loadedConfig))
 446            {
 0447                return tempConfigLoaded;
 448            }
 449
 0450            SkyboxConfiguration newConfiguration = skyboxConfigurationsDictionary[configToLoad];
 451
 0452            if (newConfiguration == null)
 453            {
 454#if UNITY_EDITOR || DEVELOPMENT_BUILD
 0455                Debug.LogError(configToLoad + " configuration not found in Addressables. Trying to load Default config: 
 456#endif
 457                // Try to load default config
 0458                configToLoad = DEFAULT_SKYBOX_ID;
 0459                newConfiguration = skyboxConfigurationsDictionary[configToLoad];
 460
 0461                if (newConfiguration == null)
 462                {
 463#if UNITY_EDITOR || DEVELOPMENT_BUILD
 0464                    Debug.LogError("Default configuration not found in Addressables. Shifting to old skybox.");
 465#endif
 0466                    tempConfigLoaded = false;
 0467                    return tempConfigLoaded;
 468                }
 469            }
 470
 471            // Register to timelineEvents
 0472            if (configuration != null)
 473            {
 0474                configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 475            }
 0476            newConfiguration.OnTimelineEvent += Configuration_OnTimelineEvent;
 0477            configuration = newConfiguration;
 478
 0479            selectedMat = materialReferenceContainer.skyboxMat;
 0480            slotCount = materialReferenceContainer.skyboxMatSlots;
 0481            configuration.ResetMaterial(selectedMat, slotCount);
 482
 0483            RenderSettings.skybox = selectedMat;
 484
 485            // Update loaded config
 0486            loadedConfig = configToLoad;
 487
 0488            return tempConfigLoaded;
 489        }
 490
 0491        private void Configuration_OnTimelineEvent(string tag, bool enable, bool trigger) { OnTimelineEvent?.Invoke(tag,
 492
 493        // Update is called once per frame
 494        public void Update()
 495        {
 0496            if (!dataStore.skyboxConfig.disableReflection.Get() && skyboxProbe != null && !probeParented)
 497            {
 0498                AssignCameraInstancetoProbe();
 499            }
 500
 0501            if (isPaused || configuration == null)
 502            {
 0503                return;
 504            }
 505
 506            // Control is in editor tool
 0507            if (overrideByEditor)
 508            {
 0509                return;
 510            }
 511
 0512            timeOfTheDay += Time.deltaTime / timeNormalizationFactor;
 513
 0514            syncCounter++;
 515
 0516            if (syncCounter >= syncAfterCount)
 517            {
 0518                GetTimeFromTheServer(dataStore.worldTimer.GetCurrentTime());
 0519                syncCounter = 0;
 520            }
 521
 0522            timeOfTheDay = Mathf.Clamp(timeOfTheDay, 0.01f, SkyboxUtils.CYCLE_TIME);
 0523            dataStore.skyboxConfig.currentVirtualTime.Set(timeOfTheDay);
 0524            timeReporter.ReportTime(timeOfTheDay);
 525
 0526            float normalizedDayTime = SkyboxUtils.GetNormalizedDayTime(timeOfTheDay);
 0527            configuration.ApplyOnMaterial(selectedMat, timeOfTheDay, normalizedDayTime, slotCount, directionalLight, Sky
 0528            ApplyAvatarColor(normalizedDayTime);
 0529            skyboxElements.ApplyConfigTo3DElements(configuration, timeOfTheDay, normalizedDayTime, directionalLight, Sky
 530
 531            // Cycle resets
 0532            if (timeOfTheDay >= SkyboxUtils.CYCLE_TIME)
 533            {
 0534                timeOfTheDay = 0.01f;
 0535                configuration.CycleResets();
 536            }
 537
 0538        }
 539
 540        public void Dispose()
 541        {
 542            // set skyboxConfig to false
 0543            dataStore.skyboxConfig.objectUpdated.OnChange -= UpdateConfig;
 544
 0545            dataStore.worldTimer.OnTimeChanged -= GetTimeFromTheServer;
 0546            if(configuration != null) configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 0547            KernelConfig.i.OnChange -= KernelConfig_OnChange;
 0548            Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 0549            dataStore.skyboxConfig.mode.OnChange -= UseDynamicSkybox_OnChange;
 0550            dataStore.skyboxConfig.fixedTime.OnChange -= FixedTime_OnChange;
 0551            dataStore.skyboxConfig.reflectionResolution.OnChange -= ReflectionResolution_OnChange;
 0552            dataStore.camera.transform.OnChange -= AssignCameraReferences;
 553
 0554            CommonScriptableObjects.isLoadingHUDOpen.OnChange -= OnFullscreenUIVisibilityChange;
 0555            CommonScriptableObjects.isFullscreenHUDOpen.OnChange -= OnFullscreenUIVisibilityChange;
 0556            dataStore.skyboxConfig.avatarMatProfile.OnChange -= OnAvatarMatProfileOnChange;
 557
 0558            timeReporter.Dispose();
 0559            DisposeCT();
 0560        }
 561
 562        public void PauseTime(bool overrideTime = false, float newTime = 0)
 563        {
 0564            isPaused = true;
 0565            if (overrideTime)
 566            {
 0567                timeOfTheDay = Mathf.Clamp(newTime, 0, SkyboxUtils.CYCLE_TIME);
 0568                float normalizedDayTime = SkyboxUtils.GetNormalizedDayTime(timeOfTheDay);
 0569                configuration.ApplyOnMaterial(selectedMat, (float)timeOfTheDay, normalizedDayTime, slotCount, directiona
 0570                ApplyAvatarColor(normalizedDayTime);
 0571                skyboxElements.ApplyConfigTo3DElements(configuration, timeOfTheDay, normalizedDayTime, directionalLight,
 572            }
 0573            timeReporter.ReportTime(timeOfTheDay);
 0574        }
 575
 576        public void ResumeTime(bool overrideTime = false, float newTime = 0)
 577        {
 0578            isPaused = false;
 0579            if (overrideTime)
 580            {
 0581                timeOfTheDay = newTime;
 582            }
 0583        }
 584
 0585        public bool IsPaused() { return isPaused; }
 586
 0587        public SkyboxConfiguration GetCurrentConfiguration() { return configuration; }
 588
 0589        public float GetCurrentTimeOfTheDay() { return (float)timeOfTheDay; }
 590
 591        public bool SetOverrideController(bool editorOveride)
 592        {
 0593            overrideByEditor = editorOveride;
 0594            return overrideByEditor;
 595        }
 596
 597        // Whenever Skybox editor closed at runtime control returns back to controller with the values in the editor
 598        public bool GetControlBackFromEditor(string currentConfig, float timeOfTheday, float lifecycleDuration, bool isP
 599        {
 0600            overrideByEditor = false;
 601
 0602            dataStore.skyboxConfig.configToLoad.Set(currentConfig);
 0603            dataStore.skyboxConfig.lifecycleDuration.Set(lifecycleDuration);
 604
 0605            if (isPaused)
 606            {
 0607                PauseTime(true, timeOfTheday);
 608            }
 609            else
 610            {
 0611                ResumeTime(true, timeOfTheday);
 612            }
 613
 614            // Call update on skybox config which will call Update config in this class.
 0615            dataStore.skyboxConfig.objectUpdated.Set(true, true);
 616
 0617            return overrideByEditor;
 618        }
 619
 620        public void UpdateConfigurationTimelineEvent(SkyboxConfiguration newConfig)
 621        {
 0622            configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 0623            newConfig.OnTimelineEvent += Configuration_OnTimelineEvent;
 0624        }
 625
 626        public void ApplyAvatarColor(float normalizedDayTime)
 627        {
 0628            if (configuration == null)
 0629                return;
 630
 0631            if (dataStore.skyboxConfig.avatarMatProfile.Get() == AvatarMaterialProfile.InWorld)
 0632                configuration.ApplyInWorldAvatarColor(normalizedDayTime, directionalLight.gameObject);
 633            else
 0634                configuration.ApplyEditorAvatarColor();
 0635        }
 636
 637        private void OnAvatarMatProfileOnChange(AvatarMaterialProfile current, AvatarMaterialProfile previous) =>
 0638            ApplyAvatarColor(SkyboxUtils.GetNormalizedDayTime(timeOfTheDay));
 639
 0640        public SkyboxElements GetSkyboxElements() { return skyboxElements; }
 641
 642        private void DisposeCT()
 643        {
 0644            if (addressableCTS != null)
 645            {
 0646                addressableCTS.Cancel();
 0647                addressableCTS.Dispose();
 0648                addressableCTS = null;
 649            }
 0650        }
 651    }
 652}