< Summary

Class:DCL.Components.ParametrizedShape[T]
Assembly:DCL.Components.ParametrizedShape
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/ParametrizedShapes/ParametrizedShape.cs
Covered lines:109
Uncovered lines:8
Coverable lines:117
Total lines:250
Line coverage:93.1% (109 of 117)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParametrizedShape()0%110100%
GenerateGeometry()0%2100%
DestroyGeometry()0%2.032080%
UpdateFromModel(...)0%110100%
UpdateRenderer(...)0%660100%
OnShapeAttached(...)0%44096.3%
OnShapeFinishedLoading(...)0%220100%
OnShapeDetached(...)0%4.024090%
ApplyChanges(...)0%990100%
AttachTo(...)0%2.062075%
IsVisible()0%110100%
HasCollisions()0%110100%
ShouldGenerateNewMesh(...)0%2100%
RemoveRendereableFromDataStore(...)0%220100%
AddRendereableToDataStore(...)0%2.012088.89%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/ParametrizedShapes/ParametrizedShape.cs

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Helpers;
 3using DCL.Models;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Linq;
 7using UnityEditor;
 8using UnityEngine;
 9
 10namespace DCL.Components
 11{
 12    public abstract class ParametrizedShape<T> : BaseShape
 13        where T : BaseShape.Model, new()
 14    {
 17815        public Dictionary<IDCLEntity, Rendereable> attachedRendereables = new Dictionary<IDCLEntity, Rendereable>();
 16        bool visibilityDirty = false;
 17        bool collisionsDirty = false;
 18
 19        public virtual Mesh GenerateGeometry()
 20        {
 021            return null;
 22        }
 23
 24        protected virtual void DestroyGeometry()
 25        {
 4726            if (currentMesh == null)
 027                return;
 28
 4729            Object.Destroy(currentMesh);
 4730            currentMesh = null;
 4731        }
 32
 033        public Mesh currentMesh { get; protected set; }
 34        private Model previousModel;
 35        private Model cachedModel;
 36
 17837        public ParametrizedShape()
 38        {
 17839            OnAttach += OnShapeAttached;
 17840            OnDetach += OnShapeDetached;
 17841        }
 42
 43        public override void UpdateFromModel(BaseModel newModel)
 44        {
 24945            cachedModel = (Model) newModel;
 24946            base.UpdateFromModel(newModel);
 24947        }
 48
 49        void UpdateRenderer(IDCLEntity entity, Model model = null)
 50        {
 26951            if (model == null)
 19352                model = (T) this.model;
 53
 26954            if (visibilityDirty)
 55            {
 22856                ConfigureVisibility(entity.meshRootGameObject, model.visible, entity.meshesInfo.renderers);
 22857                visibilityDirty = false;
 58            }
 59
 26960            if (collisionsDirty)
 61            {
 21662                CollidersManager.i.ConfigureColliders(entity.meshRootGameObject, model.withCollisions, false, entity, Ca
 21663                collisionsDirty = false;
 64            }
 65
 26966            if (entity.meshesInfo.meshFilters.Length > 0 && entity.meshesInfo.meshFilters[0].sharedMesh != currentMesh)
 67            {
 368                entity.meshesInfo.UpdateExistingMeshAtIndex(currentMesh, 0);
 69            }
 26970        }
 71
 72        void OnShapeAttached(IDCLEntity entity)
 73        {
 19374            if (entity == null)
 075                return;
 76
 77            // First we remove the old rendereable, then we compute and add the new one.
 19378            RemoveRendereableFromDataStore(entity);
 79
 19380            entity.EnsureMeshGameObject(componentName + " mesh");
 81
 19382            if (currentMesh == null)
 83            {
 16884                currentMesh = GenerateGeometry();
 85            }
 86
 19387            MeshFilter meshFilter = entity.meshRootGameObject.AddComponent<MeshFilter>();
 19388            MeshRenderer meshRenderer = entity.meshRootGameObject.AddComponent<MeshRenderer>();
 89
 19390            entity.meshesInfo.renderers = new Renderer[] { meshRenderer };
 19391            entity.meshesInfo.currentShape = this;
 92
 19393            meshFilter.sharedMesh = currentMesh;
 94
 19395            if (Configuration.ParcelSettings.VISUAL_LOADING_ENABLED)
 96            {
 197                MaterialTransitionController transition = entity.meshRootGameObject.AddComponent<MaterialTransitionContr
 198                Material finalMaterial = Utils.EnsureResourcesMaterial("Materials/Default");
 199                transition.delay = 0;
 1100                transition.useHologram = false;
 1101                transition.fadeThickness = 20;
 1102                transition.OnDidFinishLoading(finalMaterial);
 103
 3104                transition.onFinishedLoading += () => { OnShapeFinishedLoading(entity); };
 1105            }
 106            else
 107            {
 192108                meshRenderer.sharedMaterial = Utils.EnsureResourcesMaterial("Materials/Default");
 109            }
 110
 193111            visibilityDirty = true;
 193112            collisionsDirty = true;
 193113            UpdateRenderer(entity);
 193114            OnShapeFinishedLoading(entity);
 193115            AddRendereableToDataStore(entity);
 193116        }
 117
 118        void OnShapeFinishedLoading(IDCLEntity entity)
 119        {
 194120            entity.OnShapeUpdated?.Invoke(entity);
 194121        }
 122
 123        void OnShapeDetached(IDCLEntity entity)
 124        {
 149125            if (entity == null || entity.meshRootGameObject == null)
 0126                return;
 127
 149128            if (attachedEntities.Count == 0)
 129            {
 124130                DestroyGeometry();
 124131                Utils.CleanMaterials(entity.meshRootGameObject.GetComponent<Renderer>());
 124132                currentMesh = null;
 133            }
 134
 149135            Utils.SafeDestroy(entity.meshRootGameObject);
 149136            entity.meshesInfo.CleanReferences();
 137
 149138            RemoveRendereableFromDataStore(entity);
 149139        }
 140
 141        public override IEnumerator ApplyChanges(BaseModel newModelRaw)
 142        {
 249143            var newModel = (T) newModelRaw;
 144
 249145            if (previousModel != null)
 146            {
 71147                visibilityDirty = newModel.visible != previousModel.visible;
 71148                collisionsDirty = newModel.withCollisions != previousModel.withCollisions || newModel.isPointerBlocker !
 149            }
 150
 249151            bool shouldGenerateMesh = ShouldGenerateNewMesh(previousModel);
 152
 153            //NOTE(Brian): Only generate meshes here if they already are attached to something.
 154            //             Otherwise, the mesh will be created on the OnShapeAttached.
 249155            if (attachedEntities.Count > 0)
 156            {
 60157                using (var iterator = attachedEntities.GetEnumerator())
 158                {
 136159                    while (iterator.MoveNext())
 160                    {
 76161                        var entity = iterator.Current;
 76162                        RemoveRendereableFromDataStore(entity);
 163                    }
 60164                }
 165
 60166                if (shouldGenerateMesh)
 167                {
 6168                    DestroyGeometry();
 6169                    currentMesh = GenerateGeometry();
 170                }
 171
 60172                using (var iterator = attachedEntities.GetEnumerator())
 173                {
 60174                    bool cachedVisibilityDirty = visibilityDirty;
 60175                    bool cachedCollisionDirty = collisionsDirty;
 136176                    while (iterator.MoveNext())
 177                    {
 178                        //NOTE(Alex): Since UpdateRenderer updates the dirty flags as well we have to make sure every en
 179                        //            gets updated accordingly to the original flags.
 76180                        visibilityDirty = cachedVisibilityDirty;
 76181                        collisionsDirty = cachedCollisionDirty;
 182
 76183                        var entity = iterator.Current;
 76184                        UpdateRenderer(entity, newModel);
 185
 76186                        entity.OnShapeUpdated?.Invoke(entity);
 187                    }
 60188                }
 189
 60190                using (var iterator = attachedEntities.GetEnumerator())
 191                {
 136192                    while (iterator.MoveNext())
 193                    {
 76194                        var entity = iterator.Current;
 76195                        AddRendereableToDataStore(entity);
 196                    }
 60197                }
 198            }
 199
 249200            previousModel = newModel;
 249201            return null;
 202        }
 203
 204        public override void AttachTo(IDCLEntity entity, System.Type overridenAttachedType = null)
 205        {
 193206            if (attachedEntities.Contains(entity))
 0207                return;
 208
 193209            base.AttachTo(entity);
 193210        }
 211
 91212        public override bool IsVisible() { return cachedModel.visible; }
 213
 30214        public override bool HasCollisions() { return cachedModel.withCollisions; }
 215
 0216        protected virtual bool ShouldGenerateNewMesh(BaseShape.Model newModel) { return true; }
 217
 218        private void RemoveRendereableFromDataStore(IDCLEntity entity)
 219        {
 418220            if (!attachedRendereables.ContainsKey(entity))
 193221                return;
 222
 225223            DataStore.i.sceneWorldObjects.RemoveRendereable(entity.scene.sceneData.id, attachedRendereables[entity]);
 225224            attachedRendereables.Remove(entity);
 225225        }
 226
 227        private void AddRendereableToDataStore(IDCLEntity entity)
 228        {
 269229            if (attachedRendereables.ContainsKey(entity))
 0230                return;
 231
 269232            int triangleCount = currentMesh.triangles.Length;
 233
 269234            var newRendereable =
 235                new Rendereable()
 236                {
 237                    container = entity.meshRootGameObject,
 238                    totalTriangleCount = triangleCount,
 239                    meshes = new HashSet<Mesh>() { currentMesh },
 240                    meshToTriangleCount = new Dictionary<Mesh, int>() { { currentMesh, triangleCount } }
 241                };
 242
 269243            newRendereable.renderers = MeshesInfoUtils.ExtractUniqueRenderers(entity.meshRootGameObject);
 269244            newRendereable.ownerId = entity.entityId;
 245
 269246            attachedRendereables.Add(entity, newRendereable);
 269247            DataStore.i.sceneWorldObjects.AddRendereable(entity.scene.sceneData.id, newRendereable);
 269248        }
 249    }
 250}