< 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:8
Uncovered lines:4
Coverable lines:12
Total lines:301
Line coverage:66.6% (8 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%2100%

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
 7518            public override BaseModel GetDataFromJSON(string json) { return Utils.SafeFromJson<Model>(json); }
 19        }
 20
 30621        public bool isLoaded { get; protected set; }
 22
 23        public Action<LoadableShape> OnLoaded;
 24
 7525        protected Model previousModel = new Model();
 26
 22527        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        {
 4335            Model model = (Model) this.model;
 4336            return model.visible;
 37        }
 38
 39        public override bool HasCollisions()
 40        {
 6341            Model model = (Model) this.model;
 6342            return model.withCollisions;
 43        }
 44
 45        public string GetAssetId()
 46        {
 047            Model model = (Model) this.model;
 048            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
 167                bool initialVisibility = model.visible;
 168                if (!DataStore.i.debugConfig.isDebugMode.Get())
 169                    initialVisibility &= entity.isInsideSceneBoundaries;
 170                loadableShape.initialVisibility = initialVisibility;
 171
 172                loadableShape.Load(model.src, OnLoadCompleted, OnLoadFailed);
 173            }
 174            else
 175            {
 176#if UNITY_EDITOR
 177                Debug.LogWarning($"LoadableShape '{model.src}' not found in scene '{scene.sceneData.sceneNumber}' mappin
 178#endif
 179                failed = true;
 180            }
 181        }
 182
 183        void ConfigureVisibility(IDCLEntity entity)
 184        {
 185            var loadable = Environment.i.world.state.GetLoaderForEntity(entity);
 186
 187            bool initialVisibility = model.visible;
 188            if (!DataStore.i.debugConfig.isDebugMode.Get())
 189                initialVisibility &= entity.isInsideSceneBoundaries;
 190
 191            if (loadable != null)
 192                loadable.initialVisibility = initialVisibility;
 193
 194            ConfigureVisibility(entity.meshRootGameObject, initialVisibility, entity.meshesInfo.renderers);
 195
 196            if(!scene.componentsManagerLegacy.HasComponent(entity, CLASS_ID_COMPONENT.ANIMATOR) && entity.meshesInfo.ani
 197                entity.meshesInfo.animation.enabled = initialVisibility;
 198        }
 199
 200        protected virtual void ConfigureColliders(IDCLEntity entity)
 201        {
 202            CollidersManager.i.ConfigureColliders(entity.meshRootGameObject, model.withCollisions && entity.isInsideScen
 203        }
 204
 205        protected void OnLoadFailed(LoadWrapper loadWrapper, Exception exception)
 206        {
 207            if (loadWrapper != null)
 208                CleanFailedWrapper(loadWrapper);
 209
 210            failed = true;
 211            OnFinishCallbacks?.Invoke(this);
 212            OnFinishCallbacks = null;
 213        }
 214
 215        void CleanFailedWrapper(LoadWrapper loadWrapper)
 216        {
 217            if (loadWrapper == null)
 218                return;
 219            if (loadWrapper.entity == null)
 220                return;
 221            if (loadWrapper.entity.gameObject == null)
 222                return;
 223
 224            GameObject go = loadWrapper.entity.gameObject;
 225
 226            go.name += " - Failed loading";
 227
 228            MaterialTransitionController[] transitionController =
 229                go.GetComponentsInChildren<MaterialTransitionController>(true);
 230
 231            for (int i = 0; i < transitionController.Length; i++)
 232            {
 233                MaterialTransitionController material = transitionController[i];
 234                Object.Destroy(material);
 235            }
 236        }
 237
 238        protected void OnLoadCompleted(LoadWrapper loadWrapper)
 239        {
 240            IDCLEntity entity = loadWrapper.entity;
 241
 242            if (entity.meshesInfo.currentShape == null)
 243            {
 244                OnLoadFailed(loadWrapper, new Exception($"Entity {entity.entityId} current shape of mesh information is 
 245                return;
 246            }
 247
 248            isLoaded = true;
 249            OnLoaded?.Invoke(this);
 250
 251            entity.meshesInfo.meshRootGameObject = entity.meshRootGameObject;
 252
 253            ConfigureVisibility(entity);
 254            ConfigureColliders(entity);
 255            RaiseOnShapeUpdated(entity);
 256            RaiseOnShapeLoaded(entity);
 257
 258            OnFinishCallbacks?.Invoke(this);
 259            OnFinishCallbacks = null;
 260        }
 261
 262        protected virtual void DetachShape(IDCLEntity entity)
 263        {
 264            if (entity == null || entity.meshRootGameObject == null)
 265                return;
 266
 267            LoadWrapper loadWrapper = Environment.i.world.state.GetLoaderForEntity(entity);
 268            loadWrapper?.Unload();
 269            Environment.i.world.state.RemoveLoaderForEntity(entity);
 270            entity.meshesInfo.CleanReferences();
 271        }
 272
 273        public override void CallWhenReady(Action<ISharedComponent> callback)
 274        {
 275            if (attachedEntities.Count == 0 || isLoaded || failed)
 276            {
 277                callback.Invoke(this);
 278            }
 279            else
 280            {
 281                OnFinishCallbacks += callback;
 282            }
 283        }
 284
 285        private void RaiseOnShapeUpdated(IDCLEntity entity)
 286        {
 287            if (!isLoaded)
 288                return;
 289
 290            entity.OnShapeUpdated?.Invoke(entity);
 291        }
 292
 293        private void RaiseOnShapeLoaded(IDCLEntity entity)
 294        {
 295            if (!isLoaded)
 296                return;
 297
 298            entity.OnShapeLoaded?.Invoke(entity);
 299        }
 300    }
 301}