< Summary

Class:DCL.Components.LoadableShape
Assembly:DCL.Components.LoadableShapes
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/LoadableShapes/LoadableShape.cs
Covered lines:9
Uncovered lines:3
Coverable lines:12
Total lines:292
Line coverage:75% (9 of 12)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
GetDataFromJSON(...)0%110100%
LoadableShape()0%110100%
GetClassId()0%2100%
ApplyChanges(...)0%2100%
IsVisible()0%110100%
HasCollisions()0%110100%
GetAssetId()0%110100%

File(s)

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

#LineLine coverage
 1using System;
 2using DCL.Helpers;
 3using DCL.Models;
 4using System.Collections;
 5using UnityEngine;
 6using Object = UnityEngine.Object;
 7
 8namespace DCL.Components
 9{
 10    public class LoadableShape : BaseShape, IAssetCatalogReferenceHolder
 11    {
 12        [System.Serializable]
 13        public new class Model : BaseShape.Model
 14        {
 15            public string src;
 16            public string assetId;
 17
 8818            public override BaseModel GetDataFromJSON(string json) { return Utils.SafeFromJson<Model>(json); }
 19        }
 20
 021        public bool isLoaded { get; protected set; }
 22
 23        public Action<LoadableShape> OnLoaded;
 24
 10125        protected Model previousModel = new Model();
 26
 30327        protected LoadableShape() { model = new Model(); }
 28
 029        public override int GetClassId() { return -1; }
 30
 031        public override IEnumerator ApplyChanges(BaseModel newModel) { return null; }
 32
 33        public override bool IsVisible()
 34        {
 7635            Model model = (Model) this.model;
 7636            return model.visible;
 37        }
 38
 39        public override bool HasCollisions()
 40        {
 5941            Model model = (Model) this.model;
 5942            return model.withCollisions;
 43        }
 44
 45        public string GetAssetId()
 46        {
 4047            Model model = (Model) this.model;
 4048            return model.assetId;
 49        }
 50    }
 51
 52    public class LoadableShape<LoadWrapperType, LoadWrapperModelType> : LoadableShape
 53        where LoadWrapperType : LoadWrapper, new()
 54        where LoadWrapperModelType : LoadableShape.Model, new()
 55    {
 56        private bool failed = false;
 57        private event Action<BaseDisposable> OnFinishCallbacks;
 58        public System.Action<IDCLEntity> OnEntityShapeUpdated;
 59
 60        new public LoadWrapperModelType model
 61        {
 62            get
 63            {
 64                if (base.model == null)
 65                    base.model = new LoadWrapperModelType();
 66
 67                return base.model as LoadWrapperModelType;
 68            }
 69            set { base.model = value; }
 70        }
 71
 72        new protected LoadWrapperModelType previousModel
 73        {
 74            get
 75            {
 76                if (base.previousModel == null)
 77                    base.previousModel = new LoadWrapperModelType();
 78
 79                return base.previousModel as LoadWrapperModelType;
 80            }
 81            set { base.previousModel = value; }
 82        }
 83
 84        public LoadableShape()
 85        {
 86            OnDetach += DetachShape;
 87            OnAttach += AttachShape;
 88        }
 89
 90        public override IEnumerator ApplyChanges(BaseModel newModel)
 91        {
 92            LoadWrapperModelType model = (LoadWrapperModelType) newModel;
 93
 94            bool updateVisibility = true;
 95            bool updateCollisions = true;
 96            bool triggerAttachment = true;
 97
 98            if (previousModel != null)
 99            {
 100                updateVisibility = previousModel.visible != model.visible;
 101                updateCollisions = previousModel.withCollisions != model.withCollisions || previousModel.isPointerBlocke
 102                triggerAttachment = (!string.IsNullOrEmpty(model.src) && previousModel.src != model.src) ||
 103                                    (!string.IsNullOrEmpty(model.assetId) && previousModel.assetId != model.assetId);
 104            }
 105
 106            foreach (var entity in attachedEntities)
 107            {
 108                if (triggerAttachment)
 109                    AttachShape(entity);
 110
 111                if (updateVisibility)
 112                    ConfigureVisibility(entity);
 113
 114                if (updateCollisions)
 115                    ConfigureColliders(entity);
 116
 117                RaiseOnShapeUpdated(entity);
 118            }
 119
 120            previousModel = model;
 121            return null;
 122        }
 123
 124        protected virtual void AttachShape(IDCLEntity entity)
 125        {
 126            ContentProvider provider = null;
 127
 128            if (!string.IsNullOrEmpty(model.assetId))
 129            {
 130                provider = AssetCatalogBridge.i.GetContentProviderForAssetIdInSceneObjectCatalog(model.assetId);
 131                if (string.IsNullOrEmpty(model.src))
 132                {
 133                    SceneObject sceneObject = AssetCatalogBridge.i.GetSceneObjectById(model.assetId);
 134                    if (sceneObject == null)
 135                    {
 136#if UNITY_EDITOR
 137                        Debug.LogWarning($"LoadableShape '{model.assetId}' not found in catalog, probably asset pack del
 138#endif
 139                        failed = true;
 140                        OnLoadFailed(null, new Exception($"LoadableShape '{model.assetId}' not found in catalog, probabl
 141                        return;
 142                    }
 143
 144                    model.src = sceneObject.model;
 145                }
 146            }
 147
 148            if (provider == null)
 149                provider = scene.contentProvider;
 150
 151            if (provider.HasContentsUrl(model.src))
 152            {
 153                isLoaded = false;
 154                entity.EnsureMeshGameObject(componentName + " mesh");
 155
 156                LoadWrapperType loadableShape =
 157                    Environment.i.world.state.GetOrAddLoaderForEntity<LoadWrapperType>(entity);
 158
 159                if (loadableShape is LoadWrapper_GLTF gltfLoadWrapper)
 160                    gltfLoadWrapper.customContentProvider = provider;
 161
 162                entity.meshesInfo.currentShape = this;
 163
 164                loadableShape.entity = entity;
 165                loadableShape.useVisualFeedback = Configuration.ParcelSettings.VISUAL_LOADING_ENABLED;
 166                loadableShape.initialVisibility = model.visible && entity.isInsideSceneBoundaries;
 167                loadableShape.Load(model.src, OnLoadCompleted, OnLoadFailed);
 168            }
 169            else
 170            {
 171#if UNITY_EDITOR
 172                Debug.LogWarning($"LoadableShape '{model.src}' not found in scene '{scene.sceneData.id}' mappings");
 173#endif
 174                failed = true;
 175            }
 176        }
 177
 178        void ConfigureVisibility(IDCLEntity entity)
 179        {
 180            var loadable = Environment.i.world.state.GetLoaderForEntity(entity);
 181
 182            if (loadable != null)
 183                loadable.initialVisibility = model.visible && entity.isInsideSceneBoundaries;
 184
 185            ConfigureVisibility(entity.meshRootGameObject, model.visible && entity.isInsideSceneBoundaries, entity.meshe
 186
 187            if(!scene.componentsManagerLegacy.HasComponent(entity, CLASS_ID_COMPONENT.ANIMATOR) && entity.meshesInfo.ani
 188                entity.meshesInfo.animation.enabled = model.visible && entity.isInsideSceneBoundaries;
 189        }
 190
 191        protected virtual void ConfigureColliders(IDCLEntity entity)
 192        {
 193            CollidersManager.i.ConfigureColliders(entity.meshRootGameObject, model.withCollisions && entity.isInsideScen
 194        }
 195
 196        protected void OnLoadFailed(LoadWrapper loadWrapper, Exception exception)
 197        {
 198            if (loadWrapper != null)
 199                CleanFailedWrapper(loadWrapper);
 200
 201            failed = true;
 202            OnFinishCallbacks?.Invoke(this);
 203            OnFinishCallbacks = null;
 204        }
 205
 206        void CleanFailedWrapper(LoadWrapper loadWrapper)
 207        {
 208            if (loadWrapper == null)
 209                return;
 210            if (loadWrapper.entity == null)
 211                return;
 212            if (loadWrapper.entity.gameObject == null)
 213                return;
 214
 215            GameObject go = loadWrapper.entity.gameObject;
 216
 217            go.name += " - Failed loading";
 218
 219            MaterialTransitionController[] transitionController =
 220                go.GetComponentsInChildren<MaterialTransitionController>(true);
 221
 222            for (int i = 0; i < transitionController.Length; i++)
 223            {
 224                MaterialTransitionController material = transitionController[i];
 225                Object.Destroy(material);
 226            }
 227        }
 228
 229        protected void OnLoadCompleted(LoadWrapper loadWrapper)
 230        {
 231            IDCLEntity entity = loadWrapper.entity;
 232
 233            if (entity.meshesInfo.currentShape == null)
 234            {
 235                OnLoadFailed(loadWrapper, new Exception($"Entity {entity.entityId} current shape of mesh information is 
 236                return;
 237            }
 238
 239            isLoaded = true;
 240            OnLoaded?.Invoke(this);
 241
 242            entity.meshesInfo.meshRootGameObject = entity.meshRootGameObject;
 243
 244            ConfigureVisibility(entity);
 245            ConfigureColliders(entity);
 246            RaiseOnShapeUpdated(entity);
 247            RaiseOnShapeLoaded(entity);
 248
 249            OnFinishCallbacks?.Invoke(this);
 250            OnFinishCallbacks = null;
 251        }
 252
 253        protected virtual void DetachShape(IDCLEntity entity)
 254        {
 255            if (entity == null || entity.meshRootGameObject == null)
 256                return;
 257
 258            LoadWrapper loadWrapper = Environment.i.world.state.GetLoaderForEntity(entity);
 259            loadWrapper?.Unload();
 260            Environment.i.world.state.RemoveLoaderForEntity(entity);
 261            entity.meshesInfo.CleanReferences();
 262        }
 263
 264        public override void CallWhenReady(Action<ISharedComponent> callback)
 265        {
 266            if (attachedEntities.Count == 0 || isLoaded || failed)
 267            {
 268                callback.Invoke(this);
 269            }
 270            else
 271            {
 272                OnFinishCallbacks += callback;
 273            }
 274        }
 275
 276        private void RaiseOnShapeUpdated(IDCLEntity entity)
 277        {
 278            if (!isLoaded)
 279                return;
 280
 281            entity.OnShapeUpdated?.Invoke(entity);
 282        }
 283
 284        private void RaiseOnShapeLoaded(IDCLEntity entity)
 285        {
 286            if (!isLoaded)
 287                return;
 288
 289            entity.OnShapeLoaded?.Invoke(entity);
 290        }
 291    }
 292}