< Summary

Class:DCL.Components.LoadableShape[LoadWrapperType,LoadWrapperModelType]
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/LoadableShapes/LoadableShape.cs
Covered lines:89
Uncovered lines:22
Coverable lines:111
Total lines:303
Line coverage:80.1% (89 of 111)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
LoadableShape()0%110100%
ApplyChanges(...)0%11.0211095%
AttachShape(...)0%9.237064.29%
ConfigureVisibility(...)0%220100%
ConfigureColliders(...)0%110100%
OnLoadFailed(...)0%330100%
CleanFailedWrapper(...)0%6.65060%
OnLoadCompleted(...)0%3.033084.62%
DetachShape(...)0%440100%
CallWhenReady(...)0%440100%
RaiseOnShapeUpdated(...)0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/LoadableShapes/LoadableShape.cs

#LineLine coverage
 1using System;
 2using DCL.Controllers;
 3using DCL.Helpers;
 4using DCL.Models;
 5using System.Collections;
 6using UnityEngine;
 7using Object = UnityEngine.Object;
 8using System.Collections.Generic;
 9
 10namespace DCL.Components
 11{
 12    public class LoadableShape : BaseShape, IAssetCatalogReferenceHolder
 13    {
 14        [System.Serializable]
 15        public new class Model : BaseShape.Model
 16        {
 17            public string src;
 18            public string assetId;
 19
 20            public override BaseModel GetDataFromJSON(string json) { return Utils.SafeFromJson<Model>(json); }
 21        }
 22
 23        protected Model previousModel = new Model();
 24
 25        protected static Dictionary<GameObject, LoadWrapper> attachedLoaders = new Dictionary<GameObject, LoadWrapper>()
 26
 27        public static LoadWrapper GetLoaderForEntity(IDCLEntity entity)
 28        {
 29            if (entity.meshRootGameObject == null)
 30            {
 31                Debug.LogWarning("NULL meshRootGameObject at GetLoaderForEntity()");
 32                return null;
 33            }
 34
 35            attachedLoaders.TryGetValue(entity.meshRootGameObject, out LoadWrapper result);
 36            return result;
 37        }
 38
 39        public static T GetOrAddLoaderForEntity<T>(IDCLEntity entity)
 40            where T : LoadWrapper, new()
 41        {
 42            if (!attachedLoaders.TryGetValue(entity.meshRootGameObject, out LoadWrapper result))
 43            {
 44                result = new T();
 45                attachedLoaders.Add(entity.meshRootGameObject, result);
 46            }
 47
 48            return result as T;
 49        }
 50
 51        public LoadableShape() { model = new Model(); }
 52
 53        public override int GetClassId() { return -1; }
 54
 55        public override IEnumerator ApplyChanges(BaseModel newModel) { return null; }
 56
 57        public override bool IsVisible()
 58        {
 59            Model model = (Model) this.model;
 60            return model.visible;
 61        }
 62
 63        public override bool HasCollisions()
 64        {
 65            Model model = (Model) this.model;
 66            return model.withCollisions;
 67        }
 68
 69        public string GetAssetId()
 70        {
 71            Model model = (Model) this.model;
 72            return model.assetId;
 73        }
 74    }
 75
 76    public class LoadableShape<LoadWrapperType, LoadWrapperModelType> : LoadableShape
 77        where LoadWrapperType : LoadWrapper, new()
 78        where LoadWrapperModelType : LoadableShape.Model, new()
 79    {
 80        private bool isLoaded = false;
 81        private bool failed = false;
 82        private event Action<BaseDisposable> OnFinishCallbacks;
 83        public System.Action<IDCLEntity> OnEntityShapeUpdated;
 84
 85        new public LoadWrapperModelType model
 86        {
 87            get
 88            {
 58989                if (base.model == null)
 090                    base.model = new LoadWrapperModelType();
 91
 58992                return base.model as LoadWrapperModelType;
 93            }
 094            set { base.model = value; }
 95        }
 96
 97        new protected LoadWrapperModelType previousModel
 98        {
 99            get
 100            {
 383101                if (base.previousModel == null)
 0102                    base.previousModel = new LoadWrapperModelType();
 103
 383104                return base.previousModel as LoadWrapperModelType;
 105            }
 0106            set { base.previousModel = value; }
 107        }
 108
 84109        public LoadableShape()
 110        {
 84111            OnDetach += DetachShape;
 84112            OnAttach += AttachShape;
 84113        }
 114
 115        public override IEnumerator ApplyChanges(BaseModel newModel)
 116        {
 76117            LoadWrapperModelType model = (LoadWrapperModelType) newModel;
 118
 76119            bool updateVisibility = true;
 76120            bool updateCollisions = true;
 76121            bool triggerAttachment = true;
 122
 76123            if (previousModel != null)
 124            {
 67125                updateVisibility = previousModel.visible != model.visible;
 67126                updateCollisions = previousModel.withCollisions != model.withCollisions || previousModel.isPointerBlocke
 67127                triggerAttachment = (!string.IsNullOrEmpty(model.src) && previousModel.src != model.src) ||
 128                                    (!string.IsNullOrEmpty(model.assetId) && previousModel.assetId != model.assetId);
 129            }
 130
 162131            foreach (var entity in attachedEntities)
 132            {
 5133                if (triggerAttachment)
 2134                    AttachShape(entity);
 135
 5136                if (updateVisibility)
 2137                    ConfigureVisibility(entity);
 138
 5139                if (updateCollisions)
 0140                    ConfigureColliders(entity);
 141
 5142                RaiseOnShapeUpdated(entity);
 143            }
 144
 76145            previousModel = model;
 76146            return null;
 147        }
 148
 149        protected virtual void AttachShape(IDCLEntity entity)
 150        {
 78151            ContentProvider provider = null;
 152
 78153            if (!string.IsNullOrEmpty(model.assetId))
 154            {
 17155                provider = AssetCatalogBridge.i.GetContentProviderForAssetIdInSceneObjectCatalog(model.assetId);
 17156                if (string.IsNullOrEmpty(model.src))
 157                {
 0158                    SceneObject sceneObject = AssetCatalogBridge.i.GetSceneObjectById(model.assetId);
 0159                    if (sceneObject == null)
 160                    {
 161#if UNITY_EDITOR
 0162                        Debug.LogWarning($"LoadableShape '{model.assetId}' not found in catalog, probably asset pack del
 163#endif
 0164                        failed = true;
 0165                        OnLoadFailed(null);
 0166                        return;
 167                    }
 0168                    model.src = sceneObject.model;
 169                }
 170            }
 171
 78172            if (provider == null)
 62173                provider = scene.contentProvider;
 174
 78175            if (provider.HasContentsUrl(model.src))
 176            {
 78177                isLoaded = false;
 78178                entity.EnsureMeshGameObject(componentName + " mesh");
 179
 78180                LoadWrapperType loadableShape = GetOrAddLoaderForEntity<LoadWrapperType>(entity);
 181
 78182                if (loadableShape is LoadWrapper_GLTF gltfLoadWrapper)
 77183                    gltfLoadWrapper.customContentProvider = provider;
 184
 78185                entity.meshesInfo.currentShape = this;
 186
 78187                loadableShape.entity = entity;
 78188                loadableShape.useVisualFeedback = Configuration.ParcelSettings.VISUAL_LOADING_ENABLED;
 78189                loadableShape.initialVisibility = model.visible;
 78190                loadableShape.Load(model.src, OnLoadCompleted, OnLoadFailed);
 78191            }
 192            else
 193            {
 194#if UNITY_EDITOR
 0195                Debug.LogWarning($"LoadableShape '{model.src}' not found in scene '{scene.sceneData.id}' mappings");
 196#endif
 0197                failed = true;
 198            }
 0199        }
 200
 201        void ConfigureVisibility(IDCLEntity entity)
 202        {
 2203            var loadable = GetLoaderForEntity(entity);
 204
 2205            if (loadable != null)
 2206                loadable.initialVisibility = model.visible;
 207
 2208            ConfigureVisibility(entity.meshRootGameObject, model.visible, entity.meshesInfo.renderers);
 2209        }
 210
 114211        protected virtual void ConfigureColliders(IDCLEntity entity) { CollidersManager.i.ConfigureColliders(entity.mesh
 212
 213        protected void OnLoadFailed(LoadWrapper loadWrapper)
 214        {
 3215            if (loadWrapper != null)
 3216                CleanFailedWrapper(loadWrapper);
 217
 3218            failed = true;
 3219            OnFinishCallbacks?.Invoke(this);
 3220            OnFinishCallbacks = null;
 3221        }
 222
 223        void CleanFailedWrapper(LoadWrapper loadWrapper)
 224        {
 3225            if (loadWrapper == null)
 0226                return;
 3227            if (loadWrapper.entity == null)
 0228                return;
 3229            if (loadWrapper.entity.gameObject == null)
 0230                return;
 231
 3232            GameObject go = loadWrapper.entity.gameObject;
 233
 3234            go.name += " - Failed loading";
 235
 3236            MaterialTransitionController[] transitionController =
 237                go.GetComponentsInChildren<MaterialTransitionController>(true);
 238
 6239            for (int i = 0; i < transitionController.Length; i++)
 240            {
 0241                MaterialTransitionController material = transitionController[i];
 0242                Object.Destroy(material);
 243            }
 3244        }
 245
 246        protected void OnLoadCompleted(LoadWrapper loadWrapper)
 247        {
 66248            IDCLEntity entity = loadWrapper.entity;
 249
 66250            if (entity.meshesInfo.currentShape == null)
 251            {
 0252                OnLoadFailed(loadWrapper);
 0253                return;
 254            }
 255
 66256            isLoaded = true;
 257
 66258            entity.meshesInfo.renderers = entity.meshRootGameObject.GetComponentsInChildren<Renderer>();
 259
 66260            var model = (Model) (entity.meshesInfo.currentShape as LoadableShape).GetModel();
 66261            ConfigureVisibility(entity.meshRootGameObject, model.visible, loadWrapper.entity.meshesInfo.renderers);
 262
 66263            ConfigureColliders(entity);
 264
 66265            RaiseOnShapeUpdated(entity);
 266
 66267            OnFinishCallbacks?.Invoke(this);
 66268            OnFinishCallbacks = null;
 66269        }
 270
 271        protected virtual void DetachShape(IDCLEntity entity)
 272        {
 81273            if (entity == null || entity.meshRootGameObject == null)
 3274                return;
 275
 78276            LoadWrapper loadWrapper = GetLoaderForEntity(entity);
 277
 78278            loadWrapper?.Unload();
 279
 78280            entity.meshesInfo.CleanReferences();
 78281        }
 282
 283        public override void CallWhenReady(Action<ISharedComponent> callback)
 284        {
 20285            if (attachedEntities.Count == 0 || isLoaded || failed)
 286            {
 2287                callback.Invoke(this);
 2288            }
 289            else
 290            {
 18291                OnFinishCallbacks += callback;
 292            }
 18293        }
 294
 295        private void RaiseOnShapeUpdated(IDCLEntity entity)
 296        {
 71297            if (!isLoaded)
 3298                return;
 299
 68300            entity.OnShapeUpdated?.Invoke(entity);
 68301        }
 302    }
 303}