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