< 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:228
Coverable lines:228
Total lines:568
Line coverage:0% (0 of 228)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SkyboxController()0%30500%
AssignCameraReferences(...)0%2100%
FixedTime_OnChange(...)0%12300%
UseDynamicSkybox_OnChange(...)0%12300%
GetOrCreateEnvironmentProbe()0%42600%
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%6200%
GetSkyboxElements()0%2100%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Linq;
 3using UnityEngine;
 4using DCL.ServerTime;
 5using System.Collections.Generic;
 6
 7namespace DCL.Skybox
 8{
 9    /// <summary>
 10    /// This class will handle runtime execution of skybox cycle.
 11    /// Load and assign material to the Skybox.
 12    /// This will mostly increment the time cycle and apply values from configuration to the material.
 13    /// </summary>
 14    public class SkyboxController : IPlugin
 15    {
 16        public event SkyboxConfiguration.TimelineEvents OnTimelineEvent;
 17
 018        public static SkyboxController i { get; private set; }
 19
 20        public const string DEFAULT_SKYBOX_ID = "Generic_Skybox";
 21
 22        public string loadedConfig;
 023        public float lifecycleDuration = 2;
 24
 25        private float timeOfTheDay;                            // (Nishant.K) Time will be provided from outside, So rem
 26        private Light directionalLight;
 27        private SkyboxConfiguration configuration;
 28        private Material selectedMat;
 29        private bool overrideDefaultSkybox;
 30        private string overrideSkyboxID;
 31        private bool isPaused;
 32        private float timeNormalizationFactor;
 33        private int slotCount;
 34        private bool overrideByEditor = false;
 35        private SkyboxElements skyboxElements;
 36
 37        // Reflection probe//
 38        private ReflectionProbe skyboxProbe;
 39        private bool probeParented = false;
 040        private float reflectionUpdateTime = 1;                                 // In Mins
 41        private ReflectionProbeRuntime runtimeReflectionObj;
 42        private SkyboxCamera skyboxCam;
 43
 44        // Timer sync
 45        private int syncCounter = 0;
 046        private int syncAfterCount = 10;
 47
 48        // Report to kernel
 049        private ITimeReporter timeReporter { get; set; } = new TimeReporter();
 50
 051        public SkyboxController()
 52        {
 053            i = this;
 54
 55            // Find and delete test directional light obj if any
 056            Light[] testDirectionalLight = GameObject.FindObjectsOfType<Light>().Where(s => s.name == "The Sun_Temp").To
 057            for (int i = 0; i < testDirectionalLight.Length; i++)
 58            {
 059                GameObject.DestroyImmediate(testDirectionalLight[i].gameObject);
 60            }
 61
 62            // Get or Create new Directional Light Object
 063            directionalLight = GameObject.FindObjectsOfType<Light>().Where(s => s.type == LightType.Directional).FirstOr
 64
 065            if (directionalLight == null)
 66            {
 067                GameObject temp = new GameObject("The Sun");
 68                // Add the light component
 069                directionalLight = temp.AddComponent<Light>();
 070                directionalLight.type = LightType.Directional;
 71            }
 72
 073            GetOrCreateEnvironmentProbe();
 74
 075            skyboxElements = new SkyboxElements();
 76
 77            // Create skybox Camera
 078            skyboxCam = new SkyboxCamera();
 79
 80            // Get current time from the server
 081            GetTimeFromTheServer(DataStore.i.worldTimer.GetCurrentTime());
 082            DataStore.i.worldTimer.OnTimeChanged += GetTimeFromTheServer;
 83
 84            // Update config whenever skybox config changed in data store. Can be used for both testing and runtime
 085            DataStore.i.skyboxConfig.objectUpdated.OnChange += UpdateConfig;
 86
 87            // Change as Kernel config is initialized or updated
 088            KernelConfig.i.EnsureConfigInitialized()
 89                        .Then(config =>
 90                        {
 091                            KernelConfig_OnChange(config, null);
 092                        });
 93
 094            KernelConfig.i.OnChange += KernelConfig_OnChange;
 95
 096            DCL.Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, Update);
 97
 98            // Register UI related events
 099            DataStore.i.skyboxConfig.mode.OnChange += UseDynamicSkybox_OnChange;
 0100            DataStore.i.skyboxConfig.fixedTime.OnChange += FixedTime_OnChange;
 0101            DataStore.i.skyboxConfig.reflectionResolution.OnChange += ReflectionResolution_OnChange;
 102
 103            // Register for camera references
 0104            DataStore.i.camera.transform.OnChange += AssignCameraReferences;
 0105            AssignCameraReferences(DataStore.i.camera.transform.Get(), null);
 0106        }
 107
 108        private void AssignCameraReferences(Transform currentTransform, Transform prevTransform)
 109        {
 0110            skyboxCam.AssignTargetCamera(currentTransform);
 0111            skyboxElements.AssignCameraInstance(currentTransform);
 0112        }
 113
 114        private void FixedTime_OnChange(float current, float previous)
 115        {
 0116            if (DataStore.i.skyboxConfig.mode.Get() != SkyboxMode.Dynamic)
 117            {
 0118                PauseTime(true, current);
 119            }
 120
 0121            if (runtimeReflectionObj != null)
 122            {
 0123                runtimeReflectionObj.FixedSkyboxTimeChanged();
 124            }
 0125        }
 126
 127        private void UseDynamicSkybox_OnChange(SkyboxMode current, SkyboxMode _)
 128        {
 0129            if (current == SkyboxMode.Dynamic)
 130            {
 131                // Get latest time from server
 0132                UpdateConfig();
 133            }
 134            else
 135            {
 0136                PauseTime(true, DataStore.i.skyboxConfig.fixedTime.Get());
 137            }
 138
 0139            if (runtimeReflectionObj != null)
 140            {
 0141                runtimeReflectionObj.SkyboxModeChanged(current == SkyboxMode.Dynamic);
 142            }
 0143        }
 144
 145        private void GetOrCreateEnvironmentProbe()
 146        {
 147            // Get Reflection Probe Object
 0148            skyboxProbe = GameObject.FindObjectsOfType<ReflectionProbe>().Where(s => s.name == "SkyboxProbe").FirstOrDef
 149
 0150            if (DataStore.i.skyboxConfig.disableReflection.Get())
 151            {
 0152                if (skyboxProbe != null)
 153                {
 0154                    skyboxProbe.gameObject.SetActive(false);
 155                }
 156
 0157                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;
 0158                RenderSettings.customReflection = null;
 0159                return;
 160            }
 161
 0162            if (skyboxProbe == null)
 163            {
 164                // Instantiate new probe from the resources
 0165                GameObject temp = Resources.Load<GameObject>("SkyboxReflectionProbe/SkyboxProbe");
 0166                GameObject probe = GameObject.Instantiate<GameObject>(temp);
 0167                probe.name = "SkyboxProbe";
 0168                skyboxProbe = probe.GetComponent<ReflectionProbe>();
 169
 170                // make probe a child of main camera
 0171                AssignCameraInstancetoProbe();
 172            }
 173
 174            // Update time in Reflection Probe
 0175            runtimeReflectionObj = skyboxProbe.GetComponent<ReflectionProbeRuntime>();
 0176            if (runtimeReflectionObj == null)
 177            {
 0178                runtimeReflectionObj = skyboxProbe.gameObject.AddComponent<ReflectionProbeRuntime>();
 179            }
 180
 181            // Update resolution
 0182            runtimeReflectionObj.UpdateResolution(DataStore.i.skyboxConfig.reflectionResolution.Get());
 183
 184            // Assign as seconds
 0185            runtimeReflectionObj.updateAfter = reflectionUpdateTime * 60;
 186
 0187            RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;
 0188            RenderSettings.customReflection = null;
 0189        }
 190
 0191        private void ReflectionResolution_OnChange(int current, int previous) { runtimeReflectionObj.UpdateResolution(cu
 192
 193        private void AssignCameraInstancetoProbe()
 194        {
 0195            if (skyboxProbe == null)
 196            {
 197#if UNITY_EDITOR
 0198                Debug.LogError("Cannot parent the probe as probe is not instantiated");
 199#endif
 0200                return;
 201            }
 202
 203            // make probe a child of main camera
 0204            if (Camera.main != null)
 205            {
 0206                GameObject mainCam = Camera.main.gameObject;
 0207                runtimeReflectionObj.followTransform = mainCam.transform;
 0208                probeParented = true;
 209            }
 0210        }
 211
 212        private void KernelConfig_OnChange(KernelConfigModel current, KernelConfigModel previous)
 213        {
 0214            if (overrideByEditor)
 215            {
 0216                return;
 217            }
 218            // set skyboxConfig to true
 0219            DataStore.i.skyboxConfig.configToLoad.Set(current.proceduralSkyboxConfig.configToLoad);
 0220            DataStore.i.skyboxConfig.lifecycleDuration.Set(current.proceduralSkyboxConfig.lifecycleDuration);
 0221            DataStore.i.skyboxConfig.jumpToTime.Set(current.proceduralSkyboxConfig.fixedTime);
 0222            DataStore.i.skyboxConfig.updateReflectionTime.Set(current.proceduralSkyboxConfig.updateReflectionTime);
 0223            DataStore.i.skyboxConfig.disableReflection.Set(current.proceduralSkyboxConfig.disableReflection);
 224
 225            // Call update on skybox config which will call Update config in this class.
 0226            DataStore.i.skyboxConfig.objectUpdated.Set(true, true);
 0227        }
 228
 229        /// <summary>
 230        /// Called whenever any change in skyboxConfig is observed
 231        /// </summary>
 232        /// <param name="current"></param>
 233        /// <param name="previous"></param>
 234        public void UpdateConfig(bool current = true, bool previous = false)
 235        {
 0236            if (overrideByEditor)
 237            {
 0238                return;
 239            }
 240
 241            // Reset Object Update value without notifying
 0242            DataStore.i.skyboxConfig.objectUpdated.Set(false, false);
 243
 0244            if (DataStore.i.skyboxConfig.mode.Get() != SkyboxMode.Dynamic)
 245            {
 0246                return;
 247            }
 248
 0249            if (loadedConfig != DataStore.i.skyboxConfig.configToLoad.Get())
 250            {
 251                // Apply configuration
 0252                overrideDefaultSkybox = true;
 0253                overrideSkyboxID = DataStore.i.skyboxConfig.configToLoad.Get();
 254            }
 255
 256            // Apply time
 0257            lifecycleDuration = DataStore.i.skyboxConfig.lifecycleDuration.Get();
 258
 0259            ApplyConfig();
 260
 261            // if Paused
 0262            if (DataStore.i.skyboxConfig.jumpToTime.Get() >= 0)
 263            {
 0264                PauseTime(true, DataStore.i.skyboxConfig.jumpToTime.Get());
 265            }
 266            else
 267            {
 0268                ResumeTime();
 269            }
 270
 271            // Update reflection time
 0272            if (DataStore.i.skyboxConfig.disableReflection.Get())
 273            {
 0274                if (skyboxProbe != null)
 275                {
 0276                    skyboxProbe.gameObject.SetActive(false);
 277                }
 278
 0279                RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Skybox;
 0280                RenderSettings.customReflection = null;
 281            }
 0282            else if (runtimeReflectionObj != null)
 283            {
 284                // If reflection update time is -1 then calculate time based on the cycle time, else assign same
 0285                if (DataStore.i.skyboxConfig.updateReflectionTime.Get() >= 0)
 286                {
 0287                    reflectionUpdateTime = DataStore.i.skyboxConfig.updateReflectionTime.Get();
 288                }
 289                else
 290                {
 291                    // Evaluate with the cycle time
 0292                    reflectionUpdateTime = 1;               // Default for an hour is 1 min
 293                    // get cycle time in hours
 0294                    reflectionUpdateTime = (DataStore.i.skyboxConfig.lifecycleDuration.Get() / 60);
 295                }
 0296                runtimeReflectionObj.updateAfter = Mathf.Clamp(reflectionUpdateTime * 60, 5, 86400);
 297            }
 0298        }
 299
 300        /// <summary>
 301        /// Apply changed configuration
 302        /// </summary>
 303        bool ApplyConfig()
 304        {
 0305            if (overrideByEditor)
 306            {
 0307                return false;
 308            }
 309
 0310            if (!SelectSkyboxConfiguration())
 311            {
 0312                return false;
 313            }
 314
 0315            if (!configuration.useDirectionalLight)
 316            {
 0317                directionalLight.gameObject.SetActive(false);
 318            }
 319
 320            // Calculate time factor
 0321            if (lifecycleDuration <= 0)
 322            {
 0323                lifecycleDuration = 0.01f;
 324            }
 325
 326            // Convert minutes in seconds and then normalize with cycle time
 0327            timeNormalizationFactor = lifecycleDuration * 60 / SkyboxUtils.CYCLE_TIME;
 0328            timeReporter.Configure(timeNormalizationFactor, SkyboxUtils.CYCLE_TIME);
 329
 0330            GetTimeFromTheServer(DataStore.i.worldTimer.GetCurrentTime());
 331
 0332            return true;
 333        }
 334
 335        void GetTimeFromTheServer(DateTime serverTime)
 336        {
 0337            DateTime serverTimeNoTicks = new DateTime(serverTime.Year, serverTime.Month, serverTime.Day, serverTime.Hour
 0338            long elapsedTicks = serverTime.Ticks - serverTimeNoTicks.Ticks;
 339
 0340            float miliseconds = serverTime.Millisecond + (elapsedTicks / 10000);
 341
 342            // Convert miliseconds to seconds
 0343            float seconds = serverTime.Second + (miliseconds / 1000);
 344
 345            // Convert seconds to minutes
 0346            float minutes = serverTime.Minute + (seconds / 60);
 347
 348            // Convert minutes to hour (in float format)
 0349            float totalTimeInMins = serverTime.Hour * 60 + minutes;
 350
 0351            float timeInCycle = (totalTimeInMins / lifecycleDuration) + 1;
 0352            float percentageSkyboxtime = timeInCycle - (int)timeInCycle;
 353
 0354            timeOfTheDay = percentageSkyboxtime * SkyboxUtils.CYCLE_TIME;
 0355        }
 356
 357        /// <summary>
 358        /// Select Configuration to load.
 359        /// </summary>
 360        private bool SelectSkyboxConfiguration()
 361        {
 0362            bool tempConfigLoaded = true;
 363
 0364            string configToLoad = loadedConfig;
 0365            if (string.IsNullOrEmpty(loadedConfig))
 366            {
 0367                configToLoad = DEFAULT_SKYBOX_ID;
 368            }
 369
 370
 0371            if (overrideDefaultSkybox)
 372            {
 0373                configToLoad = overrideSkyboxID;
 0374                overrideDefaultSkybox = false;
 375            }
 376
 377            // config already loaded, return
 0378            if (configToLoad.Equals(loadedConfig))
 379            {
 0380                return tempConfigLoaded;
 381            }
 382
 0383            SkyboxConfiguration newConfiguration = Resources.Load<SkyboxConfiguration>("Skybox Configurations/" + config
 384
 0385            if (newConfiguration == null)
 386            {
 387#if UNITY_EDITOR || DEVELOPMENT_BUILD
 0388                Debug.LogError(configToLoad + " configuration not found in Resources. Trying to load Default config: " +
 389#endif
 390                // Try to load default config
 0391                configToLoad = DEFAULT_SKYBOX_ID;
 0392                newConfiguration = Resources.Load<SkyboxConfiguration>("Skybox Configurations/" + configToLoad);
 393
 0394                if (newConfiguration == null)
 395                {
 396#if UNITY_EDITOR || DEVELOPMENT_BUILD
 0397                    Debug.LogError("Default configuration not found in Resources. Shifting to old skybox. (Default path 
 398#endif
 0399                    tempConfigLoaded = false;
 0400                    return tempConfigLoaded;
 401                }
 402            }
 403
 404            // Register to timelineEvents
 0405            if (configuration != null)
 406            {
 0407                configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 408            }
 0409            newConfiguration.OnTimelineEvent += Configuration_OnTimelineEvent;
 0410            configuration = newConfiguration;
 411
 0412            selectedMat = MaterialReferenceContainer.i.skyboxMat;
 0413            slotCount = MaterialReferenceContainer.i.skyboxMatSlots;
 0414            configuration.ResetMaterial(selectedMat, slotCount);
 415
 0416            RenderSettings.skybox = selectedMat;
 417
 418            // Update loaded config
 0419            loadedConfig = configToLoad;
 420
 0421            return tempConfigLoaded;
 422        }
 423
 0424        private void Configuration_OnTimelineEvent(string tag, bool enable, bool trigger) { OnTimelineEvent?.Invoke(tag,
 425
 426        // Update is called once per frame
 427        public void Update()
 428        {
 0429            if (!DataStore.i.skyboxConfig.disableReflection.Get() && skyboxProbe != null && !probeParented)
 430            {
 0431                AssignCameraInstancetoProbe();
 432            }
 433
 0434            if (configuration == null || isPaused)
 435            {
 0436                return;
 437            }
 438
 439            // Control is in editor tool
 0440            if (overrideByEditor)
 441            {
 0442                return;
 443            }
 444
 0445            timeOfTheDay += Time.deltaTime / timeNormalizationFactor;
 446
 0447            syncCounter++;
 448
 0449            if (syncCounter >= syncAfterCount)
 450            {
 0451                GetTimeFromTheServer(DataStore.i.worldTimer.GetCurrentTime());
 0452                syncCounter = 0;
 453            }
 454
 0455            timeOfTheDay = Mathf.Clamp(timeOfTheDay, 0.01f, SkyboxUtils.CYCLE_TIME);
 0456            DataStore.i.skyboxConfig.currentVirtualTime.Set(timeOfTheDay);
 0457            timeReporter.ReportTime(timeOfTheDay);
 458
 0459            float normalizedDayTime = SkyboxUtils.GetNormalizedDayTime(timeOfTheDay);
 0460            configuration.ApplyOnMaterial(selectedMat, timeOfTheDay, normalizedDayTime, slotCount, directionalLight, Sky
 0461            ApplyAvatarColor(normalizedDayTime);
 0462            skyboxElements.ApplyConfigTo3DElements(configuration, timeOfTheDay, normalizedDayTime, directionalLight, Sky
 463
 464            // Cycle resets
 0465            if (timeOfTheDay >= SkyboxUtils.CYCLE_TIME)
 466            {
 0467                timeOfTheDay = 0.01f;
 0468                configuration.CycleResets();
 469            }
 470
 0471        }
 472
 473        public void Dispose()
 474        {
 475            // set skyboxConfig to false
 0476            DataStore.i.skyboxConfig.objectUpdated.OnChange -= UpdateConfig;
 477
 0478            DataStore.i.worldTimer.OnTimeChanged -= GetTimeFromTheServer;
 0479            if(configuration != null) configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 0480            KernelConfig.i.OnChange -= KernelConfig_OnChange;
 0481            Environment.i.platform.updateEventHandler.RemoveListener(IUpdateEventHandler.EventType.Update, Update);
 0482            DataStore.i.skyboxConfig.mode.OnChange -= UseDynamicSkybox_OnChange;
 0483            DataStore.i.skyboxConfig.fixedTime.OnChange -= FixedTime_OnChange;
 0484            DataStore.i.skyboxConfig.reflectionResolution.OnChange -= ReflectionResolution_OnChange;
 0485            DataStore.i.camera.transform.OnChange -= AssignCameraReferences;
 486
 0487            timeReporter.Dispose();
 0488        }
 489
 490        public void PauseTime(bool overrideTime = false, float newTime = 0)
 491        {
 0492            isPaused = true;
 0493            if (overrideTime)
 494            {
 0495                timeOfTheDay = Mathf.Clamp(newTime, 0, SkyboxUtils.CYCLE_TIME);
 0496                float normalizedDayTime = SkyboxUtils.GetNormalizedDayTime(timeOfTheDay);
 0497                configuration.ApplyOnMaterial(selectedMat, (float)timeOfTheDay, normalizedDayTime, slotCount, directiona
 0498                ApplyAvatarColor(normalizedDayTime);
 0499                skyboxElements.ApplyConfigTo3DElements(configuration, timeOfTheDay, normalizedDayTime, directionalLight,
 500            }
 0501            timeReporter.ReportTime(timeOfTheDay);
 0502        }
 503
 504        public void ResumeTime(bool overrideTime = false, float newTime = 0)
 505        {
 0506            isPaused = false;
 0507            if (overrideTime)
 508            {
 0509                timeOfTheDay = newTime;
 510            }
 0511        }
 512
 0513        public bool IsPaused() { return isPaused; }
 514
 0515        public SkyboxConfiguration GetCurrentConfiguration() { return configuration; }
 516
 0517        public float GetCurrentTimeOfTheDay() { return (float)timeOfTheDay; }
 518
 519        public bool SetOverrideController(bool editorOveride)
 520        {
 0521            overrideByEditor = editorOveride;
 0522            return overrideByEditor;
 523        }
 524
 525        // Whenever Skybox editor closed at runtime control returns back to controller with the values in the editor
 526        public bool GetControlBackFromEditor(string currentConfig, float timeOfTheday, float lifecycleDuration, bool isP
 527        {
 0528            overrideByEditor = false;
 529
 0530            DataStore.i.skyboxConfig.configToLoad.Set(currentConfig);
 0531            DataStore.i.skyboxConfig.lifecycleDuration.Set(lifecycleDuration);
 532
 0533            if (isPaused)
 534            {
 0535                PauseTime(true, timeOfTheday);
 536            }
 537            else
 538            {
 0539                ResumeTime(true, timeOfTheday);
 540            }
 541
 542            // Call update on skybox config which will call Update config in this class.
 0543            DataStore.i.skyboxConfig.objectUpdated.Set(true, true);
 544
 0545            return overrideByEditor;
 546        }
 547
 548        public void UpdateConfigurationTimelineEvent(SkyboxConfiguration newConfig)
 549        {
 0550            configuration.OnTimelineEvent -= Configuration_OnTimelineEvent;
 0551            newConfig.OnTimelineEvent += Configuration_OnTimelineEvent;
 0552        }
 553
 554        public void ApplyAvatarColor(float normalizedDayTime)
 555        {
 0556            if (DataStore.i.skyboxConfig.avatarMatProfile.Get() == AvatarMaterialProfile.InWorld)
 557            {
 0558                configuration.ApplyInWorldAvatarColor(normalizedDayTime, directionalLight.gameObject);
 559            }
 560            else
 561            {
 0562                configuration.ApplyEditorAvatarColor();
 563            }
 0564        }
 565
 0566        public SkyboxElements GetSkyboxElements() { return skyboxElements; }
 567    }
 568}