< Summary

Class:DCL.Components.DCLAudioSource
Assembly:DCL.Components.Audio
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs
Covered lines:86
Uncovered lines:26
Coverable lines:112
Total lines:260
Line coverage:76.7% (86 of 112)
Covered branches:0
Total branches:0
Covered methods:17
Total methods:21
Method coverage:80.9% (17 of 21)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Model()0%110100%
GetDataFromJSON(...)0%110100%
GetDataFromPb(...)0%72800%
Awake()0%220100%
Initialize(...)0%110100%
InitDCLAudioClip(...)0%220100%
ApplyChanges()0%6.076087.5%
ApplyCurrentModel()0%6.496076.19%
OnAudioSettingsChanged(...)0%2100%
OnVirtualAudioMixerChangedValue(...)0%2100%
UpdateAudioSourceVolume()0%880100%
OnCurrentSceneChanged(...)0%4.034087.5%
OnDestroy()0%330100%
Cleanup()0%110100%
UpdateOutOfBoundariesState(...)0%2.032080%
DclAudioClip_OnLoadingFinished(...)0%12300%
ApplyLoadedAudioClip(...)0%880100%
GetClassId()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs

#LineLine coverage
 1using DCL.Helpers;
 2using System.Collections;
 3using DCL.Controllers;
 4using UnityEngine;
 5using DCL.Models;
 6using DCL.SettingsCommon;
 7using AudioSettings = DCL.SettingsCommon.AudioSettings;
 8using Decentraland.Sdk.Ecs6;
 9
 10namespace DCL.Components
 11{
 12    public class DCLAudioSource : BaseComponent, IOutOfSceneBoundariesHandler
 13    {
 14        [System.Serializable]
 15        public class Model : BaseModel
 16        {
 17            public string audioClipId;
 18            public bool playing;
 5019            public float volume = 1f;
 20            public bool loop;
 5021            public float pitch = 1f;
 22            public long playedAtTimestamp;
 23
 24            public override BaseModel GetDataFromJSON(string json) =>
 1825                Utils.SafeFromJson<Model>(json);
 26
 27            public override BaseModel GetDataFromPb(ComponentBodyPayload pbModel)
 28            {
 029                if (pbModel.PayloadCase != ComponentBodyPayload.PayloadOneofCase.AudioSource)
 030                    return Utils.SafeUnimplemented<DCLAudioSource, Model>(expected: ComponentBodyPayload.PayloadOneofCas
 31
 032                var pb = new Model();
 033                if (pbModel.AudioSource.HasLoop) pb.loop = pbModel.AudioSource.Loop;
 034                if (pbModel.AudioSource.HasPitch) pb.pitch = pbModel.AudioSource.Pitch;
 035                if (pbModel.AudioSource.HasPlaying) pb.playing = pbModel.AudioSource.Playing;
 036                if (pbModel.AudioSource.HasVolume) pb.volume = pbModel.AudioSource.Volume;
 037                if (pbModel.AudioSource.HasAudioClipId) pb.audioClipId = pbModel.AudioSource.AudioClipId;
 038                if (pbModel.AudioSource.HasPlayedAtTimestamp) pb.playedAtTimestamp = pbModel.AudioSource.PlayedAtTimesta
 39
 040                return pb;
 41            }
 42        }
 43
 144        public float playTime => audioSource.time;
 45        internal AudioSource audioSource;
 46        DCLAudioClip lastDCLAudioClip;
 47
 48        private bool isDestroyed = false;
 49        public long playedAtTimestamp = 0;
 50        private bool isOutOfBoundaries = false;
 51
 552        public override string componentName => "AudioSource";
 53
 54        private void Awake()
 55        {
 1556            audioSource = gameObject.GetOrCreateComponent<AudioSource>();
 1557            model = new Model();
 58
 1559            if (Settings.i != null)
 1560                Settings.i.audioSettings.OnChanged += OnAudioSettingsChanged;
 61
 1562            DataStore.i.virtualAudioMixer.sceneSFXVolume.OnChange += OnVirtualAudioMixerChangedValue;
 1563        }
 64
 65        public override void Initialize(IParcelScene scene, IDCLEntity entity)
 66        {
 1567            base.Initialize(scene, entity);
 1568            isOutOfBoundaries = !entity.isInsideSceneBoundaries;
 1569            DataStore.i.sceneBoundariesChecker.Add(entity,this);
 1570        }
 71
 72        public void InitDCLAudioClip(DCLAudioClip dclAudioClip)
 73        {
 2874            if (lastDCLAudioClip != null)
 75            {
 1376                lastDCLAudioClip.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 77            }
 78
 2879            lastDCLAudioClip = dclAudioClip;
 2880        }
 81
 282        public double volume => ((Model) model).volume;
 83
 84        public override IEnumerator ApplyChanges(BaseModel baseModel)
 85        {
 3686            yield return new WaitUntil(() => CommonScriptableObjects.rendererState.Get());
 87
 88            //If the scene creates and destroy an audiosource before our renderer has been turned on bad things happen!
 89            //TODO: Analyze if we can catch this upstream and stop the IEnumerator
 1890            if (isDestroyed)
 091                yield break;
 92
 1893            CommonScriptableObjects.sceneNumber.OnChange -= OnCurrentSceneChanged;
 1894            CommonScriptableObjects.sceneNumber.OnChange += OnCurrentSceneChanged;
 95
 1896            ApplyCurrentModel();
 97
 1898            yield return null;
 1799        }
 100
 101        private void ApplyCurrentModel()
 102        {
 18103            if (audioSource == null)
 104            {
 0105                Debug.LogWarning("AudioSource is null!.");
 0106                return;
 107            }
 108
 18109            Model model = (Model) this.model;
 18110            UpdateAudioSourceVolume();
 18111            audioSource.loop = model.loop;
 18112            audioSource.pitch = model.pitch;
 18113            audioSource.spatialBlend = 1;
 18114            audioSource.dopplerLevel = 0.1f;
 115
 18116            if (model.playing)
 117            {
 13118                DCLAudioClip dclAudioClip = scene.componentsManagerLegacy.GetSceneSharedComponent(model.audioClipId) as 
 119
 13120                if (dclAudioClip != null)
 121                {
 13122                    InitDCLAudioClip(dclAudioClip);
 123                    //NOTE(Brian): Play if finished loading, otherwise will wait for the loading to complete (or fail).
 13124                    if (dclAudioClip.loadingState == DCLAudioClip.LoadState.LOADING_COMPLETED)
 125                    {
 13126                        ApplyLoadedAudioClip(dclAudioClip);
 127                    }
 128                    else
 129                    {
 0130                        dclAudioClip.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 0131                        dclAudioClip.OnLoadingFinished += DclAudioClip_OnLoadingFinished;
 132                    }
 133                }
 134                else
 135                {
 0136                    Debug.LogError("Wrong audio clip type when playing audiosource!!");
 137                }
 138            }
 139            else
 140            {
 5141                if (audioSource.isPlaying)
 142                {
 2143                    audioSource.Stop();
 144                }
 145            }
 5146        }
 147
 148        private void OnAudioSettingsChanged(AudioSettings settings)
 149        {
 0150            UpdateAudioSourceVolume();
 0151        }
 152
 153        private void OnVirtualAudioMixerChangedValue(float currentValue, float previousValue)
 154        {
 0155            UpdateAudioSourceVolume();
 0156        }
 157
 158        private void UpdateAudioSourceVolume()
 159        {
 19160            float newVolume = 0;
 161
 162            // isOutOfBoundaries will always be false for global scenes.
 19163            if (!isOutOfBoundaries)
 164            {
 15165                AudioSettings audioSettingsData = Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings
 15166                float baseVolume = ((Model) model).volume;
 15167                newVolume = baseVolume * Utils.ToVolumeCurve(DataStore.i.virtualAudioMixer.sceneSFXVolume.Get() * audioS
 168            }
 169
 19170            if (scene != null)
 171            {
 19172                bool isCurrentScene = scene.isPersistent || scene.sceneData.sceneNumber == CommonScriptableObjects.scene
 19173                audioSource.volume = isCurrentScene ? newVolume : 0f;
 174            }
 19175        }
 176
 177        private void OnCurrentSceneChanged(int currentSceneNumber, int previousSceneNumber)
 178        {
 3179            if (audioSource == null)
 0180                return;
 181
 3182            Model model = (Model) this.model;
 3183            float volume = 0;
 184
 3185            if (scene.isPersistent || scene.sceneData.sceneNumber == currentSceneNumber)
 186            {
 2187                volume = model.volume;
 188            }
 189
 3190            audioSource.volume = volume;
 3191        }
 192
 193        private void OnDestroy()
 194        {
 15195            isDestroyed = true;
 15196            CommonScriptableObjects.sceneNumber.OnChange -= OnCurrentSceneChanged;
 197
 198            //NOTE(Brian): Unsubscribe events.
 15199            InitDCLAudioClip(null);
 200
 15201            if (Settings.i != null)
 15202                Settings.i.audioSettings.OnChanged -= OnAudioSettingsChanged;
 203
 15204            DataStore.i.virtualAudioMixer.sceneSFXVolume.OnChange -= OnVirtualAudioMixerChangedValue;
 205
 15206            if (entity != null)
 15207                DataStore.i.sceneBoundariesChecker.Remove(entity, this);
 208
 15209            lastDCLAudioClip = null;
 15210            audioSource = null;
 15211        }
 212
 213        public override void Cleanup()
 214        {
 15215            base.Cleanup();
 15216            audioSource = null;
 15217        }
 218
 219        public void UpdateOutOfBoundariesState(bool isInsideBoundaries)
 220        {
 1221            if (scene.isPersistent)
 0222                isInsideBoundaries = true;
 223
 1224            isOutOfBoundaries = !isInsideBoundaries;
 1225            UpdateAudioSourceVolume();
 1226        }
 227
 228        private void DclAudioClip_OnLoadingFinished(DCLAudioClip obj)
 229        {
 0230            if (obj.loadingState == DCLAudioClip.LoadState.LOADING_COMPLETED && audioSource != null)
 231            {
 0232                ApplyLoadedAudioClip(obj);
 233            }
 234
 0235            obj.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 0236        }
 237
 238        private void ApplyLoadedAudioClip(DCLAudioClip clip)
 239        {
 13240            if (audioSource.clip != clip.audioClip)
 241            {
 13242                audioSource.clip = clip.audioClip;
 243            }
 244
 13245            Model model = (Model) this.model;
 13246            bool shouldPlay = playedAtTimestamp != model.playedAtTimestamp ||
 247                              (model.playing && !audioSource.isPlaying);
 248
 13249            if (audioSource.enabled && model.playing && shouldPlay)
 250            {
 251                //To remove a pesky and quite unlikely warning when the audiosource is out of scenebounds
 13252                audioSource.Play();
 253            }
 254
 13255            playedAtTimestamp = model.playedAtTimestamp;
 13256        }
 257
 1258        public override int GetClassId() { return (int) CLASS_ID_COMPONENT.AUDIO_SOURCE; }
 259    }
 260}