< Summary

Class:DCL.ECSComponents.ECSAudioSourceComponentHandler
Assembly:DCL.ECSComponents.AudioSource
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AudioSource/Handler/ECSAudioSourceComponentHandler.cs
Covered lines:87
Uncovered lines:20
Coverable lines:107
Total lines:235
Line coverage:81.3% (87 of 107)
Covered branches:0
Total branches:0
Covered methods:11
Total methods:15
Method coverage:73.3% (11 of 15)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ECSAudioSourceComponentHandler(...)0%110100%
OnComponentCreated(...)0%220100%
OnComponentRemoved(...)0%110100%
OnComponentModelUpdated(...)0%9.498071.43%
DisposePromise()0%2.022083.33%
Dispose(...)0%4.014091.67%
ApplyCurrentModel()0%6.076087.5%
ApplyLoadedAudioClip(...)0%220100%
OnAudioClipLoadComplete(...)0%2.022083.33%
OnAudioClipLoadFail(...)0%2100%
OnAudioSettingsChanged(...)0%2100%
OnVirtualAudioMixerChangedValue(...)0%2100%
UpdateAudioSourceVolume()0%770100%
OnCurrentSceneChanged(...)0%220100%
OnSceneBoundsStateChange(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/ECSComponents/AudioSource/Handler/ECSAudioSourceComponentHandler.cs

#LineLine coverage
 1using System;
 2using DCL.Controllers;
 3using DCL.ECS7.InternalComponents;
 4using DCL.ECSRuntime;
 5using DCL.Helpers;
 6using DCL.Models;
 7using DCL.SettingsCommon;
 8using UnityEngine;
 9using AudioSettings = DCL.SettingsCommon.AudioSettings;
 10
 11namespace DCL.ECSComponents
 12{
 13    public class ECSAudioSourceComponentHandler : IECSComponentHandler<PBAudioSource>
 14    {
 15        internal AudioSource audioSource;
 16        internal AssetPromise_AudioClip promiseAudioClip;
 17
 18        private bool isAudioClipReady = false;
 1119        private bool isPlayerInsideScene = true;
 1120        private bool isEntityInsideScene = true;
 21
 22        private PBAudioSource model;
 23        private IParcelScene scene;
 24        private AudioClip audioClip;
 25
 26        private readonly DataStore dataStore;
 27        private readonly Settings settings;
 28        private readonly AssetPromiseKeeper_AudioClip keeperAudioClip;
 29        private readonly IntVariable sceneNumber;
 30        private readonly IInternalECSComponent<InternalAudioSource> audioSourceInternalComponent;
 31        private readonly IInternalECSComponent<InternalSceneBoundsCheck> sbcInternalComponent;
 32
 1133        public ECSAudioSourceComponentHandler(
 34            DataStore dataStoreInstance,
 35            Settings settingsInstance,
 36            AssetPromiseKeeper_AudioClip keeperInstance,
 37            IntVariable sceneNumber,
 38            IInternalECSComponent<InternalAudioSource> audioSourceInternalComponent,
 39            IInternalECSComponent<InternalSceneBoundsCheck> sbcInternalComponent)
 40        {
 1141            dataStore = dataStoreInstance;
 1142            settings = settingsInstance;
 1143            keeperAudioClip = keeperInstance;
 1144            this.sceneNumber = sceneNumber;
 1145            this.audioSourceInternalComponent = audioSourceInternalComponent;
 1146            this.sbcInternalComponent = sbcInternalComponent;
 1147        }
 48
 49        public void OnComponentCreated(IParcelScene scene, IDCLEntity entity)
 50        {
 1151            this.scene = scene;
 1152            audioSource = entity.gameObject.AddComponent<AudioSource>();
 1153            audioSource.spatialBlend = 1;
 1154            audioSource.dopplerLevel = 0.1f;
 1155            audioSource.playOnAwake = false;
 56
 1157            if (settings != null)
 1158                settings.audioSettings.OnChanged += OnAudioSettingsChanged;
 59
 1160            dataStore.virtualAudioMixer.sceneSFXVolume.OnChange += OnVirtualAudioMixerChangedValue;
 1161            sceneNumber.OnChange += OnCurrentSceneChanged;
 62
 1163            audioSourceInternalComponent.PutFor(scene, entity, new InternalAudioSource()
 64            {
 65                audioSource = this.audioSource
 66            });
 67
 1168            sbcInternalComponent.RegisterOnSceneBoundsStateChangeCallback(scene, entity, OnSceneBoundsStateChange);
 69
 1170            isPlayerInsideScene = scene.sceneData.sceneNumber == sceneNumber.Get();
 1171        }
 72
 73        public void OnComponentRemoved(IParcelScene scene, IDCLEntity entity)
 74        {
 1275            audioSourceInternalComponent.RemoveFor(scene, entity, new InternalAudioSource() { audioSource = null });
 1276            Dispose(entity);
 1277        }
 78
 79        public void OnComponentModelUpdated(IParcelScene scene, IDCLEntity entity, PBAudioSource model)
 80        {
 1481            bool isSameClip = model.AudioClipUrl == this.model?.AudioClipUrl;
 1482            this.model = model;
 83
 84            // If the clip has changed, we need to forget the old clip
 1485            if (!isSameClip && promiseAudioClip != null)
 86            {
 087                isAudioClipReady = false;
 088                if (audioClip != null)
 089                    dataStore.sceneWorldObjects.RemoveAudioClip(scene.sceneData.sceneNumber, audioClip);
 090                DisposePromise();
 91            }
 92
 1493            ApplyCurrentModel();
 94
 1495            if (!isAudioClipReady && !isSameClip)
 96            {
 1197                promiseAudioClip = new AssetPromise_AudioClip(model.AudioClipUrl, scene.contentProvider);
 1198                promiseAudioClip.OnSuccessEvent += OnAudioClipLoadComplete;
 1199                promiseAudioClip.OnFailEvent += OnAudioClipLoadFail;
 100
 11101                keeperAudioClip.Keep(promiseAudioClip);
 102            }
 14103        }
 104
 105        private void DisposePromise()
 106        {
 12107            if (promiseAudioClip == null)
 0108                return;
 109
 12110            promiseAudioClip.OnSuccessEvent += OnAudioClipLoadComplete;
 12111            promiseAudioClip.OnFailEvent += OnAudioClipLoadFail;
 112
 12113            keeperAudioClip.Forget(promiseAudioClip);
 12114        }
 115
 116        private void Dispose(IDCLEntity entity)
 117        {
 12118            DisposePromise();
 119
 12120            if (audioClip != null)
 0121                dataStore.sceneWorldObjects.RemoveAudioClip(scene.sceneData.sceneNumber, audioClip);
 122
 12123            sceneNumber.OnChange -= OnCurrentSceneChanged;
 124
 12125            if (settings != null)
 12126                settings.audioSettings.OnChanged -= OnAudioSettingsChanged;
 127
 12128            dataStore.virtualAudioMixer.sceneSFXVolume.OnChange -= OnVirtualAudioMixerChangedValue;
 12129            if (audioSource != null)
 130            {
 11131                GameObject.Destroy(audioSource);
 11132                audioSource = null;
 133            }
 134
 12135            sbcInternalComponent.RemoveOnSceneBoundsStateChangeCallback(scene, entity, OnSceneBoundsStateChange);
 12136        }
 137
 138        private void ApplyCurrentModel()
 139        {
 17140            if (audioSource == null)
 141            {
 0142                Debug.LogWarning("AudioSource or model is null!.");
 0143                return;
 144            }
 145
 17146            UpdateAudioSourceVolume();
 17147            audioSource.loop = model.Loop;
 17148            audioSource.pitch = model.GetPitch();
 17149            audioSource.spatialBlend = 1;
 17150            audioSource.dopplerLevel = 0.1f;
 151
 17152            if (model.Playing != audioSource.isPlaying)
 153            {
 10154                if (audioSource.isPlaying)
 4155                    audioSource.Stop();
 6156                else if (isAudioClipReady)
 3157                    audioSource.Play();
 158            }
 7159            else if (audioSource.isPlaying)
 160            {
 3161                audioSource.Stop();
 162            }
 10163        }
 164
 165        private void ApplyLoadedAudioClip(AudioClip clip)
 166        {
 3167            isAudioClipReady = true;
 3168            if (audioSource.clip != clip)
 3169                audioSource.clip = clip;
 170
 3171            ApplyCurrentModel();
 3172        }
 173
 174        private void OnAudioClipLoadComplete(Asset_AudioClip assetAudioClip)
 175        {
 3176            if (assetAudioClip.audioClip == null)
 0177                return;
 178
 3179            audioClip = assetAudioClip.audioClip;
 180
 3181            dataStore.sceneWorldObjects.AddAudioClip(scene.sceneData.sceneNumber, audioClip);
 182
 3183            ApplyLoadedAudioClip(assetAudioClip.audioClip);
 3184        }
 185
 186        private void OnAudioClipLoadFail(Asset_AudioClip assetAudioClip, Exception exception)
 187        {
 0188            Debug.LogError("Audio clip couldn't be loaded. Url: " +model.AudioClipUrl + "     error: " + exception.Messa
 0189            DisposePromise();
 0190        }
 191
 192        private void OnAudioSettingsChanged(AudioSettings settings)
 193        {
 0194            UpdateAudioSourceVolume();
 0195        }
 196
 197        private void OnVirtualAudioMixerChangedValue(float currentValue, float previousValue)
 198        {
 0199            UpdateAudioSourceVolume();
 0200        }
 201
 202        private void UpdateAudioSourceVolume()
 203        {
 30204            if (model == null) return;
 205
 22206            if (!scene.isPersistent && (!isPlayerInsideScene || !isEntityInsideScene))
 207            {
 4208                audioSource.volume = 0;
 4209                return;
 210            }
 211
 18212            AudioSettings audioSettingsData =
 213                settings != null ? settings.audioSettings.Data : new AudioSettings();
 18214            float newVolume = model.GetVolume() * Utils.ToVolumeCurve(
 215                dataStore.virtualAudioMixer.sceneSFXVolume.Get() * audioSettingsData.sceneSFXVolume *
 216                audioSettingsData.masterVolume);
 217
 18218            audioSource.volume = newVolume;
 18219        }
 220
 221        private void OnCurrentSceneChanged(int currentSceneNumber, int previousSceneNumber)
 222        {
 9223            isPlayerInsideScene = scene.isPersistent || scene.sceneData.sceneNumber == currentSceneNumber;
 9224            UpdateAudioSourceVolume();
 9225        }
 226
 227        public void OnSceneBoundsStateChange(bool isInsideSceneBounds)
 228        {
 0229            if (isEntityInsideScene == isInsideSceneBounds) return;
 230
 0231            isEntityInsideScene = isInsideSceneBounds;
 0232            UpdateAudioSourceVolume();
 0233        }
 234    }
 235}